opendevbrowser 0.0.28 → 0.0.29
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-PA6NWNS7.js +39 -0
- package/dist/accessibility-snapshot-PA6NWNS7.js.map +1 -0
- package/dist/active-window-YNYTIPZN.js +37 -0
- package/dist/active-window-YNYTIPZN.js.map +1 -0
- package/dist/annotate-STYHXZYJ.js +205 -0
- package/dist/annotate-STYHXZYJ.js.map +1 -0
- package/dist/artifacts-KJ6RNDO2.js +120 -0
- package/dist/artifacts-KJ6RNDO2.js.map +1 -0
- package/dist/attr-GHFZZ4SA.js +84 -0
- package/dist/attr-GHFZZ4SA.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-54FBOEGP.js +309 -0
- package/dist/canvas-54FBOEGP.js.map +1 -0
- package/dist/capture-desktop-SNABC24E.js +38 -0
- package/dist/capture-desktop-SNABC24E.js.map +1 -0
- package/dist/capture-window-UJSB5AMP.js +40 -0
- package/dist/capture-window-UJSB5AMP.js.map +1 -0
- package/dist/check-ST5UQ2F5.js +71 -0
- package/dist/check-ST5UQ2F5.js.map +1 -0
- package/dist/checked-IEMWI5CU.js +71 -0
- package/dist/checked-IEMWI5CU.js.map +1 -0
- package/dist/chunk-2CG4SW3E.js +64 -0
- package/dist/chunk-2CG4SW3E.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-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-ASMHEEKY.js +10 -0
- package/dist/chunk-ASMHEEKY.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-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-LBPELU7L.js +3649 -0
- package/dist/chunk-LBPELU7L.js.map +1 -0
- package/dist/chunk-MX3NFLCE.js +940 -0
- package/dist/chunk-MX3NFLCE.js.map +1 -0
- package/dist/chunk-N44UXKIB.js +26 -0
- package/dist/chunk-N44UXKIB.js.map +1 -0
- package/dist/chunk-OW5HMYMI.js +19 -0
- package/dist/chunk-OW5HMYMI.js.map +1 -0
- package/dist/chunk-OYNLAZQU.js +838 -0
- package/dist/chunk-OYNLAZQU.js.map +1 -0
- package/dist/chunk-PDPJN2OP.js +17 -0
- package/dist/chunk-PDPJN2OP.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-T3VVHJTK.js → chunk-S6S2UP6U.js} +1074 -1459
- package/dist/chunk-S6S2UP6U.js.map +1 -0
- package/dist/{chunk-I5ZCOZZV.js → chunk-SXAGSEKZ.js} +1202 -9561
- package/dist/chunk-SXAGSEKZ.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-TENZA3Y6.js +81 -0
- package/dist/click-TENZA3Y6.js.map +1 -0
- package/dist/clone-component-STH5AR6M.js +82 -0
- package/dist/clone-component-STH5AR6M.js.map +1 -0
- package/dist/clone-page-BSTWAPAJ.js +69 -0
- package/dist/clone-page-BSTWAPAJ.js.map +1 -0
- package/dist/close-CEMMAAM7.js +63 -0
- package/dist/close-CEMMAAM7.js.map +1 -0
- package/dist/close-QCWUNRAI.js +63 -0
- package/dist/close-QCWUNRAI.js.map +1 -0
- package/dist/connect-J3RVSEZF.js +107 -0
- package/dist/connect-J3RVSEZF.js.map +1 -0
- package/dist/console-poll-HL7BVIVX.js +76 -0
- package/dist/console-poll-HL7BVIVX.js.map +1 -0
- package/dist/cookie-import-WMUCIIHN.js +177 -0
- package/dist/cookie-import-WMUCIIHN.js.map +1 -0
- package/dist/cookie-list-PB2N4RPH.js +117 -0
- package/dist/cookie-list-PB2N4RPH.js.map +1 -0
- package/dist/daemon-5KSVMGN4.js +194 -0
- package/dist/daemon-5KSVMGN4.js.map +1 -0
- package/dist/daemon-fingerprint.json +1 -1
- package/dist/debug-trace-snapshot-RK7KDXA5.js +136 -0
- package/dist/debug-trace-snapshot-RK7KDXA5.js.map +1 -0
- package/dist/dialog-P6P4U7XE.js +75 -0
- package/dist/dialog-P6P4U7XE.js.map +1 -0
- package/dist/disconnect-32F7IDIP.js +58 -0
- package/dist/disconnect-32F7IDIP.js.map +1 -0
- package/dist/enabled-A6C6ZM2O.js +71 -0
- package/dist/enabled-A6C6ZM2O.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-ULTSABDM.js +98 -0
- package/dist/goto-ULTSABDM.js.map +1 -0
- package/dist/help-EKKKEDL5.js +491 -0
- package/dist/help-EKKKEDL5.js.map +1 -0
- package/dist/hover-UF2ZUMTQ.js +71 -0
- package/dist/hover-UF2ZUMTQ.js.map +1 -0
- package/dist/html-B6TX7GK7.js +84 -0
- package/dist/html-B6TX7GK7.js.map +1 -0
- package/dist/index.js +68 -34
- package/dist/index.js.map +1 -1
- package/dist/inspector-6S5FKUZQ.js +62 -0
- package/dist/inspector-6S5FKUZQ.js.map +1 -0
- package/dist/inspector-audit-ARGEGOS7.js +84 -0
- package/dist/inspector-audit-ARGEGOS7.js.map +1 -0
- package/dist/inspector-plan-CSG5HZOC.js +69 -0
- package/dist/inspector-plan-CSG5HZOC.js.map +1 -0
- package/dist/inspiredesign-7VRMMZN4.js +234 -0
- package/dist/inspiredesign-7VRMMZN4.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-REYCIR3Z.js +225 -0
- package/dist/launch-REYCIR3Z.js.map +1 -0
- package/dist/list-NPRXRQY2.js +51 -0
- package/dist/list-NPRXRQY2.js.map +1 -0
- package/dist/list-STYD2ZWA.js +54 -0
- package/dist/list-STYD2ZWA.js.map +1 -0
- package/dist/local-HXJLUUNT.js +54 -0
- package/dist/local-HXJLUUNT.js.map +1 -0
- package/dist/macro-resolve-ZIJZ65QI.js +253 -0
- package/dist/macro-resolve-ZIJZ65QI.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-HLDOSC72.js +76 -0
- package/dist/network-poll-HLDOSC72.js.map +1 -0
- package/dist/new-HXLLN6UT.js +69 -0
- package/dist/new-HXLLN6UT.js.map +1 -0
- package/dist/onboarding-metadata-7E3KLYSZ.js +27 -0
- package/dist/onboarding-metadata-7E3KLYSZ.js.map +1 -0
- package/dist/open-KDR25LQZ.js +81 -0
- package/dist/open-KDR25LQZ.js.map +1 -0
- package/dist/opendevbrowser.js +68 -34
- package/dist/opendevbrowser.js.map +1 -1
- package/dist/perf-EM6SWFJ6.js +58 -0
- package/dist/perf-EM6SWFJ6.js.map +1 -0
- package/dist/pointer-down-ZYWRZNCH.js +55 -0
- package/dist/pointer-down-ZYWRZNCH.js.map +1 -0
- package/dist/pointer-drag-LVEAVJO4.js +54 -0
- package/dist/pointer-drag-LVEAVJO4.js.map +1 -0
- package/dist/pointer-move-7SRKUS66.js +52 -0
- package/dist/pointer-move-7SRKUS66.js.map +1 -0
- package/dist/pointer-up-KLDBSK37.js +55 -0
- package/dist/pointer-up-KLDBSK37.js.map +1 -0
- package/dist/press-UIIXFTD7.js +83 -0
- package/dist/press-UIIXFTD7.js.map +1 -0
- package/dist/product-video-PYOXJVAI.js +235 -0
- package/dist/product-video-PYOXJVAI.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/workflows.d.ts.map +1 -1
- package/dist/{providers-QF2RFB4J.js → providers-4YY2BLXG.js} +19 -14
- package/dist/providers-4YY2BLXG.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-CKXMJ2DK.js +295 -0
- package/dist/research-CKXMJ2DK.js.map +1 -0
- package/dist/review-7HWJPZOD.js +48 -0
- package/dist/review-7HWJPZOD.js.map +1 -0
- package/dist/review-desktop-2IBJHFB5.js +54 -0
- package/dist/review-desktop-2IBJHFB5.js.map +1 -0
- package/dist/rpc-3HGIEJUO.js +159 -0
- package/dist/rpc-3HGIEJUO.js.map +1 -0
- package/dist/run-ADRYI3MS.js +180 -0
- package/dist/run-ADRYI3MS.js.map +1 -0
- package/dist/screencast-start-DTLUHD5H.js +67 -0
- package/dist/screencast-start-DTLUHD5H.js.map +1 -0
- package/dist/screencast-stop-54C5LRSS.js +59 -0
- package/dist/screencast-stop-54C5LRSS.js.map +1 -0
- package/dist/screenshot-HOAKR7P7.js +68 -0
- package/dist/screenshot-HOAKR7P7.js.map +1 -0
- package/dist/scroll-IAOO5COY.js +84 -0
- package/dist/scroll-IAOO5COY.js.map +1 -0
- package/dist/scroll-into-view-RKWSLAPH.js +71 -0
- package/dist/scroll-into-view-RKWSLAPH.js.map +1 -0
- package/dist/select-IGD3T6X4.js +86 -0
- package/dist/select-IGD3T6X4.js.map +1 -0
- package/dist/serve-7X4INUCU.js +498 -0
- package/dist/serve-7X4INUCU.js.map +1 -0
- package/dist/shopping-FC6DRW76.js +273 -0
- package/dist/shopping-FC6DRW76.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-X22GG324.js +113 -0
- package/dist/snapshot-X22GG324.js.map +1 -0
- package/dist/status-SP55LMNW.js +132 -0
- package/dist/status-SP55LMNW.js.map +1 -0
- package/dist/status-VH2WXIDG.js +35 -0
- package/dist/status-VH2WXIDG.js.map +1 -0
- package/dist/status-capabilities-YBERLRRA.js +57 -0
- package/dist/status-capabilities-YBERLRRA.js.map +1 -0
- package/dist/text-6TB5WNLI.js +84 -0
- package/dist/text-6TB5WNLI.js.map +1 -0
- package/dist/tools/macro_resolve.d.ts.map +1 -1
- package/dist/type-3UI3TQH3.js +94 -0
- package/dist/type-3UI3TQH3.js.map +1 -0
- package/dist/uncheck-5L3D2D4U.js +71 -0
- package/dist/uncheck-5L3D2D4U.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-YG4J2EMI.js +56 -0
- package/dist/upload-YG4J2EMI.js.map +1 -0
- package/dist/use-V3LGFP3K.js +63 -0
- package/dist/use-V3LGFP3K.js.map +1 -0
- package/dist/value-3247D57X.js +71 -0
- package/dist/value-3247D57X.js.map +1 -0
- package/dist/visible-A7HEV36U.js +71 -0
- package/dist/visible-A7HEV36U.js.map +1 -0
- package/dist/wait-UZPP4Y4R.js +109 -0
- package/dist/wait-UZPP4Y4R.js.map +1 -0
- package/dist/windows-76TR3AIP.js +37 -0
- package/dist/windows-76TR3AIP.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";
|
|
@@ -9873,123 +9087,7 @@ var isWorkflowResumePayload = (value) => isJsonRecord(value) && isWorkflowResume
|
|
|
9873
9087
|
|
|
9874
9088
|
// src/providers/workflows.ts
|
|
9875
9089
|
import { createHash as createHash7 } from "crypto";
|
|
9876
|
-
|
|
9877
|
-
// src/providers/artifacts.ts
|
|
9878
|
-
import { mkdir, readdir as readdir2, readFile, rm as rm2, stat, writeFile } from "fs/promises";
|
|
9879
|
-
import { dirname, join as join2, resolve } from "path";
|
|
9880
|
-
import { randomUUID as randomUUID3 } from "crypto";
|
|
9881
|
-
import { tmpdir as tmpdir2 } from "os";
|
|
9882
|
-
var DEFAULT_ARTIFACT_TTL_HOURS = 72;
|
|
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 };
|
|
9945
|
-
}
|
|
9946
|
-
for (const namespace of namespaces) {
|
|
9947
|
-
const namespacePath = join2(rootDir, namespace);
|
|
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
|
-
}
|
|
9990
|
-
}
|
|
9991
|
-
return { removed, skipped };
|
|
9992
|
-
};
|
|
9090
|
+
import { join as join2 } from "path";
|
|
9993
9091
|
|
|
9994
9092
|
// src/providers/timebox.ts
|
|
9995
9093
|
var MAX_DAYS = 365;
|
|
@@ -10458,232 +9556,24 @@ var design_contract_v1_default = {
|
|
|
10458
9556
|
"keyboard-regression",
|
|
10459
9557
|
"stale-search-results",
|
|
10460
9558
|
"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"]
|
|
9559
|
+
],
|
|
9560
|
+
warnOn: [
|
|
9561
|
+
"responsive-mismatch",
|
|
9562
|
+
"layout-shift",
|
|
9563
|
+
"spinner-stacking",
|
|
9564
|
+
"scan-surface-jank"
|
|
9565
|
+
]
|
|
9566
|
+
},
|
|
9567
|
+
designVectors: {
|
|
9568
|
+
advancedMotionAdvisory: [
|
|
9569
|
+
"Advisory shader-like gradient depth",
|
|
9570
|
+
"Advisory WebGL-style spatial reveal",
|
|
9571
|
+
"Advisory Spline-style product orbit",
|
|
9572
|
+
"Runtime support: none. Library policy authorization: none."
|
|
9573
|
+
]
|
|
9574
|
+
}
|
|
10683
9575
|
}
|
|
10684
9576
|
};
|
|
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
9577
|
|
|
10688
9578
|
// skills/opendevbrowser-design-agent/assets/templates/inspiredesign-advanced-brief.v1.json
|
|
10689
9579
|
var inspiredesign_advanced_brief_v1_default = {
|
|
@@ -14287,10 +13177,111 @@ var createSuccessHandoff = (followthroughSummary, suggestedNextAction, suggested
|
|
|
14287
13177
|
});
|
|
14288
13178
|
var cliExample = (command, args = "") => `npx opendevbrowser ${command}${args ? ` ${args}` : ""}`;
|
|
14289
13179
|
var quoteCliValue = (value) => JSON.stringify(value);
|
|
14290
|
-
var
|
|
14291
|
-
"
|
|
14292
|
-
|
|
14293
|
-
|
|
13180
|
+
var GATED_PROVIDER_REASON_CODES = /* @__PURE__ */ new Set([
|
|
13181
|
+
"auth_required",
|
|
13182
|
+
"token_required",
|
|
13183
|
+
"challenge_detected"
|
|
13184
|
+
]);
|
|
13185
|
+
var buildResearchRerunCommand = (input, options = {}) => {
|
|
13186
|
+
const browserMode = options.browserMode ?? input.browserMode ?? "managed";
|
|
13187
|
+
const useCookies = options.useCookies ? " --use-cookies" : "";
|
|
13188
|
+
const challengeMode = options.challengeAutomationMode ? ` --challenge-automation-mode ${options.challengeAutomationMode}` : "";
|
|
13189
|
+
return cliExample(
|
|
13190
|
+
"research run",
|
|
13191
|
+
`--topic ${quoteCliValue(input.topic)} --days 14 --sources web,community --browser-mode ${browserMode}${useCookies}${challengeMode} --mode json --output-format json`
|
|
13192
|
+
);
|
|
13193
|
+
};
|
|
13194
|
+
var isJsonRecord3 = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
13195
|
+
var readFailureReasonCode = (failure) => {
|
|
13196
|
+
return failure.error.reasonCode ?? normalizeProviderReasonCode({
|
|
13197
|
+
code: failure.error.code,
|
|
13198
|
+
message: failure.error.message,
|
|
13199
|
+
details: failure.error.details
|
|
13200
|
+
}) ?? null;
|
|
13201
|
+
};
|
|
13202
|
+
var readDiagnosticReasonCode = (diagnostic) => {
|
|
13203
|
+
const reasonCode = diagnostic.reasonCode ?? diagnostic.browserFallbackReasonCode;
|
|
13204
|
+
return isProviderReasonCode(reasonCode) && GATED_PROVIDER_REASON_CODES.has(reasonCode) ? reasonCode : null;
|
|
13205
|
+
};
|
|
13206
|
+
var cookieDiagnosticShowsAvailableCookies = (diagnostic) => {
|
|
13207
|
+
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;
|
|
13208
|
+
};
|
|
13209
|
+
var addProviderSignal = (signal, provider, reasonCode) => {
|
|
13210
|
+
if (provider) signal.providers.push(provider);
|
|
13211
|
+
if (reasonCode) signal.reasonCodes.push(reasonCode);
|
|
13212
|
+
};
|
|
13213
|
+
var readFailureCookieDiagnostics = (failure) => {
|
|
13214
|
+
const candidate = failure.error.details?.cookieDiagnostics;
|
|
13215
|
+
return isJsonRecord3(candidate) ? candidate : null;
|
|
13216
|
+
};
|
|
13217
|
+
var emptyResearchGatedProviderSignal = () => ({
|
|
13218
|
+
providers: [],
|
|
13219
|
+
reasonCodes: [],
|
|
13220
|
+
useCookies: false
|
|
13221
|
+
});
|
|
13222
|
+
var normalizeResearchGatedProviderSignal = (signal) => {
|
|
13223
|
+
return signal.providers.length > 0 || signal.reasonCodes.length > 0 ? {
|
|
13224
|
+
providers: [...new Set(signal.providers)].sort(),
|
|
13225
|
+
reasonCodes: [...new Set(signal.reasonCodes)].sort(),
|
|
13226
|
+
useCookies: signal.useCookies
|
|
13227
|
+
} : null;
|
|
13228
|
+
};
|
|
13229
|
+
var mergeResearchGatedProviderSignals = (signals) => {
|
|
13230
|
+
const merged = emptyResearchGatedProviderSignal();
|
|
13231
|
+
for (const signal of signals) {
|
|
13232
|
+
merged.providers.push(...signal.providers);
|
|
13233
|
+
merged.reasonCodes.push(...signal.reasonCodes);
|
|
13234
|
+
merged.useCookies = merged.useCookies || signal.useCookies;
|
|
13235
|
+
}
|
|
13236
|
+
return merged;
|
|
13237
|
+
};
|
|
13238
|
+
var detectResearchFailureSignals = (failures) => {
|
|
13239
|
+
const signal = emptyResearchGatedProviderSignal();
|
|
13240
|
+
for (const failure of failures) {
|
|
13241
|
+
const reasonCode = readFailureReasonCode(failure);
|
|
13242
|
+
const isGatedFailure = Boolean(reasonCode && GATED_PROVIDER_REASON_CODES.has(reasonCode));
|
|
13243
|
+
if (isGatedFailure) {
|
|
13244
|
+
addProviderSignal(signal, failure.provider, reasonCode);
|
|
13245
|
+
const diagnostic = readFailureCookieDiagnostics(failure);
|
|
13246
|
+
signal.useCookies = signal.useCookies || Boolean(diagnostic && cookieDiagnosticShowsAvailableCookies(diagnostic));
|
|
13247
|
+
}
|
|
13248
|
+
}
|
|
13249
|
+
return signal;
|
|
13250
|
+
};
|
|
13251
|
+
var detectResearchCookieSignals = (diagnostics) => {
|
|
13252
|
+
const signal = emptyResearchGatedProviderSignal();
|
|
13253
|
+
for (const diagnostic of diagnostics) {
|
|
13254
|
+
const reasonCode = readDiagnosticReasonCode(diagnostic);
|
|
13255
|
+
const isGatedDiagnostic = Boolean(reasonCode || diagnostic.policy === "required");
|
|
13256
|
+
if (isGatedDiagnostic) {
|
|
13257
|
+
addProviderSignal(signal, typeof diagnostic.provider === "string" ? diagnostic.provider : void 0, reasonCode);
|
|
13258
|
+
signal.useCookies = signal.useCookies || cookieDiagnosticShowsAvailableCookies(diagnostic);
|
|
13259
|
+
}
|
|
13260
|
+
}
|
|
13261
|
+
return signal;
|
|
13262
|
+
};
|
|
13263
|
+
var detectResearchChallengeSignals = (diagnostics) => {
|
|
13264
|
+
const signal = emptyResearchGatedProviderSignal();
|
|
13265
|
+
for (const diagnostic of diagnostics) {
|
|
13266
|
+
const reasonCode = readDiagnosticReasonCode(diagnostic);
|
|
13267
|
+
if (reasonCode || diagnostic.blockerType === "auth_required" || diagnostic.blockerType === "anti_bot_challenge") {
|
|
13268
|
+
addProviderSignal(signal, typeof diagnostic.provider === "string" ? diagnostic.provider : void 0, reasonCode);
|
|
13269
|
+
}
|
|
13270
|
+
}
|
|
13271
|
+
return signal;
|
|
13272
|
+
};
|
|
13273
|
+
var detectResearchGatedProviderSignal = (input) => {
|
|
13274
|
+
return normalizeResearchGatedProviderSignal(mergeResearchGatedProviderSignals([
|
|
13275
|
+
detectResearchFailureSignals(input.failures ?? []),
|
|
13276
|
+
detectResearchCookieSignals(input.cookieDiagnostics ?? []),
|
|
13277
|
+
detectResearchChallengeSignals(input.challengeOrchestration ?? [])
|
|
13278
|
+
]));
|
|
13279
|
+
};
|
|
13280
|
+
var buildResearchRecoveryRerunCommand = (input, signal) => buildResearchRerunCommand(input, {
|
|
13281
|
+
browserMode: "extension",
|
|
13282
|
+
useCookies: signal.useCookies,
|
|
13283
|
+
challengeAutomationMode: "browser_with_helper"
|
|
13284
|
+
});
|
|
14294
13285
|
var buildShoppingRerunCommand = (input) => {
|
|
14295
13286
|
const providers = input.providers?.length ? ` --providers ${input.providers.join(",")}` : " --providers shopping/bestbuy,shopping/ebay";
|
|
14296
13287
|
const budget = typeof input.budget === "number" ? ` --budget ${input.budget}` : "";
|
|
@@ -14318,23 +13309,43 @@ var buildMacroResolveArgs = (input, options) => {
|
|
|
14318
13309
|
const defaultProvider = input.defaultProvider ? ` --default-provider ${input.defaultProvider}` : "";
|
|
14319
13310
|
const execute = options?.execute ? " --execute" : "";
|
|
14320
13311
|
const browserMode = options?.browserMode ? ` --browser-mode ${options.browserMode}` : "";
|
|
13312
|
+
const useCookies = options?.useCookies ? " --use-cookies" : "";
|
|
14321
13313
|
const challenge = options?.challengeAutomationMode ? ` --challenge-automation-mode ${options.challengeAutomationMode}` : "";
|
|
13314
|
+
const cookiePolicy = options?.cookiePolicyOverride ? ` --cookie-policy ${options.cookiePolicyOverride}` : "";
|
|
14322
13315
|
const outputFormat = options?.includeOutputFormat === false ? "" : " --output-format json";
|
|
14323
|
-
return `--expression ${quoteCliValue(input.expression)}${defaultProvider}${execute}${browserMode}${challenge}${outputFormat}`;
|
|
13316
|
+
return `--expression ${quoteCliValue(input.expression)}${defaultProvider}${execute}${browserMode}${useCookies}${cookiePolicy}${challenge}${outputFormat}`;
|
|
14324
13317
|
};
|
|
14325
13318
|
var buildMacroPreviewCommand = (input) => cliExample("macro-resolve", buildMacroResolveArgs(input));
|
|
14326
13319
|
var buildMacroExecuteCommand = (input, challengeAutomationMode, browserMode) => cliExample("macro-resolve", buildMacroResolveArgs(input, {
|
|
14327
13320
|
execute: true,
|
|
14328
13321
|
browserMode,
|
|
13322
|
+
...browserMode === "extension" ? { useCookies: true, cookiePolicyOverride: "required" } : {},
|
|
14329
13323
|
challengeAutomationMode
|
|
14330
13324
|
}));
|
|
14331
|
-
var
|
|
13325
|
+
var buildResearchGatedSuccessHandoff = (input, signal) => {
|
|
13326
|
+
const recoveryCommand = buildResearchRecoveryRerunCommand(input, signal);
|
|
13327
|
+
const providers = signal.providers.length > 0 ? signal.providers.join(", ") : "gated providers";
|
|
13328
|
+
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.";
|
|
13329
|
+
return createSuccessHandoff(
|
|
13330
|
+
`Review ranked records, artifact metadata, and gated-provider diagnostics for ${providers} before publishing claims.`,
|
|
13331
|
+
`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}`,
|
|
13332
|
+
[
|
|
13333
|
+
{ reason: "Check records.json, context.json, meta.json, failures, and cookie diagnostics before using the result as evidence." },
|
|
13334
|
+
{
|
|
13335
|
+
reason: "Rerun with an existing signed-in extension session and browser-scoped challenge assistance when gated providers blocked useful evidence.",
|
|
13336
|
+
command: recoveryCommand
|
|
13337
|
+
},
|
|
13338
|
+
{ reason: "Keep SERPs discovery-only and publish only claims supported by destination records that passed review." }
|
|
13339
|
+
]
|
|
13340
|
+
);
|
|
13341
|
+
};
|
|
13342
|
+
var buildResearchDefaultSuccessHandoff = (input) => {
|
|
14332
13343
|
const rerunCommand = buildResearchRerunCommand(input);
|
|
14333
13344
|
return createSuccessHandoff(
|
|
14334
|
-
"Review
|
|
14335
|
-
`Open the returned artifact path, inspect
|
|
13345
|
+
"Review ranked records, artifact metadata, and source support before turning the result into a publishable claim.",
|
|
13346
|
+
`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
13347
|
[
|
|
14337
|
-
{ reason: "Check which records actually support the final claim." },
|
|
13348
|
+
{ reason: "Check which ranked records and artifact metadata actually support the final claim." },
|
|
14338
13349
|
{
|
|
14339
13350
|
reason: "Rerun with explicit sources and a narrower timebox if the evidence set is still too broad.",
|
|
14340
13351
|
command: rerunCommand
|
|
@@ -14342,6 +13353,10 @@ var buildResearchSuccessHandoff = (input) => {
|
|
|
14342
13353
|
]
|
|
14343
13354
|
);
|
|
14344
13355
|
};
|
|
13356
|
+
var buildResearchSuccessHandoff = (input) => {
|
|
13357
|
+
const signal = detectResearchGatedProviderSignal(input);
|
|
13358
|
+
return signal ? buildResearchGatedSuccessHandoff(input, signal) : buildResearchDefaultSuccessHandoff(input);
|
|
13359
|
+
};
|
|
14345
13360
|
var buildShoppingSuccessHandoff = (input) => {
|
|
14346
13361
|
const rerunCommand = buildShoppingRerunCommand(input);
|
|
14347
13362
|
return createSuccessHandoff(
|
|
@@ -14485,19 +13500,304 @@ var compactResearchLines = (records, meta) => {
|
|
|
14485
13500
|
if (records.length === 0) {
|
|
14486
13501
|
const summary = primaryConstraintSummaryFromMeta(meta);
|
|
14487
13502
|
return summary ? [
|
|
14488
|
-
"No
|
|
13503
|
+
"No usable research findings were available.",
|
|
14489
13504
|
`Primary constraint: ${summary}`
|
|
14490
|
-
] : ["No
|
|
13505
|
+
] : ["No usable research findings were available."];
|
|
14491
13506
|
}
|
|
14492
13507
|
return records.slice(0, 10).map((record, index) => {
|
|
14493
13508
|
const title = record.title ?? record.url ?? record.provider;
|
|
14494
13509
|
const engagement = record.engagement.likes + record.engagement.comments + record.engagement.upvotes;
|
|
14495
|
-
return `${index + 1}. ${title} (${record.source}
|
|
13510
|
+
return `${index + 1}. ${title} (${record.source}; ${record.provider}) score=${record.confidence.toFixed(2)} engagement=${engagement}`;
|
|
13511
|
+
});
|
|
13512
|
+
};
|
|
13513
|
+
var RESEARCH_REPORT_LIMITS = {
|
|
13514
|
+
findings: 10,
|
|
13515
|
+
sources: 20,
|
|
13516
|
+
failures: 10,
|
|
13517
|
+
excerptCharacters: 240,
|
|
13518
|
+
failureMessageCharacters: 240
|
|
13519
|
+
};
|
|
13520
|
+
var RESEARCH_REPORT_FILE_NAMES = [
|
|
13521
|
+
"summary.md",
|
|
13522
|
+
"report.md",
|
|
13523
|
+
"records.json",
|
|
13524
|
+
"context.json",
|
|
13525
|
+
"meta.json",
|
|
13526
|
+
"bundle-manifest.json"
|
|
13527
|
+
];
|
|
13528
|
+
var plainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
|
|
13529
|
+
var researchTitle = (record) => record.title ?? record.url ?? record.provider;
|
|
13530
|
+
var normalizedInlineText = (content) => content?.replace(/\s+/g, " ").trim() ?? "";
|
|
13531
|
+
var boundedInlineText = (args) => {
|
|
13532
|
+
const normalized = normalizedInlineText(args.content);
|
|
13533
|
+
if (!normalized) {
|
|
13534
|
+
return args.fallback;
|
|
13535
|
+
}
|
|
13536
|
+
if (normalized.length <= args.limit) {
|
|
13537
|
+
return normalized;
|
|
13538
|
+
}
|
|
13539
|
+
return `${normalized.slice(0, args.limit)} [truncated; see ${args.target}]`;
|
|
13540
|
+
};
|
|
13541
|
+
var researchExcerpt = (content) => boundedInlineText({
|
|
13542
|
+
content,
|
|
13543
|
+
fallback: "No content excerpt was available.",
|
|
13544
|
+
limit: RESEARCH_REPORT_LIMITS.excerptCharacters,
|
|
13545
|
+
target: "records.json for full content"
|
|
13546
|
+
});
|
|
13547
|
+
var researchFailureMessage = (content) => boundedInlineText({
|
|
13548
|
+
content,
|
|
13549
|
+
fallback: "provider failure",
|
|
13550
|
+
limit: RESEARCH_REPORT_LIMITS.failureMessageCharacters,
|
|
13551
|
+
target: "meta.json"
|
|
13552
|
+
});
|
|
13553
|
+
var limitedCount = (total, limit) => Math.min(total, limit);
|
|
13554
|
+
var omissionLine = (args) => {
|
|
13555
|
+
const omitted = args.total - limitedCount(args.total, args.limit);
|
|
13556
|
+
if (omitted <= 0) {
|
|
13557
|
+
return [];
|
|
13558
|
+
}
|
|
13559
|
+
const noun = omitted === 1 ? args.singular : args.plural;
|
|
13560
|
+
return [`- ${omitted} more ${noun} omitted from this report; see ${args.target} for the complete dataset.`];
|
|
13561
|
+
};
|
|
13562
|
+
var researchFindingsLines = (records) => records.length === 0 ? ["- No usable findings were available."] : [
|
|
13563
|
+
...records.slice(0, RESEARCH_REPORT_LIMITS.findings).flatMap((record, index) => [
|
|
13564
|
+
`### ${index + 1}. ${researchTitle(record)}`,
|
|
13565
|
+
`- Source: ${record.source}`,
|
|
13566
|
+
`- Provider: ${record.provider}`,
|
|
13567
|
+
`- URL: ${record.url ?? "not provided"}`,
|
|
13568
|
+
`- Published: ${record.timestamp}`,
|
|
13569
|
+
`- Confidence: ${record.confidence.toFixed(2)}`,
|
|
13570
|
+
`- Evidence: ${researchExcerpt(record.content)}`
|
|
13571
|
+
]),
|
|
13572
|
+
...omissionLine({
|
|
13573
|
+
total: records.length,
|
|
13574
|
+
limit: RESEARCH_REPORT_LIMITS.findings,
|
|
13575
|
+
singular: "finding",
|
|
13576
|
+
plural: "findings",
|
|
13577
|
+
target: "records.json"
|
|
13578
|
+
})
|
|
13579
|
+
];
|
|
13580
|
+
var researchSourcesLines = (records) => records.length === 0 ? ["- No sources available."] : [
|
|
13581
|
+
...records.slice(0, RESEARCH_REPORT_LIMITS.sources).map((record) => `- ${researchTitle(record)}: ${record.url ?? "URL not provided"}`),
|
|
13582
|
+
...omissionLine({
|
|
13583
|
+
total: records.length,
|
|
13584
|
+
limit: RESEARCH_REPORT_LIMITS.sources,
|
|
13585
|
+
singular: "source",
|
|
13586
|
+
plural: "sources",
|
|
13587
|
+
target: "records.json"
|
|
13588
|
+
})
|
|
13589
|
+
];
|
|
13590
|
+
var researchReasonLine = (metrics) => {
|
|
13591
|
+
const reasons = Object.entries(plainObject(metrics.sanitized_reason_distribution)).map(([reason, count]) => `${reason}: ${String(count)}`);
|
|
13592
|
+
return reasons.length === 0 ? [] : [`- Sanitized record reasons: ${reasons.join(", ")}`];
|
|
13593
|
+
};
|
|
13594
|
+
var deadEndSearchFailures = (failures) => {
|
|
13595
|
+
if (!Array.isArray(failures)) return [];
|
|
13596
|
+
return failures.filter((failure) => {
|
|
13597
|
+
const record = plainObject(failure);
|
|
13598
|
+
const error = plainObject(record.error);
|
|
13599
|
+
const details = plainObject(error.details);
|
|
13600
|
+
return details.fallbackOutputReason === "research_dead_end_shell";
|
|
14496
13601
|
});
|
|
14497
13602
|
};
|
|
13603
|
+
var deadEndSearchFailureCount = (meta) => deadEndSearchFailures(meta.failures).length;
|
|
13604
|
+
var rejectedCandidatesFromMeta = (meta) => Array.isArray(meta.rejected_candidates) ? meta.rejected_candidates.map(plainObject).filter((candidate) => Object.keys(candidate).length > 0) : [];
|
|
13605
|
+
var rejectedCandidateCount = (meta) => {
|
|
13606
|
+
const metrics = plainObject(meta.metrics);
|
|
13607
|
+
if (typeof metrics.rejected_candidate_count === "number") {
|
|
13608
|
+
return metrics.rejected_candidate_count;
|
|
13609
|
+
}
|
|
13610
|
+
const sanitized = typeof metrics.sanitized_records === "number" ? metrics.sanitized_records : 0;
|
|
13611
|
+
return sanitized + deadEndSearchFailureCount(meta);
|
|
13612
|
+
};
|
|
13613
|
+
var deadEndSearchFailureLines = (meta) => {
|
|
13614
|
+
const failures = deadEndSearchFailures(meta.failures);
|
|
13615
|
+
if (failures.length === 0) return [];
|
|
13616
|
+
return [`- Dead-end search failures: ${failures.length}`];
|
|
13617
|
+
};
|
|
13618
|
+
var researchRejectedCandidateSummary = (candidate) => {
|
|
13619
|
+
const reason = typeof candidate.reason === "string" ? candidate.reason : "unknown_reason";
|
|
13620
|
+
const provider = typeof candidate.provider === "string" ? candidate.provider : "unknown_provider";
|
|
13621
|
+
const source = typeof candidate.source === "string" ? candidate.source : "unknown_source";
|
|
13622
|
+
const status = typeof candidate.replacement_status === "string" ? candidate.replacement_status : "not_recorded";
|
|
13623
|
+
const retrievalPath = typeof candidate.retrievalPath === "string" ? `; path=${candidate.retrievalPath}` : "";
|
|
13624
|
+
const url = typeof candidate.url === "string" ? candidate.url : "URL not recorded";
|
|
13625
|
+
return `${reason} from ${provider} (${source}; ${status}${retrievalPath}): ${url}`;
|
|
13626
|
+
};
|
|
13627
|
+
var researchFailureSummary = (failure) => {
|
|
13628
|
+
const record = plainObject(failure);
|
|
13629
|
+
const error = plainObject(record.error);
|
|
13630
|
+
const provider = typeof record.provider === "string" ? record.provider : "unknown";
|
|
13631
|
+
const source = typeof record.source === "string" ? record.source : "unknown";
|
|
13632
|
+
const reason = typeof error.reasonCode === "string" ? `${error.reasonCode}: ` : "";
|
|
13633
|
+
const message = researchFailureMessage(typeof error.message === "string" ? error.message : void 0);
|
|
13634
|
+
return `${provider} (${source}): ${reason}${message}`;
|
|
13635
|
+
};
|
|
13636
|
+
var researchFailureLines = (failures) => {
|
|
13637
|
+
if (!Array.isArray(failures) || failures.length === 0) {
|
|
13638
|
+
return [];
|
|
13639
|
+
}
|
|
13640
|
+
const summaries = failures.slice(0, RESEARCH_REPORT_LIMITS.failures).map(researchFailureSummary);
|
|
13641
|
+
const omitted = failures.length - summaries.length;
|
|
13642
|
+
const noun = omitted === 1 ? "failure" : "failures";
|
|
13643
|
+
const suffix = omitted > 0 ? `; ${omitted} more provider ${noun} omitted from this report; see meta.json` : "";
|
|
13644
|
+
return [`- Provider failures: ${summaries.join("; ")}${suffix}`];
|
|
13645
|
+
};
|
|
13646
|
+
var researchGapLines = (meta) => {
|
|
13647
|
+
const metrics = plainObject(meta.metrics);
|
|
13648
|
+
const details = [
|
|
13649
|
+
typeof metrics.final_records === "number" ? `- Final records reported by workflow: ${metrics.final_records}` : "",
|
|
13650
|
+
typeof metrics.sanitized_records === "number" ? `- Sanitized records excluded: ${metrics.sanitized_records}` : "",
|
|
13651
|
+
...researchReasonLine(metrics),
|
|
13652
|
+
...researchFailureLines(meta.failures)
|
|
13653
|
+
].filter(Boolean);
|
|
13654
|
+
const constraint = primaryConstraintSummaryFromMeta(meta);
|
|
13655
|
+
const fallback = "- No provider limitations or sanitization gaps were reported.";
|
|
13656
|
+
const gapDetails = details.length > 0 || constraint ? details : [fallback];
|
|
13657
|
+
return [
|
|
13658
|
+
"## Confidence and Gaps",
|
|
13659
|
+
...constraint ? [`- Primary constraint: ${constraint}`] : [],
|
|
13660
|
+
...gapDetails
|
|
13661
|
+
];
|
|
13662
|
+
};
|
|
13663
|
+
var researchSearchDirectionLines = (meta) => {
|
|
13664
|
+
const selection = plainObject(meta.selection);
|
|
13665
|
+
const sources = Array.isArray(selection.resolved_sources) ? selection.resolved_sources.map(String).join(", ") : "not recorded";
|
|
13666
|
+
return [
|
|
13667
|
+
"## Search Direction",
|
|
13668
|
+
`- Source families searched: ${sources}`,
|
|
13669
|
+
"- Direction: Follow accepted destination pages from provider/search output before synthesis."
|
|
13670
|
+
];
|
|
13671
|
+
};
|
|
13672
|
+
var researchSourceFamilies = (meta) => {
|
|
13673
|
+
const sources = plainObject(meta.selection).resolved_sources;
|
|
13674
|
+
return Array.isArray(sources) ? sources.map(String) : [];
|
|
13675
|
+
};
|
|
13676
|
+
var researchCandidateTriageSchema = () => ({
|
|
13677
|
+
url: "",
|
|
13678
|
+
rank: 0,
|
|
13679
|
+
engine: "",
|
|
13680
|
+
query: "",
|
|
13681
|
+
source_family: "",
|
|
13682
|
+
title: "",
|
|
13683
|
+
status: "pending|accepted|rejected",
|
|
13684
|
+
blocker_notes: "",
|
|
13685
|
+
rejection_reason: "",
|
|
13686
|
+
replacement_url: "",
|
|
13687
|
+
retrieval_notes: "",
|
|
13688
|
+
extraction_status: "pending|fetched|blocked|shell|stale|irrelevant"
|
|
13689
|
+
});
|
|
13690
|
+
var researchCandidateTriageLines = (records, meta) => {
|
|
13691
|
+
const rejected = rejectedCandidateCount(meta);
|
|
13692
|
+
return [
|
|
13693
|
+
"## Candidate Triage",
|
|
13694
|
+
`- Accepted destination records: ${records.length}`,
|
|
13695
|
+
`- Rejected shell or dead-end candidates: ${rejected}`,
|
|
13696
|
+
"- Rejection policy: search pages, login/account pages, privacy/cookie pages, JavaScript shells, not-found pages, and unsupported shells are not final evidence."
|
|
13697
|
+
];
|
|
13698
|
+
};
|
|
13699
|
+
var researchRejectedCandidateLines = (meta) => {
|
|
13700
|
+
const rejectedCandidates = rejectedCandidatesFromMeta(meta);
|
|
13701
|
+
const rejectionLines = [
|
|
13702
|
+
...researchReasonLine(plainObject(meta.metrics)),
|
|
13703
|
+
...rejectedCandidates.slice(0, RESEARCH_REPORT_LIMITS.failures).map((candidate) => `- Rejected candidate: ${researchRejectedCandidateSummary(candidate)}`),
|
|
13704
|
+
...deadEndSearchFailureLines(meta)
|
|
13705
|
+
];
|
|
13706
|
+
return [
|
|
13707
|
+
"## Rejected Candidates",
|
|
13708
|
+
...rejectionLines,
|
|
13709
|
+
...rejectionLines.length === 0 ? ["- No rejected candidate distribution was reported."] : []
|
|
13710
|
+
];
|
|
13711
|
+
};
|
|
13712
|
+
var researchDeepDiveLines = (records) => [
|
|
13713
|
+
"## Deep Dives",
|
|
13714
|
+
...records.length === 0 ? ["- No destination pages passed the evidence gate."] : records.slice(0, RESEARCH_REPORT_LIMITS.sources).map((record) => {
|
|
13715
|
+
const retrievalPath = typeof record.attributes.retrievalPath === "string" ? record.attributes.retrievalPath : "";
|
|
13716
|
+
const prefix = retrievalPath.includes(":fetch:") ? "Opened destination evidence" : "Accepted evidence record";
|
|
13717
|
+
return `- ${prefix}: ${record.url ?? researchTitle(record)}`;
|
|
13718
|
+
})
|
|
13719
|
+
];
|
|
13720
|
+
var researchSynthesisFeedbackText = (records, meta) => {
|
|
13721
|
+
const rejected = rejectedCandidateCount(meta);
|
|
13722
|
+
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.";
|
|
13723
|
+
};
|
|
13724
|
+
var researchSynthesisFeedbackLines = (records, meta) => {
|
|
13725
|
+
return ["## Synthesis Feedback", `- Next step: ${researchSynthesisFeedbackText(records, meta)}`];
|
|
13726
|
+
};
|
|
13727
|
+
var researchContextPayload = (args) => ({
|
|
13728
|
+
topic: args.topic,
|
|
13729
|
+
timebox: plainObject(args.meta.timebox),
|
|
13730
|
+
source_families: researchSourceFamilies(args.meta),
|
|
13731
|
+
evidence_gate: {
|
|
13732
|
+
status: "pending_review",
|
|
13733
|
+
reviewed_artifacts: []
|
|
13734
|
+
},
|
|
13735
|
+
artifact_files: RESEARCH_REPORT_FILE_NAMES,
|
|
13736
|
+
source_ledger: args.records.map((record) => ({
|
|
13737
|
+
title: researchTitle(record),
|
|
13738
|
+
url: record.url,
|
|
13739
|
+
source_family: record.source,
|
|
13740
|
+
provider: record.provider
|
|
13741
|
+
})),
|
|
13742
|
+
search_direction_notes: researchSearchDirectionLines(args.meta),
|
|
13743
|
+
candidate_triage_schema: researchCandidateTriageSchema(),
|
|
13744
|
+
highlights: args.lines,
|
|
13745
|
+
records: args.records,
|
|
13746
|
+
candidate_triage: {
|
|
13747
|
+
accepted_destination_records: args.records.length,
|
|
13748
|
+
rejected_shell_or_dead_end_candidates: rejectedCandidateCount(args.meta)
|
|
13749
|
+
},
|
|
13750
|
+
rejected_candidates: rejectedCandidatesFromMeta(args.meta),
|
|
13751
|
+
deep_dive_pages: args.records.map((record) => ({
|
|
13752
|
+
title: researchTitle(record),
|
|
13753
|
+
url: record.url,
|
|
13754
|
+
provider: record.provider,
|
|
13755
|
+
source: record.source,
|
|
13756
|
+
retrievalPath: record.attributes.retrievalPath
|
|
13757
|
+
})),
|
|
13758
|
+
iteration_log: researchSearchDirectionLines(args.meta),
|
|
13759
|
+
synthesis_feedback: researchSynthesisFeedbackText(args.records, args.meta),
|
|
13760
|
+
meta: args.meta
|
|
13761
|
+
});
|
|
13762
|
+
var researchArtifactFileLines = () => [
|
|
13763
|
+
"## Report Files",
|
|
13764
|
+
...RESEARCH_REPORT_FILE_NAMES.map((fileName) => `- ${fileName}`)
|
|
13765
|
+
];
|
|
13766
|
+
var buildResearchReport = (args) => [
|
|
13767
|
+
"# Research Report",
|
|
13768
|
+
"",
|
|
13769
|
+
"## Executive Summary",
|
|
13770
|
+
`- Topic: ${args.topic}`,
|
|
13771
|
+
`- Usable findings: ${args.records.length}`,
|
|
13772
|
+
`- Findings shown in report: ${limitedCount(args.records.length, RESEARCH_REPORT_LIMITS.findings)}`,
|
|
13773
|
+
`- Sources shown in report: ${limitedCount(args.records.length, RESEARCH_REPORT_LIMITS.sources)}`,
|
|
13774
|
+
"- Final output: Usable records are persisted in records.json.",
|
|
13775
|
+
"- Diagnostics: Run metadata, failures, and constraints are persisted in meta.json; this report summarizes the bounded inline subset.",
|
|
13776
|
+
"",
|
|
13777
|
+
...researchArtifactFileLines(),
|
|
13778
|
+
"",
|
|
13779
|
+
...researchSearchDirectionLines(args.meta),
|
|
13780
|
+
"",
|
|
13781
|
+
...researchCandidateTriageLines(args.records, args.meta),
|
|
13782
|
+
"",
|
|
13783
|
+
...researchRejectedCandidateLines(args.meta),
|
|
13784
|
+
"",
|
|
13785
|
+
...researchDeepDiveLines(args.records),
|
|
13786
|
+
"",
|
|
13787
|
+
...researchSynthesisFeedbackLines(args.records, args.meta),
|
|
13788
|
+
"",
|
|
13789
|
+
"## Findings",
|
|
13790
|
+
...researchFindingsLines(args.records),
|
|
13791
|
+
"",
|
|
13792
|
+
...researchGapLines(args.meta),
|
|
13793
|
+
"",
|
|
13794
|
+
"## Sources",
|
|
13795
|
+
...researchSourcesLines(args.records)
|
|
13796
|
+
].join("\n");
|
|
14498
13797
|
var renderResearch = (args) => {
|
|
14499
13798
|
const lines = compactResearchLines(args.records, args.meta);
|
|
14500
13799
|
const summary = lines.join("\n");
|
|
13800
|
+
const report = buildResearchReport(args);
|
|
14501
13801
|
const markdown = [
|
|
14502
13802
|
`# Research: ${args.topic}`,
|
|
14503
13803
|
"",
|
|
@@ -14508,14 +13808,15 @@ var renderResearch = (args) => {
|
|
|
14508
13808
|
JSON.stringify(args.meta, null, 2),
|
|
14509
13809
|
"```"
|
|
14510
13810
|
].join("\n");
|
|
14511
|
-
const contextPayload = {
|
|
13811
|
+
const contextPayload = researchContextPayload({
|
|
14512
13812
|
topic: args.topic,
|
|
14513
|
-
|
|
13813
|
+
lines,
|
|
14514
13814
|
records: args.records,
|
|
14515
13815
|
meta: args.meta
|
|
14516
|
-
};
|
|
13816
|
+
});
|
|
14517
13817
|
const files = [
|
|
14518
13818
|
{ path: "summary.md", content: markdown },
|
|
13819
|
+
{ path: "report.md", content: report },
|
|
14519
13820
|
{ path: "records.json", content: { records: args.records } },
|
|
14520
13821
|
{ path: "context.json", content: contextPayload },
|
|
14521
13822
|
{ path: "meta.json", content: args.meta }
|
|
@@ -15636,14 +14937,14 @@ import { createHash as createHash5 } from "crypto";
|
|
|
15636
14937
|
var DEFAULT_SHOPPING_SEARCH_LIMIT = 8;
|
|
15637
14938
|
var SHOPPING_FETCH_RECOVERY_LIMIT = 2;
|
|
15638
14939
|
var SEARCH_INDEX_RETRIEVAL_PATHS = /* @__PURE__ */ new Set(["shopping:search:index", "shopping:search:link"]);
|
|
15639
|
-
var
|
|
14940
|
+
var isJsonRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
15640
14941
|
var isFiniteNumber = (value) => typeof value === "number" && Number.isFinite(value);
|
|
15641
14942
|
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) =>
|
|
14943
|
+
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");
|
|
14944
|
+
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));
|
|
14945
|
+
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);
|
|
14946
|
+
var isProviderFailureEntry = (value) => isJsonRecord4(value) && typeof value.provider === "string" && isProviderSource(value.source) && isProviderError2(value.error);
|
|
14947
|
+
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
14948
|
var emptyCheckpointState = () => ({
|
|
15648
14949
|
completed_step_ids: [],
|
|
15649
14950
|
step_results_by_id: {}
|
|
@@ -15659,7 +14960,7 @@ var readShoppingCheckpointState = (checkpoint) => {
|
|
|
15659
14960
|
if (state === void 0 || state === null) {
|
|
15660
14961
|
return emptyCheckpointState();
|
|
15661
14962
|
}
|
|
15662
|
-
if (!
|
|
14963
|
+
if (!isJsonRecord4(state)) {
|
|
15663
14964
|
throw new Error("Shopping workflow checkpoint state must be a record.");
|
|
15664
14965
|
}
|
|
15665
14966
|
const completedStepIds = state.completed_step_ids;
|
|
@@ -15667,7 +14968,7 @@ var readShoppingCheckpointState = (checkpoint) => {
|
|
|
15667
14968
|
throw new Error("Shopping workflow checkpoint state is missing valid completed_step_ids.");
|
|
15668
14969
|
}
|
|
15669
14970
|
const rawResults = state.step_results_by_id;
|
|
15670
|
-
if (!
|
|
14971
|
+
if (!isJsonRecord4(rawResults)) {
|
|
15671
14972
|
throw new Error("Shopping workflow checkpoint state is missing valid step_results_by_id.");
|
|
15672
14973
|
}
|
|
15673
14974
|
const stepResultsById = {};
|
|
@@ -15978,14 +15279,14 @@ var PRODUCT_VIDEO_STEP_IDS = {
|
|
|
15978
15279
|
extractProductData: "product_video:extract_product_data",
|
|
15979
15280
|
assembleArtifacts: "product_video:assemble_artifacts"
|
|
15980
15281
|
};
|
|
15981
|
-
var
|
|
15282
|
+
var isJsonRecord5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
15982
15283
|
var isFiniteNumber2 = (value) => typeof value === "number" && Number.isFinite(value);
|
|
15983
15284
|
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) =>
|
|
15285
|
+
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");
|
|
15286
|
+
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));
|
|
15287
|
+
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);
|
|
15288
|
+
var isProviderFailureEntry2 = (value) => isJsonRecord5(value) && typeof value.provider === "string" && isProviderSource2(value.source) && isProviderError3(value.error);
|
|
15289
|
+
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
15290
|
var emptyCheckpointState2 = () => ({
|
|
15990
15291
|
completed_step_ids: []
|
|
15991
15292
|
});
|
|
@@ -16028,7 +15329,7 @@ var readProductVideoCheckpointState = (checkpoint) => {
|
|
|
16028
15329
|
if (state === void 0 || state === null) {
|
|
16029
15330
|
return emptyCheckpointState2();
|
|
16030
15331
|
}
|
|
16031
|
-
if (!
|
|
15332
|
+
if (!isJsonRecord5(state)) {
|
|
16032
15333
|
throw new Error("Product-video workflow checkpoint state must be a record.");
|
|
16033
15334
|
}
|
|
16034
15335
|
const completedStepIds = state.completed_step_ids;
|
|
@@ -16139,15 +15440,16 @@ import { createHash as createHash6 } from "crypto";
|
|
|
16139
15440
|
var RESEARCH_AUTO_SOURCES = ["web", "community", "social"];
|
|
16140
15441
|
var RESEARCH_ALL_SOURCES = [...RESEARCH_AUTO_SOURCES];
|
|
16141
15442
|
var DEFAULT_RESEARCH_SEARCH_LIMIT = 10;
|
|
16142
|
-
var RESEARCH_WEB_SEARCH_FETCH_LIMIT =
|
|
16143
|
-
var
|
|
15443
|
+
var RESEARCH_WEB_SEARCH_FETCH_LIMIT = 5;
|
|
15444
|
+
var RESEARCH_COMMUNITY_EXPANSION_PER_RECORD = 2;
|
|
15445
|
+
var isJsonRecord6 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16144
15446
|
var isFiniteNumber3 = (value) => typeof value === "number" && Number.isFinite(value);
|
|
16145
15447
|
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) =>
|
|
15448
|
+
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");
|
|
15449
|
+
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));
|
|
15450
|
+
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);
|
|
15451
|
+
var isProviderFailureEntry3 = (value) => isJsonRecord6(value) && typeof value.provider === "string" && isProviderSource3(value.source) && isProviderError4(value.error);
|
|
15452
|
+
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
15453
|
var emptyCheckpointState3 = () => ({
|
|
16152
15454
|
completed_step_ids: [],
|
|
16153
15455
|
step_results_by_id: {}
|
|
@@ -16170,7 +15472,7 @@ var readResearchCheckpointState = (checkpoint) => {
|
|
|
16170
15472
|
if (state === void 0 || state === null) {
|
|
16171
15473
|
return emptyCheckpointState3();
|
|
16172
15474
|
}
|
|
16173
|
-
if (!
|
|
15475
|
+
if (!isJsonRecord6(state)) {
|
|
16174
15476
|
throw new Error("Research workflow checkpoint state must be a record.");
|
|
16175
15477
|
}
|
|
16176
15478
|
const completedStepIds = state.completed_step_ids;
|
|
@@ -16178,7 +15480,7 @@ var readResearchCheckpointState = (checkpoint) => {
|
|
|
16178
15480
|
throw new Error("Research workflow checkpoint state is missing valid completed_step_ids.");
|
|
16179
15481
|
}
|
|
16180
15482
|
const rawResults = state.step_results_by_id;
|
|
16181
|
-
if (!
|
|
15483
|
+
if (!isJsonRecord6(rawResults)) {
|
|
16182
15484
|
throw new Error("Research workflow checkpoint state is missing valid step_results_by_id.");
|
|
16183
15485
|
}
|
|
16184
15486
|
const stepResultsById = {};
|
|
@@ -16228,8 +15530,8 @@ var buildResearchSearchFilters = (source, args) => ({
|
|
|
16228
15530
|
timebox_to: args.timebox.to,
|
|
16229
15531
|
...source === "community" || source === "social" ? {
|
|
16230
15532
|
pageLimit: 1,
|
|
16231
|
-
hopLimit: 0,
|
|
16232
|
-
expansionPerRecord: 0
|
|
15533
|
+
hopLimit: source === "community" ? 1 : 0,
|
|
15534
|
+
expansionPerRecord: source === "community" ? RESEARCH_COMMUNITY_EXPANSION_PER_RECORD : 0
|
|
16233
15535
|
} : {}
|
|
16234
15536
|
});
|
|
16235
15537
|
var compileResearchExecutionPlan = (args) => {
|
|
@@ -16296,7 +15598,12 @@ var compileResearchExecutionPlan = (args) => {
|
|
|
16296
15598
|
|
|
16297
15599
|
// src/providers/research-executor.ts
|
|
16298
15600
|
var RESEARCH_WEB_SEARCH_FETCH_PATHS = /* @__PURE__ */ new Set([
|
|
15601
|
+
"community:search:index",
|
|
15602
|
+
"community:search:url",
|
|
16299
15603
|
"web:search:index",
|
|
15604
|
+
"web:search:url",
|
|
15605
|
+
"social:youtube:search:url",
|
|
15606
|
+
"social:search:url",
|
|
16300
15607
|
"social:search:index"
|
|
16301
15608
|
]);
|
|
16302
15609
|
var appendTrace2 = (trace, stage, event, details) => [
|
|
@@ -16337,6 +15644,15 @@ var isValidHttpUrl2 = (url) => {
|
|
|
16337
15644
|
return false;
|
|
16338
15645
|
}
|
|
16339
15646
|
};
|
|
15647
|
+
var attributeLinks = (record) => {
|
|
15648
|
+
const links = record.attributes.links;
|
|
15649
|
+
if (!Array.isArray(links)) return [];
|
|
15650
|
+
return links.filter((link) => typeof link === "string");
|
|
15651
|
+
};
|
|
15652
|
+
var researchCandidateUrls = (record) => [
|
|
15653
|
+
...typeof record.url === "string" ? [record.url] : [],
|
|
15654
|
+
...attributeLinks(record)
|
|
15655
|
+
];
|
|
16340
15656
|
var resolveResearchWebFetchCandidates = (records, limit) => {
|
|
16341
15657
|
const candidates = [];
|
|
16342
15658
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -16345,27 +15661,30 @@ var resolveResearchWebFetchCandidates = (records, limit) => {
|
|
|
16345
15661
|
if (!RESEARCH_WEB_SEARCH_FETCH_PATHS.has(retrievalPath)) {
|
|
16346
15662
|
continue;
|
|
16347
15663
|
}
|
|
16348
|
-
const
|
|
16349
|
-
|
|
16350
|
-
continue;
|
|
16351
|
-
|
|
16352
|
-
|
|
16353
|
-
|
|
16354
|
-
|
|
16355
|
-
|
|
16356
|
-
|
|
16357
|
-
|
|
16358
|
-
|
|
15664
|
+
for (const candidateUrl of researchCandidateUrls(record)) {
|
|
15665
|
+
const rawUrl = canonicalizeUrl(candidateUrl);
|
|
15666
|
+
if (!rawUrl) continue;
|
|
15667
|
+
let resolvedUrl = rawUrl;
|
|
15668
|
+
try {
|
|
15669
|
+
const parsed = new URL(rawUrl);
|
|
15670
|
+
if (/duckduckgo\.com$/i.test(parsed.hostname) && (parsed.pathname === "/l" || parsed.pathname === "/l/")) {
|
|
15671
|
+
const redirect = parsed.searchParams.get("uddg");
|
|
15672
|
+
if (typeof redirect === "string" && redirect.length > 0) {
|
|
15673
|
+
resolvedUrl = canonicalizeUrl(redirect);
|
|
15674
|
+
}
|
|
16359
15675
|
}
|
|
15676
|
+
} catch {
|
|
15677
|
+
continue;
|
|
15678
|
+
}
|
|
15679
|
+
if (!resolvedUrl || !isValidHttpUrl2(resolvedUrl) || !isLikelyResearchDestinationUrl(resolvedUrl) || /duckduckgo\.com/i.test(resolvedUrl) || seen.has(resolvedUrl)) {
|
|
15680
|
+
continue;
|
|
15681
|
+
}
|
|
15682
|
+
seen.add(resolvedUrl);
|
|
15683
|
+
candidates.push(resolvedUrl);
|
|
15684
|
+
if (candidates.length >= limit) {
|
|
15685
|
+
break;
|
|
16360
15686
|
}
|
|
16361
|
-
} catch {
|
|
16362
|
-
continue;
|
|
16363
|
-
}
|
|
16364
|
-
if (!resolvedUrl || !isValidHttpUrl2(resolvedUrl) || /duckduckgo\.com/i.test(resolvedUrl) || seen.has(resolvedUrl)) {
|
|
16365
|
-
continue;
|
|
16366
15687
|
}
|
|
16367
|
-
seen.add(resolvedUrl);
|
|
16368
|
-
candidates.push(resolvedUrl);
|
|
16369
15688
|
if (candidates.length >= limit) {
|
|
16370
15689
|
break;
|
|
16371
15690
|
}
|
|
@@ -17131,7 +16450,11 @@ var rankResearchRecords = (records) => {
|
|
|
17131
16450
|
var hash2 = (value) => createHash7("sha1").update(value).digest("hex").slice(0, 16);
|
|
17132
16451
|
var RESEARCH_ALWAYS_SANITIZED_PATHS = /* @__PURE__ */ new Set([
|
|
17133
16452
|
"community:search:index",
|
|
17134
|
-
"
|
|
16453
|
+
"community:search:url",
|
|
16454
|
+
"social:search:index",
|
|
16455
|
+
"social:search:url",
|
|
16456
|
+
"social:youtube:search:url",
|
|
16457
|
+
"web:search:url"
|
|
17135
16458
|
]);
|
|
17136
16459
|
var RESEARCH_CONDITIONAL_SANITIZED_PATHS = /* @__PURE__ */ new Set([
|
|
17137
16460
|
"community:fetch:url",
|
|
@@ -17139,9 +16462,13 @@ var RESEARCH_CONDITIONAL_SANITIZED_PATHS = /* @__PURE__ */ new Set([
|
|
|
17139
16462
|
"web:search:index"
|
|
17140
16463
|
]);
|
|
17141
16464
|
var RESEARCH_LOGIN_SHELL_RE = /\b(?:log in|login|sign in|sign-in|please log in|continue with google|continue with apple)\b/i;
|
|
16465
|
+
var RESEARCH_LOGIN_SHELL_MAX_CONTENT_CHARS = 600;
|
|
16466
|
+
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
16467
|
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
16468
|
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
16469
|
var RESEARCH_NOT_FOUND_SHELL_RE = /\b(?:error 404|page not found|not found|can['’]t seem to find the page)\b/i;
|
|
16470
|
+
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;
|
|
16471
|
+
var RESEARCH_PRIVACY_RECOVERED_CONTENT_RE = /\b(?:blogs? home|permalink|comments|article)\b/i;
|
|
17145
16472
|
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
16473
|
var isDuckDuckGoResearchShellUrl = (url) => {
|
|
17147
16474
|
try {
|
|
@@ -17154,6 +16481,7 @@ var isDuckDuckGoResearchShellUrl = (url) => {
|
|
|
17154
16481
|
}
|
|
17155
16482
|
};
|
|
17156
16483
|
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;
|
|
16484
|
+
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
16485
|
var resolveShoppingProviderIdForUrl = (url) => {
|
|
17158
16486
|
try {
|
|
17159
16487
|
const host = new URL(url).hostname.toLowerCase();
|
|
@@ -17208,6 +16536,48 @@ var WALMART_TITLE_CHROME_RE = /\b(?:Walmart\.com|Skip to Main Content|Pickup or
|
|
|
17208
16536
|
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
16537
|
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
16538
|
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;
|
|
16539
|
+
var EBAY_TITLE_BRAND_PREFIX_RE = /^(?:new|used|pre-owned|preowned|open box|refurbished|renewed|genuine|authentic)\s+/i;
|
|
16540
|
+
var EBAY_KNOWN_MULTI_TOKEN_BRANDS = [
|
|
16541
|
+
"3M",
|
|
16542
|
+
"Bang & Olufsen",
|
|
16543
|
+
"Bowers & Wilkins",
|
|
16544
|
+
"Hewlett-Packard",
|
|
16545
|
+
"iRobot",
|
|
16546
|
+
"New Balance"
|
|
16547
|
+
];
|
|
16548
|
+
var EBAY_KNOWN_SINGLE_TOKEN_BRANDS = /* @__PURE__ */ new Map([
|
|
16549
|
+
["apple", "Apple"],
|
|
16550
|
+
["bose", "Bose"],
|
|
16551
|
+
["canon", "Canon"],
|
|
16552
|
+
["dell", "Dell"],
|
|
16553
|
+
["dyson", "Dyson"],
|
|
16554
|
+
["google", "Google"],
|
|
16555
|
+
["jbl", "JBL"],
|
|
16556
|
+
["lenovo", "Lenovo"],
|
|
16557
|
+
["lg", "LG"],
|
|
16558
|
+
["microsoft", "Microsoft"],
|
|
16559
|
+
["nikon", "Nikon"],
|
|
16560
|
+
["nintendo", "Nintendo"],
|
|
16561
|
+
["panasonic", "Panasonic"],
|
|
16562
|
+
["philips", "Philips"],
|
|
16563
|
+
["samsung", "Samsung"],
|
|
16564
|
+
["sony", "Sony"]
|
|
16565
|
+
]);
|
|
16566
|
+
var EBAY_TITLE_BRAND_STOP_WORDS = /* @__PURE__ */ new Set([
|
|
16567
|
+
"bluetooth",
|
|
16568
|
+
"case",
|
|
16569
|
+
"ergonomic",
|
|
16570
|
+
"gaming",
|
|
16571
|
+
"headphones",
|
|
16572
|
+
"keyboard",
|
|
16573
|
+
"leather",
|
|
16574
|
+
"noise",
|
|
16575
|
+
"portable",
|
|
16576
|
+
"rechargeable",
|
|
16577
|
+
"speaker",
|
|
16578
|
+
"vertical",
|
|
16579
|
+
"wireless"
|
|
16580
|
+
]);
|
|
17211
16581
|
var PRODUCT_FEATURE_SECTION_MARKERS = [
|
|
17212
16582
|
"about this item",
|
|
17213
16583
|
"key item features",
|
|
@@ -17273,7 +16643,7 @@ var INSPIREDESIGN_RENDER_MODES = /* @__PURE__ */ new Set(["compact", "json", "md
|
|
|
17273
16643
|
var INSPIREDESIGN_CAPTURE_MODES = /* @__PURE__ */ new Set(["off", "deep"]);
|
|
17274
16644
|
var INSPIREDESIGN_COOKIE_POLICIES = /* @__PURE__ */ new Set(["off", "auto", "required"]);
|
|
17275
16645
|
var WORKFLOW_BROWSER_MODES = /* @__PURE__ */ new Set(["auto", "extension", "managed"]);
|
|
17276
|
-
var
|
|
16646
|
+
var isJsonRecord7 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17277
16647
|
var INSPIREDESIGN_CAPTURE_UNAVAILABLE_FAILURE = "Deep capture requested, but browser capture is unavailable in this execution lane.";
|
|
17278
16648
|
var isCanvasVisualDirectionProfile = (value) => {
|
|
17279
16649
|
return CANVAS_VISUAL_DIRECTION_PROFILES.includes(value);
|
|
@@ -17302,7 +16672,7 @@ var serializeInspiredesignRunInput = (input) => ({
|
|
|
17302
16672
|
});
|
|
17303
16673
|
var isStringArray2 = (value) => Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
17304
16674
|
var parseInspiredesignBriefFormatRoute = (value) => {
|
|
17305
|
-
if (!
|
|
16675
|
+
if (!isJsonRecord7(value)) return void 0;
|
|
17306
16676
|
const profile = typeof value.profile === "string" && isCanvasVisualDirectionProfile(value.profile) ? value.profile : void 0;
|
|
17307
16677
|
const themeStrategy = typeof value.themeStrategy === "string" && isCanvasThemeStrategy(value.themeStrategy) ? value.themeStrategy : void 0;
|
|
17308
16678
|
const navigationModel = typeof value.navigationModel === "string" && isCanvasNavigationModel(value.navigationModel) ? value.navigationModel : void 0;
|
|
@@ -17317,7 +16687,7 @@ var parseInspiredesignBriefFormatRoute = (value) => {
|
|
|
17317
16687
|
};
|
|
17318
16688
|
};
|
|
17319
16689
|
var parseInspiredesignBriefFormat = (value) => {
|
|
17320
|
-
if (!
|
|
16690
|
+
if (!isJsonRecord7(value)) return void 0;
|
|
17321
16691
|
const route = parseInspiredesignBriefFormatRoute(value.route);
|
|
17322
16692
|
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
16693
|
return void 0;
|
|
@@ -17346,7 +16716,7 @@ var parseInspiredesignBriefFormat = (value) => {
|
|
|
17346
16716
|
};
|
|
17347
16717
|
};
|
|
17348
16718
|
var parseInspiredesignBriefExpansion = (value) => {
|
|
17349
|
-
if (!
|
|
16719
|
+
if (!isJsonRecord7(value)) return void 0;
|
|
17350
16720
|
const format = parseInspiredesignBriefFormat(value.format);
|
|
17351
16721
|
if (typeof value.sourceBrief !== "string" || typeof value.advancedBrief !== "string" || typeof value.templateVersion !== "string" || !format) {
|
|
17352
16722
|
return void 0;
|
|
@@ -17368,7 +16738,7 @@ var parseInspiredesignEnvelopeInput = (input) => {
|
|
|
17368
16738
|
...typeof input.captureMode === "string" && INSPIREDESIGN_CAPTURE_MODES.has(input.captureMode) ? { captureMode: input.captureMode } : {},
|
|
17369
16739
|
...typeof input.includePrototypeGuidance === "boolean" ? { includePrototypeGuidance: input.includePrototypeGuidance } : {},
|
|
17370
16740
|
...typeof input.timeoutMs === "number" ? { timeoutMs: input.timeoutMs } : {},
|
|
17371
|
-
...typeof input.outputDir === "string"
|
|
16741
|
+
...typeof input.outputDir === "string" ? { outputDir: input.outputDir } : {},
|
|
17372
16742
|
...typeof input.ttlHours === "number" ? { ttlHours: input.ttlHours } : {},
|
|
17373
16743
|
...typeof input.browserMode === "string" && WORKFLOW_BROWSER_MODES.has(input.browserMode) ? { browserMode: input.browserMode } : {},
|
|
17374
16744
|
...typeof input.useCookies === "boolean" ? { useCookies: input.useCookies } : {},
|
|
@@ -17764,9 +17134,19 @@ var buildInspiredesignMeta = (runtime, workflowInput, references, failures, foll
|
|
|
17764
17134
|
contractScope: followthrough.contractScope
|
|
17765
17135
|
};
|
|
17766
17136
|
};
|
|
17767
|
-
var
|
|
17137
|
+
var resolveWorkflowArtifactRoot = (outputDir) => {
|
|
17138
|
+
if (outputDir === void 0) {
|
|
17139
|
+
return join2(process.cwd(), ".opendevbrowser");
|
|
17140
|
+
}
|
|
17141
|
+
if (outputDir.trim() === "") {
|
|
17142
|
+
throw new Error("outputDir cannot be empty");
|
|
17143
|
+
}
|
|
17144
|
+
return outputDir;
|
|
17145
|
+
};
|
|
17146
|
+
var inferBrandFromContent = (content, productUrl) => {
|
|
17768
17147
|
const normalized = normalizePlainText(content);
|
|
17769
17148
|
if (!normalized) return void 0;
|
|
17149
|
+
const isEbayProduct = productUrl ? resolveShoppingProviderIdForUrl(productUrl) === "shopping/ebay" : false;
|
|
17770
17150
|
const bestBuyTitle = inferBestBuyTitleFromContent(normalized);
|
|
17771
17151
|
const bestBuyBrand = inferBestBuyBrandFromTitle(bestBuyTitle) ?? extractBrandFromTitle(bestBuyTitle);
|
|
17772
17152
|
if (bestBuyBrand) {
|
|
@@ -17784,6 +17164,14 @@ var inferBrandFromContent = (content) => {
|
|
|
17784
17164
|
if (productIdentifiersBrandMatch?.[1]) {
|
|
17785
17165
|
return productIdentifiersBrandMatch[1].trim();
|
|
17786
17166
|
}
|
|
17167
|
+
const ebayTitle = inferEbayTitleFromContent(normalized);
|
|
17168
|
+
const ebayBrand = inferEbayBrandFromTitle(ebayTitle);
|
|
17169
|
+
if (ebayBrand) {
|
|
17170
|
+
return ebayBrand;
|
|
17171
|
+
}
|
|
17172
|
+
if (isEbayProduct) {
|
|
17173
|
+
return void 0;
|
|
17174
|
+
}
|
|
17787
17175
|
const brandMatch = /\bBrand ([A-Z][A-Za-z0-9&+' -]{1,60})\b/i.exec(normalized);
|
|
17788
17176
|
if (brandMatch?.[1]) {
|
|
17789
17177
|
return brandMatch[1].trim();
|
|
@@ -17803,13 +17191,69 @@ var inferBestBuyTitleFromContent = (normalized) => {
|
|
|
17803
17191
|
}
|
|
17804
17192
|
return candidate;
|
|
17805
17193
|
};
|
|
17806
|
-
var
|
|
17194
|
+
var inferEbayTitleFromContent = (normalized) => {
|
|
17195
|
+
const patterns = [
|
|
17196
|
+
/\bExpand Cart Loading\.\.\.\s+(.+?)(?:\s+for sale online\s*\|\s*eBay)?\s+Condition:/i,
|
|
17197
|
+
/\bBuy It Now\s+(.+?)\s+Sign in to check out\b/i
|
|
17198
|
+
];
|
|
17199
|
+
for (const pattern of patterns) {
|
|
17200
|
+
const candidate = stripMarketplaceTitleFraming(normalizePlainText(pattern.exec(normalized)?.[1]), "https://www.ebay.com");
|
|
17201
|
+
if (candidate && candidate.length >= 20 && candidate.length <= 180 && !candidate.endsWith("...") && !LOOKS_LIKE_URL_RE.test(candidate)) {
|
|
17202
|
+
return candidate;
|
|
17203
|
+
}
|
|
17204
|
+
}
|
|
17205
|
+
return void 0;
|
|
17206
|
+
};
|
|
17207
|
+
var inferKnownEbayBrandFromTitle = (title) => {
|
|
17208
|
+
const normalized = title.toLowerCase();
|
|
17209
|
+
return EBAY_KNOWN_MULTI_TOKEN_BRANDS.find((brand) => {
|
|
17210
|
+
const candidate = brand.toLowerCase();
|
|
17211
|
+
return normalized === candidate || normalized.startsWith(`${candidate} `);
|
|
17212
|
+
});
|
|
17213
|
+
};
|
|
17214
|
+
var inferKnownSingleEbayBrandFromTitle = (title) => {
|
|
17215
|
+
const firstToken = /^([A-Za-z][A-Za-z0-9&+']{1,30})(?:\s|$)/.exec(title)?.[1];
|
|
17216
|
+
return firstToken ? EBAY_KNOWN_SINGLE_TOKEN_BRANDS.get(firstToken.toLowerCase()) : void 0;
|
|
17217
|
+
};
|
|
17218
|
+
var inferEbayBrandFromTitle = (title) => {
|
|
17219
|
+
const framed = normalizePlainText(title).replace(/\s+[-|]\s+[^-|]+$/i, "").trim();
|
|
17220
|
+
const knownBrand = inferKnownEbayBrandFromTitle(framed);
|
|
17221
|
+
if (knownBrand) return knownBrand;
|
|
17222
|
+
const cleaned = framed.replace(EBAY_TITLE_BRAND_PREFIX_RE, "");
|
|
17223
|
+
const prefixedBrand = inferKnownEbayBrandFromTitle(cleaned);
|
|
17224
|
+
if (prefixedBrand) return prefixedBrand;
|
|
17225
|
+
const singleTokenBrand = inferKnownSingleEbayBrandFromTitle(cleaned);
|
|
17226
|
+
if (singleTokenBrand) return singleTokenBrand;
|
|
17227
|
+
const exactBrand = /^([A-Z][A-Za-z0-9&+']{1,30})$/.exec(cleaned)?.[1];
|
|
17228
|
+
if (exactBrand && EBAY_KNOWN_SINGLE_TOKEN_BRANDS.has(exactBrand.toLowerCase())) {
|
|
17229
|
+
return exactBrand;
|
|
17230
|
+
}
|
|
17231
|
+
const match = /^([A-Z][A-Za-z0-9&+']{1,30})\s+([A-Z0-9][A-Za-z0-9&+'().-]+|AirPods)\b/.exec(cleaned);
|
|
17232
|
+
const brand = match?.[1]?.trim();
|
|
17233
|
+
if (!brand || EBAY_TITLE_BRAND_STOP_WORDS.has(brand.toLowerCase())) {
|
|
17234
|
+
return void 0;
|
|
17235
|
+
}
|
|
17236
|
+
if (EBAY_KNOWN_SINGLE_TOKEN_BRANDS.has(brand.toLowerCase())) {
|
|
17237
|
+
return EBAY_KNOWN_SINGLE_TOKEN_BRANDS.get(brand.toLowerCase());
|
|
17238
|
+
}
|
|
17239
|
+
if (!/[\d-]/.test(match?.[2] ?? "")) {
|
|
17240
|
+
return void 0;
|
|
17241
|
+
}
|
|
17242
|
+
return brand;
|
|
17243
|
+
};
|
|
17244
|
+
var inferTitleFromContent = (content, productUrl) => {
|
|
17807
17245
|
const normalized = normalizePlainText(content);
|
|
17808
17246
|
if (!normalized) return void 0;
|
|
17809
17247
|
const bestBuyTitle = inferBestBuyTitleFromContent(normalized);
|
|
17810
17248
|
if (bestBuyTitle) {
|
|
17811
17249
|
return bestBuyTitle;
|
|
17812
17250
|
}
|
|
17251
|
+
if (productUrl && resolveShoppingProviderIdForUrl(productUrl) === "shopping/ebay") {
|
|
17252
|
+
const ebayTitle = inferEbayTitleFromContent(normalized);
|
|
17253
|
+
if (ebayTitle) {
|
|
17254
|
+
return ebayTitle;
|
|
17255
|
+
}
|
|
17256
|
+
}
|
|
17813
17257
|
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
17258
|
const candidate = normalizePlainText(storeMatch?.[1]);
|
|
17815
17259
|
if (!candidate || candidate.length < 20 || LOOKS_LIKE_URL_RE.test(candidate)) {
|
|
@@ -17822,6 +17266,11 @@ var sanitizeProductBrandCandidate = (candidate, productUrl) => {
|
|
|
17822
17266
|
if (!normalized) return void 0;
|
|
17823
17267
|
try {
|
|
17824
17268
|
const host = new URL(productUrl).hostname.toLowerCase();
|
|
17269
|
+
const hostBrand = normalizePlainText(inferBrandFromUrl(productUrl)).replace(/\.com\b/gi, "").toLowerCase();
|
|
17270
|
+
const candidateBrand = normalized.replace(/\.com\b/gi, "").toLowerCase();
|
|
17271
|
+
if (host.includes("ebay.") && hostBrand && candidateBrand === hostBrand) {
|
|
17272
|
+
return void 0;
|
|
17273
|
+
}
|
|
17825
17274
|
if (!host.includes("walmart.")) {
|
|
17826
17275
|
return normalized;
|
|
17827
17276
|
}
|
|
@@ -17966,6 +17415,17 @@ var inferHostDefaultCurrency = (productUrl) => {
|
|
|
17966
17415
|
return void 0;
|
|
17967
17416
|
}
|
|
17968
17417
|
};
|
|
17418
|
+
var extractProductBrandFromTitle = (title, productUrl) => {
|
|
17419
|
+
try {
|
|
17420
|
+
const host = new URL(productUrl).hostname.toLowerCase();
|
|
17421
|
+
if (host.includes("ebay.")) {
|
|
17422
|
+
return inferEbayBrandFromTitle(title);
|
|
17423
|
+
}
|
|
17424
|
+
} catch {
|
|
17425
|
+
return extractBrandFromTitle(title);
|
|
17426
|
+
}
|
|
17427
|
+
return extractBrandFromTitle(title);
|
|
17428
|
+
};
|
|
17969
17429
|
var shouldSuppressMarketplacePrice = (record, productUrl, price) => {
|
|
17970
17430
|
if (price.amount <= 0) return false;
|
|
17971
17431
|
const expectedCurrency = inferHostDefaultCurrency(productUrl);
|
|
@@ -18090,12 +17550,12 @@ var resolveProductBrand = (record, productUrl, refreshedBrand) => {
|
|
|
18090
17550
|
const nestedProvider = nested && typeof nested === "object" && !Array.isArray(nested) ? nested.provider : void 0;
|
|
18091
17551
|
const providerBrand = typeof nestedProvider === "string" ? SHOPPING_PROVIDER_PROFILES.find((entry) => entry.id === nestedProvider)?.displayName : void 0;
|
|
18092
17552
|
const candidates = [
|
|
18093
|
-
inferBrandFromContent(record.content),
|
|
17553
|
+
inferBrandFromContent(record.content, productUrl),
|
|
18094
17554
|
rejectRetailerBrand(refreshedBrand),
|
|
18095
17555
|
rejectRetailerBrand(typeof record.attributes.brand === "string" ? record.attributes.brand : void 0),
|
|
18096
17556
|
rejectRetailerBrand(typeof record.attributes.site_name === "string" ? record.attributes.site_name : void 0),
|
|
18097
17557
|
rejectRetailerBrand(providerBrand && providerBrand !== "Others" ? providerBrand : void 0),
|
|
18098
|
-
|
|
17558
|
+
extractProductBrandFromTitle(record.title, productUrl),
|
|
18099
17559
|
inferBrandFromUrl(productUrl)
|
|
18100
17560
|
].map((entry) => sanitizeProductBrandCandidate(entry, productUrl)).filter(Boolean);
|
|
18101
17561
|
return candidates[0] || "unknown";
|
|
@@ -18105,7 +17565,7 @@ var resolveProductTitle = (record, productUrl, brand, refreshedTitle) => {
|
|
|
18105
17565
|
const nestedTitle = nested && typeof nested === "object" && !Array.isArray(nested) ? nested.title : void 0;
|
|
18106
17566
|
const candidates = [
|
|
18107
17567
|
refreshedTitle,
|
|
18108
|
-
inferTitleFromContent(record.content),
|
|
17568
|
+
inferTitleFromContent(record.content, productUrl),
|
|
18109
17569
|
record.title,
|
|
18110
17570
|
typeof nestedTitle === "string" ? nestedTitle : void 0,
|
|
18111
17571
|
typeof record.attributes.description === "string" ? record.attributes.description.split(/(?<=[.!?])\s+/)[0] : void 0,
|
|
@@ -18154,13 +17614,31 @@ var resolveShoppingSourceForUrl = (url) => {
|
|
|
18154
17614
|
return "web";
|
|
18155
17615
|
}
|
|
18156
17616
|
};
|
|
17617
|
+
var RESEARCH_REJECTED_CANDIDATE_LIMIT = 25;
|
|
17618
|
+
var isResearchPrivacyPreferenceShell = (content) => {
|
|
17619
|
+
const matchIndex = content.slice(0, 400).search(RESEARCH_PRIVACY_PREFERENCE_SHELL_RE);
|
|
17620
|
+
return matchIndex >= 0 && matchIndex <= 80 && !RESEARCH_PRIVACY_RECOVERED_CONTENT_RE.test(content);
|
|
17621
|
+
};
|
|
17622
|
+
var classifyResearchDeadEndUrl = (value) => {
|
|
17623
|
+
if (!value) return null;
|
|
17624
|
+
return classifyResearchDestinationRejection(value);
|
|
17625
|
+
};
|
|
17626
|
+
var isResearchLoginShellRecord = (args) => {
|
|
17627
|
+
if (args.url.includes("/login")) {
|
|
17628
|
+
return true;
|
|
17629
|
+
}
|
|
17630
|
+
if (!RESEARCH_LOGIN_SHELL_RE.test(args.combined)) {
|
|
17631
|
+
return false;
|
|
17632
|
+
}
|
|
17633
|
+
return args.content.length <= RESEARCH_LOGIN_SHELL_MAX_CONTENT_CHARS || RESEARCH_LOGIN_REQUIRED_RE.test(args.combined);
|
|
17634
|
+
};
|
|
18157
17635
|
var classifyResearchShellRecord = (record) => {
|
|
18158
17636
|
const retrievalPath = typeof record.attributes.retrievalPath === "string" ? record.attributes.retrievalPath : "";
|
|
18159
17637
|
const url = typeof record.url === "string" ? record.url.trim().toLowerCase() : "";
|
|
18160
17638
|
const title = normalizePlainText(record.title).toLowerCase();
|
|
18161
17639
|
const content = normalizePlainText(record.content).toLowerCase();
|
|
18162
17640
|
const combined = `${title} ${content}`.trim();
|
|
18163
|
-
if (
|
|
17641
|
+
if (isResearchLoginShellRecord({ url, combined, content })) {
|
|
18164
17642
|
return "login_shell";
|
|
18165
17643
|
}
|
|
18166
17644
|
if (RESEARCH_JS_REQUIRED_RE.test(combined)) {
|
|
@@ -18169,6 +17647,13 @@ var classifyResearchShellRecord = (record) => {
|
|
|
18169
17647
|
if (RESEARCH_NOT_FOUND_SHELL_RE.test(combined)) {
|
|
18170
17648
|
return "not_found_shell";
|
|
18171
17649
|
}
|
|
17650
|
+
if (isResearchPrivacyPreferenceShell(content)) {
|
|
17651
|
+
return "privacy_preference_shell";
|
|
17652
|
+
}
|
|
17653
|
+
const deadEndUrlReason = classifyResearchDeadEndUrl(url);
|
|
17654
|
+
if (deadEndUrlReason) {
|
|
17655
|
+
return deadEndUrlReason;
|
|
17656
|
+
}
|
|
18172
17657
|
if (!retrievalPath) {
|
|
18173
17658
|
return null;
|
|
18174
17659
|
}
|
|
@@ -18191,18 +17676,47 @@ var classifyResearchShellRecord = (record) => {
|
|
|
18191
17676
|
};
|
|
18192
17677
|
var sanitizeResearchRecords = (records) => {
|
|
18193
17678
|
const reasonDistribution = {};
|
|
17679
|
+
const rejectedCandidates = [];
|
|
18194
17680
|
const sanitizedRecords = records.filter((record) => {
|
|
18195
17681
|
const reason = classifyResearchShellRecord(record);
|
|
18196
17682
|
if (!reason) return true;
|
|
18197
17683
|
reasonDistribution[reason] = (reasonDistribution[reason] ?? 0) + 1;
|
|
17684
|
+
if (rejectedCandidates.length < RESEARCH_REJECTED_CANDIDATE_LIMIT) {
|
|
17685
|
+
const retrievalPath = typeof record.attributes.retrievalPath === "string" ? record.attributes.retrievalPath : void 0;
|
|
17686
|
+
rejectedCandidates.push({
|
|
17687
|
+
provider: record.provider,
|
|
17688
|
+
source: record.source,
|
|
17689
|
+
reason,
|
|
17690
|
+
replacement_status: "rejected_before_synthesis",
|
|
17691
|
+
...retrievalPath ? { retrievalPath } : {},
|
|
17692
|
+
...record.title ? { title: record.title } : {},
|
|
17693
|
+
...record.url ? { url: record.url } : {}
|
|
17694
|
+
});
|
|
17695
|
+
}
|
|
18198
17696
|
return false;
|
|
18199
17697
|
});
|
|
18200
17698
|
return {
|
|
18201
17699
|
records: sanitizedRecords,
|
|
18202
17700
|
sanitizedCount: records.length - sanitizedRecords.length,
|
|
18203
|
-
reasonDistribution
|
|
17701
|
+
reasonDistribution,
|
|
17702
|
+
rejectedCandidates
|
|
17703
|
+
};
|
|
17704
|
+
};
|
|
17705
|
+
var rejectedCandidateFromFailure = (failure) => {
|
|
17706
|
+
const details = failure.error.details ?? {};
|
|
17707
|
+
if (details.fallbackOutputReason !== "research_dead_end_shell") return null;
|
|
17708
|
+
const retrievalPath = typeof details.retrievalPath === "string" ? details.retrievalPath : void 0;
|
|
17709
|
+
const url = typeof details.url === "string" ? details.url : void 0;
|
|
17710
|
+
return {
|
|
17711
|
+
provider: failure.provider,
|
|
17712
|
+
source: failure.source,
|
|
17713
|
+
reason: "research_dead_end_shell",
|
|
17714
|
+
replacement_status: "rejected_before_synthesis",
|
|
17715
|
+
...retrievalPath ? { retrievalPath } : {},
|
|
17716
|
+
...url ? { url } : {}
|
|
18204
17717
|
};
|
|
18205
17718
|
};
|
|
17719
|
+
var rejectedCandidatesFromFailures = (failures) => failures.map(rejectedCandidateFromFailure).filter((candidate) => candidate !== null);
|
|
18206
17720
|
var isValidHttpUrl3 = (url) => {
|
|
18207
17721
|
try {
|
|
18208
17722
|
const parsed = new URL(url.trim());
|
|
@@ -18228,6 +17742,13 @@ var classifyInvalidProductTarget = (record) => {
|
|
|
18228
17742
|
message: "Product target appears to be a not-found page"
|
|
18229
17743
|
};
|
|
18230
17744
|
}
|
|
17745
|
+
const providerId = resolveShoppingProviderIdForUrl(record.url ?? "");
|
|
17746
|
+
if (providerId === "shopping/bestbuy" && combined.toLowerCase().includes("something went wrong") && BESTBUY_PDP_ERROR_SHELL_RE.test(combined)) {
|
|
17747
|
+
return {
|
|
17748
|
+
reason: "provider_error_shell",
|
|
17749
|
+
message: "Best Buy product target returned a generic error shell"
|
|
17750
|
+
};
|
|
17751
|
+
}
|
|
18231
17752
|
return null;
|
|
18232
17753
|
};
|
|
18233
17754
|
var runResearchWorkflow = async (runtime, input) => {
|
|
@@ -18235,7 +17756,9 @@ var runResearchWorkflow = async (runtime, input) => {
|
|
|
18235
17756
|
if (envelope.kind !== "research") {
|
|
18236
17757
|
throw new Error(`Research workflow envelope kind mismatch. Expected research but received ${envelope.kind}.`);
|
|
18237
17758
|
}
|
|
18238
|
-
const
|
|
17759
|
+
const rawWorkflowInput = envelope.input;
|
|
17760
|
+
const artifactRoot = resolveWorkflowArtifactRoot(rawWorkflowInput.outputDir);
|
|
17761
|
+
const workflowInput = { ...rawWorkflowInput, outputDir: artifactRoot };
|
|
18239
17762
|
let trace = [
|
|
18240
17763
|
...envelope.trace ?? [],
|
|
18241
17764
|
{
|
|
@@ -18291,21 +17814,23 @@ var runResearchWorkflow = async (runtime, input) => {
|
|
|
18291
17814
|
}
|
|
18292
17815
|
});
|
|
18293
17816
|
const excludedProviderSet = new Set(plan.compiled.autoExcludedProviders);
|
|
18294
|
-
const
|
|
18295
|
-
|
|
18296
|
-
|
|
18297
|
-
|
|
18298
|
-
|
|
18299
|
-
|
|
18300
|
-
|
|
17817
|
+
const rawRecords = [
|
|
17818
|
+
...execution.searchRuns.flatMap((run) => run.result.records),
|
|
17819
|
+
...execution.followUpRuns.flatMap((run) => run.result.records)
|
|
17820
|
+
];
|
|
17821
|
+
const rawFailures = [
|
|
17822
|
+
...execution.searchRuns.flatMap((run) => run.result.failures),
|
|
17823
|
+
...execution.followUpRuns.flatMap((run) => run.result.failures)
|
|
17824
|
+
];
|
|
17825
|
+
const mergedRecords = removeExcludedProviders(rawRecords, excludedProviderSet);
|
|
18301
17826
|
const sanitizedRecords = sanitizeResearchRecords(mergedRecords);
|
|
18302
|
-
const mergedFailures = removeExcludedProviders(
|
|
18303
|
-
|
|
18304
|
-
|
|
18305
|
-
|
|
18306
|
-
|
|
18307
|
-
|
|
18308
|
-
|
|
17827
|
+
const mergedFailures = removeExcludedProviders(rawFailures, excludedProviderSet);
|
|
17828
|
+
const rejectedFailureCandidates = rejectedCandidatesFromFailures(mergedFailures);
|
|
17829
|
+
const rejectedCandidates = [
|
|
17830
|
+
...sanitizedRecords.rejectedCandidates,
|
|
17831
|
+
...rejectedFailureCandidates
|
|
17832
|
+
].slice(0, RESEARCH_REJECTED_CANDIDATE_LIMIT);
|
|
17833
|
+
const rejectedCandidateCount2 = sanitizedRecords.sanitizedCount + rejectedFailureCandidates.length;
|
|
18309
17834
|
const reasonCodeDistribution = summarizeReasonCodeDistribution(mergedFailures);
|
|
18310
17835
|
const transcriptStrategyFailures = summarizeTranscriptStrategyFailures(mergedFailures);
|
|
18311
17836
|
const evaluationNow = /* @__PURE__ */ new Date();
|
|
@@ -18313,8 +17838,8 @@ var runResearchWorkflow = async (runtime, input) => {
|
|
|
18313
17838
|
const enriched = enrichResearchRecords(withinTimebox, plan.compiled.timebox, evaluationNow);
|
|
18314
17839
|
const deduped = dedupeResearchRecords(enriched);
|
|
18315
17840
|
const ranked = rankResearchRecords(deduped);
|
|
18316
|
-
const noUsableResearchRecords = mergedRecords.length > 0 && mergedFailures.length === 0 && ranked.length === 0;
|
|
18317
17841
|
const cookieDiagnostics = summarizeCookieDiagnostics(mergedFailures, mergedRecords);
|
|
17842
|
+
const challengeOrchestration = summarizeChallengeOrchestration(mergedFailures, mergedRecords);
|
|
18318
17843
|
const transcriptStrategyDetailDistribution = summarizeTranscriptStrategyDetailDistribution(ranked);
|
|
18319
17844
|
const transcriptDurability = summarizeTranscriptDurability(ranked, mergedFailures);
|
|
18320
17845
|
const antiBotPressure = summarizeAntiBotPressure(mergedFailures);
|
|
@@ -18322,16 +17847,16 @@ var runResearchWorkflow = async (runtime, input) => {
|
|
|
18322
17847
|
...plan.compiled.timebox,
|
|
18323
17848
|
to: new Date(Math.max(new Date(plan.compiled.timebox.to).getTime(), evaluationNow.getTime())).toISOString()
|
|
18324
17849
|
} : plan.compiled.timebox;
|
|
18325
|
-
if (
|
|
17850
|
+
if (mergedRecords.length > 0 && sanitizedRecords.records.length === 0) {
|
|
18326
17851
|
const sanitizedReasons = Object.entries(sanitizedRecords.reasonDistribution).map(([reason, count]) => `${reason}:${count}`).join(",");
|
|
18327
17852
|
throw new Error(
|
|
18328
17853
|
`Research workflow produced only shell records and no usable results (${sanitizedReasons || "sanitized"}).`
|
|
18329
17854
|
);
|
|
18330
17855
|
}
|
|
18331
|
-
if (
|
|
17856
|
+
if (sanitizedRecords.records.length > 0 && withinTimebox.length === 0) {
|
|
18332
17857
|
throw new Error("Research workflow produced no usable in-timebox results after sanitization.");
|
|
18333
17858
|
}
|
|
18334
|
-
if (
|
|
17859
|
+
if (ranked.length === 0) {
|
|
18335
17860
|
throw new Error("Research workflow produced no usable results after post-processing.");
|
|
18336
17861
|
}
|
|
18337
17862
|
const primaryConstraintFailures = selectResearchPrimaryConstraintFailures(mergedFailures);
|
|
@@ -18345,8 +17870,10 @@ var runResearchWorkflow = async (runtime, input) => {
|
|
|
18345
17870
|
metrics: {
|
|
18346
17871
|
total_records: mergedRecords.length,
|
|
18347
17872
|
sanitized_records: sanitizedRecords.sanitizedCount,
|
|
17873
|
+
rejected_candidate_count: rejectedCandidateCount2,
|
|
18348
17874
|
sanitized_reason_distribution: sanitizedRecords.reasonDistribution,
|
|
18349
17875
|
sanitizedReasonDistribution: sanitizedRecords.reasonDistribution,
|
|
17876
|
+
rejected_candidate_sample_size: rejectedCandidates.length,
|
|
18350
17877
|
within_timebox: withinTimebox.length,
|
|
18351
17878
|
final_records: ranked.length,
|
|
18352
17879
|
failed_sources: execution.searchRuns.filter((run) => !run.result.ok).map((run) => run.source),
|
|
@@ -18361,15 +17888,22 @@ var runResearchWorkflow = async (runtime, input) => {
|
|
|
18361
17888
|
transcriptDurability,
|
|
18362
17889
|
cookie_diagnostics: cookieDiagnostics,
|
|
18363
17890
|
cookieDiagnostics,
|
|
17891
|
+
challenge_orchestration: challengeOrchestration,
|
|
17892
|
+
challengeOrchestration,
|
|
18364
17893
|
anti_bot_pressure: antiBotPressure,
|
|
18365
17894
|
antiBotPressure
|
|
18366
17895
|
},
|
|
18367
17896
|
failures: mergedFailures,
|
|
17897
|
+
rejected_candidates: rejectedCandidates,
|
|
17898
|
+
rejectedCandidates,
|
|
18368
17899
|
alerts: buildWorkflowAlerts(runtime, mergedFailures)
|
|
18369
17900
|
}, primaryConstraintFailures);
|
|
18370
17901
|
const handoff = buildResearchSuccessHandoff({
|
|
18371
17902
|
topic: plan.compiled.topic,
|
|
18372
|
-
browserMode: workflowInput.browserMode
|
|
17903
|
+
browserMode: workflowInput.browserMode,
|
|
17904
|
+
failures: mergedFailures,
|
|
17905
|
+
cookieDiagnostics,
|
|
17906
|
+
challengeOrchestration
|
|
18373
17907
|
});
|
|
18374
17908
|
const responseMeta = withFollowthroughMeta(meta, handoff);
|
|
18375
17909
|
const rendered = renderResearch({
|
|
@@ -18380,7 +17914,7 @@ var runResearchWorkflow = async (runtime, input) => {
|
|
|
18380
17914
|
});
|
|
18381
17915
|
const bundle = await createArtifactBundle({
|
|
18382
17916
|
namespace: "research",
|
|
18383
|
-
outputDir:
|
|
17917
|
+
outputDir: artifactRoot,
|
|
18384
17918
|
ttlHours: workflowInput.ttlHours,
|
|
18385
17919
|
files: rendered.files
|
|
18386
17920
|
});
|
|
@@ -18388,7 +17922,7 @@ var runResearchWorkflow = async (runtime, input) => {
|
|
|
18388
17922
|
return {
|
|
18389
17923
|
...rendered.response,
|
|
18390
17924
|
...handoff,
|
|
18391
|
-
|
|
17925
|
+
artifact_path: bundle.basePath,
|
|
18392
17926
|
records: ranked,
|
|
18393
17927
|
meta: {
|
|
18394
17928
|
...responseMeta,
|
|
@@ -18412,7 +17946,9 @@ var runShoppingWorkflow = async (runtime, input) => {
|
|
|
18412
17946
|
if (envelope.kind !== "shopping") {
|
|
18413
17947
|
throw new Error(`Shopping workflow envelope kind mismatch. Expected shopping but received ${envelope.kind}.`);
|
|
18414
17948
|
}
|
|
18415
|
-
const
|
|
17949
|
+
const rawWorkflowInput = envelope.input;
|
|
17950
|
+
const artifactRoot = resolveWorkflowArtifactRoot(rawWorkflowInput.outputDir);
|
|
17951
|
+
const workflowInput = { ...rawWorkflowInput, outputDir: artifactRoot };
|
|
18416
17952
|
const remainingTimeoutMs = createRemainingTimeoutResolver(workflowInput.timeoutMs);
|
|
18417
17953
|
let trace = [
|
|
18418
17954
|
...envelope.trace ?? [],
|
|
@@ -18566,7 +18102,7 @@ var runShoppingWorkflow = async (runtime, input) => {
|
|
|
18566
18102
|
});
|
|
18567
18103
|
const bundle = await createArtifactBundle({
|
|
18568
18104
|
namespace: "shopping",
|
|
18569
|
-
outputDir:
|
|
18105
|
+
outputDir: artifactRoot,
|
|
18570
18106
|
ttlHours: workflowInput.ttlHours,
|
|
18571
18107
|
files: rendered.files
|
|
18572
18108
|
});
|
|
@@ -18574,7 +18110,7 @@ var runShoppingWorkflow = async (runtime, input) => {
|
|
|
18574
18110
|
return {
|
|
18575
18111
|
...rendered.response,
|
|
18576
18112
|
...handoff,
|
|
18577
|
-
|
|
18113
|
+
artifact_path: bundle.basePath,
|
|
18578
18114
|
offers,
|
|
18579
18115
|
meta: {
|
|
18580
18116
|
...responseMeta,
|
|
@@ -18594,7 +18130,9 @@ var runShoppingWorkflow = async (runtime, input) => {
|
|
|
18594
18130
|
};
|
|
18595
18131
|
};
|
|
18596
18132
|
var runInspiredesignWorkflow = async (runtime, input, options = {}) => {
|
|
18597
|
-
const { envelope, workflowInput } = buildInspiredesignEnvelope(input);
|
|
18133
|
+
const { envelope, workflowInput: rawWorkflowInput } = buildInspiredesignEnvelope(input);
|
|
18134
|
+
const artifactRoot = resolveWorkflowArtifactRoot(rawWorkflowInput.outputDir);
|
|
18135
|
+
const workflowInput = { ...rawWorkflowInput, outputDir: artifactRoot };
|
|
18598
18136
|
const remainingTimeoutMs = createRemainingTimeoutResolver(workflowInput.timeoutMs);
|
|
18599
18137
|
let trace = appendWorkflowTrace(envelope.trace ?? [], "compile", "compile_started", {
|
|
18600
18138
|
kind: "inspiredesign"
|
|
@@ -18668,14 +18206,14 @@ var runInspiredesignWorkflow = async (runtime, input, options = {}) => {
|
|
|
18668
18206
|
});
|
|
18669
18207
|
const bundle = await createArtifactBundle({
|
|
18670
18208
|
namespace: "inspiredesign",
|
|
18671
|
-
outputDir:
|
|
18209
|
+
outputDir: artifactRoot,
|
|
18672
18210
|
ttlHours: workflowInput.ttlHours,
|
|
18673
18211
|
files: rendered.files
|
|
18674
18212
|
});
|
|
18675
18213
|
if (workflowInput.mode === "path") {
|
|
18676
18214
|
return {
|
|
18677
18215
|
...rendered.response,
|
|
18678
|
-
|
|
18216
|
+
artifact_path: bundle.basePath,
|
|
18679
18217
|
meta: {
|
|
18680
18218
|
...meta,
|
|
18681
18219
|
artifact_manifest: bundle.manifest
|
|
@@ -18724,7 +18262,9 @@ var runProductVideoWorkflow = async (runtime, input, options = {}) => {
|
|
|
18724
18262
|
}
|
|
18725
18263
|
}
|
|
18726
18264
|
];
|
|
18727
|
-
const
|
|
18265
|
+
const rawWorkflowInput = plan.input;
|
|
18266
|
+
const productVideoArtifactRoot = resolveWorkflowArtifactRoot(rawWorkflowInput.output_dir);
|
|
18267
|
+
const workflowInput = { ...rawWorkflowInput, output_dir: productVideoArtifactRoot };
|
|
18728
18268
|
const includeScreenshots = plan.compiled.includeScreenshots;
|
|
18729
18269
|
const includeAllImages = plan.compiled.includeAllImages;
|
|
18730
18270
|
const includeCopy = plan.compiled.includeCopy;
|
|
@@ -18804,6 +18344,8 @@ var runProductVideoWorkflow = async (runtime, input, options = {}) => {
|
|
|
18804
18344
|
query: resolveStep.input.product_name,
|
|
18805
18345
|
providers: providerHint ? [providerHint] : void 0,
|
|
18806
18346
|
mode: "json",
|
|
18347
|
+
outputDir: productVideoArtifactRoot,
|
|
18348
|
+
ttlHours: workflowInput.ttl_hours,
|
|
18807
18349
|
...timeoutOptions,
|
|
18808
18350
|
browserMode: workflowInput.browserMode,
|
|
18809
18351
|
useCookies: workflowInput.useCookies,
|
|
@@ -19025,11 +18567,10 @@ var runProductVideoWorkflow = async (runtime, input, options = {}) => {
|
|
|
19025
18567
|
files: files.length
|
|
19026
18568
|
});
|
|
19027
18569
|
const bundle = await createArtifactBundle({
|
|
19028
|
-
namespace: "product-
|
|
19029
|
-
outputDir:
|
|
18570
|
+
namespace: "product-video",
|
|
18571
|
+
outputDir: productVideoArtifactRoot,
|
|
19030
18572
|
ttlHours: workflowInput.ttl_hours,
|
|
19031
|
-
files
|
|
19032
|
-
manifestFileName: "bundle-manifest.json"
|
|
18573
|
+
files
|
|
19033
18574
|
});
|
|
19034
18575
|
const reasonCodeDistribution = summarizeReasonCodeDistribution(details.failures);
|
|
19035
18576
|
const transcriptStrategyFailures = summarizeTranscriptStrategyFailures(details.failures);
|
|
@@ -19069,7 +18610,7 @@ var runProductVideoWorkflow = async (runtime, input, options = {}) => {
|
|
|
19069
18610
|
}, handoff);
|
|
19070
18611
|
return {
|
|
19071
18612
|
...handoff,
|
|
19072
|
-
|
|
18613
|
+
artifact_path: bundle.basePath,
|
|
19073
18614
|
manifest: manifestPayload,
|
|
19074
18615
|
product: productPayload,
|
|
19075
18616
|
pricing,
|
|
@@ -19123,7 +18664,10 @@ var buildSocialDefaultTraversal = (platform, options) => {
|
|
|
19123
18664
|
...existing ?? {}
|
|
19124
18665
|
};
|
|
19125
18666
|
};
|
|
19126
|
-
var shouldRecoverSocialDocumentIssue = (platform, operation, issue) => {
|
|
18667
|
+
var shouldRecoverSocialDocumentIssue = (platform, operation, issue, context) => {
|
|
18668
|
+
if (isResearchSearchDiscoveryRun(operation, context)) {
|
|
18669
|
+
return false;
|
|
18670
|
+
}
|
|
19127
18671
|
if (SOCIAL_BROWSER_RECOVERY_REASON_CODES.has(issue.reasonCode)) {
|
|
19128
18672
|
return true;
|
|
19129
18673
|
}
|
|
@@ -19132,7 +18676,7 @@ var shouldRecoverSocialDocumentIssue = (platform, operation, issue) => {
|
|
|
19132
18676
|
}
|
|
19133
18677
|
return operation === "search" && SEARCH_RENDER_RECOVERY_SOCIAL_PLATFORMS.has(platform) && issue.reasonCode === "env_limited" && issue.constraint?.kind === "render_required";
|
|
19134
18678
|
};
|
|
19135
|
-
var
|
|
18679
|
+
var isJsonRecord8 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
19136
18680
|
var unwrapWorkflowResumeEnvelope = (kind, input) => {
|
|
19137
18681
|
if (!isWorkflowResumePayload(input)) {
|
|
19138
18682
|
throw new ProviderRuntimeError(
|
|
@@ -19185,10 +18729,10 @@ var Semaphore = class {
|
|
|
19185
18729
|
this.active += 1;
|
|
19186
18730
|
return;
|
|
19187
18731
|
}
|
|
19188
|
-
await new Promise((
|
|
18732
|
+
await new Promise((resolve) => {
|
|
19189
18733
|
this.queue.push(() => {
|
|
19190
18734
|
this.active += 1;
|
|
19191
|
-
|
|
18735
|
+
resolve();
|
|
19192
18736
|
});
|
|
19193
18737
|
});
|
|
19194
18738
|
}
|
|
@@ -19367,7 +18911,7 @@ var isBlockedRedditFallbackLink = (link) => {
|
|
|
19367
18911
|
return false;
|
|
19368
18912
|
}
|
|
19369
18913
|
};
|
|
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);
|
|
18914
|
+
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
18915
|
var shouldReturnCompletedFallbackForOwnerReview = (args) => args.document.browserFallback !== void 0 && args.ownerReview?.({
|
|
19372
18916
|
providerId: args.providerId,
|
|
19373
18917
|
source: args.source,
|
|
@@ -19440,6 +18984,8 @@ var describeDefaultFetchedIssue = (document) => {
|
|
|
19440
18984
|
};
|
|
19441
18985
|
};
|
|
19442
18986
|
var shouldRecoverDefaultFetchedIssue = (issue) => issue.reasonCode === "challenge_detected" || issue.reasonCode === "token_required" || issue.reasonCode === "env_limited" && !!issue.constraint;
|
|
18987
|
+
var isUsableCommunityRedditSearchFallback = (args) => args.source === "community" && args.operation === "search" && args.document.browserFallback !== void 0 && isFirstPartySocialSearchRoute("reddit", args.document.url) && hasUsableCommunityFallbackSearchContent(args.pageMessage);
|
|
18988
|
+
var isResearchSearchDiscoveryRun = (operation, context) => operation === "search" && context.suspendedIntent?.kind === "workflow.research";
|
|
19443
18989
|
var toDefaultFetchedIssueError = (args) => {
|
|
19444
18990
|
const reasonCode = args.issueDetails.issue?.reasonCode ?? "env_limited";
|
|
19445
18991
|
return new ProviderRuntimeError(
|
|
@@ -19464,6 +19010,14 @@ var resolveDefaultFallbackDocumentIfNeeded = async (args) => {
|
|
|
19464
19010
|
if (!initialIssue) {
|
|
19465
19011
|
return { document: currentDocument, ...described };
|
|
19466
19012
|
}
|
|
19013
|
+
if (isUsableCommunityRedditSearchFallback({
|
|
19014
|
+
source: args.source,
|
|
19015
|
+
operation: args.operation,
|
|
19016
|
+
document: currentDocument,
|
|
19017
|
+
pageMessage: described.pageMessage
|
|
19018
|
+
})) {
|
|
19019
|
+
return { document: currentDocument, ...described, issue: null };
|
|
19020
|
+
}
|
|
19467
19021
|
if (shouldReturnCompletedFallbackForOwnerReview({ ...args, document: currentDocument })) {
|
|
19468
19022
|
return { document: currentDocument, ...described };
|
|
19469
19023
|
}
|
|
@@ -19506,6 +19060,14 @@ var resolveDefaultFallbackDocumentIfNeeded = async (args) => {
|
|
|
19506
19060
|
ownerReview: args.ownerReview
|
|
19507
19061
|
});
|
|
19508
19062
|
described = describeDefaultFetchedIssue(currentDocument);
|
|
19063
|
+
if (isUsableCommunityRedditSearchFallback({
|
|
19064
|
+
source: args.source,
|
|
19065
|
+
operation: args.operation,
|
|
19066
|
+
document: currentDocument,
|
|
19067
|
+
pageMessage: described.pageMessage
|
|
19068
|
+
})) {
|
|
19069
|
+
return { document: currentDocument, ...described, issue: null };
|
|
19070
|
+
}
|
|
19509
19071
|
if (shouldReturnCompletedFallbackForOwnerReview({ ...args, document: currentDocument })) {
|
|
19510
19072
|
return { document: currentDocument, ...described };
|
|
19511
19073
|
}
|
|
@@ -19522,16 +19084,32 @@ var resolveDefaultFallbackDocumentIfNeeded = async (args) => {
|
|
|
19522
19084
|
};
|
|
19523
19085
|
var COMMUNITY_SEARCH_LINK_SCAN_MULTIPLIER = 4;
|
|
19524
19086
|
var MIN_COMMUNITY_SEARCH_LINK_SCAN = 12;
|
|
19525
|
-
var resolveCommunitySearchLinks = (document, limit) => {
|
|
19087
|
+
var resolveCommunitySearchLinks = (document, limit, researchContext) => {
|
|
19526
19088
|
const scanLimit = Math.max(limit * COMMUNITY_SEARCH_LINK_SCAN_MULTIPLIER, MIN_COMMUNITY_SEARCH_LINK_SCAN);
|
|
19527
19089
|
const links = prioritizeSocialSearchLinks(
|
|
19528
19090
|
"reddit",
|
|
19529
19091
|
document.url,
|
|
19530
19092
|
dedupeLinks2(document.links, document.url, scanLimit)
|
|
19531
19093
|
);
|
|
19532
|
-
return links.filter((url) => isAllowedSocialSearchExpansionUrl("reddit", url)).slice(0, limit);
|
|
19094
|
+
return links.filter((url) => researchContext ? isLikelyResearchDestinationUrl(url) : isLikelyDocumentUrl(url)).filter((url) => isAllowedSocialSearchExpansionUrl("reddit", url)).slice(0, limit);
|
|
19095
|
+
};
|
|
19096
|
+
var shouldRejectBlockedCommunityFallback = (document, links, pageMessage) => document.browserFallback !== void 0 && isFirstPartySocialSearchRoute("reddit", document.url) && links.length === 0 && !hasUsableCommunityFallbackSearchContent(pageMessage);
|
|
19097
|
+
var COMMUNITY_FALLBACK_SEARCH_MIN_CHARS = 120;
|
|
19098
|
+
var COMMUNITY_FALLBACK_SEARCH_EVIDENCE_RE = [
|
|
19099
|
+
/\bshowing results for\b/i,
|
|
19100
|
+
/\bsearch for\b/i,
|
|
19101
|
+
/\banswers?\b/i,
|
|
19102
|
+
/\bsources?:\s+/i,
|
|
19103
|
+
/\br\/[a-z0-9_]+\b/i
|
|
19104
|
+
];
|
|
19105
|
+
var hasUsableCommunityFallbackSearchContent = (pageMessage) => {
|
|
19106
|
+
const trimmed = pageMessage.trim();
|
|
19107
|
+
if (trimmed.length < COMMUNITY_FALLBACK_SEARCH_MIN_CHARS) {
|
|
19108
|
+
return false;
|
|
19109
|
+
}
|
|
19110
|
+
const evidenceCount = COMMUNITY_FALLBACK_SEARCH_EVIDENCE_RE.filter((pattern) => pattern.test(trimmed)).length;
|
|
19111
|
+
return evidenceCount >= 2;
|
|
19533
19112
|
};
|
|
19534
|
-
var shouldRejectBlockedCommunityFallback = (document, links) => document.browserFallback !== void 0 && isFirstPartySocialSearchRoute("reddit", document.url) && links.length === 0;
|
|
19535
19113
|
var toCommunityFallbackSearchError = (args) => {
|
|
19536
19114
|
const reasonCode = args.document.browserFallback?.reasonCode ?? "env_limited";
|
|
19537
19115
|
return new ProviderRuntimeError(
|
|
@@ -19646,6 +19224,36 @@ var dedupeLinks2 = (links, baseUrl, limit) => {
|
|
|
19646
19224
|
}
|
|
19647
19225
|
return deduped;
|
|
19648
19226
|
};
|
|
19227
|
+
var isUsableWebSearchResultUrl = (url, researchContext) => !isDuckDuckGoSearchShellUrl(url) && (researchContext ? isLikelyResearchDestinationUrl(url) : isLikelyDocumentUrl(url));
|
|
19228
|
+
var isResearchWorkflowContext = (context) => context.suspendedIntent?.kind === "workflow.research";
|
|
19229
|
+
var resolveWebSearchResultLinks = (document, limit, researchContext, includeDocumentUrl) => {
|
|
19230
|
+
const links = dedupeLinks2(document.links, document.url, limit * 2);
|
|
19231
|
+
const candidates = includeDocumentUrl ? [document.url, ...links] : links;
|
|
19232
|
+
const seen = /* @__PURE__ */ new Set();
|
|
19233
|
+
return candidates.filter((url) => {
|
|
19234
|
+
const keep = isUsableWebSearchResultUrl(url, researchContext) && !seen.has(url);
|
|
19235
|
+
if (keep) seen.add(url);
|
|
19236
|
+
return keep;
|
|
19237
|
+
}).slice(0, limit);
|
|
19238
|
+
};
|
|
19239
|
+
var toResearchDeadEndSearchError = (args) => new ProviderRuntimeError(
|
|
19240
|
+
"unavailable",
|
|
19241
|
+
`Research search resolved only dead-end pages for ${args.document.url}`,
|
|
19242
|
+
{
|
|
19243
|
+
provider: args.providerId,
|
|
19244
|
+
source: args.source,
|
|
19245
|
+
retryable: false,
|
|
19246
|
+
reasonCode: "policy_blocked",
|
|
19247
|
+
details: {
|
|
19248
|
+
status: args.document.status,
|
|
19249
|
+
url: args.document.url,
|
|
19250
|
+
...args.document.browserFallback?.reasonCode ? { browserFallbackReasonCode: args.document.browserFallback.reasonCode } : {},
|
|
19251
|
+
retrievalPath: args.retrievalPath,
|
|
19252
|
+
fallbackOutputReason: "research_dead_end_shell",
|
|
19253
|
+
...browserFallbackObservationDetails(args.document.browserFallback)
|
|
19254
|
+
}
|
|
19255
|
+
}
|
|
19256
|
+
);
|
|
19649
19257
|
var RUNTIME_FALLBACK_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
19650
19258
|
"auth",
|
|
19651
19259
|
"rate_limited",
|
|
@@ -19785,6 +19393,7 @@ var readResponseTextWithAbort = async (response, args) => {
|
|
|
19785
19393
|
}
|
|
19786
19394
|
};
|
|
19787
19395
|
var fetchRuntimeDocumentWithFallback = async (args) => {
|
|
19396
|
+
const researchSearchDiscovery = args.context !== void 0 && isResearchSearchDiscoveryRun(args.operation, args.context);
|
|
19788
19397
|
const fallbackPort = args.context?.browserFallbackPort ?? args.browserFallbackPort;
|
|
19789
19398
|
const runtimePolicy = args.context?.runtimePolicy;
|
|
19790
19399
|
const forcedBrowserTransport = runtimePolicy?.browser.forceTransport === true;
|
|
@@ -19851,6 +19460,9 @@ var fetchRuntimeDocumentWithFallback = async (args) => {
|
|
|
19851
19460
|
if (args.recoverRuntimeErrors === false) {
|
|
19852
19461
|
throw error;
|
|
19853
19462
|
}
|
|
19463
|
+
if (researchSearchDiscovery) {
|
|
19464
|
+
throw error;
|
|
19465
|
+
}
|
|
19854
19466
|
if (!fallbackPort) {
|
|
19855
19467
|
throw error;
|
|
19856
19468
|
}
|
|
@@ -20216,8 +19828,9 @@ var ProviderRuntime = class {
|
|
|
20216
19828
|
};
|
|
20217
19829
|
}
|
|
20218
19830
|
async executeAll(providers, operation, input, trace, timeoutMs, selection, startedAt, tierMetadata, providerIds, runOptions = {}) {
|
|
20219
|
-
const results = await
|
|
20220
|
-
providers
|
|
19831
|
+
const results = await this.mapProvidersBounded(
|
|
19832
|
+
providers,
|
|
19833
|
+
(provider) => this.invokeProvider(provider, operation, input, trace, timeoutMs, tierMetadata, runOptions)
|
|
20221
19834
|
);
|
|
20222
19835
|
const records = [];
|
|
20223
19836
|
const failures = [];
|
|
@@ -20260,8 +19873,9 @@ var ProviderRuntime = class {
|
|
|
20260
19873
|
}
|
|
20261
19874
|
});
|
|
20262
19875
|
}
|
|
20263
|
-
const fallbackResults = await
|
|
20264
|
-
fallbackProviders
|
|
19876
|
+
const fallbackResults = await this.mapProvidersBounded(
|
|
19877
|
+
fallbackProviders,
|
|
19878
|
+
(provider) => this.invokeProvider(provider, operation, input, trace, timeoutMs, fallbackTier, runOptions)
|
|
20265
19879
|
);
|
|
20266
19880
|
for (const result of fallbackResults) {
|
|
20267
19881
|
attempted += 1;
|
|
@@ -20308,6 +19922,9 @@ var ProviderRuntime = class {
|
|
|
20308
19922
|
...!ok && failures[0] ? { error: failures[0].error } : {}
|
|
20309
19923
|
};
|
|
20310
19924
|
}
|
|
19925
|
+
async mapProvidersBounded(providers, task) {
|
|
19926
|
+
return mapBounded(providers, this.budgets.concurrency.global, task);
|
|
19927
|
+
}
|
|
20311
19928
|
async invokeProvider(provider, operation, input, trace, timeoutMs, tierMetadata, runOptions) {
|
|
20312
19929
|
const startedAt = Date.now();
|
|
20313
19930
|
const scopeKey = this.resolveScopeKey(provider.id, operation, input);
|
|
@@ -20691,7 +20308,7 @@ var ProviderRuntime = class {
|
|
|
20691
20308
|
}
|
|
20692
20309
|
async resumeSuspendedIntent(intent, options) {
|
|
20693
20310
|
const input = intent.input;
|
|
20694
|
-
if (!
|
|
20311
|
+
if (!isJsonRecord8(input)) {
|
|
20695
20312
|
throw new ProviderRuntimeError("invalid_input", "Suspended intent input is missing or malformed.", {
|
|
20696
20313
|
retryable: false
|
|
20697
20314
|
});
|
|
@@ -20779,7 +20396,7 @@ var ProviderRuntime = class {
|
|
|
20779
20396
|
return providers.some((provider) => provider.source !== "web");
|
|
20780
20397
|
}
|
|
20781
20398
|
resolveScopeKey(providerId, operation, input) {
|
|
20782
|
-
const
|
|
20399
|
+
const extractHost = (value) => {
|
|
20783
20400
|
if (!value) return null;
|
|
20784
20401
|
try {
|
|
20785
20402
|
return new URL(value).hostname.toLowerCase();
|
|
@@ -20788,14 +20405,14 @@ var ProviderRuntime = class {
|
|
|
20788
20405
|
}
|
|
20789
20406
|
};
|
|
20790
20407
|
if (operation === "fetch") {
|
|
20791
|
-
return
|
|
20408
|
+
return extractHost(input.url) ?? providerId;
|
|
20792
20409
|
}
|
|
20793
20410
|
if (operation === "crawl") {
|
|
20794
20411
|
const first = input.seedUrls[0];
|
|
20795
|
-
return
|
|
20412
|
+
return extractHost(first) ?? providerId;
|
|
20796
20413
|
}
|
|
20797
20414
|
if (operation === "search") {
|
|
20798
|
-
return
|
|
20415
|
+
return extractHost(input.query) ?? providerId;
|
|
20799
20416
|
}
|
|
20800
20417
|
return providerId;
|
|
20801
20418
|
}
|
|
@@ -20973,9 +20590,18 @@ var withDefaultWebOptions = (options, browserFallbackPort) => {
|
|
|
20973
20590
|
browserFallbackPort
|
|
20974
20591
|
});
|
|
20975
20592
|
const limit = Math.max(1, Math.min(input.limit ?? 5, 10));
|
|
20976
|
-
const
|
|
20593
|
+
const researchContext = isResearchWorkflowContext(context);
|
|
20594
|
+
const links = resolveWebSearchResultLinks(document, limit, researchContext, researchContext || isHttpUrl7(query));
|
|
20977
20595
|
const searchPath = isHttpUrl7(query) ? "web:search:url" : "web:search:index";
|
|
20978
20596
|
if (links.length === 0) {
|
|
20597
|
+
if (researchContext && !isUsableWebSearchResultUrl(document.url, true)) {
|
|
20598
|
+
throw toResearchDeadEndSearchError({
|
|
20599
|
+
providerId,
|
|
20600
|
+
source: "web",
|
|
20601
|
+
document,
|
|
20602
|
+
retrievalPath: searchPath
|
|
20603
|
+
});
|
|
20604
|
+
}
|
|
20979
20605
|
return [{
|
|
20980
20606
|
url: document.url,
|
|
20981
20607
|
title: document.url,
|
|
@@ -21018,6 +20644,14 @@ var withDefaultCommunityOptions = (options, browserFallbackPort) => {
|
|
|
21018
20644
|
...browserFallbackObservationAttributes(args.document.browserFallback)
|
|
21019
20645
|
};
|
|
21020
20646
|
if (args.links.length === 0) {
|
|
20647
|
+
if (isResearchWorkflowContext(args.context) && !isLikelyResearchDestinationUrl(args.document.url)) {
|
|
20648
|
+
throw toResearchDeadEndSearchError({
|
|
20649
|
+
providerId,
|
|
20650
|
+
source: "community",
|
|
20651
|
+
document: args.document,
|
|
20652
|
+
retrievalPath: searchPath
|
|
20653
|
+
});
|
|
20654
|
+
}
|
|
21021
20655
|
return [{
|
|
21022
20656
|
url: args.document.url,
|
|
21023
20657
|
title: isHttpUrl7(args.query) ? args.document.url : `Community search: ${args.query}`,
|
|
@@ -21059,8 +20693,8 @@ var withDefaultCommunityOptions = (options, browserFallbackPort) => {
|
|
|
21059
20693
|
browserFallbackPort,
|
|
21060
20694
|
ownerReview: shouldOwnerReviewCommunityRedditSearchFallback
|
|
21061
20695
|
});
|
|
21062
|
-
const links = resolveCommunitySearchLinks(resolvedDocument, limit);
|
|
21063
|
-
if (shouldRejectBlockedCommunityFallback(resolvedDocument, links)) {
|
|
20696
|
+
const links = resolveCommunitySearchLinks(resolvedDocument, limit, isResearchWorkflowContext(context));
|
|
20697
|
+
if (shouldRejectBlockedCommunityFallback(resolvedDocument, links, pageMessage)) {
|
|
21064
20698
|
throw toCommunityFallbackSearchError({
|
|
21065
20699
|
providerId,
|
|
21066
20700
|
document: resolvedDocument,
|
|
@@ -21072,7 +20706,8 @@ var withDefaultCommunityOptions = (options, browserFallbackPort) => {
|
|
|
21072
20706
|
page,
|
|
21073
20707
|
document: resolvedDocument,
|
|
21074
20708
|
pageMessage,
|
|
21075
|
-
links
|
|
20709
|
+
links,
|
|
20710
|
+
context
|
|
21076
20711
|
});
|
|
21077
20712
|
}),
|
|
21078
20713
|
fetch: options?.fetch ?? (async (input, context) => {
|
|
@@ -21185,7 +20820,7 @@ var withDefaultSocialPlatformOptions = (platform, options, browserFallbackPort)
|
|
|
21185
20820
|
if (initialIssue.reasonCode === "env_limited" && !initialIssue.constraint) {
|
|
21186
20821
|
return { document: currentDocument, ...described };
|
|
21187
20822
|
}
|
|
21188
|
-
if (!shouldRecoverSocialDocumentIssue(platform, operation, initialIssue)) {
|
|
20823
|
+
if (!shouldRecoverSocialDocumentIssue(platform, operation, initialIssue, context)) {
|
|
21189
20824
|
throw toIssueError(currentDocument, described);
|
|
21190
20825
|
}
|
|
21191
20826
|
const fallback = await resolveProviderBrowserFallback({
|
|
@@ -21374,19 +21009,6 @@ var mergeBudgets = (base, partial) => {
|
|
|
21374
21009
|
};
|
|
21375
21010
|
|
|
21376
21011
|
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
21012
|
CHALLENGE_AUTOMATION_MODES,
|
|
21391
21013
|
isChallengeAutomationMode,
|
|
21392
21014
|
resolveChallengeAutomationPolicy,
|
|
@@ -21411,7 +21033,6 @@ export {
|
|
|
21411
21033
|
CANVAS_BROWSER_VALIDATION_MODES,
|
|
21412
21034
|
CANVAS_VALIDATION_TARGET_BLOCK_ON_CODES,
|
|
21413
21035
|
CANVAS_PUBLIC_WARNING_CLASSES,
|
|
21414
|
-
summarizePrimaryProviderIssue,
|
|
21415
21036
|
createTraceContext,
|
|
21416
21037
|
clampConfidence,
|
|
21417
21038
|
createStableRecordId,
|
|
@@ -21439,17 +21060,11 @@ export {
|
|
|
21439
21060
|
createShoppingProviders,
|
|
21440
21061
|
createShoppingProviderById,
|
|
21441
21062
|
createWebProvider,
|
|
21442
|
-
DEFAULT_ARTIFACT_TTL_HOURS,
|
|
21443
|
-
MAX_ARTIFACT_TTL_HOURS,
|
|
21444
|
-
createArtifactBundle,
|
|
21445
|
-
cleanupExpiredArtifacts,
|
|
21446
21063
|
resolveTimebox,
|
|
21447
21064
|
isWithinTimebox,
|
|
21448
21065
|
filterByTimebox,
|
|
21449
21066
|
toResearchRecord,
|
|
21450
21067
|
enrichResearchRecords,
|
|
21451
|
-
INSPIREDESIGN_HANDOFF_COMMANDS,
|
|
21452
|
-
INSPIREDESIGN_HANDOFF_GUIDANCE,
|
|
21453
21068
|
buildMacroResolveSuccessHandoff,
|
|
21454
21069
|
renderResearch,
|
|
21455
21070
|
renderShopping,
|
|
@@ -21465,4 +21080,4 @@ export {
|
|
|
21465
21080
|
createProviderRuntime,
|
|
21466
21081
|
createDefaultRuntime
|
|
21467
21082
|
};
|
|
21468
|
-
//# sourceMappingURL=chunk-
|
|
21083
|
+
//# sourceMappingURL=chunk-S6S2UP6U.js.map
|