opendevbrowser 0.0.28 → 0.0.30
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 +2 -2
- package/dist/accessibility-snapshot-CQ4ZKWKC.js +39 -0
- package/dist/accessibility-snapshot-CQ4ZKWKC.js.map +1 -0
- package/dist/active-window-TD5HYJ72.js +37 -0
- package/dist/active-window-TD5HYJ72.js.map +1 -0
- package/dist/annotate-VTLFS2XV.js +205 -0
- package/dist/annotate-VTLFS2XV.js.map +1 -0
- package/dist/artifacts-KJ6RNDO2.js +120 -0
- package/dist/artifacts-KJ6RNDO2.js.map +1 -0
- package/dist/attr-BCI5KYCW.js +84 -0
- package/dist/attr-BCI5KYCW.js.map +1 -0
- package/dist/browser/ops-client.d.ts +1 -0
- package/dist/browser/ops-client.d.ts.map +1 -1
- package/dist/canvas-5DFEEOKM.js +309 -0
- package/dist/canvas-5DFEEOKM.js.map +1 -0
- package/dist/capture-desktop-HFTTWY4Z.js +38 -0
- package/dist/capture-desktop-HFTTWY4Z.js.map +1 -0
- package/dist/capture-window-X63XPIFF.js +40 -0
- package/dist/capture-window-X63XPIFF.js.map +1 -0
- package/dist/check-LWAUY7GC.js +71 -0
- package/dist/check-LWAUY7GC.js.map +1 -0
- package/dist/checked-ZSOUKVYT.js +71 -0
- package/dist/checked-ZSOUKVYT.js.map +1 -0
- package/dist/chunk-2SIMIPLY.js +67 -0
- package/dist/chunk-2SIMIPLY.js.map +1 -0
- package/dist/chunk-37VSRUW4.js +141 -0
- package/dist/chunk-37VSRUW4.js.map +1 -0
- package/dist/{chunk-T3VVHJTK.js → chunk-4BEJVZRK.js} +1078 -1458
- package/dist/chunk-4BEJVZRK.js.map +1 -0
- package/dist/chunk-5SWZDVOW.js +144 -0
- package/dist/chunk-5SWZDVOW.js.map +1 -0
- package/dist/chunk-6PVZ2ABC.js +429 -0
- package/dist/chunk-6PVZ2ABC.js.map +1 -0
- package/dist/chunk-7GVOUZMQ.js +64 -0
- package/dist/chunk-7GVOUZMQ.js.map +1 -0
- package/dist/chunk-7THCPS52.js +84 -0
- package/dist/chunk-7THCPS52.js.map +1 -0
- package/dist/chunk-AHEWXOKY.js +64 -0
- package/dist/chunk-AHEWXOKY.js.map +1 -0
- package/dist/chunk-ASMHEEKY.js +10 -0
- package/dist/chunk-ASMHEEKY.js.map +1 -0
- package/dist/chunk-COAOWH3G.js +3651 -0
- package/dist/chunk-COAOWH3G.js.map +1 -0
- package/dist/chunk-DBF5OKH3.js +111 -0
- package/dist/chunk-DBF5OKH3.js.map +1 -0
- package/dist/chunk-DW4TX7MU.js +54 -0
- package/dist/chunk-DW4TX7MU.js.map +1 -0
- package/dist/chunk-GQJ5S3BL.js +20 -0
- package/dist/chunk-GQJ5S3BL.js.map +1 -0
- package/dist/chunk-IPE7TF2P.js +54 -0
- package/dist/chunk-IPE7TF2P.js.map +1 -0
- package/dist/chunk-IQTJHXZJ.js +126 -0
- package/dist/chunk-IQTJHXZJ.js.map +1 -0
- package/dist/chunk-J47N77VG.js +2969 -0
- package/dist/chunk-J47N77VG.js.map +1 -0
- package/dist/chunk-JZXD6FWR.js +25 -0
- package/dist/chunk-JZXD6FWR.js.map +1 -0
- package/dist/{chunk-QVWOPIZJ.js → chunk-KDSNXS6N.js} +75 -149
- package/dist/chunk-KDSNXS6N.js.map +1 -0
- package/dist/chunk-KZ2IXVQT.js +219 -0
- package/dist/chunk-KZ2IXVQT.js.map +1 -0
- package/dist/chunk-MD655IPO.js +838 -0
- package/dist/chunk-MD655IPO.js.map +1 -0
- package/dist/chunk-MX3NFLCE.js +940 -0
- package/dist/chunk-MX3NFLCE.js.map +1 -0
- package/dist/chunk-OW5HMYMI.js +19 -0
- package/dist/chunk-OW5HMYMI.js.map +1 -0
- package/dist/chunk-PPUWQKIC.js +26 -0
- package/dist/chunk-PPUWQKIC.js.map +1 -0
- package/dist/{chunk-I5ZCOZZV.js → chunk-QOMWCRE3.js} +1202 -9561
- package/dist/chunk-QOMWCRE3.js.map +1 -0
- package/dist/chunk-RCZZGGJS.js +226 -0
- package/dist/chunk-RCZZGGJS.js.map +1 -0
- package/dist/chunk-RJNI3BHT.js +1 -0
- package/dist/chunk-RPXWUCQQ.js +112 -0
- package/dist/chunk-RPXWUCQQ.js.map +1 -0
- package/dist/chunk-S5KZQJJI.js +107 -0
- package/dist/chunk-S5KZQJJI.js.map +1 -0
- package/dist/chunk-T4GMCW6Z.js +46 -0
- package/dist/chunk-T4GMCW6Z.js.map +1 -0
- package/dist/chunk-WHQZBUNY.js +982 -0
- package/dist/chunk-WHQZBUNY.js.map +1 -0
- package/dist/chunk-WOXBLP7V.js +610 -0
- package/dist/chunk-WOXBLP7V.js.map +1 -0
- package/dist/cli/commands/inspiredesign.d.ts.map +1 -1
- package/dist/cli/commands/macro-resolve.d.ts +4 -1
- package/dist/cli/commands/macro-resolve.d.ts.map +1 -1
- package/dist/cli/commands/product-video.d.ts.map +1 -1
- package/dist/cli/commands/research.d.ts.map +1 -1
- package/dist/cli/commands/serve.d.ts.map +1 -1
- package/dist/cli/commands/shopping.d.ts.map +1 -1
- package/dist/cli/commands/workflow-output.d.ts +2 -0
- package/dist/cli/commands/workflow-output.d.ts.map +1 -0
- package/dist/cli/daemon-commands.d.ts.map +1 -1
- package/dist/cli/daemon.d.ts.map +1 -1
- package/dist/cli/index.js +204 -8123
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/installers/postinstall-skill-sync.js +2 -1
- package/dist/cli/installers/postinstall-skill-sync.js.map +1 -1
- package/dist/cli/remote-relay.d.ts.map +1 -1
- package/dist/click-2AILSEIZ.js +81 -0
- package/dist/click-2AILSEIZ.js.map +1 -0
- package/dist/clone-component-TPJS3PEG.js +82 -0
- package/dist/clone-component-TPJS3PEG.js.map +1 -0
- package/dist/clone-page-LE74CIFC.js +69 -0
- package/dist/clone-page-LE74CIFC.js.map +1 -0
- package/dist/close-HN4YI47K.js +63 -0
- package/dist/close-HN4YI47K.js.map +1 -0
- package/dist/close-WFERRHX6.js +63 -0
- package/dist/close-WFERRHX6.js.map +1 -0
- package/dist/connect-RWBV2UCQ.js +107 -0
- package/dist/connect-RWBV2UCQ.js.map +1 -0
- package/dist/console-poll-PP4YYPDF.js +76 -0
- package/dist/console-poll-PP4YYPDF.js.map +1 -0
- package/dist/cookie-import-6IP776FC.js +177 -0
- package/dist/cookie-import-6IP776FC.js.map +1 -0
- package/dist/cookie-list-O2KG6DPU.js +117 -0
- package/dist/cookie-list-O2KG6DPU.js.map +1 -0
- package/dist/daemon-2BSAZXLT.js +194 -0
- package/dist/daemon-2BSAZXLT.js.map +1 -0
- package/dist/daemon-fingerprint.json +1 -1
- package/dist/debug-trace-snapshot-F3BDVZXS.js +136 -0
- package/dist/debug-trace-snapshot-F3BDVZXS.js.map +1 -0
- package/dist/dialog-6JQYUWMQ.js +75 -0
- package/dist/dialog-6JQYUWMQ.js.map +1 -0
- package/dist/disconnect-763TP7GH.js +58 -0
- package/dist/disconnect-763TP7GH.js.map +1 -0
- package/dist/enabled-DLYQFNIP.js +71 -0
- package/dist/enabled-DLYQFNIP.js.map +1 -0
- package/dist/extension-extractor-GKWSFHPN.js +11 -0
- package/dist/extension-extractor-GKWSFHPN.js.map +1 -0
- package/dist/global-D6WLWBXA.js +56 -0
- package/dist/global-D6WLWBXA.js.map +1 -0
- package/dist/goto-S346TJJH.js +98 -0
- package/dist/goto-S346TJJH.js.map +1 -0
- package/dist/help-EKKKEDL5.js +491 -0
- package/dist/help-EKKKEDL5.js.map +1 -0
- package/dist/hover-6JVJFGO7.js +71 -0
- package/dist/hover-6JVJFGO7.js.map +1 -0
- package/dist/html-EVOSPBIT.js +84 -0
- package/dist/html-EVOSPBIT.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +87 -38
- package/dist/index.js.map +1 -1
- package/dist/inspector-H57BVUJP.js +62 -0
- package/dist/inspector-H57BVUJP.js.map +1 -0
- package/dist/inspector-audit-NQBAJWC7.js +84 -0
- package/dist/inspector-audit-NQBAJWC7.js.map +1 -0
- package/dist/inspector-plan-ZDIQVND3.js +69 -0
- package/dist/inspector-plan-ZDIQVND3.js.map +1 -0
- package/dist/inspiredesign-IEUL4PX3.js +234 -0
- package/dist/inspiredesign-IEUL4PX3.js.map +1 -0
- package/dist/install-autostart-output-5DOMKCQL.js +41 -0
- package/dist/install-autostart-output-5DOMKCQL.js.map +1 -0
- package/dist/install-autostart-reconciliation-NHKOFYTD.js +73 -0
- package/dist/install-autostart-reconciliation-NHKOFYTD.js.map +1 -0
- package/dist/launch-EK66VQPF.js +225 -0
- package/dist/launch-EK66VQPF.js.map +1 -0
- package/dist/list-ADZAQ2IU.js +51 -0
- package/dist/list-ADZAQ2IU.js.map +1 -0
- package/dist/list-KKUKN467.js +54 -0
- package/dist/list-KKUKN467.js.map +1 -0
- package/dist/local-HXJLUUNT.js +54 -0
- package/dist/local-HXJLUUNT.js.map +1 -0
- package/dist/macro-resolve-6DOQJ7CA.js +253 -0
- package/dist/macro-resolve-6DOQJ7CA.js.map +1 -0
- package/dist/macros/execute-runtime.d.ts +3 -1
- package/dist/macros/execute-runtime.d.ts.map +1 -1
- package/dist/macros/execute.d.ts +2 -0
- package/dist/macros/execute.d.ts.map +1 -1
- package/dist/native-UPLVQ2SG.js +22 -0
- package/dist/native-UPLVQ2SG.js.map +1 -0
- package/dist/network-poll-NUL4PDPY.js +76 -0
- package/dist/network-poll-NUL4PDPY.js.map +1 -0
- package/dist/new-5NKYPEFT.js +69 -0
- package/dist/new-5NKYPEFT.js.map +1 -0
- package/dist/onboarding-metadata-7E3KLYSZ.js +27 -0
- package/dist/onboarding-metadata-7E3KLYSZ.js.map +1 -0
- package/dist/open-NR3BPLXV.js +81 -0
- package/dist/open-NR3BPLXV.js.map +1 -0
- package/dist/opendevbrowser.d.ts.map +1 -1
- package/dist/opendevbrowser.js +87 -38
- package/dist/opendevbrowser.js.map +1 -1
- package/dist/perf-HJ36ZI6H.js +58 -0
- package/dist/perf-HJ36ZI6H.js.map +1 -0
- package/dist/pointer-down-IYTTQWXZ.js +55 -0
- package/dist/pointer-down-IYTTQWXZ.js.map +1 -0
- package/dist/pointer-drag-A2YC5PWI.js +54 -0
- package/dist/pointer-drag-A2YC5PWI.js.map +1 -0
- package/dist/pointer-move-W5K5FUI4.js +52 -0
- package/dist/pointer-move-W5K5FUI4.js.map +1 -0
- package/dist/pointer-up-6GWVO64Y.js +55 -0
- package/dist/pointer-up-6GWVO64Y.js.map +1 -0
- package/dist/press-A3V5WB3S.js +83 -0
- package/dist/press-A3V5WB3S.js.map +1 -0
- package/dist/product-video-52REKWF3.js +235 -0
- package/dist/product-video-52REKWF3.js.map +1 -0
- package/dist/providers/artifacts.d.ts +0 -2
- package/dist/providers/artifacts.d.ts.map +1 -1
- package/dist/providers/blocker.d.ts.map +1 -1
- package/dist/providers/bounded-map.d.ts +2 -0
- package/dist/providers/bounded-map.d.ts.map +1 -0
- package/dist/providers/community/index.d.ts.map +1 -1
- package/dist/providers/constraint.d.ts.map +1 -1
- package/dist/providers/index.d.ts +1 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/renderer.d.ts.map +1 -1
- package/dist/providers/research-compiler.d.ts +1 -1
- package/dist/providers/research-compiler.d.ts.map +1 -1
- package/dist/providers/research-executor.d.ts.map +1 -1
- package/dist/providers/runtime-factory.d.ts.map +1 -1
- package/dist/providers/shared/traversal-url.d.ts +3 -0
- package/dist/providers/shared/traversal-url.d.ts.map +1 -1
- package/dist/providers/shopping/index.d.ts.map +1 -1
- package/dist/providers/social/search-quality.d.ts.map +1 -1
- package/dist/providers/workflow-handoff.d.ts +4 -0
- package/dist/providers/workflow-handoff.d.ts.map +1 -1
- package/dist/providers/workflow-output-root.d.ts +6 -0
- package/dist/providers/workflow-output-root.d.ts.map +1 -0
- package/dist/providers/workflows.d.ts.map +1 -1
- package/dist/{providers-QF2RFB4J.js → providers-IMFYMMHQ.js} +19 -14
- package/dist/providers-IMFYMMHQ.js.map +1 -0
- 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/relay/protocol.d.ts +3 -1
- package/dist/relay/protocol.d.ts.map +1 -1
- package/dist/relay/relay-server.d.ts +6 -0
- package/dist/relay/relay-server.d.ts.map +1 -1
- package/dist/research-WB6BBCDD.js +295 -0
- package/dist/research-WB6BBCDD.js.map +1 -0
- package/dist/review-BGWVY4RA.js +48 -0
- package/dist/review-BGWVY4RA.js.map +1 -0
- package/dist/review-desktop-LEORC5VS.js +54 -0
- package/dist/review-desktop-LEORC5VS.js.map +1 -0
- package/dist/rpc-4TSKSFGC.js +159 -0
- package/dist/rpc-4TSKSFGC.js.map +1 -0
- package/dist/run-3NBLVWXD.js +180 -0
- package/dist/run-3NBLVWXD.js.map +1 -0
- package/dist/screencast-start-UZVIT3IN.js +67 -0
- package/dist/screencast-start-UZVIT3IN.js.map +1 -0
- package/dist/screencast-stop-NOSJSIUO.js +59 -0
- package/dist/screencast-stop-NOSJSIUO.js.map +1 -0
- package/dist/screenshot-LARG4JQG.js +68 -0
- package/dist/screenshot-LARG4JQG.js.map +1 -0
- package/dist/scroll-VNFMV6TW.js +84 -0
- package/dist/scroll-VNFMV6TW.js.map +1 -0
- package/dist/scroll-into-view-VYRT3JPT.js +71 -0
- package/dist/scroll-into-view-VYRT3JPT.js.map +1 -0
- package/dist/select-KJTUZDVO.js +86 -0
- package/dist/select-KJTUZDVO.js.map +1 -0
- package/dist/serve-EV7K4HKR.js +498 -0
- package/dist/serve-EV7K4HKR.js.map +1 -0
- package/dist/shopping-DTXHVQ2X.js +273 -0
- package/dist/shopping-DTXHVQ2X.js.map +1 -0
- package/dist/skill-lifecycle-5UAZGKSN.js +89 -0
- package/dist/skill-lifecycle-5UAZGKSN.js.map +1 -0
- package/dist/skills-NSXDX6YM.js +26 -0
- package/dist/skills-NSXDX6YM.js.map +1 -0
- package/dist/snapshot-3XQMCMRJ.js +113 -0
- package/dist/snapshot-3XQMCMRJ.js.map +1 -0
- package/dist/status-OXSYA5XD.js +35 -0
- package/dist/status-OXSYA5XD.js.map +1 -0
- package/dist/status-YUMDP5KY.js +132 -0
- package/dist/status-YUMDP5KY.js.map +1 -0
- package/dist/status-capabilities-P4KDSE2Y.js +57 -0
- package/dist/status-capabilities-P4KDSE2Y.js.map +1 -0
- package/dist/text-V3B7UVIH.js +84 -0
- package/dist/text-V3B7UVIH.js.map +1 -0
- package/dist/tools/deps.d.ts +1 -0
- package/dist/tools/deps.d.ts.map +1 -1
- package/dist/tools/inspiredesign_run.d.ts.map +1 -1
- package/dist/tools/macro_resolve.d.ts.map +1 -1
- package/dist/tools/product_video_run.d.ts.map +1 -1
- package/dist/tools/research_run.d.ts.map +1 -1
- package/dist/tools/shopping_run.d.ts.map +1 -1
- package/dist/tools/workflow-output.d.ts +3 -0
- package/dist/tools/workflow-output.d.ts.map +1 -0
- package/dist/type-IYBN3ZLR.js +94 -0
- package/dist/type-IYBN3ZLR.js.map +1 -0
- package/dist/uncheck-SG737EGI.js +71 -0
- package/dist/uncheck-SG737EGI.js.map +1 -0
- package/dist/uninstall-KYKGJAX7.js +91 -0
- package/dist/uninstall-KYKGJAX7.js.map +1 -0
- package/dist/update-SMXPYGXS.js +305 -0
- package/dist/update-SMXPYGXS.js.map +1 -0
- package/dist/update-skill-modes-BVX7IVMW.js +38 -0
- package/dist/update-skill-modes-BVX7IVMW.js.map +1 -0
- package/dist/upload-KH6ZABJA.js +56 -0
- package/dist/upload-KH6ZABJA.js.map +1 -0
- package/dist/use-7YDKO3U4.js +63 -0
- package/dist/use-7YDKO3U4.js.map +1 -0
- package/dist/value-RZBWSKKM.js +71 -0
- package/dist/value-RZBWSKKM.js.map +1 -0
- package/dist/visible-BSFTAKXR.js +71 -0
- package/dist/visible-BSFTAKXR.js.map +1 -0
- package/dist/wait-TMTEAYOP.js +109 -0
- package/dist/wait-TMTEAYOP.js.map +1 -0
- package/dist/windows-HIZ23OHS.js +37 -0
- package/dist/windows-HIZ23OHS.js.map +1 -0
- package/extension/dist/background.js +99 -22
- package/extension/dist/ops/ops-runtime.js +85 -7
- package/extension/dist/ops/ops-session-store.js +3 -0
- package/extension/dist/ops/target-session-coordinator.js +3 -0
- package/extension/dist/services/CDPRouter.js +9 -0
- package/extension/manifest.json +1 -1
- package/package.json +1 -1
- package/skills/opendevbrowser-best-practices/SKILL.md +8 -6
- package/skills/opendevbrowser-best-practices/artifacts/skill-runtime-surface-matrix.md +1 -1
- package/skills/opendevbrowser-best-practices/scripts/odb-workflow.sh +3 -2
- package/skills/opendevbrowser-best-practices/scripts/validator-fixture-cli.sh +39 -2
- package/skills/opendevbrowser-research/SKILL.md +64 -12
- package/skills/opendevbrowser-research/artifacts/research-workflows.md +56 -19
- package/skills/opendevbrowser-research/assets/templates/compact.md +31 -5
- package/skills/opendevbrowser-research/assets/templates/context.json +52 -1
- package/skills/opendevbrowser-research/assets/templates/report.md +57 -4
- package/skills/opendevbrowser-research/examples/sample-input.json +1 -1
- package/skills/opendevbrowser-research/examples/sample-output.md +27 -2
- package/skills/opendevbrowser-research/scripts/run-research.sh +2 -6
- package/skills/opendevbrowser-research/scripts/validate-skill-assets.sh +115 -1
- package/dist/chunk-I5ZCOZZV.js.map +0 -1
- package/dist/chunk-QVWOPIZJ.js.map +0 -1
- package/dist/chunk-T3VVHJTK.js.map +0 -1
- /package/dist/{providers-QF2RFB4J.js.map → chunk-RJNI3BHT.js.map} +0 -0
|
@@ -1,3 +1,28 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createArtifactBundle
|
|
3
|
+
} from "./chunk-S5KZQJJI.js";
|
|
4
|
+
import {
|
|
5
|
+
INSPIREDESIGN_ARTIFACT_GUIDE,
|
|
6
|
+
INSPIREDESIGN_CONTRACT_SECTION_GUIDE,
|
|
7
|
+
INSPIREDESIGN_HANDOFF_COMMANDS,
|
|
8
|
+
INSPIREDESIGN_HANDOFF_FILES,
|
|
9
|
+
INSPIREDESIGN_HANDOFF_GUIDANCE,
|
|
10
|
+
INSPIREDESIGN_HANDOFF_RECOMMENDED_SKILLS,
|
|
11
|
+
buildInspiredesignFollowthroughSummary,
|
|
12
|
+
buildInspiredesignNextStep
|
|
13
|
+
} from "./chunk-KZ2IXVQT.js";
|
|
14
|
+
import {
|
|
15
|
+
applyPromptGuard,
|
|
16
|
+
applyProviderIssueHint,
|
|
17
|
+
buildProviderIssueGuidance,
|
|
18
|
+
classifyBlockerSignal,
|
|
19
|
+
classifyProviderIssue,
|
|
20
|
+
createLogger,
|
|
21
|
+
readProviderIssueHint,
|
|
22
|
+
readProviderIssueHintFromRecord,
|
|
23
|
+
redactSensitive,
|
|
24
|
+
summarizePrimaryProviderIssue
|
|
25
|
+
} from "./chunk-WHQZBUNY.js";
|
|
1
26
|
import {
|
|
2
27
|
ProviderRuntimeError,
|
|
3
28
|
createProviderError,
|
|
@@ -8,935 +33,11 @@ import {
|
|
|
8
33
|
toProviderError
|
|
9
34
|
} from "./chunk-FUSXMW3G.js";
|
|
10
35
|
|
|
11
|
-
// src/core/logging.ts
|
|
12
|
-
import { randomUUID } from "crypto";
|
|
13
|
-
var SECRET_KEY_PATTERN = /(token|secret|password|authorization|cookie|api[-_]?key|session)/i;
|
|
14
|
-
var SECRET_VALUE_PATTERN = /(bearer\s+[a-z0-9._-]+|sk_[a-z0-9_-]+|pk_[a-z0-9_-]+|eyJ[a-z0-9_-]+\.[a-z0-9_-]+\.[a-z0-9_-]+)/gi;
|
|
15
|
-
function redactString(value) {
|
|
16
|
-
return value.replace(SECRET_VALUE_PATTERN, "[REDACTED]");
|
|
17
|
-
}
|
|
18
|
-
function redactSensitive(value, seen = /* @__PURE__ */ new WeakSet()) {
|
|
19
|
-
if (typeof value === "string") {
|
|
20
|
-
return redactString(value);
|
|
21
|
-
}
|
|
22
|
-
if (typeof value !== "object" || value === null) {
|
|
23
|
-
return value;
|
|
24
|
-
}
|
|
25
|
-
if (seen.has(value)) {
|
|
26
|
-
return "[Circular]";
|
|
27
|
-
}
|
|
28
|
-
seen.add(value);
|
|
29
|
-
if (Array.isArray(value)) {
|
|
30
|
-
return value.map((item) => redactSensitive(item, seen));
|
|
31
|
-
}
|
|
32
|
-
const output = {};
|
|
33
|
-
for (const [key, entry] of Object.entries(value)) {
|
|
34
|
-
if (SECRET_KEY_PATTERN.test(key)) {
|
|
35
|
-
output[key] = "[REDACTED]";
|
|
36
|
-
continue;
|
|
37
|
-
}
|
|
38
|
-
output[key] = redactSensitive(entry, seen);
|
|
39
|
-
}
|
|
40
|
-
return output;
|
|
41
|
-
}
|
|
42
|
-
function createRequestId() {
|
|
43
|
-
return randomUUID();
|
|
44
|
-
}
|
|
45
|
-
var defaultSink = (entry) => {
|
|
46
|
-
const payload = JSON.stringify(entry);
|
|
47
|
-
if (entry.level === "error") {
|
|
48
|
-
console.error(payload);
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
if (entry.level === "warn") {
|
|
52
|
-
console.warn(payload);
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
console.log(payload);
|
|
56
|
-
};
|
|
57
|
-
var stderrSink = (entry) => {
|
|
58
|
-
process.stderr.write(`${JSON.stringify(entry)}
|
|
59
|
-
`);
|
|
60
|
-
};
|
|
61
|
-
var configuredDefaultSink = defaultSink;
|
|
62
|
-
function setDefaultLogSink(sink) {
|
|
63
|
-
configuredDefaultSink = sink ?? defaultSink;
|
|
64
|
-
}
|
|
65
|
-
function createLogger(moduleName, sink) {
|
|
66
|
-
const emit = (level, event, fields = {}) => {
|
|
67
|
-
const entry = {
|
|
68
|
-
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
69
|
-
level,
|
|
70
|
-
module: moduleName,
|
|
71
|
-
event,
|
|
72
|
-
requestId: fields.requestId ?? createRequestId(),
|
|
73
|
-
...fields.sessionId ? { sessionId: fields.sessionId } : {},
|
|
74
|
-
...fields.traceId ? { traceId: fields.traceId } : {},
|
|
75
|
-
...typeof fields.data === "undefined" ? {} : { data: redactSensitive(fields.data) }
|
|
76
|
-
};
|
|
77
|
-
(sink ?? configuredDefaultSink)(entry);
|
|
78
|
-
return entry;
|
|
79
|
-
};
|
|
80
|
-
return {
|
|
81
|
-
debug: (event, fields) => emit("debug", event, fields),
|
|
82
|
-
info: (event, fields) => emit("info", event, fields),
|
|
83
|
-
warn: (event, fields) => emit("warn", event, fields),
|
|
84
|
-
error: (event, fields) => emit("error", event, fields),
|
|
85
|
-
audit: (event, fields) => emit("audit", event, fields)
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// src/providers/safety/prompt-guard.ts
|
|
90
|
-
var MAX_EXCERPT_LENGTH = 120;
|
|
91
|
-
var RULES = [
|
|
92
|
-
{
|
|
93
|
-
id: "reveal_system_prompt",
|
|
94
|
-
regex: /\b(reveal|show|print|dump|expose|leak)\b[^.!?\n]{0,80}\b(system prompt|hidden prompt|internal prompt)\b/gi,
|
|
95
|
-
severity: "high",
|
|
96
|
-
action: "quarantine"
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
id: "tool_abuse_directive",
|
|
100
|
-
regex: /\buse (?:the )?tool(?:ing)?\b[^.!?\n]{0,120}\b(delete|remove|drop|wipe|exfiltrat|override|bypass)\w*/gi,
|
|
101
|
-
severity: "high",
|
|
102
|
-
action: "quarantine"
|
|
103
|
-
},
|
|
104
|
-
{
|
|
105
|
-
id: "ignore_previous_instructions",
|
|
106
|
-
regex: /\bignore (?:all )?previous instructions?\b/gi,
|
|
107
|
-
severity: "medium",
|
|
108
|
-
action: "strip"
|
|
109
|
-
},
|
|
110
|
-
{
|
|
111
|
-
id: "reveal_hidden_data",
|
|
112
|
-
regex: /\breveal (?:hidden|secret|confidential) (?:data|information)\b/gi,
|
|
113
|
-
severity: "high",
|
|
114
|
-
action: "quarantine"
|
|
115
|
-
}
|
|
116
|
-
];
|
|
117
|
-
var sanitizeExcerpt = (value) => {
|
|
118
|
-
const compact = value.replace(/\s+/g, " ").trim();
|
|
119
|
-
if (compact.length <= MAX_EXCERPT_LENGTH) return compact;
|
|
120
|
-
return `${compact.slice(0, MAX_EXCERPT_LENGTH - 3)}...`;
|
|
121
|
-
};
|
|
122
|
-
var isJsonObject = (value) => {
|
|
123
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
124
|
-
};
|
|
125
|
-
var withSecurityAttributes = (record, enabled, guardEntries, quarantinedSegments) => {
|
|
126
|
-
const existingSecurity = isJsonObject(record.attributes.security) ? record.attributes.security : {};
|
|
127
|
-
return {
|
|
128
|
-
...record.attributes,
|
|
129
|
-
security: {
|
|
130
|
-
...existingSecurity,
|
|
131
|
-
untrustedContent: true,
|
|
132
|
-
dataOnlyContext: true,
|
|
133
|
-
promptGuardEnabled: enabled,
|
|
134
|
-
guardEntries,
|
|
135
|
-
quarantinedSegments
|
|
136
|
-
}
|
|
137
|
-
};
|
|
138
|
-
};
|
|
139
|
-
function sanitizePromptGuardText(text, enabled) {
|
|
140
|
-
if (!enabled || !text) {
|
|
141
|
-
return {
|
|
142
|
-
text,
|
|
143
|
-
diagnostics: { entries: 0, quarantinedSegments: 0 },
|
|
144
|
-
entries: []
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
let output = text;
|
|
148
|
-
const entries = [];
|
|
149
|
-
for (const rule of RULES) {
|
|
150
|
-
rule.regex.lastIndex = 0;
|
|
151
|
-
output = output.replace(rule.regex, (match) => {
|
|
152
|
-
entries.push({
|
|
153
|
-
pattern: rule.id,
|
|
154
|
-
action: rule.action,
|
|
155
|
-
severity: rule.severity,
|
|
156
|
-
excerpt: sanitizeExcerpt(match)
|
|
157
|
-
});
|
|
158
|
-
return rule.action === "quarantine" ? "[QUARANTINED]" : " ";
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
const normalized = output.replace(/\s{2,}/g, " ").trim();
|
|
162
|
-
const quarantinedSegments = entries.reduce((count, entry) => {
|
|
163
|
-
return entry.action === "quarantine" ? count + 1 : count;
|
|
164
|
-
}, 0);
|
|
165
|
-
return {
|
|
166
|
-
text: normalized,
|
|
167
|
-
diagnostics: {
|
|
168
|
-
entries: entries.length,
|
|
169
|
-
quarantinedSegments
|
|
170
|
-
},
|
|
171
|
-
entries
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
function applyPromptGuard(records, enabled) {
|
|
175
|
-
const auditEntries = [];
|
|
176
|
-
let totalQuarantinedSegments = 0;
|
|
177
|
-
const guardedRecords = records.map((record) => {
|
|
178
|
-
if (!enabled) {
|
|
179
|
-
return {
|
|
180
|
-
...record,
|
|
181
|
-
attributes: withSecurityAttributes(record, false, 0, 0)
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
let title = record.title;
|
|
185
|
-
let content = record.content;
|
|
186
|
-
let recordEntries = 0;
|
|
187
|
-
let recordQuarantinedSegments = 0;
|
|
188
|
-
if (typeof record.title === "string") {
|
|
189
|
-
const sanitizedTitle = sanitizePromptGuardText(record.title, true);
|
|
190
|
-
title = sanitizedTitle.text;
|
|
191
|
-
recordEntries += sanitizedTitle.diagnostics.entries;
|
|
192
|
-
recordQuarantinedSegments += sanitizedTitle.diagnostics.quarantinedSegments;
|
|
193
|
-
for (const entry of sanitizedTitle.entries) {
|
|
194
|
-
auditEntries.push({
|
|
195
|
-
...entry,
|
|
196
|
-
recordId: record.id,
|
|
197
|
-
field: "title"
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
if (typeof record.content === "string") {
|
|
202
|
-
const sanitizedContent = sanitizePromptGuardText(record.content, true);
|
|
203
|
-
content = sanitizedContent.text;
|
|
204
|
-
recordEntries += sanitizedContent.diagnostics.entries;
|
|
205
|
-
recordQuarantinedSegments += sanitizedContent.diagnostics.quarantinedSegments;
|
|
206
|
-
for (const entry of sanitizedContent.entries) {
|
|
207
|
-
auditEntries.push({
|
|
208
|
-
...entry,
|
|
209
|
-
recordId: record.id,
|
|
210
|
-
field: "content"
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
totalQuarantinedSegments += recordQuarantinedSegments;
|
|
215
|
-
return {
|
|
216
|
-
...record,
|
|
217
|
-
...typeof title === "string" ? { title } : {},
|
|
218
|
-
...typeof content === "string" ? { content } : {},
|
|
219
|
-
attributes: withSecurityAttributes(record, true, recordEntries, recordQuarantinedSegments)
|
|
220
|
-
};
|
|
221
|
-
});
|
|
222
|
-
return {
|
|
223
|
-
records: guardedRecords,
|
|
224
|
-
audit: {
|
|
225
|
-
enabled,
|
|
226
|
-
quarantinedSegments: enabled ? totalQuarantinedSegments : 0,
|
|
227
|
-
entries: enabled ? auditEntries : []
|
|
228
|
-
}
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// src/providers/blocker.ts
|
|
233
|
-
var AUTH_URL_PATTERNS = [
|
|
234
|
-
{ id: "redirect_login_flow", regex: /\/i\/flow\/login/i, confidence: 0.97 },
|
|
235
|
-
{ id: "auth_login_path", regex: /\/(login|signin|sign-in|auth)(?:[./?]|$)/i, confidence: 0.9 }
|
|
236
|
-
];
|
|
237
|
-
var AUTH_TITLE_PATTERNS = [
|
|
238
|
-
{ id: "title_login", regex: /\b(log ?in|sign ?in|login|signin)\b/i, confidence: 0.92 },
|
|
239
|
-
{ id: "title_auth_required", regex: /authentication required/i, confidence: 0.9 }
|
|
240
|
-
];
|
|
241
|
-
var CHALLENGE_PATTERNS = [
|
|
242
|
-
{ id: "challenge_keyword", regex: /\b(challenge|captcha|verify|interstitial|cf_chl|bot)\b/i, confidence: 0.88 },
|
|
243
|
-
{ id: "prove_humanity", regex: /prove your humanity/i, confidence: 0.96 },
|
|
244
|
-
{ id: "robot_or_human", regex: /robot or human/i, confidence: 0.98 },
|
|
245
|
-
{ id: "confirm_human", regex: /confirm that you(?:'|’)re human/i, confidence: 0.96 },
|
|
246
|
-
{ id: "click_and_hold", regex: /\b(?:click|press|tap|activate)\s+(?:and\s+)?hold\b/i, confidence: 0.95 },
|
|
247
|
-
{ id: "press_and_hold", regex: /activate and hold the button/i, confidence: 0.95 },
|
|
248
|
-
{ id: "drag_slider", regex: /\b(?:drag|slide|move)(?:\s+the)?\s+(?:slider|puzzle(?:\s+piece)?|piece|button)\b/i, confidence: 0.95 },
|
|
249
|
-
{ id: "pardon_interruption", regex: /pardon our interruption/i, confidence: 0.97 },
|
|
250
|
-
{ id: "checking_browser_gate", regex: /checking your browser before you access/i, confidence: 0.97 }
|
|
251
|
-
];
|
|
252
|
-
var RECAPTCHA_HOST_PATTERNS = [/recaptcha/i, /hcaptcha/i, /challenges\.cloudflare\.com/i];
|
|
253
|
-
var STATIC_BLOCK_HOST_PATTERNS = [/redditstatic\.com$/i, /abs\.twimg\.com$/i, /twimg\.com$/i];
|
|
254
|
-
var ENV_LIMITED_PATTERNS = [
|
|
255
|
-
/extension not connected/i,
|
|
256
|
-
/connect the extension/i,
|
|
257
|
-
/manual interaction/i,
|
|
258
|
-
/timed out/i,
|
|
259
|
-
/not available in this environment/i
|
|
260
|
-
];
|
|
261
|
-
var RESTRICTED_TARGET_PATTERNS = [/^chrome:\/\//i, /^chrome-extension:\/\//i, /^about:blank$/i, /^devtools:\/\//i];
|
|
262
|
-
var DEFAULT_BLOCKER_ARTIFACT_CAPS = {
|
|
263
|
-
maxNetworkEvents: 20,
|
|
264
|
-
maxConsoleEvents: 20,
|
|
265
|
-
maxExceptionEvents: 10,
|
|
266
|
-
maxHosts: 10,
|
|
267
|
-
maxTextLength: 512
|
|
268
|
-
};
|
|
269
|
-
var toLower = (value) => value.trim().toLowerCase();
|
|
270
|
-
var clampNumber = (value, min, max) => {
|
|
271
|
-
if (!Number.isFinite(value)) return min;
|
|
272
|
-
if (value < min) return min;
|
|
273
|
-
if (value > max) return max;
|
|
274
|
-
return value;
|
|
275
|
-
};
|
|
276
|
-
var clampBlockerConfidence = (value) => {
|
|
277
|
-
return clampNumber(value, 0, 1);
|
|
278
|
-
};
|
|
279
|
-
var clampThreshold = (value) => {
|
|
280
|
-
if (typeof value !== "number") return 0.7;
|
|
281
|
-
return clampNumber(value, 0, 1);
|
|
282
|
-
};
|
|
283
|
-
var clampText = (value, maxLength) => {
|
|
284
|
-
if (typeof value !== "string") return void 0;
|
|
285
|
-
if (maxLength <= 0) return "";
|
|
286
|
-
return value.length <= maxLength ? value : `${value.slice(0, Math.max(0, maxLength - 3))}...`;
|
|
287
|
-
};
|
|
288
|
-
var boundedUniqueList = (values, maxLength) => {
|
|
289
|
-
if (!values || values.length === 0 || maxLength <= 0) return [];
|
|
290
|
-
const seen = /* @__PURE__ */ new Set();
|
|
291
|
-
const list = [];
|
|
292
|
-
for (const value of values) {
|
|
293
|
-
if (typeof value !== "string") continue;
|
|
294
|
-
const normalized = value.trim();
|
|
295
|
-
if (!normalized) continue;
|
|
296
|
-
const key = normalized.toLowerCase();
|
|
297
|
-
if (seen.has(key)) continue;
|
|
298
|
-
seen.add(key);
|
|
299
|
-
list.push(normalized);
|
|
300
|
-
if (list.length >= maxLength) break;
|
|
301
|
-
}
|
|
302
|
-
return list;
|
|
303
|
-
};
|
|
304
|
-
var extractHost = (value) => {
|
|
305
|
-
if (!value) return null;
|
|
306
|
-
try {
|
|
307
|
-
return toLower(new URL(value).hostname);
|
|
308
|
-
} catch {
|
|
309
|
-
return null;
|
|
310
|
-
}
|
|
311
|
-
};
|
|
312
|
-
var scorePatternMatches = (text, patterns) => {
|
|
313
|
-
const matched = [];
|
|
314
|
-
let confidence = 0;
|
|
315
|
-
for (const pattern of patterns) {
|
|
316
|
-
if (!pattern.regex.test(text)) continue;
|
|
317
|
-
matched.push(pattern.id);
|
|
318
|
-
confidence = Math.max(confidence, pattern.confidence);
|
|
319
|
-
}
|
|
320
|
-
return { matched, confidence };
|
|
321
|
-
};
|
|
322
|
-
var hasAnyPattern = (value, patterns) => {
|
|
323
|
-
return patterns.some((pattern) => pattern.test(value));
|
|
324
|
-
};
|
|
325
|
-
var isLoopbackHost = (value) => {
|
|
326
|
-
const normalized = toLower(value).replace(/^\[|\]$/g, "");
|
|
327
|
-
if (!normalized) return false;
|
|
328
|
-
if (normalized === "localhost" || normalized === "::1") return true;
|
|
329
|
-
if (normalized === "127.0.0.1" || normalized.startsWith("127.")) return true;
|
|
330
|
-
return /^::ffff:127\.\d+\.\d+\.\d+$/.test(normalized);
|
|
331
|
-
};
|
|
332
|
-
var buildHints = (type) => {
|
|
333
|
-
switch (type) {
|
|
334
|
-
case "auth_required":
|
|
335
|
-
return [
|
|
336
|
-
{ id: "manual_login", reason: "Authentication flow requires interactive login.", priority: 1 },
|
|
337
|
-
{ id: "switch_managed_headed", reason: "Headed mode can complete login and persist session state.", priority: 2 },
|
|
338
|
-
{ id: "switch_extension_mode", reason: "Extension mode can reuse an already logged-in browser profile.", priority: 3 }
|
|
339
|
-
];
|
|
340
|
-
case "anti_bot_challenge":
|
|
341
|
-
return [
|
|
342
|
-
{ id: "manual_challenge", reason: "Challenge page requires manual completion.", priority: 1 },
|
|
343
|
-
{ id: "switch_managed_headed", reason: "Headed mode improves challenge completion reliability.", priority: 2 },
|
|
344
|
-
{ id: "collect_debug_trace", reason: "Collect trace artifacts to compare challenge indicators before and after manual action.", priority: 3 }
|
|
345
|
-
];
|
|
346
|
-
case "rate_limited":
|
|
347
|
-
return [
|
|
348
|
-
{ id: "retry_after_backoff", reason: "Rate-limited responses should be retried after a bounded delay.", priority: 1 },
|
|
349
|
-
{ id: "collect_debug_trace", reason: "Trace data can confirm cooldown and request pacing behavior.", priority: 2 }
|
|
350
|
-
];
|
|
351
|
-
case "upstream_block":
|
|
352
|
-
return [
|
|
353
|
-
{ id: "retry_after_backoff", reason: "Upstream blocks may clear after network or host recovery.", priority: 1 },
|
|
354
|
-
{ id: "switch_managed_headed", reason: "Browser-assisted retrieval may bypass runtime fetch limitations.", priority: 2 },
|
|
355
|
-
{ id: "collect_debug_trace", reason: "Trace host evidence helps confirm blocked upstream dependencies.", priority: 3 }
|
|
356
|
-
];
|
|
357
|
-
case "restricted_target":
|
|
358
|
-
return [
|
|
359
|
-
{ id: "switch_managed_headed", reason: "Restricted internal targets require navigation to a normal http(s) tab.", priority: 1 },
|
|
360
|
-
{ id: "collect_debug_trace", reason: "Trace confirms blocked scheme or tab restriction source.", priority: 2 }
|
|
361
|
-
];
|
|
362
|
-
case "env_limited":
|
|
363
|
-
return [
|
|
364
|
-
{ id: "switch_extension_mode", reason: "Extension relay availability is required for this operation.", priority: 1 },
|
|
365
|
-
{ id: "switch_managed_headed", reason: "Managed headed mode is a deterministic fallback when extension is unavailable.", priority: 2 },
|
|
366
|
-
{ id: "collect_debug_trace", reason: "Diagnostics can confirm environment capability gaps.", priority: 3 }
|
|
367
|
-
];
|
|
368
|
-
case "unknown":
|
|
369
|
-
return [{ id: "collect_debug_trace", reason: "Additional trace evidence is required for reliable classification.", priority: 1 }];
|
|
370
|
-
}
|
|
371
|
-
};
|
|
372
|
-
var classifyFromInputs = (input, normalizedHosts, matchedPatterns) => {
|
|
373
|
-
const status = input.status;
|
|
374
|
-
const code = toLower(input.providerErrorCode ?? "");
|
|
375
|
-
const url = input.url ?? "";
|
|
376
|
-
const finalUrl = input.finalUrl ?? "";
|
|
377
|
-
const title = input.title ?? "";
|
|
378
|
-
const message = input.message ?? "";
|
|
379
|
-
const challengeText = `${title} ${message}`;
|
|
380
|
-
const urlSignals = `${url} ${finalUrl}`;
|
|
381
|
-
const isUpstreamCode = code === "upstream" || code === "network" || code === "unavailable";
|
|
382
|
-
const hasStaticBlockHost = normalizedHosts.some((host) => hasAnyPattern(host, STATIC_BLOCK_HOST_PATTERNS));
|
|
383
|
-
const isLoopbackContext = [
|
|
384
|
-
extractHost(url),
|
|
385
|
-
extractHost(finalUrl),
|
|
386
|
-
...normalizedHosts
|
|
387
|
-
].some((host) => typeof host === "string" && isLoopbackHost(host));
|
|
388
|
-
const authMatches = [];
|
|
389
|
-
let authConfidence = 0;
|
|
390
|
-
if (status === 401 || status === 403) {
|
|
391
|
-
authMatches.push(`status:${status}`);
|
|
392
|
-
authConfidence = Math.max(authConfidence, status === 401 ? 0.94 : 0.9);
|
|
393
|
-
}
|
|
394
|
-
if (code === "auth") {
|
|
395
|
-
authMatches.push("provider_code:auth");
|
|
396
|
-
authConfidence = Math.max(authConfidence, 0.9);
|
|
397
|
-
}
|
|
398
|
-
const authPathMatches = scorePatternMatches(`${url} ${finalUrl}`, AUTH_URL_PATTERNS);
|
|
399
|
-
authMatches.push(...authPathMatches.matched);
|
|
400
|
-
authConfidence = Math.max(authConfidence, authPathMatches.confidence);
|
|
401
|
-
const authTitleMatches = scorePatternMatches(title, AUTH_TITLE_PATTERNS);
|
|
402
|
-
authMatches.push(...authTitleMatches.matched);
|
|
403
|
-
authConfidence = Math.max(authConfidence, authTitleMatches.confidence);
|
|
404
|
-
if (authConfidence > 0) {
|
|
405
|
-
return {
|
|
406
|
-
type: "auth_required",
|
|
407
|
-
reasonCode: "token_required",
|
|
408
|
-
confidence: authConfidence,
|
|
409
|
-
retryable: false,
|
|
410
|
-
matches: boundedUniqueList([...matchedPatterns, ...authMatches], 16)
|
|
411
|
-
};
|
|
412
|
-
}
|
|
413
|
-
if (!isLoopbackContext) {
|
|
414
|
-
const challengeMatches = [];
|
|
415
|
-
let challengeConfidence = 0;
|
|
416
|
-
const challengePatternMatches = scorePatternMatches(challengeText, CHALLENGE_PATTERNS);
|
|
417
|
-
challengeMatches.push(...challengePatternMatches.matched);
|
|
418
|
-
challengeConfidence = Math.max(challengeConfidence, challengePatternMatches.confidence);
|
|
419
|
-
if (/(captcha|cf_chl|hcaptcha|recaptcha|interstitial)/i.test(urlSignals)) {
|
|
420
|
-
challengeMatches.push("url:challenge_token");
|
|
421
|
-
challengeConfidence = Math.max(challengeConfidence, 0.9);
|
|
422
|
-
}
|
|
423
|
-
if (hasAnyPattern(title, CHALLENGE_PATTERNS.map((entry) => entry.regex)) && status === 200) {
|
|
424
|
-
challengeMatches.push("status:200_challenge_title");
|
|
425
|
-
challengeConfidence = Math.max(challengeConfidence, 0.92);
|
|
426
|
-
}
|
|
427
|
-
if (normalizedHosts.some((host) => hasAnyPattern(host, RECAPTCHA_HOST_PATTERNS))) {
|
|
428
|
-
challengeMatches.push("network:challenge_host");
|
|
429
|
-
challengeConfidence = Math.max(challengeConfidence, 0.96);
|
|
430
|
-
}
|
|
431
|
-
if (challengeConfidence > 0) {
|
|
432
|
-
return {
|
|
433
|
-
type: "anti_bot_challenge",
|
|
434
|
-
reasonCode: "challenge_detected",
|
|
435
|
-
confidence: challengeConfidence,
|
|
436
|
-
retryable: false,
|
|
437
|
-
matches: boundedUniqueList([...matchedPatterns, ...challengeMatches], 16)
|
|
438
|
-
};
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
if (status === 429 || code === "rate_limited") {
|
|
442
|
-
return {
|
|
443
|
-
type: "rate_limited",
|
|
444
|
-
reasonCode: "rate_limited",
|
|
445
|
-
confidence: 0.95,
|
|
446
|
-
retryable: true,
|
|
447
|
-
matches: boundedUniqueList([...matchedPatterns, status === 429 ? "status:429" : "provider_code:rate_limited"], 16)
|
|
448
|
-
};
|
|
449
|
-
}
|
|
450
|
-
if (isUpstreamCode && (hasStaticBlockHost || /retrieval failed/i.test(message) || typeof status === "number" && status >= 500)) {
|
|
451
|
-
return {
|
|
452
|
-
type: "upstream_block",
|
|
453
|
-
reasonCode: "ip_blocked",
|
|
454
|
-
confidence: hasStaticBlockHost ? 0.9 : 0.8,
|
|
455
|
-
retryable: input.retryable ?? true,
|
|
456
|
-
matches: boundedUniqueList(
|
|
457
|
-
[
|
|
458
|
-
...matchedPatterns,
|
|
459
|
-
`provider_code:${code}`,
|
|
460
|
-
...hasStaticBlockHost ? ["network:blocked_static_host"] : []
|
|
461
|
-
],
|
|
462
|
-
16
|
|
463
|
-
)
|
|
464
|
-
};
|
|
465
|
-
}
|
|
466
|
-
if (input.restrictedTarget || RESTRICTED_TARGET_PATTERNS.some((pattern) => pattern.test(url)) || RESTRICTED_TARGET_PATTERNS.some((pattern) => pattern.test(finalUrl))) {
|
|
467
|
-
return {
|
|
468
|
-
type: "restricted_target",
|
|
469
|
-
confidence: 0.92,
|
|
470
|
-
retryable: false,
|
|
471
|
-
matches: boundedUniqueList([...matchedPatterns, "restricted_target"], 16)
|
|
472
|
-
};
|
|
473
|
-
}
|
|
474
|
-
if (input.envLimited || code === "unavailable" && ENV_LIMITED_PATTERNS.some((pattern) => pattern.test(message))) {
|
|
475
|
-
return {
|
|
476
|
-
type: "env_limited",
|
|
477
|
-
reasonCode: "env_limited",
|
|
478
|
-
confidence: input.envLimited ? 0.9 : 0.78,
|
|
479
|
-
retryable: true,
|
|
480
|
-
matches: boundedUniqueList([...matchedPatterns, "env_limited"], 16)
|
|
481
|
-
};
|
|
482
|
-
}
|
|
483
|
-
if (status || code || title || message || normalizedHosts.length > 0) {
|
|
484
|
-
return {
|
|
485
|
-
type: "unknown",
|
|
486
|
-
confidence: 0.5,
|
|
487
|
-
retryable: input.retryable ?? false,
|
|
488
|
-
matches: boundedUniqueList(matchedPatterns, 16)
|
|
489
|
-
};
|
|
490
|
-
}
|
|
491
|
-
return null;
|
|
492
|
-
};
|
|
493
|
-
var coerceJsonValue = (value, maxTextLength, promptGuardEnabled, diagnostics, seen) => {
|
|
494
|
-
if (value === null || typeof value === "number" || typeof value === "boolean") {
|
|
495
|
-
return value;
|
|
496
|
-
}
|
|
497
|
-
if (typeof value === "string") {
|
|
498
|
-
const sanitized = sanitizePromptGuardText(value, promptGuardEnabled);
|
|
499
|
-
diagnostics.entries += sanitized.diagnostics.entries;
|
|
500
|
-
diagnostics.quarantinedSegments += sanitized.diagnostics.quarantinedSegments;
|
|
501
|
-
const redacted = redactSensitive(sanitized.text);
|
|
502
|
-
const asString = typeof redacted === "string" ? redacted : String(redacted);
|
|
503
|
-
return clampText(asString, maxTextLength) ?? "";
|
|
504
|
-
}
|
|
505
|
-
if (Array.isArray(value)) {
|
|
506
|
-
return value.slice(0, 20).map((entry) => coerceJsonValue(entry, maxTextLength, promptGuardEnabled, diagnostics, seen));
|
|
507
|
-
}
|
|
508
|
-
if (typeof value !== "object") {
|
|
509
|
-
return String(value);
|
|
510
|
-
}
|
|
511
|
-
if (seen.has(value)) {
|
|
512
|
-
return "[Circular]";
|
|
513
|
-
}
|
|
514
|
-
seen.add(value);
|
|
515
|
-
const objectValue = value;
|
|
516
|
-
const entries = Object.entries(objectValue).slice(0, 30);
|
|
517
|
-
const output = {};
|
|
518
|
-
for (const [key, entryValue] of entries) {
|
|
519
|
-
output[key] = coerceJsonValue(entryValue, maxTextLength, promptGuardEnabled, diagnostics, seen);
|
|
520
|
-
}
|
|
521
|
-
return output;
|
|
522
|
-
};
|
|
523
|
-
var coerceEventList = (values, maxItems, maxTextLength, promptGuardEnabled, diagnostics) => {
|
|
524
|
-
if (!Array.isArray(values) || maxItems <= 0) return [];
|
|
525
|
-
return values.slice(-maxItems).map((entry) => {
|
|
526
|
-
const sanitized = coerceJsonValue(
|
|
527
|
-
redactSensitive(entry),
|
|
528
|
-
maxTextLength,
|
|
529
|
-
promptGuardEnabled,
|
|
530
|
-
diagnostics,
|
|
531
|
-
/* @__PURE__ */ new WeakSet()
|
|
532
|
-
);
|
|
533
|
-
if (!sanitized || typeof sanitized !== "object" || Array.isArray(sanitized)) {
|
|
534
|
-
return { value: sanitized };
|
|
535
|
-
}
|
|
536
|
-
return sanitized;
|
|
537
|
-
});
|
|
538
|
-
};
|
|
539
|
-
var resolveBlockerArtifactCaps = (partial) => {
|
|
540
|
-
return {
|
|
541
|
-
maxNetworkEvents: clampNumber(partial?.maxNetworkEvents ?? DEFAULT_BLOCKER_ARTIFACT_CAPS.maxNetworkEvents, 1, 500),
|
|
542
|
-
maxConsoleEvents: clampNumber(partial?.maxConsoleEvents ?? DEFAULT_BLOCKER_ARTIFACT_CAPS.maxConsoleEvents, 1, 500),
|
|
543
|
-
maxExceptionEvents: clampNumber(partial?.maxExceptionEvents ?? DEFAULT_BLOCKER_ARTIFACT_CAPS.maxExceptionEvents, 1, 200),
|
|
544
|
-
maxHosts: clampNumber(partial?.maxHosts ?? DEFAULT_BLOCKER_ARTIFACT_CAPS.maxHosts, 1, 200),
|
|
545
|
-
maxTextLength: clampNumber(partial?.maxTextLength ?? DEFAULT_BLOCKER_ARTIFACT_CAPS.maxTextLength, 32, 4096)
|
|
546
|
-
};
|
|
547
|
-
};
|
|
548
|
-
var classifyBlockerSignal = (input) => {
|
|
549
|
-
const promptGuardEnabled = input.promptGuardEnabled ?? true;
|
|
550
|
-
const titleSanitized = sanitizePromptGuardText(input.title ?? "", promptGuardEnabled);
|
|
551
|
-
const messageSanitized = sanitizePromptGuardText(input.message ?? "", promptGuardEnabled);
|
|
552
|
-
const matchedPatterns = boundedUniqueList(input.matchedPatterns, 16);
|
|
553
|
-
const normalizedHosts = boundedUniqueList(input.networkHosts?.map(toLower), 20);
|
|
554
|
-
const classification = classifyFromInputs({
|
|
555
|
-
...input,
|
|
556
|
-
title: titleSanitized.text,
|
|
557
|
-
message: messageSanitized.text
|
|
558
|
-
}, normalizedHosts, matchedPatterns);
|
|
559
|
-
if (!classification) {
|
|
560
|
-
return null;
|
|
561
|
-
}
|
|
562
|
-
const threshold = clampThreshold(input.threshold);
|
|
563
|
-
const confidence = clampBlockerConfidence(classification.confidence);
|
|
564
|
-
if (confidence < threshold) {
|
|
565
|
-
return null;
|
|
566
|
-
}
|
|
567
|
-
const evidence = {
|
|
568
|
-
...input.url ? { url: clampText(input.url, 512) } : {},
|
|
569
|
-
...input.finalUrl ? { finalUrl: clampText(input.finalUrl, 512) } : {},
|
|
570
|
-
...titleSanitized.text ? { title: clampText(titleSanitized.text, 512) } : {},
|
|
571
|
-
...typeof input.status === "number" ? { status: input.status } : {},
|
|
572
|
-
...input.providerErrorCode ? { providerErrorCode: input.providerErrorCode } : {},
|
|
573
|
-
matchedPatterns: boundedUniqueList(classification.matches, 16),
|
|
574
|
-
networkHosts: boundedUniqueList(normalizedHosts, 10),
|
|
575
|
-
...input.traceRequestId ? { traceRequestId: input.traceRequestId } : {}
|
|
576
|
-
};
|
|
577
|
-
const sanitationEntries = titleSanitized.diagnostics.entries + messageSanitized.diagnostics.entries;
|
|
578
|
-
const sanitationQuarantined = titleSanitized.diagnostics.quarantinedSegments + messageSanitized.diagnostics.quarantinedSegments;
|
|
579
|
-
return {
|
|
580
|
-
schemaVersion: "1.0",
|
|
581
|
-
type: classification.type,
|
|
582
|
-
source: input.source,
|
|
583
|
-
...classification.reasonCode ? { reasonCode: classification.reasonCode } : {},
|
|
584
|
-
confidence,
|
|
585
|
-
retryable: classification.retryable,
|
|
586
|
-
detectedAt: input.detectedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
587
|
-
evidence,
|
|
588
|
-
actionHints: buildHints(classification.type),
|
|
589
|
-
...sanitationEntries > 0 || sanitationQuarantined > 0 ? {
|
|
590
|
-
sanitation: {
|
|
591
|
-
entries: sanitationEntries,
|
|
592
|
-
quarantinedSegments: sanitationQuarantined
|
|
593
|
-
}
|
|
594
|
-
} : {}
|
|
595
|
-
};
|
|
596
|
-
};
|
|
597
|
-
var buildBlockerArtifacts = (input) => {
|
|
598
|
-
const caps = resolveBlockerArtifactCaps(input.caps);
|
|
599
|
-
const promptGuardEnabled = input.promptGuardEnabled ?? true;
|
|
600
|
-
const diagnostics = {
|
|
601
|
-
entries: 0,
|
|
602
|
-
quarantinedSegments: 0
|
|
603
|
-
};
|
|
604
|
-
const network = coerceEventList(
|
|
605
|
-
input.networkEvents,
|
|
606
|
-
caps.maxNetworkEvents,
|
|
607
|
-
caps.maxTextLength,
|
|
608
|
-
promptGuardEnabled,
|
|
609
|
-
diagnostics
|
|
610
|
-
);
|
|
611
|
-
const console2 = coerceEventList(
|
|
612
|
-
input.consoleEvents,
|
|
613
|
-
caps.maxConsoleEvents,
|
|
614
|
-
caps.maxTextLength,
|
|
615
|
-
promptGuardEnabled,
|
|
616
|
-
diagnostics
|
|
617
|
-
);
|
|
618
|
-
const exception = coerceEventList(
|
|
619
|
-
input.exceptionEvents,
|
|
620
|
-
caps.maxExceptionEvents,
|
|
621
|
-
caps.maxTextLength,
|
|
622
|
-
promptGuardEnabled,
|
|
623
|
-
diagnostics
|
|
624
|
-
);
|
|
625
|
-
const hosts = boundedUniqueList(
|
|
626
|
-
network.map((event) => typeof event.url === "string" ? extractHost(event.url) : null).filter((host) => typeof host === "string"),
|
|
627
|
-
caps.maxHosts
|
|
628
|
-
);
|
|
629
|
-
return {
|
|
630
|
-
schemaVersion: "1.0",
|
|
631
|
-
network,
|
|
632
|
-
console: console2,
|
|
633
|
-
exception,
|
|
634
|
-
hosts,
|
|
635
|
-
sanitation: diagnostics
|
|
636
|
-
};
|
|
637
|
-
};
|
|
638
|
-
var __test__ = {
|
|
639
|
-
classifyFromInputs,
|
|
640
|
-
extractHost,
|
|
641
|
-
hasAnyPattern,
|
|
642
|
-
clampThreshold,
|
|
643
|
-
isLoopbackHost
|
|
644
|
-
};
|
|
645
|
-
|
|
646
|
-
// src/providers/constraint.ts
|
|
647
|
-
var BLOCKER_TYPES = /* @__PURE__ */ new Set([
|
|
648
|
-
"auth_required",
|
|
649
|
-
"anti_bot_challenge",
|
|
650
|
-
"rate_limited",
|
|
651
|
-
"upstream_block",
|
|
652
|
-
"restricted_target",
|
|
653
|
-
"env_limited",
|
|
654
|
-
"unknown"
|
|
655
|
-
]);
|
|
656
|
-
var CONSTRAINT_KINDS = /* @__PURE__ */ new Set([
|
|
657
|
-
"session_required",
|
|
658
|
-
"render_required"
|
|
659
|
-
]);
|
|
660
|
-
var RENDER_REQUIRED_SHELLS = /* @__PURE__ */ new Set([
|
|
661
|
-
"bestbuy_international_gate",
|
|
662
|
-
"duckduckgo_non_js_redirect",
|
|
663
|
-
"macys_access_denied_shell",
|
|
664
|
-
"social_first_party_help_shell",
|
|
665
|
-
"social_js_required_shell",
|
|
666
|
-
"social_render_shell",
|
|
667
|
-
"target_shell_page",
|
|
668
|
-
"temu_empty_shell"
|
|
669
|
-
]);
|
|
670
|
-
var CHALLENGE_SHELLS = /* @__PURE__ */ new Set(["social_verification_wall", "temu_challenge_shell"]);
|
|
671
|
-
var toNonEmptyString = (value) => {
|
|
672
|
-
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
673
|
-
};
|
|
674
|
-
var normalizeBlockerType = (value) => {
|
|
675
|
-
return typeof value === "string" && BLOCKER_TYPES.has(value) ? value : void 0;
|
|
676
|
-
};
|
|
677
|
-
var buildConstraint = (kind, evidenceCode, providerShell, message) => ({
|
|
678
|
-
kind,
|
|
679
|
-
evidenceCode,
|
|
680
|
-
...providerShell ? { providerShell } : {},
|
|
681
|
-
...message ? { message } : {}
|
|
682
|
-
});
|
|
683
|
-
var isProviderConstraint = (value) => {
|
|
684
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
685
|
-
return false;
|
|
686
|
-
}
|
|
687
|
-
const candidate = value;
|
|
688
|
-
return CONSTRAINT_KINDS.has(candidate.kind) && typeof candidate.evidenceCode === "string" && candidate.evidenceCode.trim().length > 0 && (candidate.providerShell === void 0 || typeof candidate.providerShell === "string") && (candidate.message === void 0 || typeof candidate.message === "string");
|
|
689
|
-
};
|
|
690
|
-
var classifyProviderIssue = (input) => {
|
|
691
|
-
const providerShell = toNonEmptyString(input.providerShell);
|
|
692
|
-
const message = toNonEmptyString(input.message);
|
|
693
|
-
if (providerShell && CHALLENGE_SHELLS.has(providerShell)) {
|
|
694
|
-
return {
|
|
695
|
-
reasonCode: "challenge_detected",
|
|
696
|
-
blockerType: "anti_bot_challenge"
|
|
697
|
-
};
|
|
698
|
-
}
|
|
699
|
-
if (providerShell && RENDER_REQUIRED_SHELLS.has(providerShell)) {
|
|
700
|
-
return {
|
|
701
|
-
reasonCode: "env_limited",
|
|
702
|
-
blockerType: "env_limited",
|
|
703
|
-
constraint: buildConstraint("render_required", providerShell, providerShell, message)
|
|
704
|
-
};
|
|
705
|
-
}
|
|
706
|
-
const blocker = classifyBlockerSignal({
|
|
707
|
-
source: input.source ?? "runtime_fetch",
|
|
708
|
-
...input.url ? { url: input.url, finalUrl: input.url } : {},
|
|
709
|
-
...input.title ? { title: input.title } : {},
|
|
710
|
-
...message ? { message } : {},
|
|
711
|
-
...typeof input.status === "number" ? { status: input.status } : {},
|
|
712
|
-
...input.providerErrorCode ? { providerErrorCode: input.providerErrorCode } : {},
|
|
713
|
-
...typeof input.retryable === "boolean" ? { retryable: input.retryable } : {},
|
|
714
|
-
envLimited: input.browserRequired === true
|
|
715
|
-
});
|
|
716
|
-
if (blocker?.type === "auth_required") {
|
|
717
|
-
return {
|
|
718
|
-
/* c8 ignore next -- classifyBlockerSignal always supplies token_required for auth_required blockers */
|
|
719
|
-
reasonCode: blocker.reasonCode ?? "token_required",
|
|
720
|
-
blockerType: blocker.type,
|
|
721
|
-
constraint: buildConstraint("session_required", providerShell ?? "auth_required", providerShell, message)
|
|
722
|
-
};
|
|
723
|
-
}
|
|
724
|
-
if (blocker?.type === "anti_bot_challenge") {
|
|
725
|
-
return {
|
|
726
|
-
/* c8 ignore next -- classifyBlockerSignal always supplies challenge_detected for anti-bot blockers */
|
|
727
|
-
reasonCode: blocker.reasonCode ?? "challenge_detected",
|
|
728
|
-
blockerType: blocker.type
|
|
729
|
-
};
|
|
730
|
-
}
|
|
731
|
-
if (input.browserRequired === true) {
|
|
732
|
-
return {
|
|
733
|
-
/* c8 ignore next -- browserRequired inputs always classify to a blocker payload in the shared classifier */
|
|
734
|
-
reasonCode: blocker?.reasonCode ?? "env_limited",
|
|
735
|
-
/* c8 ignore next -- browserRequired fallbacks only normalize unknown blocker types */
|
|
736
|
-
blockerType: blocker?.type === "unknown" ? "env_limited" : blocker?.type,
|
|
737
|
-
/* c8 ignore next -- providerShell or blocker type always survives before the defensive browser_required fallback */
|
|
738
|
-
constraint: buildConstraint("render_required", providerShell ?? blocker?.type ?? "browser_required", providerShell, message)
|
|
739
|
-
};
|
|
740
|
-
}
|
|
741
|
-
if (blocker?.type === "env_limited") {
|
|
742
|
-
return {
|
|
743
|
-
/* c8 ignore next -- classifyBlockerSignal always supplies env_limited for env_limited blockers */
|
|
744
|
-
reasonCode: blocker.reasonCode ?? "env_limited",
|
|
745
|
-
blockerType: blocker.type
|
|
746
|
-
};
|
|
747
|
-
}
|
|
748
|
-
return null;
|
|
749
|
-
};
|
|
750
|
-
var readProviderIssueHint = (args) => {
|
|
751
|
-
const details = args.details;
|
|
752
|
-
const reasonCode = isProviderReasonCode(args.reasonCode) ? args.reasonCode : isProviderReasonCode(details?.reasonCode) ? details.reasonCode : void 0;
|
|
753
|
-
const blockerType = normalizeBlockerType(args.blockerType ?? details?.blockerType);
|
|
754
|
-
const constraint = isProviderConstraint(details?.constraint) ? details.constraint : void 0;
|
|
755
|
-
if (reasonCode || blockerType || constraint) {
|
|
756
|
-
return {
|
|
757
|
-
reasonCode: reasonCode ?? (constraint?.kind === "session_required" ? "token_required" : "env_limited"),
|
|
758
|
-
...blockerType ? { blockerType } : {},
|
|
759
|
-
...constraint ? { constraint } : {}
|
|
760
|
-
};
|
|
761
|
-
}
|
|
762
|
-
return classifyProviderIssue({
|
|
763
|
-
url: toNonEmptyString(details?.url),
|
|
764
|
-
title: toNonEmptyString(details?.title),
|
|
765
|
-
message: toNonEmptyString(details?.message ?? args.message),
|
|
766
|
-
providerShell: toNonEmptyString(details?.providerShell),
|
|
767
|
-
browserRequired: details?.browserRequired === true,
|
|
768
|
-
providerErrorCode: toNonEmptyString(args.code),
|
|
769
|
-
source: "runtime_fetch"
|
|
770
|
-
});
|
|
771
|
-
};
|
|
772
|
-
var readProviderIssueHintFromRecord = (record) => {
|
|
773
|
-
const details = record.attributes;
|
|
774
|
-
return readProviderIssueHint({
|
|
775
|
-
reasonCode: details.reasonCode,
|
|
776
|
-
blockerType: details.blockerType,
|
|
777
|
-
message: record.content,
|
|
778
|
-
details: {
|
|
779
|
-
url: record.url,
|
|
780
|
-
title: record.title,
|
|
781
|
-
message: record.content,
|
|
782
|
-
providerShell: details.providerShell,
|
|
783
|
-
browserRequired: details.browserRequired,
|
|
784
|
-
constraint: details.constraint
|
|
785
|
-
}
|
|
786
|
-
});
|
|
787
|
-
};
|
|
788
|
-
var applyProviderIssueHint = (details, hint) => {
|
|
789
|
-
if (!hint) return details;
|
|
790
|
-
const next = {
|
|
791
|
-
...details ?? {},
|
|
792
|
-
reasonCode: hint.reasonCode
|
|
793
|
-
};
|
|
794
|
-
if (hint.blockerType && typeof next.blockerType !== "string") {
|
|
795
|
-
next.blockerType = hint.blockerType;
|
|
796
|
-
}
|
|
797
|
-
if (hint.constraint && !isProviderConstraint(next.constraint)) {
|
|
798
|
-
next.constraint = hint.constraint;
|
|
799
|
-
}
|
|
800
|
-
if (typeof next.guidance === "undefined") {
|
|
801
|
-
const guidance = buildProviderIssueGuidance({ hint, details: next });
|
|
802
|
-
if (guidance) {
|
|
803
|
-
next.guidance = guidance;
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
|
-
return next;
|
|
807
|
-
};
|
|
808
|
-
var providerLabel = (provider) => {
|
|
809
|
-
const normalized = toNonEmptyString(provider);
|
|
810
|
-
if (!normalized) return "Provider";
|
|
811
|
-
const separator = normalized.lastIndexOf("/");
|
|
812
|
-
const tail = separator >= 0 ? normalized.slice(separator + 1) : normalized;
|
|
813
|
-
return tail.charAt(0).toUpperCase() + tail.slice(1);
|
|
814
|
-
};
|
|
815
|
-
var hasPreservedBrowserState = (details) => {
|
|
816
|
-
return typeof details?.preservedSessionId === "string" || typeof details?.preservedTargetId === "string";
|
|
817
|
-
};
|
|
818
|
-
var buildGuidance = (reason, recommendedNextCommands) => ({
|
|
819
|
-
reason,
|
|
820
|
-
recommendedNextCommands
|
|
821
|
-
});
|
|
822
|
-
var buildAuthGuidance = (subject, preservedBrowserState) => {
|
|
823
|
-
return preservedBrowserState ? buildGuidance(
|
|
824
|
-
`${subject} preserved browser state that can finish authentication.`,
|
|
825
|
-
[
|
|
826
|
-
"Complete the login or account checkpoint in the preserved browser session.",
|
|
827
|
-
"Rerun the same provider or workflow after the session is fully authenticated."
|
|
828
|
-
]
|
|
829
|
-
) : buildGuidance(
|
|
830
|
-
`${subject} needs an authenticated session before retrying.`,
|
|
831
|
-
[
|
|
832
|
-
"Reuse an authenticated browser session, import logged-in cookies, or use the provider sign-in flow.",
|
|
833
|
-
"Rerun the same provider or workflow once the session is active."
|
|
834
|
-
]
|
|
835
|
-
);
|
|
836
|
-
};
|
|
837
|
-
var buildChallengeGuidance = (subject, preservedBrowserState) => {
|
|
838
|
-
return preservedBrowserState ? buildGuidance(
|
|
839
|
-
`${subject} preserved browser state that can complete the current challenge.`,
|
|
840
|
-
[
|
|
841
|
-
"Finish the login or anti-bot challenge in the preserved browser session.",
|
|
842
|
-
"Rerun the same provider or workflow after the page unlocks."
|
|
843
|
-
]
|
|
844
|
-
) : buildGuidance(
|
|
845
|
-
`${subject} hit a challenge that still needs browser-assisted follow-up.`,
|
|
846
|
-
[
|
|
847
|
-
"Retry with browser assistance so the challenge can be completed interactively.",
|
|
848
|
-
"Only ask for manual credentials if browser-assisted recovery still cannot unlock the page."
|
|
849
|
-
]
|
|
850
|
-
);
|
|
851
|
-
};
|
|
852
|
-
var buildRenderGuidance = (subject, preservedBrowserState) => {
|
|
853
|
-
return preservedBrowserState ? buildGuidance(
|
|
854
|
-
`${subject} still needs a live browser-rendered page, but browser state is already preserved.`,
|
|
855
|
-
[
|
|
856
|
-
"Inspect the preserved browser session until usable content is visible.",
|
|
857
|
-
"Rerun the same provider or workflow after the rendered page is ready."
|
|
858
|
-
]
|
|
859
|
-
) : buildGuidance(
|
|
860
|
-
`${subject} needs a live browser-rendered page before retrying.`,
|
|
861
|
-
[
|
|
862
|
-
"Retry with browser assistance or a headed browser session.",
|
|
863
|
-
"Rerun the same provider or workflow after the rendered page is ready."
|
|
864
|
-
]
|
|
865
|
-
);
|
|
866
|
-
};
|
|
867
|
-
var buildProviderIssueGuidance = (args) => {
|
|
868
|
-
const subject = providerLabel(args.provider);
|
|
869
|
-
const preservedBrowserState = hasPreservedBrowserState(args.details);
|
|
870
|
-
const disposition = toNonEmptyString(args.details?.disposition);
|
|
871
|
-
if (disposition === "completed") return void 0;
|
|
872
|
-
if (disposition === "challenge_preserved") {
|
|
873
|
-
return buildChallengeGuidance(subject, true);
|
|
874
|
-
}
|
|
875
|
-
if (args.hint.reasonCode === "token_required" || args.hint.reasonCode === "auth_required") {
|
|
876
|
-
return buildAuthGuidance(subject, preservedBrowserState);
|
|
877
|
-
}
|
|
878
|
-
if (args.hint.reasonCode === "challenge_detected") {
|
|
879
|
-
return buildChallengeGuidance(subject, preservedBrowserState);
|
|
880
|
-
}
|
|
881
|
-
if (args.hint.constraint?.kind === "render_required" || args.hint.reasonCode === "env_limited") {
|
|
882
|
-
return buildRenderGuidance(subject, preservedBrowserState);
|
|
883
|
-
}
|
|
884
|
-
return void 0;
|
|
885
|
-
};
|
|
886
|
-
var summaryPriority = (hint) => {
|
|
887
|
-
if (hint.reasonCode === "token_required" || hint.reasonCode === "auth_required") return 3;
|
|
888
|
-
if (hint.reasonCode === "challenge_detected") return 2;
|
|
889
|
-
if (hint.constraint?.kind === "render_required") return 1;
|
|
890
|
-
return 0;
|
|
891
|
-
};
|
|
892
|
-
var summarizeProviderIssue = (args) => {
|
|
893
|
-
const subject = providerLabel(args.provider);
|
|
894
|
-
if (args.hint.reasonCode === "token_required" || args.hint.reasonCode === "auth_required") {
|
|
895
|
-
return `${subject} requires login or an existing session.`;
|
|
896
|
-
}
|
|
897
|
-
if (args.hint.reasonCode === "challenge_detected") {
|
|
898
|
-
return `${subject} hit an anti-bot challenge that requires manual completion.`;
|
|
899
|
-
}
|
|
900
|
-
if (args.hint.constraint?.kind === "render_required") {
|
|
901
|
-
return `${subject} requires a live browser-rendered page.`;
|
|
902
|
-
}
|
|
903
|
-
return `${subject} requires manual browser follow-up; this run did not determine whether login or page rendering is required.`;
|
|
904
|
-
};
|
|
905
|
-
var summarizePrimaryProviderIssue = (failures) => {
|
|
906
|
-
if (!Array.isArray(failures) || failures.length === 0) return null;
|
|
907
|
-
let best = null;
|
|
908
|
-
for (const failure of failures) {
|
|
909
|
-
const hint = readProviderIssueHint({
|
|
910
|
-
reasonCode: failure.error?.reasonCode,
|
|
911
|
-
code: failure.error?.code,
|
|
912
|
-
message: failure.error?.message,
|
|
913
|
-
details: failure.error?.details
|
|
914
|
-
});
|
|
915
|
-
if (!hint) continue;
|
|
916
|
-
const summary = summarizeProviderIssue({ provider: failure.provider, hint });
|
|
917
|
-
const guidance = buildProviderIssueGuidance({
|
|
918
|
-
provider: failure.provider,
|
|
919
|
-
hint,
|
|
920
|
-
details: failure.error?.details
|
|
921
|
-
});
|
|
922
|
-
const candidate = {
|
|
923
|
-
provider: failure.provider,
|
|
924
|
-
summary,
|
|
925
|
-
...hint,
|
|
926
|
-
...guidance ? { guidance } : {}
|
|
927
|
-
};
|
|
928
|
-
if (!best || summaryPriority(candidate) > summaryPriority(best)) {
|
|
929
|
-
best = candidate;
|
|
930
|
-
}
|
|
931
|
-
}
|
|
932
|
-
return best;
|
|
933
|
-
};
|
|
934
|
-
|
|
935
36
|
// src/providers/normalize.ts
|
|
936
|
-
import { createHash, randomUUID
|
|
37
|
+
import { createHash, randomUUID } from "crypto";
|
|
937
38
|
var createTraceContext = (seed = {}, provider) => {
|
|
938
39
|
return {
|
|
939
|
-
requestId: seed.requestId ??
|
|
40
|
+
requestId: seed.requestId ?? randomUUID(),
|
|
940
41
|
...seed.sessionId ? { sessionId: seed.sessionId } : {},
|
|
941
42
|
...seed.targetId ? { targetId: seed.targetId } : {},
|
|
942
43
|
...provider ?? seed.provider ? { provider: provider ?? seed.provider } : {},
|
|
@@ -1648,9 +749,9 @@ var HUMAN_VERIFICATION_RE = /\b(captcha|verify (?:that )?you(?:'re| are) human|s
|
|
|
1648
749
|
var NON_SECRET_FIELD_RE = /\b(email|e-mail|username|first name|last name|full name|company|phone|city|state|country|linkedin|portfolio|resume|cv)\b/i;
|
|
1649
750
|
var CHECKPOINT_RE = /\b(next|continue|resume|verify|submit|approve|allow)\b/i;
|
|
1650
751
|
var LOGIN_PAGE_RE = /\/(login|signin|sign-in|auth|session)(?:[/?#]|$)/i;
|
|
1651
|
-
var GOOGLE_AUTH_RE = /\b(?:continue with google|sign in with google|log in with google|google sign(?: |-)?in
|
|
1652
|
-
var GITHUB_AUTH_RE = /\b(?:continue with github|sign in with github|log in with github|github)\b/i;
|
|
1653
|
-
var APPLE_AUTH_RE = /\b(?:continue with apple|sign in with apple|log in with apple|apple)\b/i;
|
|
752
|
+
var GOOGLE_AUTH_RE = /\b(?:continue with google|sign in with google|log in with google|google sign(?: |-)?in)\b/i;
|
|
753
|
+
var GITHUB_AUTH_RE = /\b(?:continue with github|sign in with github|log in with github|github sign(?: |-)?in)\b/i;
|
|
754
|
+
var APPLE_AUTH_RE = /\b(?:continue with apple|sign in with apple|log in with apple|apple sign(?: |-)?in)\b/i;
|
|
1654
755
|
var ACCOUNT_CHOOSER_NOISE_RE = /\b(?:help|privacy|terms|learn more|english|afrikaans|espa[ñn]ol)\b/i;
|
|
1655
756
|
var CLICK_ACTION_RE = /\b(click|tap|select|choose|continue|allow|dismiss|close|not now|got it|delivery|pickup|ship(?:ping)? here)\b/i;
|
|
1656
757
|
var HOLD_ACTION_RE = /\b(?:click|press|tap|activate)\s+(?:and\s+)?hold\b|\bhold (?:the )?(?:button|slider)\b/i;
|
|
@@ -2867,7 +1968,7 @@ var executeStep = async (args) => {
|
|
|
2867
1968
|
});
|
|
2868
1969
|
await args.handle.pointerMove(args.sessionId, point.x, point.y, args.targetId, 12);
|
|
2869
1970
|
await args.handle.pointerDown(args.sessionId, point.x, point.y, args.targetId, "left", 1);
|
|
2870
|
-
await new Promise((
|
|
1971
|
+
await new Promise((resolve) => setTimeout(resolve, Math.max(250, args.step.holdMs ?? DEFAULT_HOLD_MS2)));
|
|
2871
1972
|
await args.handle.pointerUp(args.sessionId, point.x, point.y, args.targetId, "left", 1);
|
|
2872
1973
|
return;
|
|
2873
1974
|
}
|
|
@@ -3948,6 +3049,14 @@ var assertPostPolicy = async (context, hooks = []) => {
|
|
|
3948
3049
|
|
|
3949
3050
|
// src/providers/shared/traversal-url.ts
|
|
3950
3051
|
var STATIC_HOST_PATTERNS = [
|
|
3052
|
+
/(^|\.)analytics\.google\.com$/i,
|
|
3053
|
+
/(^|\.)fonts\.googleapis\.com$/i,
|
|
3054
|
+
/(^|\.)google-analytics\.com$/i,
|
|
3055
|
+
/(^|\.)googleadservices\.com$/i,
|
|
3056
|
+
/(^|\.)googletagmanager\.com$/i,
|
|
3057
|
+
/(^|\.)googlesyndication\.com$/i,
|
|
3058
|
+
/(^|\.)gstatic\.com$/i,
|
|
3059
|
+
/(^|\.)doubleclick\.net$/i,
|
|
3951
3060
|
/(^|\.)redditstatic\.com$/i,
|
|
3952
3061
|
/(^|\.)twimg\.com$/i,
|
|
3953
3062
|
/(^|\.)static\.licdn\.com$/i,
|
|
@@ -3956,6 +3065,49 @@ var STATIC_HOST_PATTERNS = [
|
|
|
3956
3065
|
/(^|\.)cdninstagram\.com$/i
|
|
3957
3066
|
];
|
|
3958
3067
|
var STATIC_PATH_EXT_RE = /\.(?:avif|bmp|css|csv|gif|ico|jpe?g|js|json|map|mjs|mp3|mp4|ogg|pdf|png|svg|txt|wav|webm|webp|woff2?|xml|zip)$/i;
|
|
3068
|
+
var RESEARCH_DEAD_END_LOGIN_SEGMENTS = /* @__PURE__ */ new Set([
|
|
3069
|
+
"account",
|
|
3070
|
+
"accounts",
|
|
3071
|
+
"login",
|
|
3072
|
+
"sign-in",
|
|
3073
|
+
"signin",
|
|
3074
|
+
"submit"
|
|
3075
|
+
]);
|
|
3076
|
+
var RESEARCH_DEAD_END_PRIVACY_ROOT_SEGMENTS = /* @__PURE__ */ new Set([
|
|
3077
|
+
"choice",
|
|
3078
|
+
"choices",
|
|
3079
|
+
"consent",
|
|
3080
|
+
"cookie",
|
|
3081
|
+
"cookie-policy",
|
|
3082
|
+
"cookie-preferences",
|
|
3083
|
+
"cookies",
|
|
3084
|
+
"legal",
|
|
3085
|
+
"policies",
|
|
3086
|
+
"policy",
|
|
3087
|
+
"privacy",
|
|
3088
|
+
"privacy-policy",
|
|
3089
|
+
"prefs",
|
|
3090
|
+
"preferences",
|
|
3091
|
+
"terms",
|
|
3092
|
+
"terms-of-service"
|
|
3093
|
+
]);
|
|
3094
|
+
var RESEARCH_DEAD_END_SEARCH_ROOT_SEGMENTS = /* @__PURE__ */ new Set(["find", "results", "search"]);
|
|
3095
|
+
var RESEARCH_DEAD_END_OTHER_ROOT_SEGMENTS = /* @__PURE__ */ new Set(["settings", "verification"]);
|
|
3096
|
+
var RESEARCH_DEAD_END_PATHS = /* @__PURE__ */ new Set([
|
|
3097
|
+
"/legal/privacy",
|
|
3098
|
+
"/policies",
|
|
3099
|
+
"/privacy",
|
|
3100
|
+
"/privacy-policy",
|
|
3101
|
+
"/privacy/choices",
|
|
3102
|
+
"/privacychoices",
|
|
3103
|
+
"/privacychoices/"
|
|
3104
|
+
]);
|
|
3105
|
+
var isPrivacyDeadEndPath = (segments) => {
|
|
3106
|
+
const [first, second] = segments;
|
|
3107
|
+
if (!first || !RESEARCH_DEAD_END_PRIVACY_ROOT_SEGMENTS.has(first)) return false;
|
|
3108
|
+
if (segments.length === 1) return true;
|
|
3109
|
+
return first === "consent" && second === "manage" || first === "privacy" && second === "choices" || first === "prefs" && second === "privacy" || first === "preferences" && second === "privacy" || first === "legal" && (second === "privacy" || second === "terms") || first === "policies" && second === "privacy-policy";
|
|
3110
|
+
};
|
|
3959
3111
|
var isLikelyDocumentUrl = (value) => {
|
|
3960
3112
|
try {
|
|
3961
3113
|
const parsed = new URL(value);
|
|
@@ -3969,6 +3121,22 @@ var isLikelyDocumentUrl = (value) => {
|
|
|
3969
3121
|
return false;
|
|
3970
3122
|
}
|
|
3971
3123
|
};
|
|
3124
|
+
var isLikelyResearchDestinationUrl = (value) => {
|
|
3125
|
+
return classifyResearchDestinationRejection(value) === null;
|
|
3126
|
+
};
|
|
3127
|
+
var classifyResearchDestinationRejection = (value) => {
|
|
3128
|
+
if (!isLikelyDocumentUrl(value)) return "research_dead_end_shell";
|
|
3129
|
+
const parsed = new URL(value);
|
|
3130
|
+
const pathname = parsed.pathname.toLowerCase().replace(/\/+$/, "") || "/";
|
|
3131
|
+
if (RESEARCH_DEAD_END_PATHS.has(pathname)) return "privacy_preference_shell";
|
|
3132
|
+
const segments = pathname.split("/").filter(Boolean);
|
|
3133
|
+
const firstSegment = segments[0] ?? "";
|
|
3134
|
+
if (segments.some((segment) => RESEARCH_DEAD_END_LOGIN_SEGMENTS.has(segment))) return "login_shell";
|
|
3135
|
+
if (RESEARCH_DEAD_END_SEARCH_ROOT_SEGMENTS.has(firstSegment)) return "search_results_shell";
|
|
3136
|
+
if (RESEARCH_DEAD_END_OTHER_ROOT_SEGMENTS.has(firstSegment)) return "research_dead_end_shell";
|
|
3137
|
+
if (isPrivacyDeadEndPath(segments)) return "privacy_preference_shell";
|
|
3138
|
+
return null;
|
|
3139
|
+
};
|
|
3972
3140
|
|
|
3973
3141
|
// src/providers/web/policy.ts
|
|
3974
3142
|
var normalizeDomain = (value) => value.trim().toLowerCase();
|
|
@@ -4517,8 +3685,8 @@ var CrawlWorkerPool = class {
|
|
|
4517
3685
|
}
|
|
4518
3686
|
const taskId = this.nextTaskId;
|
|
4519
3687
|
this.nextTaskId += 1;
|
|
4520
|
-
return new Promise((
|
|
4521
|
-
this.queue.push({ id: taskId, input, resolve
|
|
3688
|
+
return new Promise((resolve, reject) => {
|
|
3689
|
+
this.queue.push({ id: taskId, input, resolve, reject });
|
|
4522
3690
|
this.dispatch();
|
|
4523
3691
|
});
|
|
4524
3692
|
}
|
|
@@ -5122,7 +4290,7 @@ var coerceStringArray = (value) => {
|
|
|
5122
4290
|
return value.filter((entry) => typeof entry === "string");
|
|
5123
4291
|
};
|
|
5124
4292
|
var extractLinks2 = (row, fallbackUrl) => {
|
|
5125
|
-
const
|
|
4293
|
+
const attributeLinks2 = [
|
|
5126
4294
|
...coerceStringArray(row.attributes?.links),
|
|
5127
4295
|
...coerceStringArray(row.attributes?.threadLinks),
|
|
5128
4296
|
...coerceStringArray(row.attributes?.replyLinks),
|
|
@@ -5130,7 +4298,7 @@ var extractLinks2 = (row, fallbackUrl) => {
|
|
|
5130
4298
|
];
|
|
5131
4299
|
const contentLinks = [...row.content?.match(LINK_RE) ?? []];
|
|
5132
4300
|
const deduped = /* @__PURE__ */ new Set();
|
|
5133
|
-
for (const candidate of [...
|
|
4301
|
+
for (const candidate of [...attributeLinks2, ...contentLinks]) {
|
|
5134
4302
|
const canonical = canonicalizeUrl(candidate);
|
|
5135
4303
|
if (!isHttpUrl2(canonical) || canonical === fallbackUrl || !isLikelyDocumentUrl(canonical)) continue;
|
|
5136
4304
|
deduped.add(canonical);
|
|
@@ -5206,13 +4374,21 @@ var createCommunityProvider = (options = {}) => {
|
|
|
5206
4374
|
const pending = [];
|
|
5207
4375
|
const rows = [];
|
|
5208
4376
|
for (let page = 1; page <= traversal.pageLimit && rows.length < traversal.maxRecords; page += 1) {
|
|
5209
|
-
|
|
5210
|
-
|
|
5211
|
-
|
|
5212
|
-
...input
|
|
5213
|
-
|
|
4377
|
+
let pageRows;
|
|
4378
|
+
try {
|
|
4379
|
+
pageRows = await options.search({
|
|
4380
|
+
...input,
|
|
4381
|
+
filters: {
|
|
4382
|
+
...input.filters ?? {},
|
|
4383
|
+
page
|
|
4384
|
+
}
|
|
4385
|
+
}, context);
|
|
4386
|
+
} catch (error) {
|
|
4387
|
+
if (rows.length > 0 && shouldSkipExpansionError(error)) {
|
|
4388
|
+
break;
|
|
5214
4389
|
}
|
|
5215
|
-
|
|
4390
|
+
throw error;
|
|
4391
|
+
}
|
|
5216
4392
|
for (const row of sortRows(pageRows)) {
|
|
5217
4393
|
const canonical = canonicalizeUrl(row.url);
|
|
5218
4394
|
if (!isHttpUrl2(canonical) || seen.has(canonical)) continue;
|
|
@@ -5469,6 +4645,7 @@ var createCommunityProvider = (options = {}) => {
|
|
|
5469
4645
|
// src/providers/social/search-quality.ts
|
|
5470
4646
|
var TARGETED_PLATFORMS = /* @__PURE__ */ new Set(["x", "bluesky", "reddit", "facebook", "threads"]);
|
|
5471
4647
|
var SOCIAL_JS_REQUIRED_RE = /\b(?:javascript (?:is not available|required|is disabled(?: in this browser)?)|you need to enable javascript|please enable javascript)\b/i;
|
|
4648
|
+
var SOCIAL_JS_REQUIRED_SHELL_CONTEXT_RE = /\b(?:supported browsers?|help center|something went wrong|try again|privacy policy|cookie policy|ads info)\b/i;
|
|
5472
4649
|
var BLUESKY_LOGGED_OUT_SEARCH_RE = /\bsearch is currently unavailable when logged out\b/i;
|
|
5473
4650
|
var BLUESKY_EMPTY_SEARCH_SHELL_RE = /\b(?:follow 10 people to get started|find people to follow)\b/i;
|
|
5474
4651
|
var REDDIT_VERIFICATION_WALL_RE = /\b(?:please wait for verification|verify (?:you(?:'re| are) human|that you(?:'re| are) human)|security check)\b/i;
|
|
@@ -5585,8 +4762,6 @@ var isRootShellUrl = (platform, parsed) => {
|
|
|
5585
4762
|
return isBlockedFacebookNonContentUrl(parsed, { includeSearchRoute: false });
|
|
5586
4763
|
case "threads":
|
|
5587
4764
|
return isPrimaryThreadsHost(host) && (pathname === "/" || pathname === "/login" || pathname === "/login/");
|
|
5588
|
-
default:
|
|
5589
|
-
return false;
|
|
5590
4765
|
}
|
|
5591
4766
|
};
|
|
5592
4767
|
var isBlockedExpansionPath = (platform, parsed) => {
|
|
@@ -5603,8 +4778,6 @@ var isBlockedExpansionPath = (platform, parsed) => {
|
|
|
5603
4778
|
return isBlockedFacebookNonContentUrl(parsed, { includeSearchRoute: true });
|
|
5604
4779
|
case "threads":
|
|
5605
4780
|
return isPrimaryThreadsHost(host) && (pathname === "/" || pathname === "/login" || pathname === "/search" || pathname === "/search/" || isStaticMetadataPath(pathname));
|
|
5606
|
-
default:
|
|
5607
|
-
return false;
|
|
5608
4781
|
}
|
|
5609
4782
|
};
|
|
5610
4783
|
var isFirstPartySearchRoute = (platform, parsed) => {
|
|
@@ -5621,8 +4794,6 @@ var isFirstPartySearchRoute = (platform, parsed) => {
|
|
|
5621
4794
|
return isPrimaryFacebookHost(host) && isFacebookSearchLikePath(pathname);
|
|
5622
4795
|
case "threads":
|
|
5623
4796
|
return isPrimaryThreadsHost(host) && (pathname === "/search" || pathname === "/search/");
|
|
5624
|
-
default:
|
|
5625
|
-
return false;
|
|
5626
4797
|
}
|
|
5627
4798
|
};
|
|
5628
4799
|
var collectSocialSearchLinkEvidence = (platform, baseUrl, links) => {
|
|
@@ -5662,16 +4833,13 @@ var collectSocialSearchLinkEvidence = (platform, baseUrl, links) => {
|
|
|
5662
4833
|
};
|
|
5663
4834
|
var isUsableFirstPartySearchResultUrl = (platform, url) => {
|
|
5664
4835
|
const parsed = parseUrl(url);
|
|
5665
|
-
if (
|
|
4836
|
+
if (parsed === null) {
|
|
5666
4837
|
return false;
|
|
5667
4838
|
}
|
|
5668
4839
|
const host = parsed.hostname.toLowerCase();
|
|
5669
4840
|
if (platform === "x" && host !== "x.com" || platform === "bluesky" && host !== "bsky.app") {
|
|
5670
4841
|
return false;
|
|
5671
4842
|
}
|
|
5672
|
-
if (isFirstPartyHelpHost(platform, host)) {
|
|
5673
|
-
return false;
|
|
5674
|
-
}
|
|
5675
4843
|
return !isBlockedExpansionPath(platform, parsed);
|
|
5676
4844
|
};
|
|
5677
4845
|
var isUsableBlueskySearchEvidenceUrl = (url) => {
|
|
@@ -5706,19 +4874,9 @@ var isRetainableFacebookSearchSupportUrl = (url) => {
|
|
|
5706
4874
|
if (parsed === null || !isPrimaryFacebookHost(parsed.hostname)) {
|
|
5707
4875
|
return false;
|
|
5708
4876
|
}
|
|
5709
|
-
if (isBlockedFacebookNonContentUrl(parsed, { includeSearchRoute: true })) {
|
|
5710
|
-
return false;
|
|
5711
|
-
}
|
|
5712
|
-
if (isFirstPartySearchRoute("facebook", parsed)) {
|
|
5713
|
-
return false;
|
|
5714
|
-
}
|
|
5715
4877
|
return !isUsableFacebookSearchEvidenceUrl(url);
|
|
5716
4878
|
};
|
|
5717
|
-
var hasFacebookSearchResultSignals = (input) => {
|
|
5718
|
-
const parsed = parseUrl(input.url);
|
|
5719
|
-
if (parsed === null || !isFirstPartySearchRoute("facebook", parsed)) {
|
|
5720
|
-
return false;
|
|
5721
|
-
}
|
|
4879
|
+
var hasFacebookSearchResultSignals = (parsed, input) => {
|
|
5722
4880
|
const combined = `${normalizeText2(input.title)} ${normalizeText2(input.content)}`.trim();
|
|
5723
4881
|
const hasSearchHeading = FACEBOOK_SEARCH_RESULTS_HEADING_RE.test(combined);
|
|
5724
4882
|
const markerCount = FACEBOOK_SEARCH_RESULT_MARKERS.filter((pattern) => pattern.test(combined)).length;
|
|
@@ -5748,14 +4906,12 @@ var isUsableSocialSearchContentUrl = (platform, url) => {
|
|
|
5748
4906
|
return isUsableFacebookSearchEvidenceUrl(url);
|
|
5749
4907
|
case "threads":
|
|
5750
4908
|
return isUsableThreadsSearchEvidenceUrl(url);
|
|
5751
|
-
default:
|
|
5752
|
-
return false;
|
|
5753
4909
|
}
|
|
5754
4910
|
};
|
|
5755
4911
|
var hasUsableFirstPartySearchEvidence = (platform, parsed, links) => parsed !== null && isFirstPartySearchRoute(platform, parsed) && collectSocialSearchLinkEvidence(platform, parsed.toString(), links).usableContentLinks.length > 0;
|
|
5756
4912
|
var isFirstPartySocialSearchRoute = (platform, url) => {
|
|
5757
4913
|
const parsed = parseUrl(url);
|
|
5758
|
-
return parsed !== null && isFirstPartySearchRoute(platform, parsed);
|
|
4914
|
+
return parsed !== null && isTargetedPlatform(platform) && isFirstPartySearchRoute(platform, parsed);
|
|
5759
4915
|
};
|
|
5760
4916
|
var detectSocialSearchShell = (platform, input) => {
|
|
5761
4917
|
if (!isTargetedPlatform(platform)) {
|
|
@@ -5770,13 +4926,19 @@ var detectSocialSearchShell = (platform, input) => {
|
|
|
5770
4926
|
browserRequired: true
|
|
5771
4927
|
};
|
|
5772
4928
|
}
|
|
4929
|
+
if ((platform === "x" || platform === "bluesky") && parsed && SOCIAL_JS_REQUIRED_RE.test(combined) && SOCIAL_JS_REQUIRED_SHELL_CONTEXT_RE.test(combined) && !hasUsableFirstPartySearchEvidence(platform, parsed, links)) {
|
|
4930
|
+
return {
|
|
4931
|
+
providerShell: "social_js_required_shell",
|
|
4932
|
+
browserRequired: true
|
|
4933
|
+
};
|
|
4934
|
+
}
|
|
5773
4935
|
if (platform === "reddit" && REDDIT_VERIFICATION_WALL_RE.test(combined)) {
|
|
5774
4936
|
return {
|
|
5775
4937
|
providerShell: "social_verification_wall",
|
|
5776
4938
|
browserRequired: true
|
|
5777
4939
|
};
|
|
5778
4940
|
}
|
|
5779
|
-
if (platform === "bluesky" && parsed && isFirstPartySearchRoute(platform, parsed) && BLUESKY_LOGGED_OUT_SEARCH_RE.test(combined)) {
|
|
4941
|
+
if (platform === "bluesky" && parsed && isFirstPartySearchRoute(platform, parsed) && BLUESKY_LOGGED_OUT_SEARCH_RE.test(combined) && !hasUsableFirstPartySearchEvidence(platform, parsed, links)) {
|
|
5780
4942
|
return {
|
|
5781
4943
|
providerShell: "social_js_required_shell",
|
|
5782
4944
|
browserRequired: true
|
|
@@ -5800,7 +4962,7 @@ var detectSocialSearchShell = (platform, input) => {
|
|
|
5800
4962
|
browserRequired: true
|
|
5801
4963
|
};
|
|
5802
4964
|
}
|
|
5803
|
-
if (parsed && isFirstPartySearchRoute(platform, parsed) && platform === "facebook" && hasFacebookSearchResultSignals(input)) {
|
|
4965
|
+
if (parsed && isFirstPartySearchRoute(platform, parsed) && platform === "facebook" && hasFacebookSearchResultSignals(parsed, input)) {
|
|
5804
4966
|
return null;
|
|
5805
4967
|
}
|
|
5806
4968
|
if (parsed && isFirstPartySearchRoute(platform, parsed) && !hasUsableFirstPartySearchEvidence(platform, parsed, links)) {
|
|
@@ -5958,7 +5120,7 @@ var hasBrowserFallbackMode = (attributes) => typeof attributes?.browser_fallback
|
|
|
5958
5120
|
var hasVisibleSearchContent = (row) => typeof row.title === "string" && row.title.trim().length > 0 || typeof row.content === "string" && row.content.trim().length > 0;
|
|
5959
5121
|
var shouldKeepRecoveredFacebookSearchRow = (platform, row) => platform === "facebook" && hasBrowserFallbackMode(row.attributes) && hasVisibleSearchContent(row);
|
|
5960
5122
|
var extractLinks3 = (platform, row, fallbackUrl) => {
|
|
5961
|
-
const
|
|
5123
|
+
const attributeLinks2 = [
|
|
5962
5124
|
...coerceStringArray2(row.attributes?.links),
|
|
5963
5125
|
...coerceStringArray2(row.attributes?.threadLinks),
|
|
5964
5126
|
...coerceStringArray2(row.attributes?.replyLinks),
|
|
@@ -5966,7 +5128,7 @@ var extractLinks3 = (platform, row, fallbackUrl) => {
|
|
|
5966
5128
|
];
|
|
5967
5129
|
const contentLinks = [...row.content?.match(LINK_RE2) ?? []];
|
|
5968
5130
|
const deduped = /* @__PURE__ */ new Set();
|
|
5969
|
-
for (const candidate of [...
|
|
5131
|
+
for (const candidate of [...attributeLinks2, ...contentLinks]) {
|
|
5970
5132
|
const canonical = canonicalizeUrl(candidate);
|
|
5971
5133
|
if (!isHttpUrl3(canonical) || canonical === fallbackUrl || !isLikelyDocumentUrl(canonical) || !isAllowedSocialSearchExpansionUrl(platform, canonical)) {
|
|
5972
5134
|
continue;
|
|
@@ -8678,7 +7840,7 @@ var PROVIDER_PRODUCT_URL_HINT_RE = {
|
|
|
8678
7840
|
bestbuy: /\/site\/[^?#]*\/\d+\.p(?:[?#]|$)/i,
|
|
8679
7841
|
ebay: /\/itm(?:\/|$)/i,
|
|
8680
7842
|
costco: /(?:\/|\.)(?:product|warehouse)\.[^?#]+\.html(?:[?#]|$)|[?&](?:prodid|itemnumber)=/i,
|
|
8681
|
-
macys: /\/shop\/product
|
|
7843
|
+
macys: /\/shop\/product\/[^?#]+(?:[?#]|$)/i,
|
|
8682
7844
|
aliexpress: /\/(?:item|i)\/[^?#]+/i,
|
|
8683
7845
|
temu: /\/(?:goods\.html|g-[^/?#]+\.html)(?:[?#]|$)/i,
|
|
8684
7846
|
others: /(?:\/ip(?:\/|$)|\/itm(?:\/|$)|\/product(?:s)?\/|\/sku\/|\/site\/[^?#]*\/\d+\.p(?:[?#]|$)|(?:\/|\.)(?:product|warehouse)\.[^?#]+\.html(?:[?#]|$))/i
|
|
@@ -8902,6 +8064,14 @@ var requiresBrowserAssistance = (profile, responseUrl, html) => {
|
|
|
8902
8064
|
...text ? { message: toSnippet(text, 400) } : {}
|
|
8903
8065
|
};
|
|
8904
8066
|
}
|
|
8067
|
+
const hasPdpErrorShell = textLower.includes("something went wrong") && (textLower.includes("use our search bar") || textLower.includes("pick a category below") || textLower.includes("typed in a url"));
|
|
8068
|
+
if (hasPdpErrorShell) {
|
|
8069
|
+
return {
|
|
8070
|
+
reason: "bestbuy_pdp_error_shell",
|
|
8071
|
+
...title ? { title } : {},
|
|
8072
|
+
...text ? { message: toSnippet(text, 400) } : {}
|
|
8073
|
+
};
|
|
8074
|
+
}
|
|
8905
8075
|
}
|
|
8906
8076
|
if (profile.name === "target") {
|
|
8907
8077
|
const isShellPage = /:\s*target$/i.test(title) && textLower.includes("skip to main content") && textLower.includes("skip to footer");
|
|
@@ -9496,6 +8666,19 @@ var createDefaultFetch = (profile, providerId, fetcher) => async (input, context
|
|
|
9496
8666
|
context
|
|
9497
8667
|
});
|
|
9498
8668
|
const extracted = extractStructuredContent(fetched.html, fetched.url);
|
|
8669
|
+
const content = toSnippet(extracted.text, 2e3);
|
|
8670
|
+
const providerShell = requiresBrowserAssistance(profile, fetched.url, fetched.html);
|
|
8671
|
+
if (providerShell) {
|
|
8672
|
+
const pageIssue = classifySearchPageIssue(profile, fetched, extracted, content, providerShell);
|
|
8673
|
+
throwShoppingPageIssue({
|
|
8674
|
+
providerId,
|
|
8675
|
+
fetched,
|
|
8676
|
+
extracted,
|
|
8677
|
+
content,
|
|
8678
|
+
pageIssue: ensureProviderShellIssue(pageIssue, providerShell, content),
|
|
8679
|
+
providerShell
|
|
8680
|
+
});
|
|
8681
|
+
}
|
|
9499
8682
|
const title = toSnippet(extracted.text, 120) || fetched.url;
|
|
9500
8683
|
const extractedPrice = extracted.metadata.price ? {
|
|
9501
8684
|
amount: extracted.metadata.price.amount,
|
|
@@ -9856,6 +9039,37 @@ var createWebProvider = (options = {}) => {
|
|
|
9856
9039
|
};
|
|
9857
9040
|
};
|
|
9858
9041
|
|
|
9042
|
+
// src/providers/bounded-map.ts
|
|
9043
|
+
var resolveWorkerCount = (itemCount, limit) => {
|
|
9044
|
+
if (itemCount <= 0) return 0;
|
|
9045
|
+
const finiteLimit = Number.isFinite(limit) ? Math.floor(limit) : 1;
|
|
9046
|
+
return Math.min(Math.max(1, finiteLimit), itemCount);
|
|
9047
|
+
};
|
|
9048
|
+
var mapBounded = async (items, limit, task) => {
|
|
9049
|
+
const results = new Array(items.length);
|
|
9050
|
+
let cursor = 0;
|
|
9051
|
+
let firstError = null;
|
|
9052
|
+
const workers = Array.from({ length: resolveWorkerCount(items.length, limit) }, async () => {
|
|
9053
|
+
for (; ; ) {
|
|
9054
|
+
if (firstError) return;
|
|
9055
|
+
const index = cursor;
|
|
9056
|
+
cursor += 1;
|
|
9057
|
+
if (index >= items.length) return;
|
|
9058
|
+
try {
|
|
9059
|
+
results[index] = await task(items[index], index);
|
|
9060
|
+
} catch (error) {
|
|
9061
|
+
if (!firstError) {
|
|
9062
|
+
firstError = error instanceof Error ? error : new Error(String(error));
|
|
9063
|
+
}
|
|
9064
|
+
return;
|
|
9065
|
+
}
|
|
9066
|
+
}
|
|
9067
|
+
});
|
|
9068
|
+
await Promise.all(workers);
|
|
9069
|
+
if (firstError) throw firstError;
|
|
9070
|
+
return results;
|
|
9071
|
+
};
|
|
9072
|
+
|
|
9859
9073
|
// src/providers/workflow-contracts.ts
|
|
9860
9074
|
var isJsonRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9861
9075
|
var isWorkflowStage = (value) => value === "compile" || value === "execute" || value === "postprocess" || value === "resume";
|
|
@@ -9874,121 +9088,17 @@ var isWorkflowResumePayload = (value) => isJsonRecord(value) && isWorkflowResume
|
|
|
9874
9088
|
// src/providers/workflows.ts
|
|
9875
9089
|
import { createHash as createHash7 } from "crypto";
|
|
9876
9090
|
|
|
9877
|
-
// src/providers/
|
|
9878
|
-
import {
|
|
9879
|
-
|
|
9880
|
-
|
|
9881
|
-
|
|
9882
|
-
|
|
9883
|
-
var MAX_ARTIFACT_TTL_HOURS = 168;
|
|
9884
|
-
var clampTtlHours = (value) => {
|
|
9885
|
-
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
9886
|
-
return DEFAULT_ARTIFACT_TTL_HOURS;
|
|
9887
|
-
}
|
|
9888
|
-
return Math.min(MAX_ARTIFACT_TTL_HOURS, Math.floor(value));
|
|
9889
|
-
};
|
|
9890
|
-
var serializeContent = (content) => {
|
|
9891
|
-
if (typeof content === "string" || Buffer.isBuffer(content)) {
|
|
9892
|
-
return content;
|
|
9893
|
-
}
|
|
9894
|
-
return `${JSON.stringify(content, null, 2)}
|
|
9895
|
-
`;
|
|
9896
|
-
};
|
|
9897
|
-
var createArtifactBundle = async (args) => {
|
|
9898
|
-
const runId = randomUUID3();
|
|
9899
|
-
const now = args.now ?? /* @__PURE__ */ new Date();
|
|
9900
|
-
const ttlHours = clampTtlHours(args.ttlHours);
|
|
9901
|
-
const manifestFileName = args.manifestFileName ?? "bundle-manifest.json";
|
|
9902
|
-
const expiresAt = new Date(now.getTime() + ttlHours * 60 * 60 * 1e3);
|
|
9903
|
-
const root = args.outputDir ? resolve(args.outputDir) : join2(tmpdir2(), "opendevbrowser");
|
|
9904
|
-
const basePath = join2(root, args.namespace, runId);
|
|
9905
|
-
await mkdir(basePath, { recursive: true, mode: 448 });
|
|
9906
|
-
const writtenFiles = [];
|
|
9907
|
-
for (const file of args.files) {
|
|
9908
|
-
const filePath = join2(basePath, file.path);
|
|
9909
|
-
const directory = dirname(filePath);
|
|
9910
|
-
if (directory && directory !== basePath) {
|
|
9911
|
-
await mkdir(directory, { recursive: true, mode: 448 });
|
|
9912
|
-
}
|
|
9913
|
-
await writeFile(filePath, serializeContent(file.content), { mode: 384 });
|
|
9914
|
-
writtenFiles.push(file.path);
|
|
9915
|
-
}
|
|
9916
|
-
const manifest = {
|
|
9917
|
-
run_id: runId,
|
|
9918
|
-
created_at: now.toISOString(),
|
|
9919
|
-
ttl_hours: ttlHours,
|
|
9920
|
-
expires_at: expiresAt.toISOString(),
|
|
9921
|
-
files: [...writtenFiles, manifestFileName]
|
|
9922
|
-
};
|
|
9923
|
-
await writeFile(join2(basePath, manifestFileName), `${JSON.stringify(manifest, null, 2)}
|
|
9924
|
-
`, { mode: 384 });
|
|
9925
|
-
return {
|
|
9926
|
-
runId,
|
|
9927
|
-
basePath,
|
|
9928
|
-
manifest,
|
|
9929
|
-
manifestFileName
|
|
9930
|
-
};
|
|
9931
|
-
};
|
|
9932
|
-
var isExpired = (manifest, now) => {
|
|
9933
|
-
const expiry = new Date(manifest.expires_at);
|
|
9934
|
-
if (Number.isNaN(expiry.getTime())) return false;
|
|
9935
|
-
return expiry.getTime() <= now.getTime();
|
|
9936
|
-
};
|
|
9937
|
-
var cleanupExpiredArtifacts = async (rootDir, now = /* @__PURE__ */ new Date()) => {
|
|
9938
|
-
const removed = [];
|
|
9939
|
-
const skipped = [];
|
|
9940
|
-
let namespaces = [];
|
|
9941
|
-
try {
|
|
9942
|
-
namespaces = await readdir2(rootDir);
|
|
9943
|
-
} catch {
|
|
9944
|
-
return { removed, skipped };
|
|
9091
|
+
// src/providers/workflow-output-root.ts
|
|
9092
|
+
import { join as join2 } from "path";
|
|
9093
|
+
var WORKFLOW_ARTIFACT_DIRECTORY = ".opendevbrowser";
|
|
9094
|
+
var resolveWorkflowArtifactRoot = (outputDir, options = {}) => {
|
|
9095
|
+
if (outputDir === void 0) {
|
|
9096
|
+
return join2(options.workspaceRoot ?? process.cwd(), WORKFLOW_ARTIFACT_DIRECTORY);
|
|
9945
9097
|
}
|
|
9946
|
-
|
|
9947
|
-
|
|
9948
|
-
let runs = [];
|
|
9949
|
-
try {
|
|
9950
|
-
runs = await readdir2(namespacePath);
|
|
9951
|
-
} catch {
|
|
9952
|
-
continue;
|
|
9953
|
-
}
|
|
9954
|
-
for (const run of runs) {
|
|
9955
|
-
const runPath = join2(namespacePath, run);
|
|
9956
|
-
const manifestCandidates = [join2(runPath, "bundle-manifest.json"), join2(runPath, "manifest.json")];
|
|
9957
|
-
try {
|
|
9958
|
-
let manifestPath = null;
|
|
9959
|
-
for (const candidate of manifestCandidates) {
|
|
9960
|
-
try {
|
|
9961
|
-
const candidateMetadata = await stat(candidate);
|
|
9962
|
-
if (candidateMetadata.isFile()) {
|
|
9963
|
-
manifestPath = candidate;
|
|
9964
|
-
break;
|
|
9965
|
-
}
|
|
9966
|
-
} catch {
|
|
9967
|
-
}
|
|
9968
|
-
}
|
|
9969
|
-
if (!manifestPath) {
|
|
9970
|
-
skipped.push(runPath);
|
|
9971
|
-
continue;
|
|
9972
|
-
}
|
|
9973
|
-
const metadata = await stat(manifestPath);
|
|
9974
|
-
if (!metadata.isFile()) {
|
|
9975
|
-
skipped.push(runPath);
|
|
9976
|
-
continue;
|
|
9977
|
-
}
|
|
9978
|
-
const manifestRaw = await readFile(manifestPath, "utf8");
|
|
9979
|
-
const manifest = JSON.parse(manifestRaw);
|
|
9980
|
-
if (isExpired(manifest, now)) {
|
|
9981
|
-
await rm2(runPath, { recursive: true, force: true });
|
|
9982
|
-
removed.push(runPath);
|
|
9983
|
-
} else {
|
|
9984
|
-
skipped.push(runPath);
|
|
9985
|
-
}
|
|
9986
|
-
} catch {
|
|
9987
|
-
skipped.push(runPath);
|
|
9988
|
-
}
|
|
9989
|
-
}
|
|
9098
|
+
if (outputDir.trim() === "") {
|
|
9099
|
+
throw new Error("outputDir cannot be empty");
|
|
9990
9100
|
}
|
|
9991
|
-
return
|
|
9101
|
+
return outputDir;
|
|
9992
9102
|
};
|
|
9993
9103
|
|
|
9994
9104
|
// src/providers/timebox.ts
|
|
@@ -10455,235 +9565,27 @@ var design_contract_v1_default = {
|
|
|
10455
9565
|
validationTargets: {
|
|
10456
9566
|
blockOn: [
|
|
10457
9567
|
"contrast-failure",
|
|
10458
|
-
"keyboard-regression",
|
|
10459
|
-
"stale-search-results",
|
|
10460
|
-
"invalid-route-recovery-failure"
|
|
10461
|
-
],
|
|
10462
|
-
warnOn: [
|
|
10463
|
-
"responsive-mismatch",
|
|
10464
|
-
"layout-shift",
|
|
10465
|
-
"spinner-stacking",
|
|
10466
|
-
"scan-surface-jank"
|
|
10467
|
-
]
|
|
10468
|
-
},
|
|
10469
|
-
designVectors: {
|
|
10470
|
-
advancedMotionAdvisory: [
|
|
10471
|
-
"Advisory shader-like gradient depth",
|
|
10472
|
-
"Advisory WebGL-style spatial reveal",
|
|
10473
|
-
"Advisory Spline-style product orbit",
|
|
10474
|
-
"Runtime support: none. Library policy authorization: none."
|
|
10475
|
-
]
|
|
10476
|
-
}
|
|
10477
|
-
}
|
|
10478
|
-
};
|
|
10479
|
-
|
|
10480
|
-
// src/inspiredesign/handoff.ts
|
|
10481
|
-
var INSPIREDESIGN_HANDOFF_FILES = {
|
|
10482
|
-
designMarkdown: "design.md",
|
|
10483
|
-
advancedBrief: "advanced-brief.md",
|
|
10484
|
-
designContract: "design-contract.json",
|
|
10485
|
-
canvasPlanRequest: "canvas-plan.request.json",
|
|
10486
|
-
designAgentHandoff: "design-agent-handoff.json",
|
|
10487
|
-
generationPlan: "generation-plan.json",
|
|
10488
|
-
implementationPlanMarkdown: "implementation-plan.md",
|
|
10489
|
-
implementationPlan: "implementation-plan.json",
|
|
10490
|
-
evidence: "evidence.json",
|
|
10491
|
-
prototypeGuidance: "prototype-guidance.md"
|
|
10492
|
-
};
|
|
10493
|
-
var INSPIREDESIGN_HANDOFF_SKILLS = {
|
|
10494
|
-
bestPractices: {
|
|
10495
|
-
name: "opendevbrowser-best-practices",
|
|
10496
|
-
topic: "quick start"
|
|
10497
|
-
},
|
|
10498
|
-
designAgent: {
|
|
10499
|
-
name: "opendevbrowser-design-agent",
|
|
10500
|
-
topic: "canvas-contract"
|
|
10501
|
-
}
|
|
10502
|
-
};
|
|
10503
|
-
var formatSkillReference = (skill) => `${skill.name} "${skill.topic}"`;
|
|
10504
|
-
var formatSkillLoadCommand = (skill) => `opendevbrowser_skill_load ${skill.name} "${skill.topic}"`;
|
|
10505
|
-
var INSPIREDESIGN_HANDOFF_COMMANDS = {
|
|
10506
|
-
loadBestPractices: formatSkillLoadCommand(INSPIREDESIGN_HANDOFF_SKILLS.bestPractices),
|
|
10507
|
-
loadDesignAgent: formatSkillLoadCommand(INSPIREDESIGN_HANDOFF_SKILLS.designAgent),
|
|
10508
|
-
continueInCanvas: `opendevbrowser canvas --command canvas.plan.set --params-file ./${INSPIREDESIGN_HANDOFF_FILES.canvasPlanRequest}`
|
|
10509
|
-
};
|
|
10510
|
-
var INSPIREDESIGN_HANDOFF_RECOMMENDED_SKILLS = [
|
|
10511
|
-
formatSkillReference(INSPIREDESIGN_HANDOFF_SKILLS.bestPractices),
|
|
10512
|
-
formatSkillReference(INSPIREDESIGN_HANDOFF_SKILLS.designAgent)
|
|
10513
|
-
];
|
|
10514
|
-
var INSPIREDESIGN_HANDOFF_GUIDANCE = {
|
|
10515
|
-
reviewAdvancedBrief: `${INSPIREDESIGN_HANDOFF_FILES.advancedBrief} is the authoritative reference-first brief. When URL references exist, captured evidence leads the creative direction; selected format, profile defaults, layout posture, motion grammar, and anti-patterns are route guardrails only. Read it before touching Canvas or implementation files.`,
|
|
10516
|
-
prepareCanvasPlanRequest: `Fill canvasSessionId, leaseId, and documentId in ${INSPIREDESIGN_HANDOFF_FILES.canvasPlanRequest} before running ${INSPIREDESIGN_HANDOFF_COMMANDS.continueInCanvas}.`,
|
|
10517
|
-
deepCaptureRecommendation: "Any inspiredesign run with reference URLs already uses captureMode=deep. Rerun with the same URLs only when you need refreshed DOM/layout evidence, restored session state, or capture-specific debugging."
|
|
10518
|
-
};
|
|
10519
|
-
var INSPIREDESIGN_ARTIFACT_GUIDE = {
|
|
10520
|
-
[INSPIREDESIGN_HANDOFF_FILES.advancedBrief]: {
|
|
10521
|
-
purpose: "Authoritative reference-first brief for the downstream design agent.",
|
|
10522
|
-
expectedContents: ["Selected prompt format", "reference pattern board", "route guardrails"],
|
|
10523
|
-
howToUse: ["Read first", "treat captured evidence as creative priority", "use guardrails to avoid route drift"],
|
|
10524
|
-
mustNot: ["Do not treat defaults as stronger than captured references"]
|
|
10525
|
-
},
|
|
10526
|
-
[INSPIREDESIGN_HANDOFF_FILES.designMarkdown]: {
|
|
10527
|
-
purpose: "Human-readable design specification and implementation narrative.",
|
|
10528
|
-
expectedContents: ["inspiration analysis", "unified direction", "governance summary", "deliverables"],
|
|
10529
|
-
howToUse: ["Use as the readable project brief", "cross-check implementation choices against its sections"],
|
|
10530
|
-
mustNot: ["Do not use prose as a substitute for the JSON contract when patching Canvas"]
|
|
10531
|
-
},
|
|
10532
|
-
[INSPIREDESIGN_HANDOFF_FILES.designContract]: {
|
|
10533
|
-
purpose: "Narrowed Canvas governance contract for design decisions.",
|
|
10534
|
-
expectedContents: ["emitted governance blocks", "motion system", "library policy", "runtime budgets"],
|
|
10535
|
-
howToUse: ["Patch only emitted governance blocks", "compare implementation against this contract before shipping"],
|
|
10536
|
-
mustNot: ["Do not add navigation, async, or performance context as Canvas governance patches"]
|
|
10537
|
-
},
|
|
10538
|
-
[INSPIREDESIGN_HANDOFF_FILES.canvasPlanRequest]: {
|
|
10539
|
-
purpose: "Ready-to-fill request payload for `canvas.plan.set`.",
|
|
10540
|
-
expectedContents: ["request ids", "Canvas session ids", "mutation-safe generationPlan"],
|
|
10541
|
-
howToUse: ["Fill canvasSessionId, leaseId, and documentId", "submit with the provided canvas.plan.set command"],
|
|
10542
|
-
mustNot: ["Do not add handoff-only fields or reference-only analysis to generationPlan"]
|
|
10543
|
-
},
|
|
10544
|
-
[INSPIREDESIGN_HANDOFF_FILES.designAgentHandoff]: {
|
|
10545
|
-
purpose: "Downstream index for artifact usage, skills, commands, and omitted implementation context.",
|
|
10546
|
-
expectedContents: ["skills", "commands", "contract scope", "implementation context", "artifact and section guides"],
|
|
10547
|
-
howToUse: ["Use as the navigation map for the bundle", "load recommended skills before implementation"],
|
|
10548
|
-
mustNot: ["Do not treat handoff context as runtime Canvas schema"]
|
|
10549
|
-
},
|
|
10550
|
-
[INSPIREDESIGN_HANDOFF_FILES.generationPlan]: {
|
|
10551
|
-
purpose: "Full generated plan for reasoning about design intent.",
|
|
10552
|
-
expectedContents: ["Canvas plan fields", "design vectors", "reference analysis when available"],
|
|
10553
|
-
howToUse: ["Use for agent reasoning and audit traceability", "compare with canvas-plan.request.json for runtime subset"],
|
|
10554
|
-
mustNot: ["Do not submit this file directly to Canvas when it contains non-request context"]
|
|
10555
|
-
},
|
|
10556
|
-
[INSPIREDESIGN_HANDOFF_FILES.implementationPlanMarkdown]: {
|
|
10557
|
-
purpose: "Human-readable engineering sequence for the first implementation pass.",
|
|
10558
|
-
expectedContents: ["build sequence", "component plan", "token strategy", "QA and risk checks"],
|
|
10559
|
-
howToUse: ["Convert sections into implementation tasks", "keep tests and browser validation aligned to the plan"],
|
|
10560
|
-
mustNot: ["Do not implement sections unsupported by brief or reference evidence"]
|
|
10561
|
-
},
|
|
10562
|
-
[INSPIREDESIGN_HANDOFF_FILES.implementationPlan]: {
|
|
10563
|
-
purpose: "Machine-readable implementation plan matching the Markdown plan.",
|
|
10564
|
-
expectedContents: ["architecture steps", "component inventory", "state and validation tasks"],
|
|
10565
|
-
howToUse: ["Use for structured task extraction", "keep it synchronized with implementation-plan.md"],
|
|
10566
|
-
mustNot: ["Do not treat it as a Canvas document patch payload"]
|
|
10567
|
-
},
|
|
10568
|
-
[INSPIREDESIGN_HANDOFF_FILES.evidence]: {
|
|
10569
|
-
purpose: "Evidence digest for brief, reference, capture, and design-vector provenance.",
|
|
10570
|
-
expectedContents: ["brief expansion", "reference outcomes", "capture attempts", "design vectors"],
|
|
10571
|
-
howToUse: ["Audit why choices were made", "prefer evidence over generic template defaults"],
|
|
10572
|
-
mustNot: ["Do not ignore failed or skipped capture statuses when judging confidence"]
|
|
10573
|
-
},
|
|
10574
|
-
[INSPIREDESIGN_HANDOFF_FILES.prototypeGuidance]: {
|
|
10575
|
-
purpose: "Optional first prototype guidance when the workflow requests prototype output.",
|
|
10576
|
-
expectedContents: ["prototype structure", "design-vector guidance", "browser proof checklist"],
|
|
10577
|
-
howToUse: ["Use only for the first prototype pass", "promote proven ideas back into contract-aligned work"],
|
|
10578
|
-
mustNot: ["Do not treat prototype guidance as final implementation authority"]
|
|
10579
|
-
}
|
|
10580
|
-
};
|
|
10581
|
-
var INSPIREDESIGN_CONTRACT_SECTION_GUIDE = {
|
|
10582
|
-
intent: {
|
|
10583
|
-
purpose: "Define why the design exists and what success means.",
|
|
10584
|
-
expectedContents: ["audience", "task", "success criteria", "trust posture"],
|
|
10585
|
-
howToUse: ["Validate the primary user job before styling", "reject sections that do not serve the task"],
|
|
10586
|
-
mustNot: ["Do not start visual polish before the audience and task are clear"]
|
|
10587
|
-
},
|
|
10588
|
-
generationPlan: {
|
|
10589
|
-
purpose: "Mutation-safe subset accepted by Canvas planning.",
|
|
10590
|
-
expectedContents: ["target outcome", "visual, layout, content, component, motion, responsive, accessibility posture"],
|
|
10591
|
-
howToUse: ["Submit only through canvas-plan.request.json", "repair generationPlanIssues before mutation"],
|
|
10592
|
-
mustNot: ["Do not add handoff-only guide fields to the Canvas generation plan"]
|
|
10593
|
-
},
|
|
10594
|
-
designLanguage: {
|
|
10595
|
-
purpose: "Name the coherent visual direction and token ownership.",
|
|
10596
|
-
expectedContents: ["direction", "style axes", "semantic token source", "approved libraries"],
|
|
10597
|
-
howToUse: ["Keep one design language per task", "align repeated components to semantic tokens"],
|
|
10598
|
-
mustNot: ["Do not mix unrelated visual families inside one surface"]
|
|
10599
|
-
},
|
|
10600
|
-
contentModel: {
|
|
10601
|
-
purpose: "Define real content, message hierarchy, and UI states.",
|
|
10602
|
-
expectedContents: ["primary message", "supporting messages", "states", "loading, empty, and error behavior"],
|
|
10603
|
-
howToUse: ["Use real content first", "plan non-happy-path states before polish"],
|
|
10604
|
-
mustNot: ["Do not ship placeholder copy as product content"]
|
|
10605
|
-
},
|
|
10606
|
-
layoutSystem: {
|
|
10607
|
-
purpose: "Describe page architecture and section rhythm.",
|
|
10608
|
-
expectedContents: ["grid", "containers", "spacing rhythm", "alignment rules"],
|
|
10609
|
-
howToUse: ["Use to place sections and scan units consistently", "verify desktop and mobile structure"],
|
|
10610
|
-
mustNot: ["Do not invent one-off layout rules for repeated sections"]
|
|
10611
|
-
},
|
|
10612
|
-
typographySystem: {
|
|
10613
|
-
purpose: "Define type families, scale, measure, and loading behavior.",
|
|
10614
|
-
expectedContents: ["families", "scale", "measure", "fallback policy", "loading strategy"],
|
|
10615
|
-
howToUse: ["Apply type hierarchy consistently", "avoid layout shift from font loading"],
|
|
10616
|
-
mustNot: ["Do not default to unapproved system stacks for a distinctive design"]
|
|
10617
|
-
},
|
|
10618
|
-
colorSystem: {
|
|
10619
|
-
purpose: "Define semantic color roles and theme behavior.",
|
|
10620
|
-
expectedContents: ["primary roles", "surface roles", "text roles", "state colors"],
|
|
10621
|
-
howToUse: ["Map repeated UI to semantic tokens", "validate contrast in every required theme"],
|
|
10622
|
-
mustNot: ["Do not scatter raw color values across leaf components"]
|
|
10623
|
-
},
|
|
10624
|
-
surfaceSystem: {
|
|
10625
|
-
purpose: "Define material, depth, borders, and background behavior.",
|
|
10626
|
-
expectedContents: ["surface hierarchy", "border rules", "shadow rules", "material effects"],
|
|
10627
|
-
howToUse: ["Use depth only to clarify hierarchy", "align material effects with design vectors"],
|
|
10628
|
-
mustNot: ["Do not turn every content group into a card by default"]
|
|
10629
|
-
},
|
|
10630
|
-
iconSystem: {
|
|
10631
|
-
purpose: "Define icon usage and decorative asset boundaries.",
|
|
10632
|
-
expectedContents: ["icon family", "stroke policy", "labeling rules", "decorative rules"],
|
|
10633
|
-
howToUse: ["Use icons to clarify actions", "keep accessible names on icon-only controls"],
|
|
10634
|
-
mustNot: ["Do not rely on icons as the only explanation for critical actions"]
|
|
10635
|
-
},
|
|
10636
|
-
motionSystem: {
|
|
10637
|
-
purpose: "Define motion that supports comprehension.",
|
|
10638
|
-
expectedContents: ["timing", "interaction moments", "reduced-motion posture", "advanced motion advisory"],
|
|
10639
|
-
howToUse: ["Keep shader, WebGL, and Spline cues advisory", "provide reduced-motion replacements"],
|
|
10640
|
-
mustNot: ["Do not use motion cues to authorize new runtime libraries"]
|
|
10641
|
-
},
|
|
10642
|
-
responsiveSystem: {
|
|
10643
|
-
purpose: "Define authored behavior across desktop, tablet, and mobile.",
|
|
10644
|
-
expectedContents: ["breakpoints", "adaptation rules", "touch policy", "overflow policy"],
|
|
10645
|
-
howToUse: ["Validate the primary action at every viewport", "collapse structure before copy becomes cramped"],
|
|
10646
|
-
mustNot: ["Do not assume desktop layouts naturally scale down"]
|
|
10647
|
-
},
|
|
10648
|
-
accessibilityPolicy: {
|
|
10649
|
-
purpose: "Set accessibility requirements before implementation.",
|
|
10650
|
-
expectedContents: ["WCAG target", "keyboard requirements", "focus policy", "semantic requirements"],
|
|
10651
|
-
howToUse: ["Block release on contrast or keyboard regressions", "validate focus on every interactive state"],
|
|
10652
|
-
mustNot: ["Do not defer accessibility until after visual implementation"]
|
|
10653
|
-
},
|
|
10654
|
-
libraryPolicy: {
|
|
10655
|
-
purpose: "Declare approved implementation libraries and runtime boundaries.",
|
|
10656
|
-
expectedContents: ["components", "icons", "styling", "motion", "threeD"],
|
|
10657
|
-
howToUse: ["Use as the dependency authorization boundary", "keep motion and threeD empty unless separately approved"],
|
|
10658
|
-
mustNot: ["Do not infer WebGL, shader, Spline, or 3D runtime support from advisory motion"]
|
|
10659
|
-
},
|
|
10660
|
-
runtimeBudgets: {
|
|
10661
|
-
purpose: "Set practical limits for sections, actions, interaction latency, and preview cost.",
|
|
10662
|
-
expectedContents: ["section budgets", "action budgets", "latency budgets", "preview notes"],
|
|
10663
|
-
howToUse: ["Use as a constraint during implementation", "validate slow or animation-heavy surfaces against it"],
|
|
10664
|
-
mustNot: ["Do not add decorative weight that violates the budget"]
|
|
10665
|
-
},
|
|
10666
|
-
navigationModel: {
|
|
10667
|
-
purpose: "Implementation-only context for route, tab, overlay, and deep-link ownership.",
|
|
10668
|
-
expectedContents: ["route owner", "deep-link policy", "invalid route fallback", "overlay entry points"],
|
|
10669
|
-
howToUse: ["Use from design-agent-handoff.json when wiring implementation state"],
|
|
10670
|
-
mustNot: ["Do not patch this omitted block into Canvas governance"]
|
|
10671
|
-
},
|
|
10672
|
-
asyncModel: {
|
|
10673
|
-
purpose: "Implementation-only context for loading, restart, cancellation, and URL-owned query state.",
|
|
10674
|
-
expectedContents: ["owner", "load trigger", "restart triggers", "cancellation policy"],
|
|
10675
|
-
howToUse: ["Use when wiring fetch/search state and stale-request handling"],
|
|
10676
|
-
mustNot: ["Do not let components invent independent async ownership"]
|
|
10677
|
-
},
|
|
10678
|
-
performanceModel: {
|
|
10679
|
-
purpose: "Implementation-only context for render hotspots and measurement posture.",
|
|
10680
|
-
expectedContents: ["render hotspots", "stable identity policy", "list strategy", "measurement plan"],
|
|
10681
|
-
howToUse: ["Use before building scan-heavy or motion-heavy surfaces"],
|
|
10682
|
-
mustNot: ["Do not ship heavy interaction surfaces without measurement evidence"]
|
|
9568
|
+
"keyboard-regression",
|
|
9569
|
+
"stale-search-results",
|
|
9570
|
+
"invalid-route-recovery-failure"
|
|
9571
|
+
],
|
|
9572
|
+
warnOn: [
|
|
9573
|
+
"responsive-mismatch",
|
|
9574
|
+
"layout-shift",
|
|
9575
|
+
"spinner-stacking",
|
|
9576
|
+
"scan-surface-jank"
|
|
9577
|
+
]
|
|
9578
|
+
},
|
|
9579
|
+
designVectors: {
|
|
9580
|
+
advancedMotionAdvisory: [
|
|
9581
|
+
"Advisory shader-like gradient depth",
|
|
9582
|
+
"Advisory WebGL-style spatial reveal",
|
|
9583
|
+
"Advisory Spline-style product orbit",
|
|
9584
|
+
"Runtime support: none. Library policy authorization: none."
|
|
9585
|
+
]
|
|
9586
|
+
}
|
|
10683
9587
|
}
|
|
10684
9588
|
};
|
|
10685
|
-
var buildInspiredesignFollowthroughSummary = () => `Read ${INSPIREDESIGN_HANDOFF_FILES.advancedBrief} first, then continue in OpenDevBrowser Canvas with ${INSPIREDESIGN_HANDOFF_FILES.canvasPlanRequest} and ${INSPIREDESIGN_HANDOFF_FILES.designAgentHandoff}, load ${INSPIREDESIGN_HANDOFF_RECOMMENDED_SKILLS[0]} plus ${INSPIREDESIGN_HANDOFF_RECOMMENDED_SKILLS[1]} before implementation, and note that any supplied reference URL already uses captureMode=deep.`;
|
|
10686
|
-
var buildInspiredesignNextStep = () => `Read ${INSPIREDESIGN_HANDOFF_FILES.advancedBrief} first. ${INSPIREDESIGN_HANDOFF_GUIDANCE.prepareCanvasPlanRequest} Then run ${INSPIREDESIGN_HANDOFF_COMMANDS.continueInCanvas}, confirm planStatus=accepted, then patch only the governance blocks listed in ${INSPIREDESIGN_HANDOFF_FILES.designAgentHandoff}.`;
|
|
10687
9589
|
|
|
10688
9590
|
// skills/opendevbrowser-design-agent/assets/templates/inspiredesign-advanced-brief.v1.json
|
|
10689
9591
|
var inspiredesign_advanced_brief_v1_default = {
|
|
@@ -14287,10 +13189,111 @@ var createSuccessHandoff = (followthroughSummary, suggestedNextAction, suggested
|
|
|
14287
13189
|
});
|
|
14288
13190
|
var cliExample = (command, args = "") => `npx opendevbrowser ${command}${args ? ` ${args}` : ""}`;
|
|
14289
13191
|
var quoteCliValue = (value) => JSON.stringify(value);
|
|
14290
|
-
var
|
|
14291
|
-
"
|
|
14292
|
-
|
|
14293
|
-
|
|
13192
|
+
var GATED_PROVIDER_REASON_CODES = /* @__PURE__ */ new Set([
|
|
13193
|
+
"auth_required",
|
|
13194
|
+
"token_required",
|
|
13195
|
+
"challenge_detected"
|
|
13196
|
+
]);
|
|
13197
|
+
var buildResearchRerunCommand = (input, options = {}) => {
|
|
13198
|
+
const browserMode = options.browserMode ?? input.browserMode ?? "managed";
|
|
13199
|
+
const useCookies = options.useCookies ? " --use-cookies" : "";
|
|
13200
|
+
const challengeMode = options.challengeAutomationMode ? ` --challenge-automation-mode ${options.challengeAutomationMode}` : "";
|
|
13201
|
+
return cliExample(
|
|
13202
|
+
"research run",
|
|
13203
|
+
`--topic ${quoteCliValue(input.topic)} --days 14 --sources web,community --browser-mode ${browserMode}${useCookies}${challengeMode} --mode json --output-format json`
|
|
13204
|
+
);
|
|
13205
|
+
};
|
|
13206
|
+
var isJsonRecord3 = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
13207
|
+
var readFailureReasonCode = (failure) => {
|
|
13208
|
+
return failure.error.reasonCode ?? normalizeProviderReasonCode({
|
|
13209
|
+
code: failure.error.code,
|
|
13210
|
+
message: failure.error.message,
|
|
13211
|
+
details: failure.error.details
|
|
13212
|
+
}) ?? null;
|
|
13213
|
+
};
|
|
13214
|
+
var readDiagnosticReasonCode = (diagnostic) => {
|
|
13215
|
+
const reasonCode = diagnostic.reasonCode ?? diagnostic.browserFallbackReasonCode;
|
|
13216
|
+
return isProviderReasonCode(reasonCode) && GATED_PROVIDER_REASON_CODES.has(reasonCode) ? reasonCode : null;
|
|
13217
|
+
};
|
|
13218
|
+
var cookieDiagnosticShowsAvailableCookies = (diagnostic) => {
|
|
13219
|
+
return diagnostic.available === true || typeof diagnostic.loaded === "number" && diagnostic.loaded > 0 || typeof diagnostic.injected === "number" && diagnostic.injected > 0 || typeof diagnostic.verifiedCount === "number" && diagnostic.verifiedCount > 0;
|
|
13220
|
+
};
|
|
13221
|
+
var addProviderSignal = (signal, provider, reasonCode) => {
|
|
13222
|
+
if (provider) signal.providers.push(provider);
|
|
13223
|
+
if (reasonCode) signal.reasonCodes.push(reasonCode);
|
|
13224
|
+
};
|
|
13225
|
+
var readFailureCookieDiagnostics = (failure) => {
|
|
13226
|
+
const candidate = failure.error.details?.cookieDiagnostics;
|
|
13227
|
+
return isJsonRecord3(candidate) ? candidate : null;
|
|
13228
|
+
};
|
|
13229
|
+
var emptyResearchGatedProviderSignal = () => ({
|
|
13230
|
+
providers: [],
|
|
13231
|
+
reasonCodes: [],
|
|
13232
|
+
useCookies: false
|
|
13233
|
+
});
|
|
13234
|
+
var normalizeResearchGatedProviderSignal = (signal) => {
|
|
13235
|
+
return signal.providers.length > 0 || signal.reasonCodes.length > 0 ? {
|
|
13236
|
+
providers: [...new Set(signal.providers)].sort(),
|
|
13237
|
+
reasonCodes: [...new Set(signal.reasonCodes)].sort(),
|
|
13238
|
+
useCookies: signal.useCookies
|
|
13239
|
+
} : null;
|
|
13240
|
+
};
|
|
13241
|
+
var mergeResearchGatedProviderSignals = (signals) => {
|
|
13242
|
+
const merged = emptyResearchGatedProviderSignal();
|
|
13243
|
+
for (const signal of signals) {
|
|
13244
|
+
merged.providers.push(...signal.providers);
|
|
13245
|
+
merged.reasonCodes.push(...signal.reasonCodes);
|
|
13246
|
+
merged.useCookies = merged.useCookies || signal.useCookies;
|
|
13247
|
+
}
|
|
13248
|
+
return merged;
|
|
13249
|
+
};
|
|
13250
|
+
var detectResearchFailureSignals = (failures) => {
|
|
13251
|
+
const signal = emptyResearchGatedProviderSignal();
|
|
13252
|
+
for (const failure of failures) {
|
|
13253
|
+
const reasonCode = readFailureReasonCode(failure);
|
|
13254
|
+
const isGatedFailure = Boolean(reasonCode && GATED_PROVIDER_REASON_CODES.has(reasonCode));
|
|
13255
|
+
if (isGatedFailure) {
|
|
13256
|
+
addProviderSignal(signal, failure.provider, reasonCode);
|
|
13257
|
+
const diagnostic = readFailureCookieDiagnostics(failure);
|
|
13258
|
+
signal.useCookies = signal.useCookies || Boolean(diagnostic && cookieDiagnosticShowsAvailableCookies(diagnostic));
|
|
13259
|
+
}
|
|
13260
|
+
}
|
|
13261
|
+
return signal;
|
|
13262
|
+
};
|
|
13263
|
+
var detectResearchCookieSignals = (diagnostics) => {
|
|
13264
|
+
const signal = emptyResearchGatedProviderSignal();
|
|
13265
|
+
for (const diagnostic of diagnostics) {
|
|
13266
|
+
const reasonCode = readDiagnosticReasonCode(diagnostic);
|
|
13267
|
+
const isGatedDiagnostic = Boolean(reasonCode || diagnostic.policy === "required");
|
|
13268
|
+
if (isGatedDiagnostic) {
|
|
13269
|
+
addProviderSignal(signal, typeof diagnostic.provider === "string" ? diagnostic.provider : void 0, reasonCode);
|
|
13270
|
+
signal.useCookies = signal.useCookies || cookieDiagnosticShowsAvailableCookies(diagnostic);
|
|
13271
|
+
}
|
|
13272
|
+
}
|
|
13273
|
+
return signal;
|
|
13274
|
+
};
|
|
13275
|
+
var detectResearchChallengeSignals = (diagnostics) => {
|
|
13276
|
+
const signal = emptyResearchGatedProviderSignal();
|
|
13277
|
+
for (const diagnostic of diagnostics) {
|
|
13278
|
+
const reasonCode = readDiagnosticReasonCode(diagnostic);
|
|
13279
|
+
if (reasonCode || diagnostic.blockerType === "auth_required" || diagnostic.blockerType === "anti_bot_challenge") {
|
|
13280
|
+
addProviderSignal(signal, typeof diagnostic.provider === "string" ? diagnostic.provider : void 0, reasonCode);
|
|
13281
|
+
}
|
|
13282
|
+
}
|
|
13283
|
+
return signal;
|
|
13284
|
+
};
|
|
13285
|
+
var detectResearchGatedProviderSignal = (input) => {
|
|
13286
|
+
return normalizeResearchGatedProviderSignal(mergeResearchGatedProviderSignals([
|
|
13287
|
+
detectResearchFailureSignals(input.failures ?? []),
|
|
13288
|
+
detectResearchCookieSignals(input.cookieDiagnostics ?? []),
|
|
13289
|
+
detectResearchChallengeSignals(input.challengeOrchestration ?? [])
|
|
13290
|
+
]));
|
|
13291
|
+
};
|
|
13292
|
+
var buildResearchRecoveryRerunCommand = (input, signal) => buildResearchRerunCommand(input, {
|
|
13293
|
+
browserMode: "extension",
|
|
13294
|
+
useCookies: signal.useCookies,
|
|
13295
|
+
challengeAutomationMode: "browser_with_helper"
|
|
13296
|
+
});
|
|
14294
13297
|
var buildShoppingRerunCommand = (input) => {
|
|
14295
13298
|
const providers = input.providers?.length ? ` --providers ${input.providers.join(",")}` : " --providers shopping/bestbuy,shopping/ebay";
|
|
14296
13299
|
const budget = typeof input.budget === "number" ? ` --budget ${input.budget}` : "";
|
|
@@ -14318,23 +13321,43 @@ var buildMacroResolveArgs = (input, options) => {
|
|
|
14318
13321
|
const defaultProvider = input.defaultProvider ? ` --default-provider ${input.defaultProvider}` : "";
|
|
14319
13322
|
const execute = options?.execute ? " --execute" : "";
|
|
14320
13323
|
const browserMode = options?.browserMode ? ` --browser-mode ${options.browserMode}` : "";
|
|
13324
|
+
const useCookies = options?.useCookies ? " --use-cookies" : "";
|
|
14321
13325
|
const challenge = options?.challengeAutomationMode ? ` --challenge-automation-mode ${options.challengeAutomationMode}` : "";
|
|
13326
|
+
const cookiePolicy = options?.cookiePolicyOverride ? ` --cookie-policy ${options.cookiePolicyOverride}` : "";
|
|
14322
13327
|
const outputFormat = options?.includeOutputFormat === false ? "" : " --output-format json";
|
|
14323
|
-
return `--expression ${quoteCliValue(input.expression)}${defaultProvider}${execute}${browserMode}${challenge}${outputFormat}`;
|
|
13328
|
+
return `--expression ${quoteCliValue(input.expression)}${defaultProvider}${execute}${browserMode}${useCookies}${cookiePolicy}${challenge}${outputFormat}`;
|
|
14324
13329
|
};
|
|
14325
13330
|
var buildMacroPreviewCommand = (input) => cliExample("macro-resolve", buildMacroResolveArgs(input));
|
|
14326
13331
|
var buildMacroExecuteCommand = (input, challengeAutomationMode, browserMode) => cliExample("macro-resolve", buildMacroResolveArgs(input, {
|
|
14327
13332
|
execute: true,
|
|
14328
13333
|
browserMode,
|
|
13334
|
+
...browserMode === "extension" ? { useCookies: true, cookiePolicyOverride: "required" } : {},
|
|
14329
13335
|
challengeAutomationMode
|
|
14330
13336
|
}));
|
|
14331
|
-
var
|
|
13337
|
+
var buildResearchGatedSuccessHandoff = (input, signal) => {
|
|
13338
|
+
const recoveryCommand = buildResearchRecoveryRerunCommand(input, signal);
|
|
13339
|
+
const providers = signal.providers.length > 0 ? signal.providers.join(", ") : "gated providers";
|
|
13340
|
+
const cookieNote = signal.useCookies ? " The command includes --use-cookies because cookie diagnostics show available cookies." : " Add --use-cookies only when legitimate provider cookies are available.";
|
|
13341
|
+
return createSuccessHandoff(
|
|
13342
|
+
`Review ranked records, artifact metadata, and gated-provider diagnostics for ${providers} before publishing claims.`,
|
|
13343
|
+
`Open the returned artifact path, inspect records.json, context.json, meta.json, and report.md, then rerun ${recoveryCommand} only with a user-authorized signed-in relay session.${cookieNote}`,
|
|
13344
|
+
[
|
|
13345
|
+
{ reason: "Check records.json, context.json, meta.json, failures, and cookie diagnostics before using the result as evidence." },
|
|
13346
|
+
{
|
|
13347
|
+
reason: "Rerun with an existing signed-in extension session and browser-scoped challenge assistance when gated providers blocked useful evidence.",
|
|
13348
|
+
command: recoveryCommand
|
|
13349
|
+
},
|
|
13350
|
+
{ reason: "Keep SERPs discovery-only and publish only claims supported by destination records that passed review." }
|
|
13351
|
+
]
|
|
13352
|
+
);
|
|
13353
|
+
};
|
|
13354
|
+
var buildResearchDefaultSuccessHandoff = (input) => {
|
|
14332
13355
|
const rerunCommand = buildResearchRerunCommand(input);
|
|
14333
13356
|
return createSuccessHandoff(
|
|
14334
|
-
"Review
|
|
14335
|
-
`Open the returned artifact path, inspect
|
|
13357
|
+
"Review ranked records, artifact metadata, and source support before turning the result into a publishable claim.",
|
|
13358
|
+
`Open the returned artifact path, inspect records.json, context.json, meta.json, and report.md, then rerun ${rerunCommand} if you need a tighter evidence set.`,
|
|
14336
13359
|
[
|
|
14337
|
-
{ reason: "Check which records actually support the final claim." },
|
|
13360
|
+
{ reason: "Check which ranked records and artifact metadata actually support the final claim." },
|
|
14338
13361
|
{
|
|
14339
13362
|
reason: "Rerun with explicit sources and a narrower timebox if the evidence set is still too broad.",
|
|
14340
13363
|
command: rerunCommand
|
|
@@ -14342,6 +13365,10 @@ var buildResearchSuccessHandoff = (input) => {
|
|
|
14342
13365
|
]
|
|
14343
13366
|
);
|
|
14344
13367
|
};
|
|
13368
|
+
var buildResearchSuccessHandoff = (input) => {
|
|
13369
|
+
const signal = detectResearchGatedProviderSignal(input);
|
|
13370
|
+
return signal ? buildResearchGatedSuccessHandoff(input, signal) : buildResearchDefaultSuccessHandoff(input);
|
|
13371
|
+
};
|
|
14345
13372
|
var buildShoppingSuccessHandoff = (input) => {
|
|
14346
13373
|
const rerunCommand = buildShoppingRerunCommand(input);
|
|
14347
13374
|
return createSuccessHandoff(
|
|
@@ -14485,19 +13512,304 @@ var compactResearchLines = (records, meta) => {
|
|
|
14485
13512
|
if (records.length === 0) {
|
|
14486
13513
|
const summary = primaryConstraintSummaryFromMeta(meta);
|
|
14487
13514
|
return summary ? [
|
|
14488
|
-
"No
|
|
13515
|
+
"No usable research findings were available.",
|
|
14489
13516
|
`Primary constraint: ${summary}`
|
|
14490
|
-
] : ["No
|
|
13517
|
+
] : ["No usable research findings were available."];
|
|
14491
13518
|
}
|
|
14492
13519
|
return records.slice(0, 10).map((record, index) => {
|
|
14493
13520
|
const title = record.title ?? record.url ?? record.provider;
|
|
14494
13521
|
const engagement = record.engagement.likes + record.engagement.comments + record.engagement.upvotes;
|
|
14495
|
-
return `${index + 1}. ${title} (${record.source}
|
|
13522
|
+
return `${index + 1}. ${title} (${record.source}; ${record.provider}) score=${record.confidence.toFixed(2)} engagement=${engagement}`;
|
|
13523
|
+
});
|
|
13524
|
+
};
|
|
13525
|
+
var RESEARCH_REPORT_LIMITS = {
|
|
13526
|
+
findings: 10,
|
|
13527
|
+
sources: 20,
|
|
13528
|
+
failures: 10,
|
|
13529
|
+
excerptCharacters: 240,
|
|
13530
|
+
failureMessageCharacters: 240
|
|
13531
|
+
};
|
|
13532
|
+
var RESEARCH_REPORT_FILE_NAMES = [
|
|
13533
|
+
"summary.md",
|
|
13534
|
+
"report.md",
|
|
13535
|
+
"records.json",
|
|
13536
|
+
"context.json",
|
|
13537
|
+
"meta.json",
|
|
13538
|
+
"bundle-manifest.json"
|
|
13539
|
+
];
|
|
13540
|
+
var plainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
|
|
13541
|
+
var researchTitle = (record) => record.title ?? record.url ?? record.provider;
|
|
13542
|
+
var normalizedInlineText = (content) => content?.replace(/\s+/g, " ").trim() ?? "";
|
|
13543
|
+
var boundedInlineText = (args) => {
|
|
13544
|
+
const normalized = normalizedInlineText(args.content);
|
|
13545
|
+
if (!normalized) {
|
|
13546
|
+
return args.fallback;
|
|
13547
|
+
}
|
|
13548
|
+
if (normalized.length <= args.limit) {
|
|
13549
|
+
return normalized;
|
|
13550
|
+
}
|
|
13551
|
+
return `${normalized.slice(0, args.limit)} [truncated; see ${args.target}]`;
|
|
13552
|
+
};
|
|
13553
|
+
var researchExcerpt = (content) => boundedInlineText({
|
|
13554
|
+
content,
|
|
13555
|
+
fallback: "No content excerpt was available.",
|
|
13556
|
+
limit: RESEARCH_REPORT_LIMITS.excerptCharacters,
|
|
13557
|
+
target: "records.json for full content"
|
|
13558
|
+
});
|
|
13559
|
+
var researchFailureMessage = (content) => boundedInlineText({
|
|
13560
|
+
content,
|
|
13561
|
+
fallback: "provider failure",
|
|
13562
|
+
limit: RESEARCH_REPORT_LIMITS.failureMessageCharacters,
|
|
13563
|
+
target: "meta.json"
|
|
13564
|
+
});
|
|
13565
|
+
var limitedCount = (total, limit) => Math.min(total, limit);
|
|
13566
|
+
var omissionLine = (args) => {
|
|
13567
|
+
const omitted = args.total - limitedCount(args.total, args.limit);
|
|
13568
|
+
if (omitted <= 0) {
|
|
13569
|
+
return [];
|
|
13570
|
+
}
|
|
13571
|
+
const noun = omitted === 1 ? args.singular : args.plural;
|
|
13572
|
+
return [`- ${omitted} more ${noun} omitted from this report; see ${args.target} for the complete dataset.`];
|
|
13573
|
+
};
|
|
13574
|
+
var researchFindingsLines = (records) => records.length === 0 ? ["- No usable findings were available."] : [
|
|
13575
|
+
...records.slice(0, RESEARCH_REPORT_LIMITS.findings).flatMap((record, index) => [
|
|
13576
|
+
`### ${index + 1}. ${researchTitle(record)}`,
|
|
13577
|
+
`- Source: ${record.source}`,
|
|
13578
|
+
`- Provider: ${record.provider}`,
|
|
13579
|
+
`- URL: ${record.url ?? "not provided"}`,
|
|
13580
|
+
`- Published: ${record.timestamp}`,
|
|
13581
|
+
`- Confidence: ${record.confidence.toFixed(2)}`,
|
|
13582
|
+
`- Evidence: ${researchExcerpt(record.content)}`
|
|
13583
|
+
]),
|
|
13584
|
+
...omissionLine({
|
|
13585
|
+
total: records.length,
|
|
13586
|
+
limit: RESEARCH_REPORT_LIMITS.findings,
|
|
13587
|
+
singular: "finding",
|
|
13588
|
+
plural: "findings",
|
|
13589
|
+
target: "records.json"
|
|
13590
|
+
})
|
|
13591
|
+
];
|
|
13592
|
+
var researchSourcesLines = (records) => records.length === 0 ? ["- No sources available."] : [
|
|
13593
|
+
...records.slice(0, RESEARCH_REPORT_LIMITS.sources).map((record) => `- ${researchTitle(record)}: ${record.url ?? "URL not provided"}`),
|
|
13594
|
+
...omissionLine({
|
|
13595
|
+
total: records.length,
|
|
13596
|
+
limit: RESEARCH_REPORT_LIMITS.sources,
|
|
13597
|
+
singular: "source",
|
|
13598
|
+
plural: "sources",
|
|
13599
|
+
target: "records.json"
|
|
13600
|
+
})
|
|
13601
|
+
];
|
|
13602
|
+
var researchReasonLine = (metrics) => {
|
|
13603
|
+
const reasons = Object.entries(plainObject(metrics.sanitized_reason_distribution)).map(([reason, count]) => `${reason}: ${String(count)}`);
|
|
13604
|
+
return reasons.length === 0 ? [] : [`- Sanitized record reasons: ${reasons.join(", ")}`];
|
|
13605
|
+
};
|
|
13606
|
+
var deadEndSearchFailures = (failures) => {
|
|
13607
|
+
if (!Array.isArray(failures)) return [];
|
|
13608
|
+
return failures.filter((failure) => {
|
|
13609
|
+
const record = plainObject(failure);
|
|
13610
|
+
const error = plainObject(record.error);
|
|
13611
|
+
const details = plainObject(error.details);
|
|
13612
|
+
return details.fallbackOutputReason === "research_dead_end_shell";
|
|
14496
13613
|
});
|
|
14497
13614
|
};
|
|
13615
|
+
var deadEndSearchFailureCount = (meta) => deadEndSearchFailures(meta.failures).length;
|
|
13616
|
+
var rejectedCandidatesFromMeta = (meta) => Array.isArray(meta.rejected_candidates) ? meta.rejected_candidates.map(plainObject).filter((candidate) => Object.keys(candidate).length > 0) : [];
|
|
13617
|
+
var rejectedCandidateCount = (meta) => {
|
|
13618
|
+
const metrics = plainObject(meta.metrics);
|
|
13619
|
+
if (typeof metrics.rejected_candidate_count === "number") {
|
|
13620
|
+
return metrics.rejected_candidate_count;
|
|
13621
|
+
}
|
|
13622
|
+
const sanitized = typeof metrics.sanitized_records === "number" ? metrics.sanitized_records : 0;
|
|
13623
|
+
return sanitized + deadEndSearchFailureCount(meta);
|
|
13624
|
+
};
|
|
13625
|
+
var deadEndSearchFailureLines = (meta) => {
|
|
13626
|
+
const failures = deadEndSearchFailures(meta.failures);
|
|
13627
|
+
if (failures.length === 0) return [];
|
|
13628
|
+
return [`- Dead-end search failures: ${failures.length}`];
|
|
13629
|
+
};
|
|
13630
|
+
var researchRejectedCandidateSummary = (candidate) => {
|
|
13631
|
+
const reason = typeof candidate.reason === "string" ? candidate.reason : "unknown_reason";
|
|
13632
|
+
const provider = typeof candidate.provider === "string" ? candidate.provider : "unknown_provider";
|
|
13633
|
+
const source = typeof candidate.source === "string" ? candidate.source : "unknown_source";
|
|
13634
|
+
const status = typeof candidate.replacement_status === "string" ? candidate.replacement_status : "not_recorded";
|
|
13635
|
+
const retrievalPath = typeof candidate.retrievalPath === "string" ? `; path=${candidate.retrievalPath}` : "";
|
|
13636
|
+
const url = typeof candidate.url === "string" ? candidate.url : "URL not recorded";
|
|
13637
|
+
return `${reason} from ${provider} (${source}; ${status}${retrievalPath}): ${url}`;
|
|
13638
|
+
};
|
|
13639
|
+
var researchFailureSummary = (failure) => {
|
|
13640
|
+
const record = plainObject(failure);
|
|
13641
|
+
const error = plainObject(record.error);
|
|
13642
|
+
const provider = typeof record.provider === "string" ? record.provider : "unknown";
|
|
13643
|
+
const source = typeof record.source === "string" ? record.source : "unknown";
|
|
13644
|
+
const reason = typeof error.reasonCode === "string" ? `${error.reasonCode}: ` : "";
|
|
13645
|
+
const message = researchFailureMessage(typeof error.message === "string" ? error.message : void 0);
|
|
13646
|
+
return `${provider} (${source}): ${reason}${message}`;
|
|
13647
|
+
};
|
|
13648
|
+
var researchFailureLines = (failures) => {
|
|
13649
|
+
if (!Array.isArray(failures) || failures.length === 0) {
|
|
13650
|
+
return [];
|
|
13651
|
+
}
|
|
13652
|
+
const summaries = failures.slice(0, RESEARCH_REPORT_LIMITS.failures).map(researchFailureSummary);
|
|
13653
|
+
const omitted = failures.length - summaries.length;
|
|
13654
|
+
const noun = omitted === 1 ? "failure" : "failures";
|
|
13655
|
+
const suffix = omitted > 0 ? `; ${omitted} more provider ${noun} omitted from this report; see meta.json` : "";
|
|
13656
|
+
return [`- Provider failures: ${summaries.join("; ")}${suffix}`];
|
|
13657
|
+
};
|
|
13658
|
+
var researchGapLines = (meta) => {
|
|
13659
|
+
const metrics = plainObject(meta.metrics);
|
|
13660
|
+
const details = [
|
|
13661
|
+
typeof metrics.final_records === "number" ? `- Final records reported by workflow: ${metrics.final_records}` : "",
|
|
13662
|
+
typeof metrics.sanitized_records === "number" ? `- Sanitized records excluded: ${metrics.sanitized_records}` : "",
|
|
13663
|
+
...researchReasonLine(metrics),
|
|
13664
|
+
...researchFailureLines(meta.failures)
|
|
13665
|
+
].filter(Boolean);
|
|
13666
|
+
const constraint = primaryConstraintSummaryFromMeta(meta);
|
|
13667
|
+
const fallback = "- No provider limitations or sanitization gaps were reported.";
|
|
13668
|
+
const gapDetails = details.length > 0 || constraint ? details : [fallback];
|
|
13669
|
+
return [
|
|
13670
|
+
"## Confidence and Gaps",
|
|
13671
|
+
...constraint ? [`- Primary constraint: ${constraint}`] : [],
|
|
13672
|
+
...gapDetails
|
|
13673
|
+
];
|
|
13674
|
+
};
|
|
13675
|
+
var researchSearchDirectionLines = (meta) => {
|
|
13676
|
+
const selection = plainObject(meta.selection);
|
|
13677
|
+
const sources = Array.isArray(selection.resolved_sources) ? selection.resolved_sources.map(String).join(", ") : "not recorded";
|
|
13678
|
+
return [
|
|
13679
|
+
"## Search Direction",
|
|
13680
|
+
`- Source families searched: ${sources}`,
|
|
13681
|
+
"- Direction: Follow accepted destination pages from provider/search output before synthesis."
|
|
13682
|
+
];
|
|
13683
|
+
};
|
|
13684
|
+
var researchSourceFamilies = (meta) => {
|
|
13685
|
+
const sources = plainObject(meta.selection).resolved_sources;
|
|
13686
|
+
return Array.isArray(sources) ? sources.map(String) : [];
|
|
13687
|
+
};
|
|
13688
|
+
var researchCandidateTriageSchema = () => ({
|
|
13689
|
+
url: "",
|
|
13690
|
+
rank: 0,
|
|
13691
|
+
engine: "",
|
|
13692
|
+
query: "",
|
|
13693
|
+
source_family: "",
|
|
13694
|
+
title: "",
|
|
13695
|
+
status: "pending|accepted|rejected",
|
|
13696
|
+
blocker_notes: "",
|
|
13697
|
+
rejection_reason: "",
|
|
13698
|
+
replacement_url: "",
|
|
13699
|
+
retrieval_notes: "",
|
|
13700
|
+
extraction_status: "pending|fetched|blocked|shell|stale|irrelevant"
|
|
13701
|
+
});
|
|
13702
|
+
var researchCandidateTriageLines = (records, meta) => {
|
|
13703
|
+
const rejected = rejectedCandidateCount(meta);
|
|
13704
|
+
return [
|
|
13705
|
+
"## Candidate Triage",
|
|
13706
|
+
`- Accepted destination records: ${records.length}`,
|
|
13707
|
+
`- Rejected shell or dead-end candidates: ${rejected}`,
|
|
13708
|
+
"- Rejection policy: search pages, login/account pages, privacy/cookie pages, JavaScript shells, not-found pages, and unsupported shells are not final evidence."
|
|
13709
|
+
];
|
|
13710
|
+
};
|
|
13711
|
+
var researchRejectedCandidateLines = (meta) => {
|
|
13712
|
+
const rejectedCandidates = rejectedCandidatesFromMeta(meta);
|
|
13713
|
+
const rejectionLines = [
|
|
13714
|
+
...researchReasonLine(plainObject(meta.metrics)),
|
|
13715
|
+
...rejectedCandidates.slice(0, RESEARCH_REPORT_LIMITS.failures).map((candidate) => `- Rejected candidate: ${researchRejectedCandidateSummary(candidate)}`),
|
|
13716
|
+
...deadEndSearchFailureLines(meta)
|
|
13717
|
+
];
|
|
13718
|
+
return [
|
|
13719
|
+
"## Rejected Candidates",
|
|
13720
|
+
...rejectionLines,
|
|
13721
|
+
...rejectionLines.length === 0 ? ["- No rejected candidate distribution was reported."] : []
|
|
13722
|
+
];
|
|
13723
|
+
};
|
|
13724
|
+
var researchDeepDiveLines = (records) => [
|
|
13725
|
+
"## Deep Dives",
|
|
13726
|
+
...records.length === 0 ? ["- No destination pages passed the evidence gate."] : records.slice(0, RESEARCH_REPORT_LIMITS.sources).map((record) => {
|
|
13727
|
+
const retrievalPath = typeof record.attributes.retrievalPath === "string" ? record.attributes.retrievalPath : "";
|
|
13728
|
+
const prefix = retrievalPath.includes(":fetch:") ? "Opened destination evidence" : "Accepted evidence record";
|
|
13729
|
+
return `- ${prefix}: ${record.url ?? researchTitle(record)}`;
|
|
13730
|
+
})
|
|
13731
|
+
];
|
|
13732
|
+
var researchSynthesisFeedbackText = (records, meta) => {
|
|
13733
|
+
const rejected = rejectedCandidateCount(meta);
|
|
13734
|
+
return records.length === 0 || rejected > records.length ? "Continue with remaining public destination candidates or narrow the query; use auth/cookies only when a selected evidence page itself requires authorized access." : "Synthesize only the accepted destination evidence and cite records.json for full source text.";
|
|
13735
|
+
};
|
|
13736
|
+
var researchSynthesisFeedbackLines = (records, meta) => {
|
|
13737
|
+
return ["## Synthesis Feedback", `- Next step: ${researchSynthesisFeedbackText(records, meta)}`];
|
|
13738
|
+
};
|
|
13739
|
+
var researchContextPayload = (args) => ({
|
|
13740
|
+
topic: args.topic,
|
|
13741
|
+
timebox: plainObject(args.meta.timebox),
|
|
13742
|
+
source_families: researchSourceFamilies(args.meta),
|
|
13743
|
+
evidence_gate: {
|
|
13744
|
+
status: "pending_review",
|
|
13745
|
+
reviewed_artifacts: []
|
|
13746
|
+
},
|
|
13747
|
+
artifact_files: RESEARCH_REPORT_FILE_NAMES,
|
|
13748
|
+
source_ledger: args.records.map((record) => ({
|
|
13749
|
+
title: researchTitle(record),
|
|
13750
|
+
url: record.url,
|
|
13751
|
+
source_family: record.source,
|
|
13752
|
+
provider: record.provider
|
|
13753
|
+
})),
|
|
13754
|
+
search_direction_notes: researchSearchDirectionLines(args.meta),
|
|
13755
|
+
candidate_triage_schema: researchCandidateTriageSchema(),
|
|
13756
|
+
highlights: args.lines,
|
|
13757
|
+
records: args.records,
|
|
13758
|
+
candidate_triage: {
|
|
13759
|
+
accepted_destination_records: args.records.length,
|
|
13760
|
+
rejected_shell_or_dead_end_candidates: rejectedCandidateCount(args.meta)
|
|
13761
|
+
},
|
|
13762
|
+
rejected_candidates: rejectedCandidatesFromMeta(args.meta),
|
|
13763
|
+
deep_dive_pages: args.records.map((record) => ({
|
|
13764
|
+
title: researchTitle(record),
|
|
13765
|
+
url: record.url,
|
|
13766
|
+
provider: record.provider,
|
|
13767
|
+
source: record.source,
|
|
13768
|
+
retrievalPath: record.attributes.retrievalPath
|
|
13769
|
+
})),
|
|
13770
|
+
iteration_log: researchSearchDirectionLines(args.meta),
|
|
13771
|
+
synthesis_feedback: researchSynthesisFeedbackText(args.records, args.meta),
|
|
13772
|
+
meta: args.meta
|
|
13773
|
+
});
|
|
13774
|
+
var researchArtifactFileLines = () => [
|
|
13775
|
+
"## Report Files",
|
|
13776
|
+
...RESEARCH_REPORT_FILE_NAMES.map((fileName) => `- ${fileName}`)
|
|
13777
|
+
];
|
|
13778
|
+
var buildResearchReport = (args) => [
|
|
13779
|
+
"# Research Report",
|
|
13780
|
+
"",
|
|
13781
|
+
"## Executive Summary",
|
|
13782
|
+
`- Topic: ${args.topic}`,
|
|
13783
|
+
`- Usable findings: ${args.records.length}`,
|
|
13784
|
+
`- Findings shown in report: ${limitedCount(args.records.length, RESEARCH_REPORT_LIMITS.findings)}`,
|
|
13785
|
+
`- Sources shown in report: ${limitedCount(args.records.length, RESEARCH_REPORT_LIMITS.sources)}`,
|
|
13786
|
+
"- Final output: Usable records are persisted in records.json.",
|
|
13787
|
+
"- Diagnostics: Run metadata, failures, and constraints are persisted in meta.json; this report summarizes the bounded inline subset.",
|
|
13788
|
+
"",
|
|
13789
|
+
...researchArtifactFileLines(),
|
|
13790
|
+
"",
|
|
13791
|
+
...researchSearchDirectionLines(args.meta),
|
|
13792
|
+
"",
|
|
13793
|
+
...researchCandidateTriageLines(args.records, args.meta),
|
|
13794
|
+
"",
|
|
13795
|
+
...researchRejectedCandidateLines(args.meta),
|
|
13796
|
+
"",
|
|
13797
|
+
...researchDeepDiveLines(args.records),
|
|
13798
|
+
"",
|
|
13799
|
+
...researchSynthesisFeedbackLines(args.records, args.meta),
|
|
13800
|
+
"",
|
|
13801
|
+
"## Findings",
|
|
13802
|
+
...researchFindingsLines(args.records),
|
|
13803
|
+
"",
|
|
13804
|
+
...researchGapLines(args.meta),
|
|
13805
|
+
"",
|
|
13806
|
+
"## Sources",
|
|
13807
|
+
...researchSourcesLines(args.records)
|
|
13808
|
+
].join("\n");
|
|
14498
13809
|
var renderResearch = (args) => {
|
|
14499
13810
|
const lines = compactResearchLines(args.records, args.meta);
|
|
14500
13811
|
const summary = lines.join("\n");
|
|
13812
|
+
const report = buildResearchReport(args);
|
|
14501
13813
|
const markdown = [
|
|
14502
13814
|
`# Research: ${args.topic}`,
|
|
14503
13815
|
"",
|
|
@@ -14508,14 +13820,15 @@ var renderResearch = (args) => {
|
|
|
14508
13820
|
JSON.stringify(args.meta, null, 2),
|
|
14509
13821
|
"```"
|
|
14510
13822
|
].join("\n");
|
|
14511
|
-
const contextPayload = {
|
|
13823
|
+
const contextPayload = researchContextPayload({
|
|
14512
13824
|
topic: args.topic,
|
|
14513
|
-
|
|
13825
|
+
lines,
|
|
14514
13826
|
records: args.records,
|
|
14515
13827
|
meta: args.meta
|
|
14516
|
-
};
|
|
13828
|
+
});
|
|
14517
13829
|
const files = [
|
|
14518
13830
|
{ path: "summary.md", content: markdown },
|
|
13831
|
+
{ path: "report.md", content: report },
|
|
14519
13832
|
{ path: "records.json", content: { records: args.records } },
|
|
14520
13833
|
{ path: "context.json", content: contextPayload },
|
|
14521
13834
|
{ path: "meta.json", content: args.meta }
|
|
@@ -15636,14 +14949,14 @@ import { createHash as createHash5 } from "crypto";
|
|
|
15636
14949
|
var DEFAULT_SHOPPING_SEARCH_LIMIT = 8;
|
|
15637
14950
|
var SHOPPING_FETCH_RECOVERY_LIMIT = 2;
|
|
15638
14951
|
var SEARCH_INDEX_RETRIEVAL_PATHS = /* @__PURE__ */ new Set(["shopping:search:index", "shopping:search:link"]);
|
|
15639
|
-
var
|
|
14952
|
+
var isJsonRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
15640
14953
|
var isFiniteNumber = (value) => typeof value === "number" && Number.isFinite(value);
|
|
15641
14954
|
var isProviderSource = (value) => value === "web" || value === "community" || value === "social" || value === "shopping";
|
|
15642
|
-
var isTraceContext = (value) =>
|
|
15643
|
-
var isProviderError2 = (value) =>
|
|
15644
|
-
var isNormalizedRecord = (value) =>
|
|
15645
|
-
var isProviderFailureEntry = (value) =>
|
|
15646
|
-
var isProviderAggregateResult = (value) =>
|
|
14955
|
+
var isTraceContext = (value) => isJsonRecord4(value) && typeof value.requestId === "string" && typeof value.ts === "string" && (value.sessionId === void 0 || typeof value.sessionId === "string") && (value.targetId === void 0 || typeof value.targetId === "string") && (value.provider === void 0 || typeof value.provider === "string");
|
|
14956
|
+
var isProviderError2 = (value) => isJsonRecord4(value) && typeof value.code === "string" && typeof value.message === "string" && typeof value.retryable === "boolean" && (value.reasonCode === void 0 || typeof value.reasonCode === "string") && (value.provider === void 0 || typeof value.provider === "string") && (value.source === void 0 || isProviderSource(value.source)) && (value.details === void 0 || isJsonRecord4(value.details));
|
|
14957
|
+
var isNormalizedRecord = (value) => isJsonRecord4(value) && typeof value.id === "string" && isProviderSource(value.source) && typeof value.provider === "string" && (value.url === void 0 || typeof value.url === "string") && (value.title === void 0 || typeof value.title === "string") && (value.content === void 0 || typeof value.content === "string") && typeof value.timestamp === "string" && isFiniteNumber(value.confidence) && isJsonRecord4(value.attributes);
|
|
14958
|
+
var isProviderFailureEntry = (value) => isJsonRecord4(value) && typeof value.provider === "string" && isProviderSource(value.source) && isProviderError2(value.error);
|
|
14959
|
+
var isProviderAggregateResult = (value) => isJsonRecord4(value) && typeof value.ok === "boolean" && Array.isArray(value.records) && value.records.every((entry) => isNormalizedRecord(entry)) && isTraceContext(value.trace) && typeof value.partial === "boolean" && Array.isArray(value.failures) && value.failures.every((entry) => isProviderFailureEntry(entry)) && isJsonRecord4(value.metrics) && isFiniteNumber(value.metrics.attempted) && isFiniteNumber(value.metrics.succeeded) && isFiniteNumber(value.metrics.failed) && isFiniteNumber(value.metrics.retries) && isFiniteNumber(value.metrics.latencyMs) && typeof value.sourceSelection === "string" && Array.isArray(value.providerOrder) && value.providerOrder.every((entry) => typeof entry === "string") && (value.meta === void 0 || isJsonRecord4(value.meta)) && (value.diagnostics === void 0 || isJsonRecord4(value.diagnostics)) && (value.error === void 0 || isProviderError2(value.error));
|
|
15647
14960
|
var emptyCheckpointState = () => ({
|
|
15648
14961
|
completed_step_ids: [],
|
|
15649
14962
|
step_results_by_id: {}
|
|
@@ -15659,7 +14972,7 @@ var readShoppingCheckpointState = (checkpoint) => {
|
|
|
15659
14972
|
if (state === void 0 || state === null) {
|
|
15660
14973
|
return emptyCheckpointState();
|
|
15661
14974
|
}
|
|
15662
|
-
if (!
|
|
14975
|
+
if (!isJsonRecord4(state)) {
|
|
15663
14976
|
throw new Error("Shopping workflow checkpoint state must be a record.");
|
|
15664
14977
|
}
|
|
15665
14978
|
const completedStepIds = state.completed_step_ids;
|
|
@@ -15667,7 +14980,7 @@ var readShoppingCheckpointState = (checkpoint) => {
|
|
|
15667
14980
|
throw new Error("Shopping workflow checkpoint state is missing valid completed_step_ids.");
|
|
15668
14981
|
}
|
|
15669
14982
|
const rawResults = state.step_results_by_id;
|
|
15670
|
-
if (!
|
|
14983
|
+
if (!isJsonRecord4(rawResults)) {
|
|
15671
14984
|
throw new Error("Shopping workflow checkpoint state is missing valid step_results_by_id.");
|
|
15672
14985
|
}
|
|
15673
14986
|
const stepResultsById = {};
|
|
@@ -15978,14 +15291,14 @@ var PRODUCT_VIDEO_STEP_IDS = {
|
|
|
15978
15291
|
extractProductData: "product_video:extract_product_data",
|
|
15979
15292
|
assembleArtifacts: "product_video:assemble_artifacts"
|
|
15980
15293
|
};
|
|
15981
|
-
var
|
|
15294
|
+
var isJsonRecord5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
15982
15295
|
var isFiniteNumber2 = (value) => typeof value === "number" && Number.isFinite(value);
|
|
15983
15296
|
var isProviderSource2 = (value) => value === "web" || value === "community" || value === "social" || value === "shopping";
|
|
15984
|
-
var isTraceContext2 = (value) =>
|
|
15985
|
-
var isProviderError3 = (value) =>
|
|
15986
|
-
var isNormalizedRecord2 = (value) =>
|
|
15987
|
-
var isProviderFailureEntry2 = (value) =>
|
|
15988
|
-
var isProviderAggregateResult2 = (value) =>
|
|
15297
|
+
var isTraceContext2 = (value) => isJsonRecord5(value) && typeof value.requestId === "string" && typeof value.ts === "string" && (value.sessionId === void 0 || typeof value.sessionId === "string") && (value.targetId === void 0 || typeof value.targetId === "string") && (value.provider === void 0 || typeof value.provider === "string");
|
|
15298
|
+
var isProviderError3 = (value) => isJsonRecord5(value) && typeof value.code === "string" && typeof value.message === "string" && typeof value.retryable === "boolean" && (value.reasonCode === void 0 || typeof value.reasonCode === "string") && (value.provider === void 0 || typeof value.provider === "string") && (value.source === void 0 || isProviderSource2(value.source)) && (value.details === void 0 || isJsonRecord5(value.details));
|
|
15299
|
+
var isNormalizedRecord2 = (value) => isJsonRecord5(value) && typeof value.id === "string" && isProviderSource2(value.source) && typeof value.provider === "string" && (value.url === void 0 || typeof value.url === "string") && (value.title === void 0 || typeof value.title === "string") && (value.content === void 0 || typeof value.content === "string") && typeof value.timestamp === "string" && isFiniteNumber2(value.confidence) && isJsonRecord5(value.attributes);
|
|
15300
|
+
var isProviderFailureEntry2 = (value) => isJsonRecord5(value) && typeof value.provider === "string" && isProviderSource2(value.source) && isProviderError3(value.error);
|
|
15301
|
+
var isProviderAggregateResult2 = (value) => isJsonRecord5(value) && typeof value.ok === "boolean" && Array.isArray(value.records) && value.records.every((entry) => isNormalizedRecord2(entry)) && isTraceContext2(value.trace) && typeof value.partial === "boolean" && Array.isArray(value.failures) && value.failures.every((entry) => isProviderFailureEntry2(entry)) && isJsonRecord5(value.metrics) && isFiniteNumber2(value.metrics.attempted) && isFiniteNumber2(value.metrics.succeeded) && isFiniteNumber2(value.metrics.failed) && isFiniteNumber2(value.metrics.retries) && isFiniteNumber2(value.metrics.latencyMs) && typeof value.sourceSelection === "string" && Array.isArray(value.providerOrder) && value.providerOrder.every((entry) => typeof entry === "string") && (value.meta === void 0 || isJsonRecord5(value.meta)) && (value.diagnostics === void 0 || isJsonRecord5(value.diagnostics)) && (value.error === void 0 || isProviderError3(value.error));
|
|
15989
15302
|
var emptyCheckpointState2 = () => ({
|
|
15990
15303
|
completed_step_ids: []
|
|
15991
15304
|
});
|
|
@@ -16028,7 +15341,7 @@ var readProductVideoCheckpointState = (checkpoint) => {
|
|
|
16028
15341
|
if (state === void 0 || state === null) {
|
|
16029
15342
|
return emptyCheckpointState2();
|
|
16030
15343
|
}
|
|
16031
|
-
if (!
|
|
15344
|
+
if (!isJsonRecord5(state)) {
|
|
16032
15345
|
throw new Error("Product-video workflow checkpoint state must be a record.");
|
|
16033
15346
|
}
|
|
16034
15347
|
const completedStepIds = state.completed_step_ids;
|
|
@@ -16139,15 +15452,16 @@ import { createHash as createHash6 } from "crypto";
|
|
|
16139
15452
|
var RESEARCH_AUTO_SOURCES = ["web", "community", "social"];
|
|
16140
15453
|
var RESEARCH_ALL_SOURCES = [...RESEARCH_AUTO_SOURCES];
|
|
16141
15454
|
var DEFAULT_RESEARCH_SEARCH_LIMIT = 10;
|
|
16142
|
-
var RESEARCH_WEB_SEARCH_FETCH_LIMIT =
|
|
16143
|
-
var
|
|
15455
|
+
var RESEARCH_WEB_SEARCH_FETCH_LIMIT = 5;
|
|
15456
|
+
var RESEARCH_COMMUNITY_EXPANSION_PER_RECORD = 2;
|
|
15457
|
+
var isJsonRecord6 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16144
15458
|
var isFiniteNumber3 = (value) => typeof value === "number" && Number.isFinite(value);
|
|
16145
15459
|
var isProviderSource3 = (value) => value === "web" || value === "community" || value === "social" || value === "shopping";
|
|
16146
|
-
var isTraceContext3 = (value) =>
|
|
16147
|
-
var isProviderError4 = (value) =>
|
|
16148
|
-
var isNormalizedRecord3 = (value) =>
|
|
16149
|
-
var isProviderFailureEntry3 = (value) =>
|
|
16150
|
-
var isProviderAggregateResult3 = (value) =>
|
|
15460
|
+
var isTraceContext3 = (value) => isJsonRecord6(value) && typeof value.requestId === "string" && typeof value.ts === "string" && (value.sessionId === void 0 || typeof value.sessionId === "string") && (value.targetId === void 0 || typeof value.targetId === "string") && (value.provider === void 0 || typeof value.provider === "string");
|
|
15461
|
+
var isProviderError4 = (value) => isJsonRecord6(value) && typeof value.code === "string" && typeof value.message === "string" && typeof value.retryable === "boolean" && (value.reasonCode === void 0 || typeof value.reasonCode === "string") && (value.provider === void 0 || typeof value.provider === "string") && (value.source === void 0 || isProviderSource3(value.source)) && (value.details === void 0 || isJsonRecord6(value.details));
|
|
15462
|
+
var isNormalizedRecord3 = (value) => isJsonRecord6(value) && typeof value.id === "string" && isProviderSource3(value.source) && typeof value.provider === "string" && (value.url === void 0 || typeof value.url === "string") && (value.title === void 0 || typeof value.title === "string") && (value.content === void 0 || typeof value.content === "string") && typeof value.timestamp === "string" && isFiniteNumber3(value.confidence) && isJsonRecord6(value.attributes);
|
|
15463
|
+
var isProviderFailureEntry3 = (value) => isJsonRecord6(value) && typeof value.provider === "string" && isProviderSource3(value.source) && isProviderError4(value.error);
|
|
15464
|
+
var isProviderAggregateResult3 = (value) => isJsonRecord6(value) && typeof value.ok === "boolean" && Array.isArray(value.records) && value.records.every((entry) => isNormalizedRecord3(entry)) && isTraceContext3(value.trace) && typeof value.partial === "boolean" && Array.isArray(value.failures) && value.failures.every((entry) => isProviderFailureEntry3(entry)) && isJsonRecord6(value.metrics) && isFiniteNumber3(value.metrics.attempted) && isFiniteNumber3(value.metrics.succeeded) && isFiniteNumber3(value.metrics.failed) && isFiniteNumber3(value.metrics.retries) && isFiniteNumber3(value.metrics.latencyMs) && typeof value.sourceSelection === "string" && Array.isArray(value.providerOrder) && value.providerOrder.every((entry) => typeof entry === "string") && (value.meta === void 0 || isJsonRecord6(value.meta)) && (value.diagnostics === void 0 || isJsonRecord6(value.diagnostics)) && (value.error === void 0 || isProviderError4(value.error));
|
|
16151
15465
|
var emptyCheckpointState3 = () => ({
|
|
16152
15466
|
completed_step_ids: [],
|
|
16153
15467
|
step_results_by_id: {}
|
|
@@ -16170,7 +15484,7 @@ var readResearchCheckpointState = (checkpoint) => {
|
|
|
16170
15484
|
if (state === void 0 || state === null) {
|
|
16171
15485
|
return emptyCheckpointState3();
|
|
16172
15486
|
}
|
|
16173
|
-
if (!
|
|
15487
|
+
if (!isJsonRecord6(state)) {
|
|
16174
15488
|
throw new Error("Research workflow checkpoint state must be a record.");
|
|
16175
15489
|
}
|
|
16176
15490
|
const completedStepIds = state.completed_step_ids;
|
|
@@ -16178,7 +15492,7 @@ var readResearchCheckpointState = (checkpoint) => {
|
|
|
16178
15492
|
throw new Error("Research workflow checkpoint state is missing valid completed_step_ids.");
|
|
16179
15493
|
}
|
|
16180
15494
|
const rawResults = state.step_results_by_id;
|
|
16181
|
-
if (!
|
|
15495
|
+
if (!isJsonRecord6(rawResults)) {
|
|
16182
15496
|
throw new Error("Research workflow checkpoint state is missing valid step_results_by_id.");
|
|
16183
15497
|
}
|
|
16184
15498
|
const stepResultsById = {};
|
|
@@ -16228,8 +15542,8 @@ var buildResearchSearchFilters = (source, args) => ({
|
|
|
16228
15542
|
timebox_to: args.timebox.to,
|
|
16229
15543
|
...source === "community" || source === "social" ? {
|
|
16230
15544
|
pageLimit: 1,
|
|
16231
|
-
hopLimit: 0,
|
|
16232
|
-
expansionPerRecord: 0
|
|
15545
|
+
hopLimit: source === "community" ? 1 : 0,
|
|
15546
|
+
expansionPerRecord: source === "community" ? RESEARCH_COMMUNITY_EXPANSION_PER_RECORD : 0
|
|
16233
15547
|
} : {}
|
|
16234
15548
|
});
|
|
16235
15549
|
var compileResearchExecutionPlan = (args) => {
|
|
@@ -16296,7 +15610,12 @@ var compileResearchExecutionPlan = (args) => {
|
|
|
16296
15610
|
|
|
16297
15611
|
// src/providers/research-executor.ts
|
|
16298
15612
|
var RESEARCH_WEB_SEARCH_FETCH_PATHS = /* @__PURE__ */ new Set([
|
|
15613
|
+
"community:search:index",
|
|
15614
|
+
"community:search:url",
|
|
16299
15615
|
"web:search:index",
|
|
15616
|
+
"web:search:url",
|
|
15617
|
+
"social:youtube:search:url",
|
|
15618
|
+
"social:search:url",
|
|
16300
15619
|
"social:search:index"
|
|
16301
15620
|
]);
|
|
16302
15621
|
var appendTrace2 = (trace, stage, event, details) => [
|
|
@@ -16337,6 +15656,15 @@ var isValidHttpUrl2 = (url) => {
|
|
|
16337
15656
|
return false;
|
|
16338
15657
|
}
|
|
16339
15658
|
};
|
|
15659
|
+
var attributeLinks = (record) => {
|
|
15660
|
+
const links = record.attributes.links;
|
|
15661
|
+
if (!Array.isArray(links)) return [];
|
|
15662
|
+
return links.filter((link) => typeof link === "string");
|
|
15663
|
+
};
|
|
15664
|
+
var researchCandidateUrls = (record) => [
|
|
15665
|
+
...typeof record.url === "string" ? [record.url] : [],
|
|
15666
|
+
...attributeLinks(record)
|
|
15667
|
+
];
|
|
16340
15668
|
var resolveResearchWebFetchCandidates = (records, limit) => {
|
|
16341
15669
|
const candidates = [];
|
|
16342
15670
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -16345,27 +15673,30 @@ var resolveResearchWebFetchCandidates = (records, limit) => {
|
|
|
16345
15673
|
if (!RESEARCH_WEB_SEARCH_FETCH_PATHS.has(retrievalPath)) {
|
|
16346
15674
|
continue;
|
|
16347
15675
|
}
|
|
16348
|
-
const
|
|
16349
|
-
|
|
16350
|
-
continue;
|
|
16351
|
-
|
|
16352
|
-
|
|
16353
|
-
|
|
16354
|
-
|
|
16355
|
-
|
|
16356
|
-
|
|
16357
|
-
|
|
16358
|
-
|
|
15676
|
+
for (const candidateUrl of researchCandidateUrls(record)) {
|
|
15677
|
+
const rawUrl = canonicalizeUrl(candidateUrl);
|
|
15678
|
+
if (!rawUrl) continue;
|
|
15679
|
+
let resolvedUrl = rawUrl;
|
|
15680
|
+
try {
|
|
15681
|
+
const parsed = new URL(rawUrl);
|
|
15682
|
+
if (/duckduckgo\.com$/i.test(parsed.hostname) && (parsed.pathname === "/l" || parsed.pathname === "/l/")) {
|
|
15683
|
+
const redirect = parsed.searchParams.get("uddg");
|
|
15684
|
+
if (typeof redirect === "string" && redirect.length > 0) {
|
|
15685
|
+
resolvedUrl = canonicalizeUrl(redirect);
|
|
15686
|
+
}
|
|
16359
15687
|
}
|
|
15688
|
+
} catch {
|
|
15689
|
+
continue;
|
|
15690
|
+
}
|
|
15691
|
+
if (!resolvedUrl || !isValidHttpUrl2(resolvedUrl) || !isLikelyResearchDestinationUrl(resolvedUrl) || /duckduckgo\.com/i.test(resolvedUrl) || seen.has(resolvedUrl)) {
|
|
15692
|
+
continue;
|
|
15693
|
+
}
|
|
15694
|
+
seen.add(resolvedUrl);
|
|
15695
|
+
candidates.push(resolvedUrl);
|
|
15696
|
+
if (candidates.length >= limit) {
|
|
15697
|
+
break;
|
|
16360
15698
|
}
|
|
16361
|
-
} catch {
|
|
16362
|
-
continue;
|
|
16363
|
-
}
|
|
16364
|
-
if (!resolvedUrl || !isValidHttpUrl2(resolvedUrl) || /duckduckgo\.com/i.test(resolvedUrl) || seen.has(resolvedUrl)) {
|
|
16365
|
-
continue;
|
|
16366
15699
|
}
|
|
16367
|
-
seen.add(resolvedUrl);
|
|
16368
|
-
candidates.push(resolvedUrl);
|
|
16369
15700
|
if (candidates.length >= limit) {
|
|
16370
15701
|
break;
|
|
16371
15702
|
}
|
|
@@ -17131,7 +16462,11 @@ var rankResearchRecords = (records) => {
|
|
|
17131
16462
|
var hash2 = (value) => createHash7("sha1").update(value).digest("hex").slice(0, 16);
|
|
17132
16463
|
var RESEARCH_ALWAYS_SANITIZED_PATHS = /* @__PURE__ */ new Set([
|
|
17133
16464
|
"community:search:index",
|
|
17134
|
-
"
|
|
16465
|
+
"community:search:url",
|
|
16466
|
+
"social:search:index",
|
|
16467
|
+
"social:search:url",
|
|
16468
|
+
"social:youtube:search:url",
|
|
16469
|
+
"web:search:url"
|
|
17135
16470
|
]);
|
|
17136
16471
|
var RESEARCH_CONDITIONAL_SANITIZED_PATHS = /* @__PURE__ */ new Set([
|
|
17137
16472
|
"community:fetch:url",
|
|
@@ -17139,9 +16474,13 @@ var RESEARCH_CONDITIONAL_SANITIZED_PATHS = /* @__PURE__ */ new Set([
|
|
|
17139
16474
|
"web:search:index"
|
|
17140
16475
|
]);
|
|
17141
16476
|
var RESEARCH_LOGIN_SHELL_RE = /\b(?:log in|login|sign in|sign-in|please log in|continue with google|continue with apple)\b/i;
|
|
16477
|
+
var RESEARCH_LOGIN_SHELL_MAX_CONTENT_CHARS = 600;
|
|
16478
|
+
var RESEARCH_LOGIN_REQUIRED_RE = /\b(?:log in to continue|sign in to continue|authentication required|please log in|continue with google|continue with apple)\b/i;
|
|
17142
16479
|
var RESEARCH_JS_REQUIRED_RE = /\b(?:enable javascript|javascript required|javascript is not available|javascript is disabled|you need to enable javascript)\b/i;
|
|
17143
16480
|
var RESEARCH_GENERIC_SHELL_RE = /\b(?:skip to main content|the heart of the internet|open navigation|get the app|view in app|please wait for verification|verify you are human|security check)\b/i;
|
|
17144
16481
|
var RESEARCH_NOT_FOUND_SHELL_RE = /\b(?:error 404|page not found|not found|can['’]t seem to find the page)\b/i;
|
|
16482
|
+
var RESEARCH_PRIVACY_PREFERENCE_SHELL_RE = /\b(?:select your cookie preferences|customize cookie preferences|unable to save cookie preferences|your privacy choices|manage consent preferences|privacy opt[- ]out|do not sell or share my personal information)\b/i;
|
|
16483
|
+
var RESEARCH_PRIVACY_RECOVERED_CONTENT_RE = /\b(?:blogs? home|permalink|comments|article)\b/i;
|
|
17145
16484
|
var RESEARCH_SEARCH_SHELL_RE = /\b(?:duckduckgo|search results|all posts|communities|comments|try another search|no relevant content found|unable to load answer|search page)\b/i;
|
|
17146
16485
|
var isDuckDuckGoResearchShellUrl = (url) => {
|
|
17147
16486
|
try {
|
|
@@ -17154,6 +16493,7 @@ var isDuckDuckGoResearchShellUrl = (url) => {
|
|
|
17154
16493
|
}
|
|
17155
16494
|
};
|
|
17156
16495
|
var PRODUCT_TARGET_NOT_FOUND_RE = /\b(?:error 404|page not found|not found|we can['’]t seem to find the page|can['’]t seem to find the page|return to homepage)\b/i;
|
|
16496
|
+
var BESTBUY_PDP_ERROR_SHELL_RE = /\b(?:something went wrong|use our search bar|pick a category below|typed in a url|check it for errors)\b/i;
|
|
17157
16497
|
var resolveShoppingProviderIdForUrl = (url) => {
|
|
17158
16498
|
try {
|
|
17159
16499
|
const host = new URL(url).hostname.toLowerCase();
|
|
@@ -17208,6 +16548,48 @@ var WALMART_TITLE_CHROME_RE = /\b(?:Walmart\.com|Skip to Main Content|Pickup or
|
|
|
17208
16548
|
var WALMART_BRAND_COLOR_RE = /\bColor\s+[A-Z0-9][A-Za-z0-9 /-]*(?=\s+(?:View full specifications|Current price is|Skip to Main Content|Pickup or delivery\?|How do you want your item\?|Sold and shipped by|Seller Rating|Free shipping|Arrives\b|Shipping\b|Delivery\b|Pickup\b|Departments Services|More details|Add to cart)|$)/i;
|
|
17209
16549
|
var WALMART_BRAND_CHROME_TAIL_RE = /\b(?:View full specifications|Current price is|Skip to Main Content|Pickup or delivery\?|How do you want your item\?|Sold and shipped by|Seller Rating|Free shipping|Arrives\b|Shipping\b|Delivery\b|Pickup\b|Departments Services|More details|Add to cart)\b.*$/i;
|
|
17210
16550
|
var WALMART_BRAND_CHROME_RE = /\b(?:Walmart\.com|Skip to Main Content|Pickup or delivery\?|How do you want your item\?|Sold and shipped by|Seller Rating|View full specifications|Current price is|Free shipping|Departments Services)\b/i;
|
|
16551
|
+
var EBAY_TITLE_BRAND_PREFIX_RE = /^(?:new|used|pre-owned|preowned|open box|refurbished|renewed|genuine|authentic)\s+/i;
|
|
16552
|
+
var EBAY_KNOWN_MULTI_TOKEN_BRANDS = [
|
|
16553
|
+
"3M",
|
|
16554
|
+
"Bang & Olufsen",
|
|
16555
|
+
"Bowers & Wilkins",
|
|
16556
|
+
"Hewlett-Packard",
|
|
16557
|
+
"iRobot",
|
|
16558
|
+
"New Balance"
|
|
16559
|
+
];
|
|
16560
|
+
var EBAY_KNOWN_SINGLE_TOKEN_BRANDS = /* @__PURE__ */ new Map([
|
|
16561
|
+
["apple", "Apple"],
|
|
16562
|
+
["bose", "Bose"],
|
|
16563
|
+
["canon", "Canon"],
|
|
16564
|
+
["dell", "Dell"],
|
|
16565
|
+
["dyson", "Dyson"],
|
|
16566
|
+
["google", "Google"],
|
|
16567
|
+
["jbl", "JBL"],
|
|
16568
|
+
["lenovo", "Lenovo"],
|
|
16569
|
+
["lg", "LG"],
|
|
16570
|
+
["microsoft", "Microsoft"],
|
|
16571
|
+
["nikon", "Nikon"],
|
|
16572
|
+
["nintendo", "Nintendo"],
|
|
16573
|
+
["panasonic", "Panasonic"],
|
|
16574
|
+
["philips", "Philips"],
|
|
16575
|
+
["samsung", "Samsung"],
|
|
16576
|
+
["sony", "Sony"]
|
|
16577
|
+
]);
|
|
16578
|
+
var EBAY_TITLE_BRAND_STOP_WORDS = /* @__PURE__ */ new Set([
|
|
16579
|
+
"bluetooth",
|
|
16580
|
+
"case",
|
|
16581
|
+
"ergonomic",
|
|
16582
|
+
"gaming",
|
|
16583
|
+
"headphones",
|
|
16584
|
+
"keyboard",
|
|
16585
|
+
"leather",
|
|
16586
|
+
"noise",
|
|
16587
|
+
"portable",
|
|
16588
|
+
"rechargeable",
|
|
16589
|
+
"speaker",
|
|
16590
|
+
"vertical",
|
|
16591
|
+
"wireless"
|
|
16592
|
+
]);
|
|
17211
16593
|
var PRODUCT_FEATURE_SECTION_MARKERS = [
|
|
17212
16594
|
"about this item",
|
|
17213
16595
|
"key item features",
|
|
@@ -17273,7 +16655,7 @@ var INSPIREDESIGN_RENDER_MODES = /* @__PURE__ */ new Set(["compact", "json", "md
|
|
|
17273
16655
|
var INSPIREDESIGN_CAPTURE_MODES = /* @__PURE__ */ new Set(["off", "deep"]);
|
|
17274
16656
|
var INSPIREDESIGN_COOKIE_POLICIES = /* @__PURE__ */ new Set(["off", "auto", "required"]);
|
|
17275
16657
|
var WORKFLOW_BROWSER_MODES = /* @__PURE__ */ new Set(["auto", "extension", "managed"]);
|
|
17276
|
-
var
|
|
16658
|
+
var isJsonRecord7 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17277
16659
|
var INSPIREDESIGN_CAPTURE_UNAVAILABLE_FAILURE = "Deep capture requested, but browser capture is unavailable in this execution lane.";
|
|
17278
16660
|
var isCanvasVisualDirectionProfile = (value) => {
|
|
17279
16661
|
return CANVAS_VISUAL_DIRECTION_PROFILES.includes(value);
|
|
@@ -17302,7 +16684,7 @@ var serializeInspiredesignRunInput = (input) => ({
|
|
|
17302
16684
|
});
|
|
17303
16685
|
var isStringArray2 = (value) => Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
17304
16686
|
var parseInspiredesignBriefFormatRoute = (value) => {
|
|
17305
|
-
if (!
|
|
16687
|
+
if (!isJsonRecord7(value)) return void 0;
|
|
17306
16688
|
const profile = typeof value.profile === "string" && isCanvasVisualDirectionProfile(value.profile) ? value.profile : void 0;
|
|
17307
16689
|
const themeStrategy = typeof value.themeStrategy === "string" && isCanvasThemeStrategy(value.themeStrategy) ? value.themeStrategy : void 0;
|
|
17308
16690
|
const navigationModel = typeof value.navigationModel === "string" && isCanvasNavigationModel(value.navigationModel) ? value.navigationModel : void 0;
|
|
@@ -17317,7 +16699,7 @@ var parseInspiredesignBriefFormatRoute = (value) => {
|
|
|
17317
16699
|
};
|
|
17318
16700
|
};
|
|
17319
16701
|
var parseInspiredesignBriefFormat = (value) => {
|
|
17320
|
-
if (!
|
|
16702
|
+
if (!isJsonRecord7(value)) return void 0;
|
|
17321
16703
|
const route = parseInspiredesignBriefFormatRoute(value.route);
|
|
17322
16704
|
if (typeof value.id !== "string" || typeof value.label !== "string" || !isStringArray2(value.bestFor) || !isStringArray2(value.businessFocus) || !isStringArray2(value.keywords) || typeof value.archetype !== "string" || typeof value.layoutArchetype !== "string" || typeof value.typographySystem !== "string" || typeof value.surfaceTreatment !== "string" || typeof value.shapeLanguage !== "string" || typeof value.componentGrammar !== "string" || typeof value.motionGrammar !== "string" || typeof value.paletteIntent !== "string" || typeof value.visualDensity !== "string" || typeof value.designVariance !== "string" || !isStringArray2(value.responsiveCollapseRules) || !isStringArray2(value.guardrails) || !isStringArray2(value.antiPatterns) || !isStringArray2(value.deliverables) || !route) {
|
|
17323
16705
|
return void 0;
|
|
@@ -17346,7 +16728,7 @@ var parseInspiredesignBriefFormat = (value) => {
|
|
|
17346
16728
|
};
|
|
17347
16729
|
};
|
|
17348
16730
|
var parseInspiredesignBriefExpansion = (value) => {
|
|
17349
|
-
if (!
|
|
16731
|
+
if (!isJsonRecord7(value)) return void 0;
|
|
17350
16732
|
const format = parseInspiredesignBriefFormat(value.format);
|
|
17351
16733
|
if (typeof value.sourceBrief !== "string" || typeof value.advancedBrief !== "string" || typeof value.templateVersion !== "string" || !format) {
|
|
17352
16734
|
return void 0;
|
|
@@ -17368,7 +16750,7 @@ var parseInspiredesignEnvelopeInput = (input) => {
|
|
|
17368
16750
|
...typeof input.captureMode === "string" && INSPIREDESIGN_CAPTURE_MODES.has(input.captureMode) ? { captureMode: input.captureMode } : {},
|
|
17369
16751
|
...typeof input.includePrototypeGuidance === "boolean" ? { includePrototypeGuidance: input.includePrototypeGuidance } : {},
|
|
17370
16752
|
...typeof input.timeoutMs === "number" ? { timeoutMs: input.timeoutMs } : {},
|
|
17371
|
-
...typeof input.outputDir === "string"
|
|
16753
|
+
...typeof input.outputDir === "string" ? { outputDir: input.outputDir } : {},
|
|
17372
16754
|
...typeof input.ttlHours === "number" ? { ttlHours: input.ttlHours } : {},
|
|
17373
16755
|
...typeof input.browserMode === "string" && WORKFLOW_BROWSER_MODES.has(input.browserMode) ? { browserMode: input.browserMode } : {},
|
|
17374
16756
|
...typeof input.useCookies === "boolean" ? { useCookies: input.useCookies } : {},
|
|
@@ -17764,9 +17146,10 @@ var buildInspiredesignMeta = (runtime, workflowInput, references, failures, foll
|
|
|
17764
17146
|
contractScope: followthrough.contractScope
|
|
17765
17147
|
};
|
|
17766
17148
|
};
|
|
17767
|
-
var inferBrandFromContent = (content) => {
|
|
17149
|
+
var inferBrandFromContent = (content, productUrl) => {
|
|
17768
17150
|
const normalized = normalizePlainText(content);
|
|
17769
17151
|
if (!normalized) return void 0;
|
|
17152
|
+
const isEbayProduct = productUrl ? resolveShoppingProviderIdForUrl(productUrl) === "shopping/ebay" : false;
|
|
17770
17153
|
const bestBuyTitle = inferBestBuyTitleFromContent(normalized);
|
|
17771
17154
|
const bestBuyBrand = inferBestBuyBrandFromTitle(bestBuyTitle) ?? extractBrandFromTitle(bestBuyTitle);
|
|
17772
17155
|
if (bestBuyBrand) {
|
|
@@ -17784,6 +17167,14 @@ var inferBrandFromContent = (content) => {
|
|
|
17784
17167
|
if (productIdentifiersBrandMatch?.[1]) {
|
|
17785
17168
|
return productIdentifiersBrandMatch[1].trim();
|
|
17786
17169
|
}
|
|
17170
|
+
const ebayTitle = inferEbayTitleFromContent(normalized);
|
|
17171
|
+
const ebayBrand = inferEbayBrandFromTitle(ebayTitle);
|
|
17172
|
+
if (ebayBrand) {
|
|
17173
|
+
return ebayBrand;
|
|
17174
|
+
}
|
|
17175
|
+
if (isEbayProduct) {
|
|
17176
|
+
return void 0;
|
|
17177
|
+
}
|
|
17787
17178
|
const brandMatch = /\bBrand ([A-Z][A-Za-z0-9&+' -]{1,60})\b/i.exec(normalized);
|
|
17788
17179
|
if (brandMatch?.[1]) {
|
|
17789
17180
|
return brandMatch[1].trim();
|
|
@@ -17803,13 +17194,69 @@ var inferBestBuyTitleFromContent = (normalized) => {
|
|
|
17803
17194
|
}
|
|
17804
17195
|
return candidate;
|
|
17805
17196
|
};
|
|
17806
|
-
var
|
|
17197
|
+
var inferEbayTitleFromContent = (normalized) => {
|
|
17198
|
+
const patterns = [
|
|
17199
|
+
/\bExpand Cart Loading\.\.\.\s+(.+?)(?:\s+for sale online\s*\|\s*eBay)?\s+Condition:/i,
|
|
17200
|
+
/\bBuy It Now\s+(.+?)\s+Sign in to check out\b/i
|
|
17201
|
+
];
|
|
17202
|
+
for (const pattern of patterns) {
|
|
17203
|
+
const candidate = stripMarketplaceTitleFraming(normalizePlainText(pattern.exec(normalized)?.[1]), "https://www.ebay.com");
|
|
17204
|
+
if (candidate && candidate.length >= 20 && candidate.length <= 180 && !candidate.endsWith("...") && !LOOKS_LIKE_URL_RE.test(candidate)) {
|
|
17205
|
+
return candidate;
|
|
17206
|
+
}
|
|
17207
|
+
}
|
|
17208
|
+
return void 0;
|
|
17209
|
+
};
|
|
17210
|
+
var inferKnownEbayBrandFromTitle = (title) => {
|
|
17211
|
+
const normalized = title.toLowerCase();
|
|
17212
|
+
return EBAY_KNOWN_MULTI_TOKEN_BRANDS.find((brand) => {
|
|
17213
|
+
const candidate = brand.toLowerCase();
|
|
17214
|
+
return normalized === candidate || normalized.startsWith(`${candidate} `);
|
|
17215
|
+
});
|
|
17216
|
+
};
|
|
17217
|
+
var inferKnownSingleEbayBrandFromTitle = (title) => {
|
|
17218
|
+
const firstToken = /^([A-Za-z][A-Za-z0-9&+']{1,30})(?:\s|$)/.exec(title)?.[1];
|
|
17219
|
+
return firstToken ? EBAY_KNOWN_SINGLE_TOKEN_BRANDS.get(firstToken.toLowerCase()) : void 0;
|
|
17220
|
+
};
|
|
17221
|
+
var inferEbayBrandFromTitle = (title) => {
|
|
17222
|
+
const framed = normalizePlainText(title).replace(/\s+[-|]\s+[^-|]+$/i, "").trim();
|
|
17223
|
+
const knownBrand = inferKnownEbayBrandFromTitle(framed);
|
|
17224
|
+
if (knownBrand) return knownBrand;
|
|
17225
|
+
const cleaned = framed.replace(EBAY_TITLE_BRAND_PREFIX_RE, "");
|
|
17226
|
+
const prefixedBrand = inferKnownEbayBrandFromTitle(cleaned);
|
|
17227
|
+
if (prefixedBrand) return prefixedBrand;
|
|
17228
|
+
const singleTokenBrand = inferKnownSingleEbayBrandFromTitle(cleaned);
|
|
17229
|
+
if (singleTokenBrand) return singleTokenBrand;
|
|
17230
|
+
const exactBrand = /^([A-Z][A-Za-z0-9&+']{1,30})$/.exec(cleaned)?.[1];
|
|
17231
|
+
if (exactBrand && EBAY_KNOWN_SINGLE_TOKEN_BRANDS.has(exactBrand.toLowerCase())) {
|
|
17232
|
+
return exactBrand;
|
|
17233
|
+
}
|
|
17234
|
+
const match = /^([A-Z][A-Za-z0-9&+']{1,30})\s+([A-Z0-9][A-Za-z0-9&+'().-]+|AirPods)\b/.exec(cleaned);
|
|
17235
|
+
const brand = match?.[1]?.trim();
|
|
17236
|
+
if (!brand || EBAY_TITLE_BRAND_STOP_WORDS.has(brand.toLowerCase())) {
|
|
17237
|
+
return void 0;
|
|
17238
|
+
}
|
|
17239
|
+
if (EBAY_KNOWN_SINGLE_TOKEN_BRANDS.has(brand.toLowerCase())) {
|
|
17240
|
+
return EBAY_KNOWN_SINGLE_TOKEN_BRANDS.get(brand.toLowerCase());
|
|
17241
|
+
}
|
|
17242
|
+
if (!/[\d-]/.test(match?.[2] ?? "")) {
|
|
17243
|
+
return void 0;
|
|
17244
|
+
}
|
|
17245
|
+
return brand;
|
|
17246
|
+
};
|
|
17247
|
+
var inferTitleFromContent = (content, productUrl) => {
|
|
17807
17248
|
const normalized = normalizePlainText(content);
|
|
17808
17249
|
if (!normalized) return void 0;
|
|
17809
17250
|
const bestBuyTitle = inferBestBuyTitleFromContent(normalized);
|
|
17810
17251
|
if (bestBuyTitle) {
|
|
17811
17252
|
return bestBuyTitle;
|
|
17812
17253
|
}
|
|
17254
|
+
if (productUrl && resolveShoppingProviderIdForUrl(productUrl) === "shopping/ebay") {
|
|
17255
|
+
const ebayTitle = inferEbayTitleFromContent(normalized);
|
|
17256
|
+
if (ebayTitle) {
|
|
17257
|
+
return ebayTitle;
|
|
17258
|
+
}
|
|
17259
|
+
}
|
|
17813
17260
|
const storeMatch = /\bVisit the [A-Z][A-Za-z0-9&+' -]{1,60} Store\s+(.+?)(?=\s+(?:Brand [A-Z]|About this item|Key item features|Current price is|Actual Color|[0-9]+(?:\.[0-9]+)? stars out of|Best seller\b))/i.exec(normalized);
|
|
17814
17261
|
const candidate = normalizePlainText(storeMatch?.[1]);
|
|
17815
17262
|
if (!candidate || candidate.length < 20 || LOOKS_LIKE_URL_RE.test(candidate)) {
|
|
@@ -17822,6 +17269,11 @@ var sanitizeProductBrandCandidate = (candidate, productUrl) => {
|
|
|
17822
17269
|
if (!normalized) return void 0;
|
|
17823
17270
|
try {
|
|
17824
17271
|
const host = new URL(productUrl).hostname.toLowerCase();
|
|
17272
|
+
const hostBrand = normalizePlainText(inferBrandFromUrl(productUrl)).replace(/\.com\b/gi, "").toLowerCase();
|
|
17273
|
+
const candidateBrand = normalized.replace(/\.com\b/gi, "").toLowerCase();
|
|
17274
|
+
if (host.includes("ebay.") && hostBrand && candidateBrand === hostBrand) {
|
|
17275
|
+
return void 0;
|
|
17276
|
+
}
|
|
17825
17277
|
if (!host.includes("walmart.")) {
|
|
17826
17278
|
return normalized;
|
|
17827
17279
|
}
|
|
@@ -17966,6 +17418,17 @@ var inferHostDefaultCurrency = (productUrl) => {
|
|
|
17966
17418
|
return void 0;
|
|
17967
17419
|
}
|
|
17968
17420
|
};
|
|
17421
|
+
var extractProductBrandFromTitle = (title, productUrl) => {
|
|
17422
|
+
try {
|
|
17423
|
+
const host = new URL(productUrl).hostname.toLowerCase();
|
|
17424
|
+
if (host.includes("ebay.")) {
|
|
17425
|
+
return inferEbayBrandFromTitle(title);
|
|
17426
|
+
}
|
|
17427
|
+
} catch {
|
|
17428
|
+
return extractBrandFromTitle(title);
|
|
17429
|
+
}
|
|
17430
|
+
return extractBrandFromTitle(title);
|
|
17431
|
+
};
|
|
17969
17432
|
var shouldSuppressMarketplacePrice = (record, productUrl, price) => {
|
|
17970
17433
|
if (price.amount <= 0) return false;
|
|
17971
17434
|
const expectedCurrency = inferHostDefaultCurrency(productUrl);
|
|
@@ -18090,12 +17553,12 @@ var resolveProductBrand = (record, productUrl, refreshedBrand) => {
|
|
|
18090
17553
|
const nestedProvider = nested && typeof nested === "object" && !Array.isArray(nested) ? nested.provider : void 0;
|
|
18091
17554
|
const providerBrand = typeof nestedProvider === "string" ? SHOPPING_PROVIDER_PROFILES.find((entry) => entry.id === nestedProvider)?.displayName : void 0;
|
|
18092
17555
|
const candidates = [
|
|
18093
|
-
inferBrandFromContent(record.content),
|
|
17556
|
+
inferBrandFromContent(record.content, productUrl),
|
|
18094
17557
|
rejectRetailerBrand(refreshedBrand),
|
|
18095
17558
|
rejectRetailerBrand(typeof record.attributes.brand === "string" ? record.attributes.brand : void 0),
|
|
18096
17559
|
rejectRetailerBrand(typeof record.attributes.site_name === "string" ? record.attributes.site_name : void 0),
|
|
18097
17560
|
rejectRetailerBrand(providerBrand && providerBrand !== "Others" ? providerBrand : void 0),
|
|
18098
|
-
|
|
17561
|
+
extractProductBrandFromTitle(record.title, productUrl),
|
|
18099
17562
|
inferBrandFromUrl(productUrl)
|
|
18100
17563
|
].map((entry) => sanitizeProductBrandCandidate(entry, productUrl)).filter(Boolean);
|
|
18101
17564
|
return candidates[0] || "unknown";
|
|
@@ -18105,7 +17568,7 @@ var resolveProductTitle = (record, productUrl, brand, refreshedTitle) => {
|
|
|
18105
17568
|
const nestedTitle = nested && typeof nested === "object" && !Array.isArray(nested) ? nested.title : void 0;
|
|
18106
17569
|
const candidates = [
|
|
18107
17570
|
refreshedTitle,
|
|
18108
|
-
inferTitleFromContent(record.content),
|
|
17571
|
+
inferTitleFromContent(record.content, productUrl),
|
|
18109
17572
|
record.title,
|
|
18110
17573
|
typeof nestedTitle === "string" ? nestedTitle : void 0,
|
|
18111
17574
|
typeof record.attributes.description === "string" ? record.attributes.description.split(/(?<=[.!?])\s+/)[0] : void 0,
|
|
@@ -18154,13 +17617,31 @@ var resolveShoppingSourceForUrl = (url) => {
|
|
|
18154
17617
|
return "web";
|
|
18155
17618
|
}
|
|
18156
17619
|
};
|
|
17620
|
+
var RESEARCH_REJECTED_CANDIDATE_LIMIT = 25;
|
|
17621
|
+
var isResearchPrivacyPreferenceShell = (content) => {
|
|
17622
|
+
const matchIndex = content.slice(0, 400).search(RESEARCH_PRIVACY_PREFERENCE_SHELL_RE);
|
|
17623
|
+
return matchIndex >= 0 && matchIndex <= 80 && !RESEARCH_PRIVACY_RECOVERED_CONTENT_RE.test(content);
|
|
17624
|
+
};
|
|
17625
|
+
var classifyResearchDeadEndUrl = (value) => {
|
|
17626
|
+
if (!value) return null;
|
|
17627
|
+
return classifyResearchDestinationRejection(value);
|
|
17628
|
+
};
|
|
17629
|
+
var isResearchLoginShellRecord = (args) => {
|
|
17630
|
+
if (args.url.includes("/login")) {
|
|
17631
|
+
return true;
|
|
17632
|
+
}
|
|
17633
|
+
if (!RESEARCH_LOGIN_SHELL_RE.test(args.combined)) {
|
|
17634
|
+
return false;
|
|
17635
|
+
}
|
|
17636
|
+
return args.content.length <= RESEARCH_LOGIN_SHELL_MAX_CONTENT_CHARS || RESEARCH_LOGIN_REQUIRED_RE.test(args.combined);
|
|
17637
|
+
};
|
|
18157
17638
|
var classifyResearchShellRecord = (record) => {
|
|
18158
17639
|
const retrievalPath = typeof record.attributes.retrievalPath === "string" ? record.attributes.retrievalPath : "";
|
|
18159
17640
|
const url = typeof record.url === "string" ? record.url.trim().toLowerCase() : "";
|
|
18160
17641
|
const title = normalizePlainText(record.title).toLowerCase();
|
|
18161
17642
|
const content = normalizePlainText(record.content).toLowerCase();
|
|
18162
17643
|
const combined = `${title} ${content}`.trim();
|
|
18163
|
-
if (
|
|
17644
|
+
if (isResearchLoginShellRecord({ url, combined, content })) {
|
|
18164
17645
|
return "login_shell";
|
|
18165
17646
|
}
|
|
18166
17647
|
if (RESEARCH_JS_REQUIRED_RE.test(combined)) {
|
|
@@ -18169,6 +17650,13 @@ var classifyResearchShellRecord = (record) => {
|
|
|
18169
17650
|
if (RESEARCH_NOT_FOUND_SHELL_RE.test(combined)) {
|
|
18170
17651
|
return "not_found_shell";
|
|
18171
17652
|
}
|
|
17653
|
+
if (isResearchPrivacyPreferenceShell(content)) {
|
|
17654
|
+
return "privacy_preference_shell";
|
|
17655
|
+
}
|
|
17656
|
+
const deadEndUrlReason = classifyResearchDeadEndUrl(url);
|
|
17657
|
+
if (deadEndUrlReason) {
|
|
17658
|
+
return deadEndUrlReason;
|
|
17659
|
+
}
|
|
18172
17660
|
if (!retrievalPath) {
|
|
18173
17661
|
return null;
|
|
18174
17662
|
}
|
|
@@ -18191,18 +17679,47 @@ var classifyResearchShellRecord = (record) => {
|
|
|
18191
17679
|
};
|
|
18192
17680
|
var sanitizeResearchRecords = (records) => {
|
|
18193
17681
|
const reasonDistribution = {};
|
|
17682
|
+
const rejectedCandidates = [];
|
|
18194
17683
|
const sanitizedRecords = records.filter((record) => {
|
|
18195
17684
|
const reason = classifyResearchShellRecord(record);
|
|
18196
17685
|
if (!reason) return true;
|
|
18197
17686
|
reasonDistribution[reason] = (reasonDistribution[reason] ?? 0) + 1;
|
|
17687
|
+
if (rejectedCandidates.length < RESEARCH_REJECTED_CANDIDATE_LIMIT) {
|
|
17688
|
+
const retrievalPath = typeof record.attributes.retrievalPath === "string" ? record.attributes.retrievalPath : void 0;
|
|
17689
|
+
rejectedCandidates.push({
|
|
17690
|
+
provider: record.provider,
|
|
17691
|
+
source: record.source,
|
|
17692
|
+
reason,
|
|
17693
|
+
replacement_status: "rejected_before_synthesis",
|
|
17694
|
+
...retrievalPath ? { retrievalPath } : {},
|
|
17695
|
+
...record.title ? { title: record.title } : {},
|
|
17696
|
+
...record.url ? { url: record.url } : {}
|
|
17697
|
+
});
|
|
17698
|
+
}
|
|
18198
17699
|
return false;
|
|
18199
17700
|
});
|
|
18200
17701
|
return {
|
|
18201
17702
|
records: sanitizedRecords,
|
|
18202
17703
|
sanitizedCount: records.length - sanitizedRecords.length,
|
|
18203
|
-
reasonDistribution
|
|
17704
|
+
reasonDistribution,
|
|
17705
|
+
rejectedCandidates
|
|
17706
|
+
};
|
|
17707
|
+
};
|
|
17708
|
+
var rejectedCandidateFromFailure = (failure) => {
|
|
17709
|
+
const details = failure.error.details ?? {};
|
|
17710
|
+
if (details.fallbackOutputReason !== "research_dead_end_shell") return null;
|
|
17711
|
+
const retrievalPath = typeof details.retrievalPath === "string" ? details.retrievalPath : void 0;
|
|
17712
|
+
const url = typeof details.url === "string" ? details.url : void 0;
|
|
17713
|
+
return {
|
|
17714
|
+
provider: failure.provider,
|
|
17715
|
+
source: failure.source,
|
|
17716
|
+
reason: "research_dead_end_shell",
|
|
17717
|
+
replacement_status: "rejected_before_synthesis",
|
|
17718
|
+
...retrievalPath ? { retrievalPath } : {},
|
|
17719
|
+
...url ? { url } : {}
|
|
18204
17720
|
};
|
|
18205
17721
|
};
|
|
17722
|
+
var rejectedCandidatesFromFailures = (failures) => failures.map(rejectedCandidateFromFailure).filter((candidate) => candidate !== null);
|
|
18206
17723
|
var isValidHttpUrl3 = (url) => {
|
|
18207
17724
|
try {
|
|
18208
17725
|
const parsed = new URL(url.trim());
|
|
@@ -18228,6 +17745,13 @@ var classifyInvalidProductTarget = (record) => {
|
|
|
18228
17745
|
message: "Product target appears to be a not-found page"
|
|
18229
17746
|
};
|
|
18230
17747
|
}
|
|
17748
|
+
const providerId = resolveShoppingProviderIdForUrl(record.url ?? "");
|
|
17749
|
+
if (providerId === "shopping/bestbuy" && combined.toLowerCase().includes("something went wrong") && BESTBUY_PDP_ERROR_SHELL_RE.test(combined)) {
|
|
17750
|
+
return {
|
|
17751
|
+
reason: "provider_error_shell",
|
|
17752
|
+
message: "Best Buy product target returned a generic error shell"
|
|
17753
|
+
};
|
|
17754
|
+
}
|
|
18231
17755
|
return null;
|
|
18232
17756
|
};
|
|
18233
17757
|
var runResearchWorkflow = async (runtime, input) => {
|
|
@@ -18235,7 +17759,9 @@ var runResearchWorkflow = async (runtime, input) => {
|
|
|
18235
17759
|
if (envelope.kind !== "research") {
|
|
18236
17760
|
throw new Error(`Research workflow envelope kind mismatch. Expected research but received ${envelope.kind}.`);
|
|
18237
17761
|
}
|
|
18238
|
-
const
|
|
17762
|
+
const rawWorkflowInput = envelope.input;
|
|
17763
|
+
const artifactRoot = resolveWorkflowArtifactRoot(rawWorkflowInput.outputDir);
|
|
17764
|
+
const workflowInput = { ...rawWorkflowInput, outputDir: artifactRoot };
|
|
18239
17765
|
let trace = [
|
|
18240
17766
|
...envelope.trace ?? [],
|
|
18241
17767
|
{
|
|
@@ -18291,21 +17817,23 @@ var runResearchWorkflow = async (runtime, input) => {
|
|
|
18291
17817
|
}
|
|
18292
17818
|
});
|
|
18293
17819
|
const excludedProviderSet = new Set(plan.compiled.autoExcludedProviders);
|
|
18294
|
-
const
|
|
18295
|
-
|
|
18296
|
-
|
|
18297
|
-
|
|
18298
|
-
|
|
18299
|
-
|
|
18300
|
-
|
|
17820
|
+
const rawRecords = [
|
|
17821
|
+
...execution.searchRuns.flatMap((run) => run.result.records),
|
|
17822
|
+
...execution.followUpRuns.flatMap((run) => run.result.records)
|
|
17823
|
+
];
|
|
17824
|
+
const rawFailures = [
|
|
17825
|
+
...execution.searchRuns.flatMap((run) => run.result.failures),
|
|
17826
|
+
...execution.followUpRuns.flatMap((run) => run.result.failures)
|
|
17827
|
+
];
|
|
17828
|
+
const mergedRecords = removeExcludedProviders(rawRecords, excludedProviderSet);
|
|
18301
17829
|
const sanitizedRecords = sanitizeResearchRecords(mergedRecords);
|
|
18302
|
-
const mergedFailures = removeExcludedProviders(
|
|
18303
|
-
|
|
18304
|
-
|
|
18305
|
-
|
|
18306
|
-
|
|
18307
|
-
|
|
18308
|
-
|
|
17830
|
+
const mergedFailures = removeExcludedProviders(rawFailures, excludedProviderSet);
|
|
17831
|
+
const rejectedFailureCandidates = rejectedCandidatesFromFailures(mergedFailures);
|
|
17832
|
+
const rejectedCandidates = [
|
|
17833
|
+
...sanitizedRecords.rejectedCandidates,
|
|
17834
|
+
...rejectedFailureCandidates
|
|
17835
|
+
].slice(0, RESEARCH_REJECTED_CANDIDATE_LIMIT);
|
|
17836
|
+
const rejectedCandidateCount2 = sanitizedRecords.sanitizedCount + rejectedFailureCandidates.length;
|
|
18309
17837
|
const reasonCodeDistribution = summarizeReasonCodeDistribution(mergedFailures);
|
|
18310
17838
|
const transcriptStrategyFailures = summarizeTranscriptStrategyFailures(mergedFailures);
|
|
18311
17839
|
const evaluationNow = /* @__PURE__ */ new Date();
|
|
@@ -18313,8 +17841,8 @@ var runResearchWorkflow = async (runtime, input) => {
|
|
|
18313
17841
|
const enriched = enrichResearchRecords(withinTimebox, plan.compiled.timebox, evaluationNow);
|
|
18314
17842
|
const deduped = dedupeResearchRecords(enriched);
|
|
18315
17843
|
const ranked = rankResearchRecords(deduped);
|
|
18316
|
-
const noUsableResearchRecords = mergedRecords.length > 0 && mergedFailures.length === 0 && ranked.length === 0;
|
|
18317
17844
|
const cookieDiagnostics = summarizeCookieDiagnostics(mergedFailures, mergedRecords);
|
|
17845
|
+
const challengeOrchestration = summarizeChallengeOrchestration(mergedFailures, mergedRecords);
|
|
18318
17846
|
const transcriptStrategyDetailDistribution = summarizeTranscriptStrategyDetailDistribution(ranked);
|
|
18319
17847
|
const transcriptDurability = summarizeTranscriptDurability(ranked, mergedFailures);
|
|
18320
17848
|
const antiBotPressure = summarizeAntiBotPressure(mergedFailures);
|
|
@@ -18322,16 +17850,16 @@ var runResearchWorkflow = async (runtime, input) => {
|
|
|
18322
17850
|
...plan.compiled.timebox,
|
|
18323
17851
|
to: new Date(Math.max(new Date(plan.compiled.timebox.to).getTime(), evaluationNow.getTime())).toISOString()
|
|
18324
17852
|
} : plan.compiled.timebox;
|
|
18325
|
-
if (
|
|
17853
|
+
if (mergedRecords.length > 0 && sanitizedRecords.records.length === 0) {
|
|
18326
17854
|
const sanitizedReasons = Object.entries(sanitizedRecords.reasonDistribution).map(([reason, count]) => `${reason}:${count}`).join(",");
|
|
18327
17855
|
throw new Error(
|
|
18328
17856
|
`Research workflow produced only shell records and no usable results (${sanitizedReasons || "sanitized"}).`
|
|
18329
17857
|
);
|
|
18330
17858
|
}
|
|
18331
|
-
if (
|
|
17859
|
+
if (sanitizedRecords.records.length > 0 && withinTimebox.length === 0) {
|
|
18332
17860
|
throw new Error("Research workflow produced no usable in-timebox results after sanitization.");
|
|
18333
17861
|
}
|
|
18334
|
-
if (
|
|
17862
|
+
if (ranked.length === 0) {
|
|
18335
17863
|
throw new Error("Research workflow produced no usable results after post-processing.");
|
|
18336
17864
|
}
|
|
18337
17865
|
const primaryConstraintFailures = selectResearchPrimaryConstraintFailures(mergedFailures);
|
|
@@ -18345,8 +17873,10 @@ var runResearchWorkflow = async (runtime, input) => {
|
|
|
18345
17873
|
metrics: {
|
|
18346
17874
|
total_records: mergedRecords.length,
|
|
18347
17875
|
sanitized_records: sanitizedRecords.sanitizedCount,
|
|
17876
|
+
rejected_candidate_count: rejectedCandidateCount2,
|
|
18348
17877
|
sanitized_reason_distribution: sanitizedRecords.reasonDistribution,
|
|
18349
17878
|
sanitizedReasonDistribution: sanitizedRecords.reasonDistribution,
|
|
17879
|
+
rejected_candidate_sample_size: rejectedCandidates.length,
|
|
18350
17880
|
within_timebox: withinTimebox.length,
|
|
18351
17881
|
final_records: ranked.length,
|
|
18352
17882
|
failed_sources: execution.searchRuns.filter((run) => !run.result.ok).map((run) => run.source),
|
|
@@ -18361,15 +17891,22 @@ var runResearchWorkflow = async (runtime, input) => {
|
|
|
18361
17891
|
transcriptDurability,
|
|
18362
17892
|
cookie_diagnostics: cookieDiagnostics,
|
|
18363
17893
|
cookieDiagnostics,
|
|
17894
|
+
challenge_orchestration: challengeOrchestration,
|
|
17895
|
+
challengeOrchestration,
|
|
18364
17896
|
anti_bot_pressure: antiBotPressure,
|
|
18365
17897
|
antiBotPressure
|
|
18366
17898
|
},
|
|
18367
17899
|
failures: mergedFailures,
|
|
17900
|
+
rejected_candidates: rejectedCandidates,
|
|
17901
|
+
rejectedCandidates,
|
|
18368
17902
|
alerts: buildWorkflowAlerts(runtime, mergedFailures)
|
|
18369
17903
|
}, primaryConstraintFailures);
|
|
18370
17904
|
const handoff = buildResearchSuccessHandoff({
|
|
18371
17905
|
topic: plan.compiled.topic,
|
|
18372
|
-
browserMode: workflowInput.browserMode
|
|
17906
|
+
browserMode: workflowInput.browserMode,
|
|
17907
|
+
failures: mergedFailures,
|
|
17908
|
+
cookieDiagnostics,
|
|
17909
|
+
challengeOrchestration
|
|
18373
17910
|
});
|
|
18374
17911
|
const responseMeta = withFollowthroughMeta(meta, handoff);
|
|
18375
17912
|
const rendered = renderResearch({
|
|
@@ -18380,7 +17917,7 @@ var runResearchWorkflow = async (runtime, input) => {
|
|
|
18380
17917
|
});
|
|
18381
17918
|
const bundle = await createArtifactBundle({
|
|
18382
17919
|
namespace: "research",
|
|
18383
|
-
outputDir:
|
|
17920
|
+
outputDir: artifactRoot,
|
|
18384
17921
|
ttlHours: workflowInput.ttlHours,
|
|
18385
17922
|
files: rendered.files
|
|
18386
17923
|
});
|
|
@@ -18388,7 +17925,7 @@ var runResearchWorkflow = async (runtime, input) => {
|
|
|
18388
17925
|
return {
|
|
18389
17926
|
...rendered.response,
|
|
18390
17927
|
...handoff,
|
|
18391
|
-
|
|
17928
|
+
artifact_path: bundle.basePath,
|
|
18392
17929
|
records: ranked,
|
|
18393
17930
|
meta: {
|
|
18394
17931
|
...responseMeta,
|
|
@@ -18412,7 +17949,9 @@ var runShoppingWorkflow = async (runtime, input) => {
|
|
|
18412
17949
|
if (envelope.kind !== "shopping") {
|
|
18413
17950
|
throw new Error(`Shopping workflow envelope kind mismatch. Expected shopping but received ${envelope.kind}.`);
|
|
18414
17951
|
}
|
|
18415
|
-
const
|
|
17952
|
+
const rawWorkflowInput = envelope.input;
|
|
17953
|
+
const artifactRoot = resolveWorkflowArtifactRoot(rawWorkflowInput.outputDir);
|
|
17954
|
+
const workflowInput = { ...rawWorkflowInput, outputDir: artifactRoot };
|
|
18416
17955
|
const remainingTimeoutMs = createRemainingTimeoutResolver(workflowInput.timeoutMs);
|
|
18417
17956
|
let trace = [
|
|
18418
17957
|
...envelope.trace ?? [],
|
|
@@ -18566,7 +18105,7 @@ var runShoppingWorkflow = async (runtime, input) => {
|
|
|
18566
18105
|
});
|
|
18567
18106
|
const bundle = await createArtifactBundle({
|
|
18568
18107
|
namespace: "shopping",
|
|
18569
|
-
outputDir:
|
|
18108
|
+
outputDir: artifactRoot,
|
|
18570
18109
|
ttlHours: workflowInput.ttlHours,
|
|
18571
18110
|
files: rendered.files
|
|
18572
18111
|
});
|
|
@@ -18574,7 +18113,7 @@ var runShoppingWorkflow = async (runtime, input) => {
|
|
|
18574
18113
|
return {
|
|
18575
18114
|
...rendered.response,
|
|
18576
18115
|
...handoff,
|
|
18577
|
-
|
|
18116
|
+
artifact_path: bundle.basePath,
|
|
18578
18117
|
offers,
|
|
18579
18118
|
meta: {
|
|
18580
18119
|
...responseMeta,
|
|
@@ -18594,7 +18133,9 @@ var runShoppingWorkflow = async (runtime, input) => {
|
|
|
18594
18133
|
};
|
|
18595
18134
|
};
|
|
18596
18135
|
var runInspiredesignWorkflow = async (runtime, input, options = {}) => {
|
|
18597
|
-
const { envelope, workflowInput } = buildInspiredesignEnvelope(input);
|
|
18136
|
+
const { envelope, workflowInput: rawWorkflowInput } = buildInspiredesignEnvelope(input);
|
|
18137
|
+
const artifactRoot = resolveWorkflowArtifactRoot(rawWorkflowInput.outputDir);
|
|
18138
|
+
const workflowInput = { ...rawWorkflowInput, outputDir: artifactRoot };
|
|
18598
18139
|
const remainingTimeoutMs = createRemainingTimeoutResolver(workflowInput.timeoutMs);
|
|
18599
18140
|
let trace = appendWorkflowTrace(envelope.trace ?? [], "compile", "compile_started", {
|
|
18600
18141
|
kind: "inspiredesign"
|
|
@@ -18668,14 +18209,14 @@ var runInspiredesignWorkflow = async (runtime, input, options = {}) => {
|
|
|
18668
18209
|
});
|
|
18669
18210
|
const bundle = await createArtifactBundle({
|
|
18670
18211
|
namespace: "inspiredesign",
|
|
18671
|
-
outputDir:
|
|
18212
|
+
outputDir: artifactRoot,
|
|
18672
18213
|
ttlHours: workflowInput.ttlHours,
|
|
18673
18214
|
files: rendered.files
|
|
18674
18215
|
});
|
|
18675
18216
|
if (workflowInput.mode === "path") {
|
|
18676
18217
|
return {
|
|
18677
18218
|
...rendered.response,
|
|
18678
|
-
|
|
18219
|
+
artifact_path: bundle.basePath,
|
|
18679
18220
|
meta: {
|
|
18680
18221
|
...meta,
|
|
18681
18222
|
artifact_manifest: bundle.manifest
|
|
@@ -18724,7 +18265,9 @@ var runProductVideoWorkflow = async (runtime, input, options = {}) => {
|
|
|
18724
18265
|
}
|
|
18725
18266
|
}
|
|
18726
18267
|
];
|
|
18727
|
-
const
|
|
18268
|
+
const rawWorkflowInput = plan.input;
|
|
18269
|
+
const productVideoArtifactRoot = resolveWorkflowArtifactRoot(rawWorkflowInput.output_dir);
|
|
18270
|
+
const workflowInput = { ...rawWorkflowInput, output_dir: productVideoArtifactRoot };
|
|
18728
18271
|
const includeScreenshots = plan.compiled.includeScreenshots;
|
|
18729
18272
|
const includeAllImages = plan.compiled.includeAllImages;
|
|
18730
18273
|
const includeCopy = plan.compiled.includeCopy;
|
|
@@ -18804,6 +18347,8 @@ var runProductVideoWorkflow = async (runtime, input, options = {}) => {
|
|
|
18804
18347
|
query: resolveStep.input.product_name,
|
|
18805
18348
|
providers: providerHint ? [providerHint] : void 0,
|
|
18806
18349
|
mode: "json",
|
|
18350
|
+
outputDir: productVideoArtifactRoot,
|
|
18351
|
+
ttlHours: workflowInput.ttl_hours,
|
|
18807
18352
|
...timeoutOptions,
|
|
18808
18353
|
browserMode: workflowInput.browserMode,
|
|
18809
18354
|
useCookies: workflowInput.useCookies,
|
|
@@ -19025,11 +18570,10 @@ var runProductVideoWorkflow = async (runtime, input, options = {}) => {
|
|
|
19025
18570
|
files: files.length
|
|
19026
18571
|
});
|
|
19027
18572
|
const bundle = await createArtifactBundle({
|
|
19028
|
-
namespace: "product-
|
|
19029
|
-
outputDir:
|
|
18573
|
+
namespace: "product-video",
|
|
18574
|
+
outputDir: productVideoArtifactRoot,
|
|
19030
18575
|
ttlHours: workflowInput.ttl_hours,
|
|
19031
|
-
files
|
|
19032
|
-
manifestFileName: "bundle-manifest.json"
|
|
18576
|
+
files
|
|
19033
18577
|
});
|
|
19034
18578
|
const reasonCodeDistribution = summarizeReasonCodeDistribution(details.failures);
|
|
19035
18579
|
const transcriptStrategyFailures = summarizeTranscriptStrategyFailures(details.failures);
|
|
@@ -19069,7 +18613,7 @@ var runProductVideoWorkflow = async (runtime, input, options = {}) => {
|
|
|
19069
18613
|
}, handoff);
|
|
19070
18614
|
return {
|
|
19071
18615
|
...handoff,
|
|
19072
|
-
|
|
18616
|
+
artifact_path: bundle.basePath,
|
|
19073
18617
|
manifest: manifestPayload,
|
|
19074
18618
|
product: productPayload,
|
|
19075
18619
|
pricing,
|
|
@@ -19123,7 +18667,10 @@ var buildSocialDefaultTraversal = (platform, options) => {
|
|
|
19123
18667
|
...existing ?? {}
|
|
19124
18668
|
};
|
|
19125
18669
|
};
|
|
19126
|
-
var shouldRecoverSocialDocumentIssue = (platform, operation, issue) => {
|
|
18670
|
+
var shouldRecoverSocialDocumentIssue = (platform, operation, issue, context) => {
|
|
18671
|
+
if (isResearchSearchDiscoveryRun(operation, context)) {
|
|
18672
|
+
return false;
|
|
18673
|
+
}
|
|
19127
18674
|
if (SOCIAL_BROWSER_RECOVERY_REASON_CODES.has(issue.reasonCode)) {
|
|
19128
18675
|
return true;
|
|
19129
18676
|
}
|
|
@@ -19132,7 +18679,7 @@ var shouldRecoverSocialDocumentIssue = (platform, operation, issue) => {
|
|
|
19132
18679
|
}
|
|
19133
18680
|
return operation === "search" && SEARCH_RENDER_RECOVERY_SOCIAL_PLATFORMS.has(platform) && issue.reasonCode === "env_limited" && issue.constraint?.kind === "render_required";
|
|
19134
18681
|
};
|
|
19135
|
-
var
|
|
18682
|
+
var isJsonRecord8 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
19136
18683
|
var unwrapWorkflowResumeEnvelope = (kind, input) => {
|
|
19137
18684
|
if (!isWorkflowResumePayload(input)) {
|
|
19138
18685
|
throw new ProviderRuntimeError(
|
|
@@ -19185,10 +18732,10 @@ var Semaphore = class {
|
|
|
19185
18732
|
this.active += 1;
|
|
19186
18733
|
return;
|
|
19187
18734
|
}
|
|
19188
|
-
await new Promise((
|
|
18735
|
+
await new Promise((resolve) => {
|
|
19189
18736
|
this.queue.push(() => {
|
|
19190
18737
|
this.active += 1;
|
|
19191
|
-
|
|
18738
|
+
resolve();
|
|
19192
18739
|
});
|
|
19193
18740
|
});
|
|
19194
18741
|
}
|
|
@@ -19367,7 +18914,7 @@ var isBlockedRedditFallbackLink = (link) => {
|
|
|
19367
18914
|
return false;
|
|
19368
18915
|
}
|
|
19369
18916
|
};
|
|
19370
|
-
var shouldOwnerReviewCommunityRedditSearchFallback = (input) => input.providerId === "community/default" && input.source === "community" && input.operation === "search" && isFirstPartySocialSearchRoute("reddit", input.url) && input.extracted.links.length > 0 && input.extracted.links.every(isBlockedRedditFallbackLink);
|
|
18917
|
+
var shouldOwnerReviewCommunityRedditSearchFallback = (input) => input.providerId === "community/default" && input.source === "community" && input.operation === "search" && isFirstPartySocialSearchRoute("reddit", input.url) && (hasUsableCommunityFallbackSearchContent(input.extracted.text) || input.extracted.links.length > 0 && input.extracted.links.every(isBlockedRedditFallbackLink));
|
|
19371
18918
|
var shouldReturnCompletedFallbackForOwnerReview = (args) => args.document.browserFallback !== void 0 && args.ownerReview?.({
|
|
19372
18919
|
providerId: args.providerId,
|
|
19373
18920
|
source: args.source,
|
|
@@ -19440,6 +18987,8 @@ var describeDefaultFetchedIssue = (document) => {
|
|
|
19440
18987
|
};
|
|
19441
18988
|
};
|
|
19442
18989
|
var shouldRecoverDefaultFetchedIssue = (issue) => issue.reasonCode === "challenge_detected" || issue.reasonCode === "token_required" || issue.reasonCode === "env_limited" && !!issue.constraint;
|
|
18990
|
+
var isUsableCommunityRedditSearchFallback = (args) => args.source === "community" && args.operation === "search" && args.document.browserFallback !== void 0 && isFirstPartySocialSearchRoute("reddit", args.document.url) && hasUsableCommunityFallbackSearchContent(args.pageMessage);
|
|
18991
|
+
var isResearchSearchDiscoveryRun = (operation, context) => operation === "search" && context.suspendedIntent?.kind === "workflow.research";
|
|
19443
18992
|
var toDefaultFetchedIssueError = (args) => {
|
|
19444
18993
|
const reasonCode = args.issueDetails.issue?.reasonCode ?? "env_limited";
|
|
19445
18994
|
return new ProviderRuntimeError(
|
|
@@ -19464,6 +19013,14 @@ var resolveDefaultFallbackDocumentIfNeeded = async (args) => {
|
|
|
19464
19013
|
if (!initialIssue) {
|
|
19465
19014
|
return { document: currentDocument, ...described };
|
|
19466
19015
|
}
|
|
19016
|
+
if (isUsableCommunityRedditSearchFallback({
|
|
19017
|
+
source: args.source,
|
|
19018
|
+
operation: args.operation,
|
|
19019
|
+
document: currentDocument,
|
|
19020
|
+
pageMessage: described.pageMessage
|
|
19021
|
+
})) {
|
|
19022
|
+
return { document: currentDocument, ...described, issue: null };
|
|
19023
|
+
}
|
|
19467
19024
|
if (shouldReturnCompletedFallbackForOwnerReview({ ...args, document: currentDocument })) {
|
|
19468
19025
|
return { document: currentDocument, ...described };
|
|
19469
19026
|
}
|
|
@@ -19506,6 +19063,14 @@ var resolveDefaultFallbackDocumentIfNeeded = async (args) => {
|
|
|
19506
19063
|
ownerReview: args.ownerReview
|
|
19507
19064
|
});
|
|
19508
19065
|
described = describeDefaultFetchedIssue(currentDocument);
|
|
19066
|
+
if (isUsableCommunityRedditSearchFallback({
|
|
19067
|
+
source: args.source,
|
|
19068
|
+
operation: args.operation,
|
|
19069
|
+
document: currentDocument,
|
|
19070
|
+
pageMessage: described.pageMessage
|
|
19071
|
+
})) {
|
|
19072
|
+
return { document: currentDocument, ...described, issue: null };
|
|
19073
|
+
}
|
|
19509
19074
|
if (shouldReturnCompletedFallbackForOwnerReview({ ...args, document: currentDocument })) {
|
|
19510
19075
|
return { document: currentDocument, ...described };
|
|
19511
19076
|
}
|
|
@@ -19522,16 +19087,32 @@ var resolveDefaultFallbackDocumentIfNeeded = async (args) => {
|
|
|
19522
19087
|
};
|
|
19523
19088
|
var COMMUNITY_SEARCH_LINK_SCAN_MULTIPLIER = 4;
|
|
19524
19089
|
var MIN_COMMUNITY_SEARCH_LINK_SCAN = 12;
|
|
19525
|
-
var resolveCommunitySearchLinks = (document, limit) => {
|
|
19090
|
+
var resolveCommunitySearchLinks = (document, limit, researchContext) => {
|
|
19526
19091
|
const scanLimit = Math.max(limit * COMMUNITY_SEARCH_LINK_SCAN_MULTIPLIER, MIN_COMMUNITY_SEARCH_LINK_SCAN);
|
|
19527
19092
|
const links = prioritizeSocialSearchLinks(
|
|
19528
19093
|
"reddit",
|
|
19529
19094
|
document.url,
|
|
19530
19095
|
dedupeLinks2(document.links, document.url, scanLimit)
|
|
19531
19096
|
);
|
|
19532
|
-
return links.filter((url) => isAllowedSocialSearchExpansionUrl("reddit", url)).slice(0, limit);
|
|
19097
|
+
return links.filter((url) => researchContext ? isLikelyResearchDestinationUrl(url) : isLikelyDocumentUrl(url)).filter((url) => isAllowedSocialSearchExpansionUrl("reddit", url)).slice(0, limit);
|
|
19098
|
+
};
|
|
19099
|
+
var shouldRejectBlockedCommunityFallback = (document, links, pageMessage) => document.browserFallback !== void 0 && isFirstPartySocialSearchRoute("reddit", document.url) && links.length === 0 && !hasUsableCommunityFallbackSearchContent(pageMessage);
|
|
19100
|
+
var COMMUNITY_FALLBACK_SEARCH_MIN_CHARS = 120;
|
|
19101
|
+
var COMMUNITY_FALLBACK_SEARCH_EVIDENCE_RE = [
|
|
19102
|
+
/\bshowing results for\b/i,
|
|
19103
|
+
/\bsearch for\b/i,
|
|
19104
|
+
/\banswers?\b/i,
|
|
19105
|
+
/\bsources?:\s+/i,
|
|
19106
|
+
/\br\/[a-z0-9_]+\b/i
|
|
19107
|
+
];
|
|
19108
|
+
var hasUsableCommunityFallbackSearchContent = (pageMessage) => {
|
|
19109
|
+
const trimmed = pageMessage.trim();
|
|
19110
|
+
if (trimmed.length < COMMUNITY_FALLBACK_SEARCH_MIN_CHARS) {
|
|
19111
|
+
return false;
|
|
19112
|
+
}
|
|
19113
|
+
const evidenceCount = COMMUNITY_FALLBACK_SEARCH_EVIDENCE_RE.filter((pattern) => pattern.test(trimmed)).length;
|
|
19114
|
+
return evidenceCount >= 2;
|
|
19533
19115
|
};
|
|
19534
|
-
var shouldRejectBlockedCommunityFallback = (document, links) => document.browserFallback !== void 0 && isFirstPartySocialSearchRoute("reddit", document.url) && links.length === 0;
|
|
19535
19116
|
var toCommunityFallbackSearchError = (args) => {
|
|
19536
19117
|
const reasonCode = args.document.browserFallback?.reasonCode ?? "env_limited";
|
|
19537
19118
|
return new ProviderRuntimeError(
|
|
@@ -19646,6 +19227,36 @@ var dedupeLinks2 = (links, baseUrl, limit) => {
|
|
|
19646
19227
|
}
|
|
19647
19228
|
return deduped;
|
|
19648
19229
|
};
|
|
19230
|
+
var isUsableWebSearchResultUrl = (url, researchContext) => !isDuckDuckGoSearchShellUrl(url) && (researchContext ? isLikelyResearchDestinationUrl(url) : isLikelyDocumentUrl(url));
|
|
19231
|
+
var isResearchWorkflowContext = (context) => context.suspendedIntent?.kind === "workflow.research";
|
|
19232
|
+
var resolveWebSearchResultLinks = (document, limit, researchContext, includeDocumentUrl) => {
|
|
19233
|
+
const links = dedupeLinks2(document.links, document.url, limit * 2);
|
|
19234
|
+
const candidates = includeDocumentUrl ? [document.url, ...links] : links;
|
|
19235
|
+
const seen = /* @__PURE__ */ new Set();
|
|
19236
|
+
return candidates.filter((url) => {
|
|
19237
|
+
const keep = isUsableWebSearchResultUrl(url, researchContext) && !seen.has(url);
|
|
19238
|
+
if (keep) seen.add(url);
|
|
19239
|
+
return keep;
|
|
19240
|
+
}).slice(0, limit);
|
|
19241
|
+
};
|
|
19242
|
+
var toResearchDeadEndSearchError = (args) => new ProviderRuntimeError(
|
|
19243
|
+
"unavailable",
|
|
19244
|
+
`Research search resolved only dead-end pages for ${args.document.url}`,
|
|
19245
|
+
{
|
|
19246
|
+
provider: args.providerId,
|
|
19247
|
+
source: args.source,
|
|
19248
|
+
retryable: false,
|
|
19249
|
+
reasonCode: "policy_blocked",
|
|
19250
|
+
details: {
|
|
19251
|
+
status: args.document.status,
|
|
19252
|
+
url: args.document.url,
|
|
19253
|
+
...args.document.browserFallback?.reasonCode ? { browserFallbackReasonCode: args.document.browserFallback.reasonCode } : {},
|
|
19254
|
+
retrievalPath: args.retrievalPath,
|
|
19255
|
+
fallbackOutputReason: "research_dead_end_shell",
|
|
19256
|
+
...browserFallbackObservationDetails(args.document.browserFallback)
|
|
19257
|
+
}
|
|
19258
|
+
}
|
|
19259
|
+
);
|
|
19649
19260
|
var RUNTIME_FALLBACK_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
19650
19261
|
"auth",
|
|
19651
19262
|
"rate_limited",
|
|
@@ -19785,6 +19396,7 @@ var readResponseTextWithAbort = async (response, args) => {
|
|
|
19785
19396
|
}
|
|
19786
19397
|
};
|
|
19787
19398
|
var fetchRuntimeDocumentWithFallback = async (args) => {
|
|
19399
|
+
const researchSearchDiscovery = args.context !== void 0 && isResearchSearchDiscoveryRun(args.operation, args.context);
|
|
19788
19400
|
const fallbackPort = args.context?.browserFallbackPort ?? args.browserFallbackPort;
|
|
19789
19401
|
const runtimePolicy = args.context?.runtimePolicy;
|
|
19790
19402
|
const forcedBrowserTransport = runtimePolicy?.browser.forceTransport === true;
|
|
@@ -19851,6 +19463,9 @@ var fetchRuntimeDocumentWithFallback = async (args) => {
|
|
|
19851
19463
|
if (args.recoverRuntimeErrors === false) {
|
|
19852
19464
|
throw error;
|
|
19853
19465
|
}
|
|
19466
|
+
if (researchSearchDiscovery) {
|
|
19467
|
+
throw error;
|
|
19468
|
+
}
|
|
19854
19469
|
if (!fallbackPort) {
|
|
19855
19470
|
throw error;
|
|
19856
19471
|
}
|
|
@@ -20216,8 +19831,9 @@ var ProviderRuntime = class {
|
|
|
20216
19831
|
};
|
|
20217
19832
|
}
|
|
20218
19833
|
async executeAll(providers, operation, input, trace, timeoutMs, selection, startedAt, tierMetadata, providerIds, runOptions = {}) {
|
|
20219
|
-
const results = await
|
|
20220
|
-
providers
|
|
19834
|
+
const results = await this.mapProvidersBounded(
|
|
19835
|
+
providers,
|
|
19836
|
+
(provider) => this.invokeProvider(provider, operation, input, trace, timeoutMs, tierMetadata, runOptions)
|
|
20221
19837
|
);
|
|
20222
19838
|
const records = [];
|
|
20223
19839
|
const failures = [];
|
|
@@ -20260,8 +19876,9 @@ var ProviderRuntime = class {
|
|
|
20260
19876
|
}
|
|
20261
19877
|
});
|
|
20262
19878
|
}
|
|
20263
|
-
const fallbackResults = await
|
|
20264
|
-
fallbackProviders
|
|
19879
|
+
const fallbackResults = await this.mapProvidersBounded(
|
|
19880
|
+
fallbackProviders,
|
|
19881
|
+
(provider) => this.invokeProvider(provider, operation, input, trace, timeoutMs, fallbackTier, runOptions)
|
|
20265
19882
|
);
|
|
20266
19883
|
for (const result of fallbackResults) {
|
|
20267
19884
|
attempted += 1;
|
|
@@ -20308,6 +19925,9 @@ var ProviderRuntime = class {
|
|
|
20308
19925
|
...!ok && failures[0] ? { error: failures[0].error } : {}
|
|
20309
19926
|
};
|
|
20310
19927
|
}
|
|
19928
|
+
async mapProvidersBounded(providers, task) {
|
|
19929
|
+
return mapBounded(providers, this.budgets.concurrency.global, task);
|
|
19930
|
+
}
|
|
20311
19931
|
async invokeProvider(provider, operation, input, trace, timeoutMs, tierMetadata, runOptions) {
|
|
20312
19932
|
const startedAt = Date.now();
|
|
20313
19933
|
const scopeKey = this.resolveScopeKey(provider.id, operation, input);
|
|
@@ -20691,7 +20311,7 @@ var ProviderRuntime = class {
|
|
|
20691
20311
|
}
|
|
20692
20312
|
async resumeSuspendedIntent(intent, options) {
|
|
20693
20313
|
const input = intent.input;
|
|
20694
|
-
if (!
|
|
20314
|
+
if (!isJsonRecord8(input)) {
|
|
20695
20315
|
throw new ProviderRuntimeError("invalid_input", "Suspended intent input is missing or malformed.", {
|
|
20696
20316
|
retryable: false
|
|
20697
20317
|
});
|
|
@@ -20779,7 +20399,7 @@ var ProviderRuntime = class {
|
|
|
20779
20399
|
return providers.some((provider) => provider.source !== "web");
|
|
20780
20400
|
}
|
|
20781
20401
|
resolveScopeKey(providerId, operation, input) {
|
|
20782
|
-
const
|
|
20402
|
+
const extractHost = (value) => {
|
|
20783
20403
|
if (!value) return null;
|
|
20784
20404
|
try {
|
|
20785
20405
|
return new URL(value).hostname.toLowerCase();
|
|
@@ -20788,14 +20408,14 @@ var ProviderRuntime = class {
|
|
|
20788
20408
|
}
|
|
20789
20409
|
};
|
|
20790
20410
|
if (operation === "fetch") {
|
|
20791
|
-
return
|
|
20411
|
+
return extractHost(input.url) ?? providerId;
|
|
20792
20412
|
}
|
|
20793
20413
|
if (operation === "crawl") {
|
|
20794
20414
|
const first = input.seedUrls[0];
|
|
20795
|
-
return
|
|
20415
|
+
return extractHost(first) ?? providerId;
|
|
20796
20416
|
}
|
|
20797
20417
|
if (operation === "search") {
|
|
20798
|
-
return
|
|
20418
|
+
return extractHost(input.query) ?? providerId;
|
|
20799
20419
|
}
|
|
20800
20420
|
return providerId;
|
|
20801
20421
|
}
|
|
@@ -20973,9 +20593,18 @@ var withDefaultWebOptions = (options, browserFallbackPort) => {
|
|
|
20973
20593
|
browserFallbackPort
|
|
20974
20594
|
});
|
|
20975
20595
|
const limit = Math.max(1, Math.min(input.limit ?? 5, 10));
|
|
20976
|
-
const
|
|
20596
|
+
const researchContext = isResearchWorkflowContext(context);
|
|
20597
|
+
const links = resolveWebSearchResultLinks(document, limit, researchContext, researchContext || isHttpUrl7(query));
|
|
20977
20598
|
const searchPath = isHttpUrl7(query) ? "web:search:url" : "web:search:index";
|
|
20978
20599
|
if (links.length === 0) {
|
|
20600
|
+
if (researchContext && !isUsableWebSearchResultUrl(document.url, true)) {
|
|
20601
|
+
throw toResearchDeadEndSearchError({
|
|
20602
|
+
providerId,
|
|
20603
|
+
source: "web",
|
|
20604
|
+
document,
|
|
20605
|
+
retrievalPath: searchPath
|
|
20606
|
+
});
|
|
20607
|
+
}
|
|
20979
20608
|
return [{
|
|
20980
20609
|
url: document.url,
|
|
20981
20610
|
title: document.url,
|
|
@@ -21018,6 +20647,14 @@ var withDefaultCommunityOptions = (options, browserFallbackPort) => {
|
|
|
21018
20647
|
...browserFallbackObservationAttributes(args.document.browserFallback)
|
|
21019
20648
|
};
|
|
21020
20649
|
if (args.links.length === 0) {
|
|
20650
|
+
if (isResearchWorkflowContext(args.context) && !isLikelyResearchDestinationUrl(args.document.url)) {
|
|
20651
|
+
throw toResearchDeadEndSearchError({
|
|
20652
|
+
providerId,
|
|
20653
|
+
source: "community",
|
|
20654
|
+
document: args.document,
|
|
20655
|
+
retrievalPath: searchPath
|
|
20656
|
+
});
|
|
20657
|
+
}
|
|
21021
20658
|
return [{
|
|
21022
20659
|
url: args.document.url,
|
|
21023
20660
|
title: isHttpUrl7(args.query) ? args.document.url : `Community search: ${args.query}`,
|
|
@@ -21059,8 +20696,8 @@ var withDefaultCommunityOptions = (options, browserFallbackPort) => {
|
|
|
21059
20696
|
browserFallbackPort,
|
|
21060
20697
|
ownerReview: shouldOwnerReviewCommunityRedditSearchFallback
|
|
21061
20698
|
});
|
|
21062
|
-
const links = resolveCommunitySearchLinks(resolvedDocument, limit);
|
|
21063
|
-
if (shouldRejectBlockedCommunityFallback(resolvedDocument, links)) {
|
|
20699
|
+
const links = resolveCommunitySearchLinks(resolvedDocument, limit, isResearchWorkflowContext(context));
|
|
20700
|
+
if (shouldRejectBlockedCommunityFallback(resolvedDocument, links, pageMessage)) {
|
|
21064
20701
|
throw toCommunityFallbackSearchError({
|
|
21065
20702
|
providerId,
|
|
21066
20703
|
document: resolvedDocument,
|
|
@@ -21072,7 +20709,8 @@ var withDefaultCommunityOptions = (options, browserFallbackPort) => {
|
|
|
21072
20709
|
page,
|
|
21073
20710
|
document: resolvedDocument,
|
|
21074
20711
|
pageMessage,
|
|
21075
|
-
links
|
|
20712
|
+
links,
|
|
20713
|
+
context
|
|
21076
20714
|
});
|
|
21077
20715
|
}),
|
|
21078
20716
|
fetch: options?.fetch ?? (async (input, context) => {
|
|
@@ -21185,7 +20823,7 @@ var withDefaultSocialPlatformOptions = (platform, options, browserFallbackPort)
|
|
|
21185
20823
|
if (initialIssue.reasonCode === "env_limited" && !initialIssue.constraint) {
|
|
21186
20824
|
return { document: currentDocument, ...described };
|
|
21187
20825
|
}
|
|
21188
|
-
if (!shouldRecoverSocialDocumentIssue(platform, operation, initialIssue)) {
|
|
20826
|
+
if (!shouldRecoverSocialDocumentIssue(platform, operation, initialIssue, context)) {
|
|
21189
20827
|
throw toIssueError(currentDocument, described);
|
|
21190
20828
|
}
|
|
21191
20829
|
const fallback = await resolveProviderBrowserFallback({
|
|
@@ -21374,19 +21012,6 @@ var mergeBudgets = (base, partial) => {
|
|
|
21374
21012
|
};
|
|
21375
21013
|
|
|
21376
21014
|
export {
|
|
21377
|
-
redactSensitive,
|
|
21378
|
-
createRequestId,
|
|
21379
|
-
stderrSink,
|
|
21380
|
-
setDefaultLogSink,
|
|
21381
|
-
createLogger,
|
|
21382
|
-
DEFAULT_BLOCKER_ARTIFACT_CAPS,
|
|
21383
|
-
clampBlockerConfidence,
|
|
21384
|
-
clampText,
|
|
21385
|
-
boundedUniqueList,
|
|
21386
|
-
resolveBlockerArtifactCaps,
|
|
21387
|
-
classifyBlockerSignal,
|
|
21388
|
-
buildBlockerArtifacts,
|
|
21389
|
-
__test__,
|
|
21390
21015
|
CHALLENGE_AUTOMATION_MODES,
|
|
21391
21016
|
isChallengeAutomationMode,
|
|
21392
21017
|
resolveChallengeAutomationPolicy,
|
|
@@ -21411,7 +21036,6 @@ export {
|
|
|
21411
21036
|
CANVAS_BROWSER_VALIDATION_MODES,
|
|
21412
21037
|
CANVAS_VALIDATION_TARGET_BLOCK_ON_CODES,
|
|
21413
21038
|
CANVAS_PUBLIC_WARNING_CLASSES,
|
|
21414
|
-
summarizePrimaryProviderIssue,
|
|
21415
21039
|
createTraceContext,
|
|
21416
21040
|
clampConfidence,
|
|
21417
21041
|
createStableRecordId,
|
|
@@ -21439,17 +21063,13 @@ export {
|
|
|
21439
21063
|
createShoppingProviders,
|
|
21440
21064
|
createShoppingProviderById,
|
|
21441
21065
|
createWebProvider,
|
|
21442
|
-
|
|
21443
|
-
|
|
21444
|
-
createArtifactBundle,
|
|
21445
|
-
cleanupExpiredArtifacts,
|
|
21066
|
+
WORKFLOW_ARTIFACT_DIRECTORY,
|
|
21067
|
+
resolveWorkflowArtifactRoot,
|
|
21446
21068
|
resolveTimebox,
|
|
21447
21069
|
isWithinTimebox,
|
|
21448
21070
|
filterByTimebox,
|
|
21449
21071
|
toResearchRecord,
|
|
21450
21072
|
enrichResearchRecords,
|
|
21451
|
-
INSPIREDESIGN_HANDOFF_COMMANDS,
|
|
21452
|
-
INSPIREDESIGN_HANDOFF_GUIDANCE,
|
|
21453
21073
|
buildMacroResolveSuccessHandoff,
|
|
21454
21074
|
renderResearch,
|
|
21455
21075
|
renderShopping,
|
|
@@ -21465,4 +21085,4 @@ export {
|
|
|
21465
21085
|
createProviderRuntime,
|
|
21466
21086
|
createDefaultRuntime
|
|
21467
21087
|
};
|
|
21468
|
-
//# sourceMappingURL=chunk-
|
|
21088
|
+
//# sourceMappingURL=chunk-4BEJVZRK.js.map
|