opendevbrowser 0.0.12 → 0.0.16
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/LICENSE +21 -0
- package/README.md +425 -42
- package/dist/annotate/direct-annotator.d.ts +22 -0
- package/dist/annotate/direct-annotator.d.ts.map +1 -0
- package/dist/annotate/output.d.ts +10 -0
- package/dist/annotate/output.d.ts.map +1 -0
- package/dist/browser/annotation-manager.d.ts +30 -0
- package/dist/browser/annotation-manager.d.ts.map +1 -0
- package/dist/browser/browser-manager.d.ts +397 -0
- package/dist/browser/browser-manager.d.ts.map +1 -0
- package/dist/browser/fingerprint/adapters.d.ts +26 -0
- package/dist/browser/fingerprint/adapters.d.ts.map +1 -0
- package/dist/browser/fingerprint/canary.d.ts +25 -0
- package/dist/browser/fingerprint/canary.d.ts.map +1 -0
- package/dist/browser/fingerprint/profiles.d.ts +16 -0
- package/dist/browser/fingerprint/profiles.d.ts.map +1 -0
- package/dist/browser/fingerprint/tier1-coherence.d.ts +36 -0
- package/dist/browser/fingerprint/tier1-coherence.d.ts.map +1 -0
- package/dist/browser/fingerprint/tier2-runtime.d.ts +40 -0
- package/dist/browser/fingerprint/tier2-runtime.d.ts.map +1 -0
- package/dist/browser/fingerprint/tier3-adaptive.d.ts +30 -0
- package/dist/browser/fingerprint/tier3-adaptive.d.ts.map +1 -0
- package/dist/browser/manager-types.d.ts +3 -0
- package/dist/browser/manager-types.d.ts.map +1 -0
- package/dist/browser/ops-browser-manager.d.ts +131 -0
- package/dist/browser/ops-browser-manager.d.ts.map +1 -0
- package/dist/browser/ops-client.d.ts +56 -0
- package/dist/browser/ops-client.d.ts.map +1 -0
- package/dist/browser/parallelism-governor.d.ts +31 -0
- package/dist/browser/parallelism-governor.d.ts.map +1 -0
- package/dist/browser/script-runner.d.ts +23 -0
- package/dist/browser/script-runner.d.ts.map +1 -0
- package/dist/browser/session-store.d.ts +63 -0
- package/dist/browser/session-store.d.ts.map +1 -0
- package/dist/browser/target-manager.d.ts +36 -0
- package/dist/browser/target-manager.d.ts.map +1 -0
- package/dist/cache/chrome-locator.d.ts +2 -0
- package/dist/cache/chrome-locator.d.ts.map +1 -0
- package/dist/cache/downloader.d.ts +6 -0
- package/dist/cache/downloader.d.ts.map +1 -0
- package/dist/cache/paths.d.ts +9 -0
- package/dist/cache/paths.d.ts.map +1 -0
- package/dist/chunk-7W3SPXIB.js +166 -0
- package/dist/chunk-7W3SPXIB.js.map +1 -0
- package/dist/chunk-ST7CO5FA.js +18668 -0
- package/dist/chunk-ST7CO5FA.js.map +1 -0
- package/dist/cli/args.d.ts +25 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/client.d.ts +2 -0
- package/dist/cli/client.d.ts.map +1 -0
- package/dist/cli/commands/annotate.d.ts +27 -0
- package/dist/cli/commands/annotate.d.ts.map +1 -0
- package/dist/cli/commands/artifacts.d.ts +24 -0
- package/dist/cli/commands/artifacts.d.ts.map +1 -0
- package/dist/cli/commands/daemon.d.ts +35 -0
- package/dist/cli/commands/daemon.d.ts.map +1 -0
- package/dist/cli/commands/devtools/console-poll.d.ts +7 -0
- package/dist/cli/commands/devtools/console-poll.d.ts.map +1 -0
- package/dist/cli/commands/devtools/debug-trace-snapshot.d.ts +20 -0
- package/dist/cli/commands/devtools/debug-trace-snapshot.d.ts.map +1 -0
- package/dist/cli/commands/devtools/network-poll.d.ts +7 -0
- package/dist/cli/commands/devtools/network-poll.d.ts.map +1 -0
- package/dist/cli/commands/devtools/perf.d.ts +7 -0
- package/dist/cli/commands/devtools/perf.d.ts.map +1 -0
- package/dist/cli/commands/devtools/screenshot.d.ts +17 -0
- package/dist/cli/commands/devtools/screenshot.d.ts.map +1 -0
- package/dist/cli/commands/dom/attr.d.ts +7 -0
- package/dist/cli/commands/dom/attr.d.ts.map +1 -0
- package/dist/cli/commands/dom/checked.d.ts +7 -0
- package/dist/cli/commands/dom/checked.d.ts.map +1 -0
- package/dist/cli/commands/dom/enabled.d.ts +7 -0
- package/dist/cli/commands/dom/enabled.d.ts.map +1 -0
- package/dist/cli/commands/dom/html.d.ts +7 -0
- package/dist/cli/commands/dom/html.d.ts.map +1 -0
- package/dist/cli/commands/dom/text.d.ts +7 -0
- package/dist/cli/commands/dom/text.d.ts.map +1 -0
- package/dist/cli/commands/dom/value.d.ts +7 -0
- package/dist/cli/commands/dom/value.d.ts.map +1 -0
- package/dist/cli/commands/dom/visible.d.ts +7 -0
- package/dist/cli/commands/dom/visible.d.ts.map +1 -0
- package/dist/cli/commands/export/clone-component.d.ts +7 -0
- package/dist/cli/commands/export/clone-component.d.ts.map +1 -0
- package/dist/cli/commands/export/clone-page.d.ts +7 -0
- package/dist/cli/commands/export/clone-page.d.ts.map +1 -0
- package/dist/cli/commands/interact/check.d.ts +7 -0
- package/dist/cli/commands/interact/check.d.ts.map +1 -0
- package/dist/cli/commands/interact/click.d.ts +7 -0
- package/dist/cli/commands/interact/click.d.ts.map +1 -0
- package/dist/cli/commands/interact/hover.d.ts +7 -0
- package/dist/cli/commands/interact/hover.d.ts.map +1 -0
- package/dist/cli/commands/interact/press.d.ts +7 -0
- package/dist/cli/commands/interact/press.d.ts.map +1 -0
- package/dist/cli/commands/interact/scroll-into-view.d.ts +7 -0
- package/dist/cli/commands/interact/scroll-into-view.d.ts.map +1 -0
- package/dist/cli/commands/interact/scroll.d.ts +7 -0
- package/dist/cli/commands/interact/scroll.d.ts.map +1 -0
- package/dist/cli/commands/interact/select.d.ts +7 -0
- package/dist/cli/commands/interact/select.d.ts.map +1 -0
- package/dist/cli/commands/interact/type.d.ts +7 -0
- package/dist/cli/commands/interact/type.d.ts.map +1 -0
- package/dist/cli/commands/interact/uncheck.d.ts +7 -0
- package/dist/cli/commands/interact/uncheck.d.ts.map +1 -0
- package/dist/cli/commands/macro-resolve.d.ts +18 -0
- package/dist/cli/commands/macro-resolve.d.ts.map +1 -0
- package/dist/cli/commands/native.d.ts +82 -0
- package/dist/cli/commands/native.d.ts.map +1 -0
- package/dist/cli/commands/nav/goto.d.ts +7 -0
- package/dist/cli/commands/nav/goto.d.ts.map +1 -0
- package/dist/cli/commands/nav/snapshot.d.ts +7 -0
- package/dist/cli/commands/nav/snapshot.d.ts.map +1 -0
- package/dist/cli/commands/nav/wait.d.ts +7 -0
- package/dist/cli/commands/nav/wait.d.ts.map +1 -0
- package/dist/cli/commands/pages/close.d.ts +6 -0
- package/dist/cli/commands/pages/close.d.ts.map +1 -0
- package/dist/cli/commands/pages/list.d.ts +7 -0
- package/dist/cli/commands/pages/list.d.ts.map +1 -0
- package/dist/cli/commands/pages/open.d.ts +7 -0
- package/dist/cli/commands/pages/open.d.ts.map +1 -0
- package/dist/cli/commands/product-video.d.ts +25 -0
- package/dist/cli/commands/product-video.d.ts.map +1 -0
- package/dist/cli/commands/registry.d.ts +5 -0
- package/dist/cli/commands/registry.d.ts.map +1 -0
- package/dist/cli/commands/research.d.ts +27 -0
- package/dist/cli/commands/research.d.ts.map +1 -0
- package/dist/cli/commands/rpc.d.ts +28 -0
- package/dist/cli/commands/rpc.d.ts.map +1 -0
- package/dist/cli/commands/run.d.ts +17 -0
- package/dist/cli/commands/run.d.ts.map +1 -0
- package/dist/cli/commands/serve.d.ts +59 -0
- package/dist/cli/commands/serve.d.ts.map +1 -0
- package/dist/cli/commands/session/connect.d.ts +9 -0
- package/dist/cli/commands/session/connect.d.ts.map +1 -0
- package/dist/cli/commands/session/cookie-import.d.ts +31 -0
- package/dist/cli/commands/session/cookie-import.d.ts.map +1 -0
- package/dist/cli/commands/session/cookie-list.d.ts +17 -0
- package/dist/cli/commands/session/cookie-list.d.ts.map +1 -0
- package/dist/cli/commands/session/disconnect.d.ts +6 -0
- package/dist/cli/commands/session/disconnect.d.ts.map +1 -0
- package/dist/cli/commands/session/launch.d.ts +29 -0
- package/dist/cli/commands/session/launch.d.ts.map +1 -0
- package/dist/cli/commands/session/status.d.ts +7 -0
- package/dist/cli/commands/session/status.d.ts.map +1 -0
- package/dist/cli/commands/shopping.d.ts +25 -0
- package/dist/cli/commands/shopping.d.ts.map +1 -0
- package/dist/cli/commands/status.d.ts +19 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/targets/close.d.ts +6 -0
- package/dist/cli/commands/targets/close.d.ts.map +1 -0
- package/dist/cli/commands/targets/list.d.ts +7 -0
- package/dist/cli/commands/targets/list.d.ts.map +1 -0
- package/dist/cli/commands/targets/new.d.ts +7 -0
- package/dist/cli/commands/targets/new.d.ts.map +1 -0
- package/dist/cli/commands/targets/use.d.ts +7 -0
- package/dist/cli/commands/targets/use.d.ts.map +1 -0
- package/dist/cli/commands/types.d.ts +13 -0
- package/dist/cli/commands/types.d.ts.map +1 -0
- package/dist/cli/commands/uninstall.d.ts +14 -0
- package/dist/cli/commands/uninstall.d.ts.map +1 -0
- package/dist/cli/commands/update.d.ts +7 -0
- package/dist/cli/commands/update.d.ts.map +1 -0
- package/dist/cli/daemon-autostart.d.ts +46 -0
- package/dist/cli/daemon-autostart.d.ts.map +1 -0
- package/dist/cli/daemon-client.d.ts +33 -0
- package/dist/cli/daemon-client.d.ts.map +1 -0
- package/dist/cli/daemon-commands.d.ts +7 -0
- package/dist/cli/daemon-commands.d.ts.map +1 -0
- package/dist/cli/daemon-state.d.ts +56 -0
- package/dist/cli/daemon-state.d.ts.map +1 -0
- package/dist/cli/daemon-status.d.ts +19 -0
- package/dist/cli/daemon-status.d.ts.map +1 -0
- package/dist/cli/daemon.d.ts +29 -0
- package/dist/cli/daemon.d.ts.map +1 -0
- package/dist/cli/errors.d.ts +20 -0
- package/dist/cli/errors.d.ts.map +1 -0
- package/dist/cli/help.d.ts +28 -0
- package/dist/cli/help.d.ts.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +4604 -769
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/installers/global.d.ts +9 -0
- package/dist/cli/installers/global.d.ts.map +1 -0
- package/dist/cli/installers/local.d.ts +9 -0
- package/dist/cli/installers/local.d.ts.map +1 -0
- package/dist/cli/installers/skills.d.ts +19 -0
- package/dist/cli/installers/skills.d.ts.map +1 -0
- package/dist/cli/output.d.ts +7 -0
- package/dist/cli/output.d.ts.map +1 -0
- package/dist/cli/remote-manager.d.ts +96 -0
- package/dist/cli/remote-manager.d.ts.map +1 -0
- package/dist/cli/remote-relay.d.ts +17 -0
- package/dist/cli/remote-relay.d.ts.map +1 -0
- package/dist/cli/templates/config.d.ts +7 -0
- package/dist/cli/templates/config.d.ts.map +1 -0
- package/dist/cli/utils/config.d.ts +20 -0
- package/dist/cli/utils/config.d.ts.map +1 -0
- package/dist/cli/utils/http.d.ts +5 -0
- package/dist/cli/utils/http.d.ts.map +1 -0
- package/dist/cli/utils/parse.d.ts +8 -0
- package/dist/cli/utils/parse.d.ts.map +1 -0
- package/dist/cli/utils/skills.d.ts +12 -0
- package/dist/cli/utils/skills.d.ts.map +1 -0
- package/dist/config.d.ts +208 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/core/bootstrap.d.ts +3 -0
- package/dist/core/bootstrap.d.ts.map +1 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/logging.d.ts +34 -0
- package/dist/core/logging.d.ts.map +1 -0
- package/dist/core/types.d.ts +34 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/devtools/console-tracker.d.ts +44 -0
- package/dist/devtools/console-tracker.d.ts.map +1 -0
- package/dist/devtools/exception-tracker.d.ts +42 -0
- package/dist/devtools/exception-tracker.d.ts.map +1 -0
- package/dist/devtools/network-tracker.d.ts +34 -0
- package/dist/devtools/network-tracker.d.ts.map +1 -0
- package/dist/export/css-extract.d.ts +5 -0
- package/dist/export/css-extract.d.ts.map +1 -0
- package/dist/export/dom-capture.d.ts +15 -0
- package/dist/export/dom-capture.d.ts.map +1 -0
- package/dist/export/react-emitter.d.ts +11 -0
- package/dist/export/react-emitter.d.ts.map +1 -0
- package/dist/extension-extractor.d.ts +3 -0
- package/dist/extension-extractor.d.ts.map +1 -0
- package/dist/index.d.ts +3 -4
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1905 -262
- package/dist/index.js.map +1 -1
- package/dist/macros/execute.d.ts +44 -0
- package/dist/macros/execute.d.ts.map +1 -0
- package/dist/macros/index.d.ts +9 -0
- package/dist/macros/index.d.ts.map +1 -0
- package/dist/macros/packs/core.d.ts +3 -0
- package/dist/macros/packs/core.d.ts.map +1 -0
- package/dist/macros/registry.d.ts +48 -0
- package/dist/macros/registry.d.ts.map +1 -0
- package/dist/macros-NUBRM44Y.js +399 -0
- package/dist/macros-NUBRM44Y.js.map +1 -0
- package/dist/opendevbrowser.d.ts +3 -4
- package/dist/opendevbrowser.d.ts.map +1 -0
- package/dist/opendevbrowser.js +1905 -262
- package/dist/opendevbrowser.js.map +1 -1
- package/dist/providers/adaptive-concurrency.d.ts +42 -0
- package/dist/providers/adaptive-concurrency.d.ts.map +1 -0
- package/dist/providers/artifacts.d.ts +34 -0
- package/dist/providers/artifacts.d.ts.map +1 -0
- package/dist/providers/blocker.d.ts +47 -0
- package/dist/providers/blocker.d.ts.map +1 -0
- package/dist/providers/community/index.d.ts +44 -0
- package/dist/providers/community/index.d.ts.map +1 -0
- package/dist/providers/enrichment.d.ts +33 -0
- package/dist/providers/enrichment.d.ts.map +1 -0
- package/dist/providers/errors.d.ts +41 -0
- package/dist/providers/errors.d.ts.map +1 -0
- package/dist/providers/index.d.ts +121 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/normalize.d.ts +39 -0
- package/dist/providers/normalize.d.ts.map +1 -0
- package/dist/providers/policy.d.ts +5 -0
- package/dist/providers/policy.d.ts.map +1 -0
- package/dist/providers/registry.d.ts +22 -0
- package/dist/providers/registry.d.ts.map +1 -0
- package/dist/providers/renderer.d.ts +49 -0
- package/dist/providers/renderer.d.ts.map +1 -0
- package/dist/providers/runtime-factory.d.ts +20 -0
- package/dist/providers/runtime-factory.d.ts.map +1 -0
- package/dist/providers/safety/prompt-guard.d.ts +34 -0
- package/dist/providers/safety/prompt-guard.d.ts.map +1 -0
- package/dist/providers/shared/anti-bot-policy.d.ts +51 -0
- package/dist/providers/shared/anti-bot-policy.d.ts.map +1 -0
- package/dist/providers/shared/post-policy.d.ts +31 -0
- package/dist/providers/shared/post-policy.d.ts.map +1 -0
- package/dist/providers/shared/request-headers.d.ts +5 -0
- package/dist/providers/shared/request-headers.d.ts.map +1 -0
- package/dist/providers/shared/traversal-url.d.ts +2 -0
- package/dist/providers/shared/traversal-url.d.ts.map +1 -0
- package/dist/providers/shopping/index.d.ts +63 -0
- package/dist/providers/shopping/index.d.ts.map +1 -0
- package/dist/providers/social/bluesky.d.ts +3 -0
- package/dist/providers/social/bluesky.d.ts.map +1 -0
- package/dist/providers/social/facebook.d.ts +3 -0
- package/dist/providers/social/facebook.d.ts.map +1 -0
- package/dist/providers/social/index.d.ts +31 -0
- package/dist/providers/social/index.d.ts.map +1 -0
- package/dist/providers/social/instagram.d.ts +3 -0
- package/dist/providers/social/instagram.d.ts.map +1 -0
- package/dist/providers/social/linkedin.d.ts +3 -0
- package/dist/providers/social/linkedin.d.ts.map +1 -0
- package/dist/providers/social/platform.d.ts +40 -0
- package/dist/providers/social/platform.d.ts.map +1 -0
- package/dist/providers/social/reddit.d.ts +3 -0
- package/dist/providers/social/reddit.d.ts.map +1 -0
- package/dist/providers/social/threads.d.ts +3 -0
- package/dist/providers/social/threads.d.ts.map +1 -0
- package/dist/providers/social/tiktok.d.ts +3 -0
- package/dist/providers/social/tiktok.d.ts.map +1 -0
- package/dist/providers/social/x.d.ts +3 -0
- package/dist/providers/social/x.d.ts.map +1 -0
- package/dist/providers/social/youtube-resolver.d.ts +78 -0
- package/dist/providers/social/youtube-resolver.d.ts.map +1 -0
- package/dist/providers/social/youtube.d.ts +34 -0
- package/dist/providers/social/youtube.d.ts.map +1 -0
- package/dist/providers/tier-router.d.ts +30 -0
- package/dist/providers/tier-router.d.ts.map +1 -0
- package/dist/providers/timebox.d.ts +20 -0
- package/dist/providers/timebox.d.ts.map +1 -0
- package/dist/providers/types.d.ts +344 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/web/crawl-worker.d.ts +36 -0
- package/dist/providers/web/crawl-worker.d.ts.map +1 -0
- package/dist/providers/web/crawler.d.ts +101 -0
- package/dist/providers/web/crawler.d.ts.map +1 -0
- package/dist/providers/web/extract.d.ts +11 -0
- package/dist/providers/web/extract.d.ts.map +1 -0
- package/dist/providers/web/index.d.ts +24 -0
- package/dist/providers/web/index.d.ts.map +1 -0
- package/dist/providers/web/policy.d.ts +14 -0
- package/dist/providers/web/policy.d.ts.map +1 -0
- package/dist/providers/workflows.d.ts +67 -0
- package/dist/providers/workflows.d.ts.map +1 -0
- package/dist/relay/protocol.d.ts +317 -0
- package/dist/relay/protocol.d.ts.map +1 -0
- package/dist/relay/relay-endpoints.d.ts +16 -0
- package/dist/relay/relay-endpoints.d.ts.map +1 -0
- package/dist/relay/relay-server.d.ts +111 -0
- package/dist/relay/relay-server.d.ts.map +1 -0
- package/dist/relay/relay-types.d.ts +9 -0
- package/dist/relay/relay-types.d.ts.map +1 -0
- package/dist/skills/continuity-nudge.d.ts +12 -0
- package/dist/skills/continuity-nudge.d.ts.map +1 -0
- package/dist/skills/skill-loader.d.ts +20 -0
- package/dist/skills/skill-loader.d.ts.map +1 -0
- package/dist/skills/skill-nudge.d.ts +18 -0
- package/dist/skills/skill-nudge.d.ts.map +1 -0
- package/dist/skills/types.d.ts +12 -0
- package/dist/skills/types.d.ts.map +1 -0
- package/dist/snapshot/ops-snapshot.d.ts +16 -0
- package/dist/snapshot/ops-snapshot.d.ts.map +1 -0
- package/dist/snapshot/refs.d.ts +23 -0
- package/dist/snapshot/refs.d.ts.map +1 -0
- package/dist/snapshot/snapshotter.d.ts +27 -0
- package/dist/snapshot/snapshotter.d.ts.map +1 -0
- package/dist/tools/annotate.d.ts +4 -0
- package/dist/tools/annotate.d.ts.map +1 -0
- package/dist/tools/check.d.ts +4 -0
- package/dist/tools/check.d.ts.map +1 -0
- package/dist/tools/click.d.ts +4 -0
- package/dist/tools/click.d.ts.map +1 -0
- package/dist/tools/clone_component.d.ts +4 -0
- package/dist/tools/clone_component.d.ts.map +1 -0
- package/dist/tools/clone_page.d.ts +4 -0
- package/dist/tools/clone_page.d.ts.map +1 -0
- package/dist/tools/close.d.ts +4 -0
- package/dist/tools/close.d.ts.map +1 -0
- package/dist/tools/connect.d.ts +4 -0
- package/dist/tools/connect.d.ts.map +1 -0
- package/dist/tools/console_poll.d.ts +4 -0
- package/dist/tools/console_poll.d.ts.map +1 -0
- package/dist/tools/cookie_import.d.ts +25 -0
- package/dist/tools/cookie_import.d.ts.map +1 -0
- package/dist/tools/cookie_list.d.ts +9 -0
- package/dist/tools/cookie_list.d.ts.map +1 -0
- package/dist/tools/debug_trace_snapshot.d.ts +4 -0
- package/dist/tools/debug_trace_snapshot.d.ts.map +1 -0
- package/dist/tools/deps.d.ts +26 -0
- package/dist/tools/deps.d.ts.map +1 -0
- package/dist/tools/disconnect.d.ts +4 -0
- package/dist/tools/disconnect.d.ts.map +1 -0
- package/dist/tools/dom_get_html.d.ts +4 -0
- package/dist/tools/dom_get_html.d.ts.map +1 -0
- package/dist/tools/dom_get_text.d.ts +4 -0
- package/dist/tools/dom_get_text.d.ts.map +1 -0
- package/dist/tools/get_attr.d.ts +4 -0
- package/dist/tools/get_attr.d.ts.map +1 -0
- package/dist/tools/get_value.d.ts +4 -0
- package/dist/tools/get_value.d.ts.map +1 -0
- package/dist/tools/goto.d.ts +4 -0
- package/dist/tools/goto.d.ts.map +1 -0
- package/dist/tools/hover.d.ts +4 -0
- package/dist/tools/hover.d.ts.map +1 -0
- package/dist/tools/index.d.ts +4 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/is_checked.d.ts +4 -0
- package/dist/tools/is_checked.d.ts.map +1 -0
- package/dist/tools/is_enabled.d.ts +4 -0
- package/dist/tools/is_enabled.d.ts.map +1 -0
- package/dist/tools/is_visible.d.ts +4 -0
- package/dist/tools/is_visible.d.ts.map +1 -0
- package/dist/tools/launch.d.ts +4 -0
- package/dist/tools/launch.d.ts.map +1 -0
- package/dist/tools/list.d.ts +4 -0
- package/dist/tools/list.d.ts.map +1 -0
- package/dist/tools/macro_resolve.d.ts +25 -0
- package/dist/tools/macro_resolve.d.ts.map +1 -0
- package/dist/tools/network_poll.d.ts +4 -0
- package/dist/tools/network_poll.d.ts.map +1 -0
- package/dist/tools/page.d.ts +4 -0
- package/dist/tools/page.d.ts.map +1 -0
- package/dist/tools/perf.d.ts +4 -0
- package/dist/tools/perf.d.ts.map +1 -0
- package/dist/tools/press.d.ts +4 -0
- package/dist/tools/press.d.ts.map +1 -0
- package/dist/tools/product_video_run.d.ts +4 -0
- package/dist/tools/product_video_run.d.ts.map +1 -0
- package/dist/tools/prompting_guide.d.ts +4 -0
- package/dist/tools/prompting_guide.d.ts.map +1 -0
- package/dist/tools/research_run.d.ts +4 -0
- package/dist/tools/research_run.d.ts.map +1 -0
- package/dist/tools/response.d.ts +16 -0
- package/dist/tools/response.d.ts.map +1 -0
- package/dist/tools/run.d.ts +4 -0
- package/dist/tools/run.d.ts.map +1 -0
- package/dist/tools/screenshot.d.ts +4 -0
- package/dist/tools/screenshot.d.ts.map +1 -0
- package/dist/tools/scroll.d.ts +4 -0
- package/dist/tools/scroll.d.ts.map +1 -0
- package/dist/tools/scroll_into_view.d.ts +4 -0
- package/dist/tools/scroll_into_view.d.ts.map +1 -0
- package/dist/tools/select.d.ts +4 -0
- package/dist/tools/select.d.ts.map +1 -0
- package/dist/tools/shopping_run.d.ts +4 -0
- package/dist/tools/shopping_run.d.ts.map +1 -0
- package/dist/tools/skill_list.d.ts +4 -0
- package/dist/tools/skill_list.d.ts.map +1 -0
- package/dist/tools/skill_load.d.ts +4 -0
- package/dist/tools/skill_load.d.ts.map +1 -0
- package/dist/tools/snapshot.d.ts +4 -0
- package/dist/tools/snapshot.d.ts.map +1 -0
- package/dist/tools/status.d.ts +4 -0
- package/dist/tools/status.d.ts.map +1 -0
- package/dist/tools/target_close.d.ts +4 -0
- package/dist/tools/target_close.d.ts.map +1 -0
- package/dist/tools/target_new.d.ts +4 -0
- package/dist/tools/target_new.d.ts.map +1 -0
- package/dist/tools/target_use.d.ts +4 -0
- package/dist/tools/target_use.d.ts.map +1 -0
- package/dist/tools/targets_list.d.ts +4 -0
- package/dist/tools/targets_list.d.ts.map +1 -0
- package/dist/tools/type.d.ts +4 -0
- package/dist/tools/type.d.ts.map +1 -0
- package/dist/tools/uncheck.d.ts +4 -0
- package/dist/tools/uncheck.d.ts.map +1 -0
- package/dist/tools/wait.d.ts +4 -0
- package/dist/tools/wait.d.ts.map +1 -0
- package/dist/tools/workflow-runtime.d.ts +4 -0
- package/dist/tools/workflow-runtime.d.ts.map +1 -0
- package/dist/utils/crypto.d.ts +2 -0
- package/dist/utils/crypto.d.ts.map +1 -0
- package/dist/utils/endpoint-validation.d.ts +2 -0
- package/dist/utils/endpoint-validation.d.ts.map +1 -0
- package/dist/utils/fs.d.ts +5 -0
- package/dist/utils/fs.d.ts.map +1 -0
- package/dist/utils/hub-enabled.d.ts +3 -0
- package/dist/utils/hub-enabled.d.ts.map +1 -0
- package/extension/dist/annotate-content.css +237 -0
- package/extension/dist/annotate-content.js +934 -0
- package/extension/dist/background.js +1203 -35
- package/extension/dist/logging.js +50 -0
- package/extension/dist/ops/dom-bridge.js +355 -0
- package/extension/dist/ops/ops-runtime.js +1751 -0
- package/extension/dist/ops/ops-session-store.js +203 -0
- package/extension/dist/ops/parallelism-governor.js +117 -0
- package/extension/dist/ops/redaction.js +52 -0
- package/extension/dist/ops/snapshot-builder.js +4 -0
- package/extension/dist/ops/snapshot-shared.js +236 -0
- package/extension/dist/popup.js +370 -25
- package/extension/dist/relay-settings.js +1 -0
- package/extension/dist/services/CDPRouter.js +567 -104
- package/extension/dist/services/ConnectionManager.js +469 -60
- package/extension/dist/services/NativePortManager.js +182 -0
- package/extension/dist/services/RelayClient.js +227 -26
- package/extension/dist/services/TabManager.js +81 -0
- package/extension/dist/services/TargetSessionMap.js +146 -0
- package/extension/dist/services/cdp-router-commands.js +203 -0
- package/extension/dist/services/url-restrictions.js +41 -0
- package/extension/dist/types.js +3 -1
- package/extension/icons/icon128.png +0 -0
- package/extension/icons/icon16.png +0 -0
- package/extension/icons/icon32.png +0 -0
- package/extension/icons/icon48.png +0 -0
- package/extension/manifest.json +17 -3
- package/extension/popup.html +144 -0
- package/package.json +26 -17
- package/scripts/native/host.cjs +230 -0
- package/scripts/native/install.ps1 +73 -0
- package/scripts/native/install.sh +66 -0
- package/scripts/native/uninstall.ps1 +25 -0
- package/scripts/native/uninstall.sh +26 -0
- package/skills/AGENTS.md +47 -66
- package/skills/opendevbrowser-best-practices/SKILL.md +196 -49
- package/skills/opendevbrowser-best-practices/artifacts/browser-agent-known-issues-matrix.md +44 -0
- package/skills/opendevbrowser-best-practices/artifacts/command-channel-reference.md +95 -0
- package/skills/opendevbrowser-best-practices/artifacts/debug-trace-playbook.md +36 -0
- package/skills/opendevbrowser-best-practices/artifacts/fingerprint-tiers.md +36 -0
- package/skills/opendevbrowser-best-practices/artifacts/macro-workflows.md +43 -0
- package/skills/opendevbrowser-best-practices/artifacts/parity-gates.md +36 -0
- package/skills/opendevbrowser-best-practices/artifacts/provider-workflows.md +89 -0
- package/skills/opendevbrowser-best-practices/assets/templates/cdp-forward-envelope.json +11 -0
- package/skills/opendevbrowser-best-practices/assets/templates/mode-flag-matrix.json +56 -0
- package/skills/opendevbrowser-best-practices/assets/templates/ops-request-envelope.json +9 -0
- package/skills/opendevbrowser-best-practices/assets/templates/robustness-checklist.json +79 -0
- package/skills/opendevbrowser-best-practices/assets/templates/surface-audit-checklist.json +24 -0
- package/skills/opendevbrowser-best-practices/scripts/odb-workflow.sh +144 -0
- package/skills/opendevbrowser-best-practices/scripts/run-robustness-audit.sh +83 -0
- package/skills/opendevbrowser-best-practices/scripts/validate-skill-assets.sh +93 -0
- package/skills/opendevbrowser-continuity-ledger/SKILL.md +67 -23
- package/skills/opendevbrowser-data-extraction/SKILL.md +126 -0
- package/skills/opendevbrowser-data-extraction/artifacts/extraction-workflows.md +31 -0
- package/skills/opendevbrowser-data-extraction/assets/templates/compliance-checklist.md +7 -0
- package/skills/opendevbrowser-data-extraction/assets/templates/extraction-schema.json +17 -0
- package/skills/opendevbrowser-data-extraction/assets/templates/pagination-state.json +11 -0
- package/skills/opendevbrowser-data-extraction/assets/templates/quality-gates.json +10 -0
- package/skills/opendevbrowser-data-extraction/examples/sample-schema.json +19 -0
- package/skills/opendevbrowser-data-extraction/scripts/run-extraction-workflow.sh +83 -0
- package/skills/opendevbrowser-data-extraction/scripts/validate-skill-assets.sh +49 -0
- package/skills/opendevbrowser-form-testing/SKILL.md +143 -0
- package/skills/opendevbrowser-form-testing/artifacts/form-workflows.md +37 -0
- package/skills/opendevbrowser-form-testing/assets/templates/a11y-assertions.md +7 -0
- package/skills/opendevbrowser-form-testing/assets/templates/challenge-decision-tree.json +16 -0
- package/skills/opendevbrowser-form-testing/assets/templates/multi-step-state.json +11 -0
- package/skills/opendevbrowser-form-testing/assets/templates/validation-matrix.json +24 -0
- package/skills/opendevbrowser-form-testing/examples/sample-validation-matrix.json +29 -0
- package/skills/opendevbrowser-form-testing/scripts/run-form-workflow.sh +82 -0
- package/skills/opendevbrowser-form-testing/scripts/validate-skill-assets.sh +49 -0
- package/skills/opendevbrowser-login-automation/SKILL.md +159 -0
- package/skills/opendevbrowser-login-automation/artifacts/login-workflows.md +39 -0
- package/skills/opendevbrowser-login-automation/assets/templates/auth-signals.json +21 -0
- package/skills/opendevbrowser-login-automation/assets/templates/challenge-checkpoint.md +10 -0
- package/skills/opendevbrowser-login-automation/assets/templates/login-scenario-matrix.json +26 -0
- package/skills/opendevbrowser-login-automation/examples/sample-auth-signals.json +14 -0
- package/skills/opendevbrowser-login-automation/scripts/record-auth-signals.sh +18 -0
- package/skills/opendevbrowser-login-automation/scripts/run-login-workflow.sh +99 -0
- package/skills/opendevbrowser-login-automation/scripts/validate-skill-assets.sh +50 -0
- package/skills/opendevbrowser-product-presentation-asset/SKILL.md +98 -0
- package/skills/opendevbrowser-product-presentation-asset/artifacts/asset-pack-assembly.md +23 -0
- package/skills/opendevbrowser-product-presentation-asset/artifacts/ugc-creative-guide.md +21 -0
- package/skills/opendevbrowser-product-presentation-asset/assets/templates/claims-evidence-map.md +5 -0
- package/skills/opendevbrowser-product-presentation-asset/assets/templates/copy.md +5 -0
- package/skills/opendevbrowser-product-presentation-asset/assets/templates/features.md +4 -0
- package/skills/opendevbrowser-product-presentation-asset/assets/templates/manifest.schema.json +14 -0
- package/skills/opendevbrowser-product-presentation-asset/assets/templates/shot-list.md +7 -0
- package/skills/opendevbrowser-product-presentation-asset/assets/templates/ugc-concepts.md +17 -0
- package/skills/opendevbrowser-product-presentation-asset/assets/templates/user-actions.md +7 -0
- package/skills/opendevbrowser-product-presentation-asset/assets/templates/video-assembly.md +18 -0
- package/skills/opendevbrowser-product-presentation-asset/examples/sample-input.json +6 -0
- package/skills/opendevbrowser-product-presentation-asset/examples/sample-manifest.json +18 -0
- package/skills/opendevbrowser-product-presentation-asset/scripts/capture-screenshots.sh +9 -0
- package/skills/opendevbrowser-product-presentation-asset/scripts/collect-product.sh +14 -0
- package/skills/opendevbrowser-product-presentation-asset/scripts/download-images.sh +9 -0
- package/skills/opendevbrowser-product-presentation-asset/scripts/render-video-brief.sh +96 -0
- package/skills/opendevbrowser-product-presentation-asset/scripts/validate-skill-assets.sh +56 -0
- package/skills/opendevbrowser-product-presentation-asset/scripts/write-manifest.sh +43 -0
- package/skills/opendevbrowser-research/SKILL.md +73 -0
- package/skills/opendevbrowser-research/artifacts/research-workflows.md +29 -0
- package/skills/opendevbrowser-research/assets/templates/compact.md +7 -0
- package/skills/opendevbrowser-research/assets/templates/context.json +18 -0
- package/skills/opendevbrowser-research/assets/templates/report.md +9 -0
- package/skills/opendevbrowser-research/examples/sample-input.json +6 -0
- package/skills/opendevbrowser-research/examples/sample-output.md +4 -0
- package/skills/opendevbrowser-research/scripts/render-output.sh +12 -0
- package/skills/opendevbrowser-research/scripts/run-research.sh +23 -0
- package/skills/opendevbrowser-research/scripts/validate-skill-assets.sh +48 -0
- package/skills/opendevbrowser-research/scripts/write-artifacts.sh +29 -0
- package/skills/opendevbrowser-shopping/SKILL.md +118 -0
- package/skills/opendevbrowser-shopping/artifacts/deal-hunting-workflows.md +37 -0
- package/skills/opendevbrowser-shopping/assets/templates/deal-thresholds.json +8 -0
- package/skills/opendevbrowser-shopping/assets/templates/deals-context.json +9 -0
- package/skills/opendevbrowser-shopping/assets/templates/deals-table.md +4 -0
- package/skills/opendevbrowser-shopping/assets/templates/market-analysis.json +30 -0
- package/skills/opendevbrowser-shopping/examples/sample-deals.md +4 -0
- package/skills/opendevbrowser-shopping/examples/sample-query.json +5 -0
- package/skills/opendevbrowser-shopping/scripts/analyze-market.sh +307 -0
- package/skills/opendevbrowser-shopping/scripts/normalize-offers.sh +28 -0
- package/skills/opendevbrowser-shopping/scripts/render-deals.sh +13 -0
- package/skills/opendevbrowser-shopping/scripts/run-deal-hunt.sh +32 -0
- package/skills/opendevbrowser-shopping/scripts/run-shopping.sh +19 -0
- package/skills/opendevbrowser-shopping/scripts/validate-skill-assets.sh +53 -0
- package/dist/chunk-WTFSMBVH.js +0 -2815
- package/dist/chunk-WTFSMBVH.js.map +0 -1
- package/extension/dist/popup.jsx +0 -150
- package/skills/data-extraction/SKILL.md +0 -136
- package/skills/form-testing/SKILL.md +0 -113
- package/skills/login-automation/SKILL.md +0 -98
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
if [[ $# -lt 2 ]]; then
|
|
5
|
+
echo "Usage: write-artifacts.sh <topic> <output-dir>"
|
|
6
|
+
exit 1
|
|
7
|
+
fi
|
|
8
|
+
|
|
9
|
+
TOPIC="$1"
|
|
10
|
+
OUTDIR="$2"
|
|
11
|
+
|
|
12
|
+
json_output="$(opendevbrowser research run --topic "$TOPIC" --mode path --output-dir "$OUTDIR" --output-format json)"
|
|
13
|
+
printf '%s\n' "$json_output"
|
|
14
|
+
|
|
15
|
+
artifact_path="$(printf '%s\n' "$json_output" | node -e 'const fs=require("fs");const lines=fs.readFileSync(0,"utf8").split(/\r?\n/).map((line)=>line.trim()).filter(Boolean);let payload=null;for(const line of lines){try{payload=JSON.parse(line);}catch{}}const p=payload?.data?.path; if(typeof p==="string") process.stdout.write(p);')"
|
|
16
|
+
if [[ -z "$artifact_path" || ! -d "$artifact_path" ]]; then
|
|
17
|
+
manifest_path="$(find "$OUTDIR" -maxdepth 4 -type f -name bundle-manifest.json 2>/dev/null | head -n 1)"
|
|
18
|
+
if [[ -n "$manifest_path" ]]; then
|
|
19
|
+
artifact_path="$(dirname "$manifest_path")"
|
|
20
|
+
fi
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
if [[ -z "$artifact_path" || ! -d "$artifact_path" ]]; then
|
|
24
|
+
echo "Artifact path not found for output dir: $OUTDIR" >&2
|
|
25
|
+
exit 2
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
node -e 'console.log(JSON.stringify({ data: { path: process.argv[1] } }));' "$artifact_path"
|
|
29
|
+
echo "Artifacts ready: $artifact_path"
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: opendevbrowser-shopping
|
|
3
|
+
description: Deterministic multi-provider shopping and deal-comparison workflow.
|
|
4
|
+
version: 2.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Shopping Skill
|
|
8
|
+
|
|
9
|
+
Use this skill for robust deal hunting across providers with market-baseline validation and savings analysis.
|
|
10
|
+
|
|
11
|
+
## Pack Contents
|
|
12
|
+
|
|
13
|
+
- `artifacts/deal-hunting-workflows.md`
|
|
14
|
+
- `assets/templates/deals-context.json`
|
|
15
|
+
- `assets/templates/deals-table.md`
|
|
16
|
+
- `assets/templates/market-analysis.json`
|
|
17
|
+
- `assets/templates/deal-thresholds.json`
|
|
18
|
+
- `scripts/run-shopping.sh`
|
|
19
|
+
- `scripts/normalize-offers.sh`
|
|
20
|
+
- `scripts/render-deals.sh`
|
|
21
|
+
- `scripts/analyze-market.sh`
|
|
22
|
+
- `scripts/run-deal-hunt.sh`
|
|
23
|
+
- `scripts/validate-skill-assets.sh`
|
|
24
|
+
- Shared robustness matrix: `../opendevbrowser-best-practices/artifacts/browser-agent-known-issues-matrix.md`
|
|
25
|
+
|
|
26
|
+
## Fast Start
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
./skills/opendevbrowser-shopping/scripts/validate-skill-assets.sh
|
|
30
|
+
./skills/opendevbrowser-shopping/scripts/run-shopping.sh "wireless earbuds" context best_deal
|
|
31
|
+
./skills/opendevbrowser-shopping/scripts/run-deal-hunt.sh "wireless earbuds" "shopping/amazon,shopping/walmart"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Deal-Hunting Model
|
|
35
|
+
|
|
36
|
+
Use a two-layer check for each offer:
|
|
37
|
+
|
|
38
|
+
1. Provider discount check
|
|
39
|
+
- Compare listed total to provider anchor price (MSRP/list/original) when available.
|
|
40
|
+
- Capture absolute savings and percentage savings.
|
|
41
|
+
|
|
42
|
+
2. Market baseline check
|
|
43
|
+
- Compare listed total against cross-provider market average and median.
|
|
44
|
+
- Flag offers that are truly cheaper than market, not just marked "on sale".
|
|
45
|
+
|
|
46
|
+
## Parallel Multitab Alignment
|
|
47
|
+
|
|
48
|
+
- Apply shared concurrency policy from `../opendevbrowser-best-practices/SKILL.md` ("Parallel Operations").
|
|
49
|
+
- Validate shopping workflows across `managed`, `extension`, and `cdpConnect` when browser-backed provider paths are exercised.
|
|
50
|
+
- Keep one session per worker for parallel offer collection and avoid session-level target contention.
|
|
51
|
+
|
|
52
|
+
## Savings Math
|
|
53
|
+
|
|
54
|
+
Per offer:
|
|
55
|
+
- `total_price = item_price + shipping`
|
|
56
|
+
- `anchor_savings_abs = max(anchor_price - total_price, 0)`
|
|
57
|
+
- `anchor_savings_pct = anchor_savings_abs / anchor_price * 100`
|
|
58
|
+
|
|
59
|
+
Per market group (same currency):
|
|
60
|
+
- `market_avg = average(total_price)`
|
|
61
|
+
- `market_median = median(total_price)`
|
|
62
|
+
- `market_savings_abs = market_avg - offer_total`
|
|
63
|
+
- `market_savings_pct = market_savings_abs / market_avg * 100`
|
|
64
|
+
|
|
65
|
+
This captures both:
|
|
66
|
+
- high-percentage discounts (for example 50% off)
|
|
67
|
+
- high-absolute savings (for example $500 saved)
|
|
68
|
+
|
|
69
|
+
## Robustness Coverage (Known-Issue Matrix)
|
|
70
|
+
|
|
71
|
+
Matrix source: `../opendevbrowser-best-practices/artifacts/browser-agent-known-issues-matrix.md`
|
|
72
|
+
|
|
73
|
+
- `ISSUE-06`: rate-limit/backoff handling while collecting offers
|
|
74
|
+
- `ISSUE-09`: dedupe and pagination drift controls in offer collection
|
|
75
|
+
- `ISSUE-10`: currency normalization and same-currency grouping
|
|
76
|
+
- `ISSUE-11`: weak/missing anchor price detection
|
|
77
|
+
- `ISSUE-12`: stale price and unsupported claim controls
|
|
78
|
+
|
|
79
|
+
## Canonical Workflow
|
|
80
|
+
|
|
81
|
+
1. Run shopping search across selected providers.
|
|
82
|
+
2. Normalize offers into stable records.
|
|
83
|
+
3. Compute market analysis with `analyze-market.sh`.
|
|
84
|
+
4. Render markdown/json summary for user decision.
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
opendevbrowser shopping run --query "<query>" --providers shopping/amazon,shopping/walmart --mode json --output-format json
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Classification Heuristics
|
|
91
|
+
|
|
92
|
+
Default tags from analysis script:
|
|
93
|
+
- `high_percent` when anchor discount percent exceeds threshold.
|
|
94
|
+
- `high_absolute` when anchor discount absolute exceeds threshold.
|
|
95
|
+
- `high_value` when both are true.
|
|
96
|
+
- `market_beating` when offer is materially below market average.
|
|
97
|
+
|
|
98
|
+
Threshold defaults are in `assets/templates/deal-thresholds.json`.
|
|
99
|
+
|
|
100
|
+
Confidence model:
|
|
101
|
+
- score combines sample size, anchor coverage, and freshness coverage.
|
|
102
|
+
- warnings call out low-sample, missing-anchor, and stale/missing timestamp risk.
|
|
103
|
+
|
|
104
|
+
## Good Deal Decision Rules
|
|
105
|
+
|
|
106
|
+
Mark as strong only when at least one is true:
|
|
107
|
+
- anchor discount is material and market gap is positive
|
|
108
|
+
- market price is materially below average/median even without anchor
|
|
109
|
+
|
|
110
|
+
Avoid false positives:
|
|
111
|
+
- anchor discount exists but market total is not competitive
|
|
112
|
+
- low total due to unavailable stock or hidden constraints
|
|
113
|
+
|
|
114
|
+
## References
|
|
115
|
+
|
|
116
|
+
- FTC Guides Against Deceptive Pricing (16 CFR 233): https://www.ecfr.gov/current/title-16/chapter-I/subchapter-B/part-233
|
|
117
|
+
- NIST SP 1181 (unit pricing and value comparison): https://www.nist.gov/publications/unit-pricing-guide
|
|
118
|
+
- Schema.org Offer (price metadata): https://schema.org/Offer
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Deal Hunting Workflows
|
|
2
|
+
|
|
3
|
+
## Baseline deal workflow
|
|
4
|
+
|
|
5
|
+
1. Query providers
|
|
6
|
+
2. Normalize offers
|
|
7
|
+
3. Compute market averages/medians
|
|
8
|
+
4. Rank by true savings
|
|
9
|
+
5. Attach confidence tier and warnings per currency group
|
|
10
|
+
|
|
11
|
+
## Cross-provider verification workflow
|
|
12
|
+
|
|
13
|
+
1. Start from discounted listing
|
|
14
|
+
2. Query same product across alternate providers
|
|
15
|
+
3. Compare totals in same currency
|
|
16
|
+
4. Report verified savings and confidence
|
|
17
|
+
|
|
18
|
+
## High-value prioritization workflow
|
|
19
|
+
|
|
20
|
+
1. Compute percent discount
|
|
21
|
+
2. Compute absolute savings
|
|
22
|
+
3. Tag high-value if both thresholds pass
|
|
23
|
+
4. Present top-ranked offers first
|
|
24
|
+
|
|
25
|
+
## Anchor reliability workflow
|
|
26
|
+
|
|
27
|
+
1. Detect whether anchor/list price exists per offer
|
|
28
|
+
2. Compute anchor coverage by currency group
|
|
29
|
+
3. Distinguish anchor-only discounts from market-beating discounts
|
|
30
|
+
4. Warn when anchor evidence is weak
|
|
31
|
+
|
|
32
|
+
## Freshness workflow
|
|
33
|
+
|
|
34
|
+
1. Capture offer retrieval timestamp when available
|
|
35
|
+
2. Compute price age hours
|
|
36
|
+
3. Flag stale or missing timestamps
|
|
37
|
+
4. Lower confidence tier when freshness coverage is low
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"generated_at": "",
|
|
3
|
+
"offers_count": 0,
|
|
4
|
+
"currency_summaries": [
|
|
5
|
+
{
|
|
6
|
+
"currency": "USD",
|
|
7
|
+
"offer_count": 0,
|
|
8
|
+
"market_average_total": 0,
|
|
9
|
+
"market_median_total": 0,
|
|
10
|
+
"best_offer": {
|
|
11
|
+
"provider": "",
|
|
12
|
+
"title": "",
|
|
13
|
+
"total": 0
|
|
14
|
+
},
|
|
15
|
+
"confidence": {
|
|
16
|
+
"score": 0,
|
|
17
|
+
"tier": "low",
|
|
18
|
+
"sample_size": 0,
|
|
19
|
+
"anchor_coverage": 0,
|
|
20
|
+
"fresh_price_coverage": 0,
|
|
21
|
+
"warnings": []
|
|
22
|
+
},
|
|
23
|
+
"savings_vs_market_average": {
|
|
24
|
+
"absolute": 0,
|
|
25
|
+
"percent": 0
|
|
26
|
+
},
|
|
27
|
+
"top_discounts": []
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
}
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
if [[ $# -lt 1 ]]; then
|
|
5
|
+
echo "Usage: analyze-market.sh <shopping-json-file> [json|md] [thresholds-json-file]" >&2
|
|
6
|
+
exit 1
|
|
7
|
+
fi
|
|
8
|
+
|
|
9
|
+
input="$1"
|
|
10
|
+
mode="${2:-json}"
|
|
11
|
+
script_root="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
12
|
+
default_thresholds="$script_root/../assets/templates/deal-thresholds.json"
|
|
13
|
+
thresholds_file="${3:-$default_thresholds}"
|
|
14
|
+
|
|
15
|
+
node - "$input" "$mode" "$thresholds_file" <<'NODE'
|
|
16
|
+
const fs = require("fs");
|
|
17
|
+
|
|
18
|
+
const inputPath = process.argv[2];
|
|
19
|
+
const mode = process.argv[3] || "json";
|
|
20
|
+
const thresholdsPath = process.argv[4];
|
|
21
|
+
|
|
22
|
+
const nowMs = Date.now();
|
|
23
|
+
|
|
24
|
+
const defaults = {
|
|
25
|
+
high_percent_threshold: 40,
|
|
26
|
+
high_absolute_threshold: 100,
|
|
27
|
+
min_market_gap_percent: 5,
|
|
28
|
+
min_offer_count_for_confidence: 3,
|
|
29
|
+
max_price_age_hours_for_freshness: 24,
|
|
30
|
+
min_anchor_coverage_for_confidence: 0.5
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const asNumber = (value, fallback = 0) => {
|
|
34
|
+
const parsed = typeof value === "number" ? value : Number(value);
|
|
35
|
+
return Number.isFinite(parsed) ? parsed : fallback;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const round2 = (value) => Number(value.toFixed(2));
|
|
39
|
+
|
|
40
|
+
const parseTimestamp = (value) => {
|
|
41
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
42
|
+
const ms = value < 1e12 ? value * 1000 : value;
|
|
43
|
+
const dt = new Date(ms);
|
|
44
|
+
return Number.isFinite(dt.getTime()) ? dt : null;
|
|
45
|
+
}
|
|
46
|
+
if (typeof value !== "string" || value.trim() === "") return null;
|
|
47
|
+
const dt = new Date(value);
|
|
48
|
+
return Number.isFinite(dt.getTime()) ? dt : null;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const readThresholds = (filePath) => {
|
|
52
|
+
if (!filePath || !fs.existsSync(filePath)) return { ...defaults };
|
|
53
|
+
try {
|
|
54
|
+
const parsed = JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
55
|
+
return {
|
|
56
|
+
high_percent_threshold: asNumber(parsed.high_percent_threshold, defaults.high_percent_threshold),
|
|
57
|
+
high_absolute_threshold: asNumber(parsed.high_absolute_threshold, defaults.high_absolute_threshold),
|
|
58
|
+
min_market_gap_percent: asNumber(parsed.min_market_gap_percent, defaults.min_market_gap_percent),
|
|
59
|
+
min_offer_count_for_confidence: Math.max(1, asNumber(parsed.min_offer_count_for_confidence, defaults.min_offer_count_for_confidence)),
|
|
60
|
+
max_price_age_hours_for_freshness: Math.max(1, asNumber(parsed.max_price_age_hours_for_freshness, defaults.max_price_age_hours_for_freshness)),
|
|
61
|
+
min_anchor_coverage_for_confidence: Math.min(1, Math.max(0, asNumber(parsed.min_anchor_coverage_for_confidence, defaults.min_anchor_coverage_for_confidence)))
|
|
62
|
+
};
|
|
63
|
+
} catch {
|
|
64
|
+
return { ...defaults };
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const readAnchor = (offer) => {
|
|
69
|
+
const attrs = offer && typeof offer === "object" ? (offer.attributes || {}) : {};
|
|
70
|
+
const candidates = [
|
|
71
|
+
attrs.list_price,
|
|
72
|
+
attrs.original_price,
|
|
73
|
+
attrs.msrp,
|
|
74
|
+
attrs?.shopping_offer?.list_price,
|
|
75
|
+
attrs?.shopping_offer?.original_price,
|
|
76
|
+
attrs?.shopping_offer?.msrp
|
|
77
|
+
];
|
|
78
|
+
|
|
79
|
+
for (const candidate of candidates) {
|
|
80
|
+
if (typeof candidate === "number") return candidate;
|
|
81
|
+
if (candidate && typeof candidate === "object") {
|
|
82
|
+
const amount = asNumber(candidate.amount);
|
|
83
|
+
if (amount > 0) return amount;
|
|
84
|
+
}
|
|
85
|
+
const parsed = asNumber(candidate);
|
|
86
|
+
if (parsed > 0) return parsed;
|
|
87
|
+
}
|
|
88
|
+
return 0;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const readRetrievedAt = (offer) => {
|
|
92
|
+
const attrs = offer && typeof offer === "object" ? (offer.attributes || {}) : {};
|
|
93
|
+
const candidates = [
|
|
94
|
+
offer?.retrieved_at,
|
|
95
|
+
offer?.retrievedAt,
|
|
96
|
+
offer?.captured_at,
|
|
97
|
+
offer?.capturedAt,
|
|
98
|
+
attrs.retrieved_at,
|
|
99
|
+
attrs.retrievedAt,
|
|
100
|
+
attrs.captured_at,
|
|
101
|
+
attrs.capturedAt,
|
|
102
|
+
attrs?.shopping_offer?.retrieved_at,
|
|
103
|
+
attrs?.shopping_offer?.captured_at
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
for (const candidate of candidates) {
|
|
107
|
+
const parsed = parseTimestamp(candidate);
|
|
108
|
+
if (parsed) return parsed;
|
|
109
|
+
}
|
|
110
|
+
return null;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const pickOffers = (payload) => {
|
|
114
|
+
if (Array.isArray(payload?.offers)) return payload.offers;
|
|
115
|
+
if (Array.isArray(payload?.data?.offers)) return payload.data.offers;
|
|
116
|
+
if (Array.isArray(payload?.context?.offers)) return payload.context.offers;
|
|
117
|
+
if (Array.isArray(payload?.data?.context?.offers)) return payload.data.context.offers;
|
|
118
|
+
return [];
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const median = (values) => {
|
|
122
|
+
if (values.length === 0) return 0;
|
|
123
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
124
|
+
const mid = Math.floor(sorted.length / 2);
|
|
125
|
+
if (sorted.length % 2 === 0) return (sorted[mid - 1] + sorted[mid]) / 2;
|
|
126
|
+
return sorted[mid];
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const payload = JSON.parse(fs.readFileSync(inputPath, "utf8"));
|
|
130
|
+
const thresholds = readThresholds(thresholdsPath);
|
|
131
|
+
|
|
132
|
+
const offers = pickOffers(payload).filter((offer) => offer && typeof offer === "object");
|
|
133
|
+
const rows = offers.map((offer) => {
|
|
134
|
+
const currency = String(offer?.price?.currency || offer?.currency || "USD").toUpperCase();
|
|
135
|
+
const item = asNumber(offer?.price?.amount);
|
|
136
|
+
const shipping = asNumber(offer?.shipping?.amount);
|
|
137
|
+
const total = item + shipping;
|
|
138
|
+
const anchor = readAnchor(offer);
|
|
139
|
+
const retrievedAt = readRetrievedAt(offer);
|
|
140
|
+
const priceAgeHours = retrievedAt ? (nowMs - retrievedAt.getTime()) / 3600000 : null;
|
|
141
|
+
const anchorSavingsAbs = anchor > total ? anchor - total : 0;
|
|
142
|
+
const anchorSavingsPct = anchor > 0 ? (anchorSavingsAbs / anchor) * 100 : 0;
|
|
143
|
+
|
|
144
|
+
return {
|
|
145
|
+
provider: String(offer.provider || "unknown"),
|
|
146
|
+
title: String(offer.title || "untitled"),
|
|
147
|
+
url: String(offer.url || ""),
|
|
148
|
+
currency,
|
|
149
|
+
total,
|
|
150
|
+
item,
|
|
151
|
+
shipping,
|
|
152
|
+
anchor,
|
|
153
|
+
anchorSavingsAbs,
|
|
154
|
+
anchorSavingsPct,
|
|
155
|
+
dealScore: asNumber(offer?.deal_score),
|
|
156
|
+
retrievedAt: retrievedAt ? retrievedAt.toISOString() : null,
|
|
157
|
+
priceAgeHours
|
|
158
|
+
};
|
|
159
|
+
}).filter((row) => row.total > 0);
|
|
160
|
+
|
|
161
|
+
const byCurrency = new Map();
|
|
162
|
+
for (const row of rows) {
|
|
163
|
+
const list = byCurrency.get(row.currency) || [];
|
|
164
|
+
list.push(row);
|
|
165
|
+
byCurrency.set(row.currency, list);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const currencySummaries = [];
|
|
169
|
+
for (const [currency, list] of byCurrency.entries()) {
|
|
170
|
+
const totals = list.map((row) => row.total);
|
|
171
|
+
const avg = totals.reduce((sum, value) => sum + value, 0) / totals.length;
|
|
172
|
+
const med = median(totals);
|
|
173
|
+
|
|
174
|
+
const enriched = list.map((row) => {
|
|
175
|
+
const marketGapAbs = avg - row.total;
|
|
176
|
+
const marketGapPct = avg > 0 ? (marketGapAbs / avg) * 100 : 0;
|
|
177
|
+
const tags = [];
|
|
178
|
+
const flags = [];
|
|
179
|
+
|
|
180
|
+
if (row.anchorSavingsPct >= thresholds.high_percent_threshold) tags.push("high_percent");
|
|
181
|
+
if (row.anchorSavingsAbs >= thresholds.high_absolute_threshold) tags.push("high_absolute");
|
|
182
|
+
if (marketGapAbs > 0 && marketGapPct >= thresholds.min_market_gap_percent) tags.push("market_beating");
|
|
183
|
+
if (tags.includes("high_percent") && tags.includes("high_absolute")) tags.push("high_value");
|
|
184
|
+
|
|
185
|
+
if (row.anchor <= 0) flags.push("missing_anchor_price");
|
|
186
|
+
if (row.retrievedAt === null) flags.push("missing_price_timestamp");
|
|
187
|
+
if (row.priceAgeHours !== null && row.priceAgeHours > thresholds.max_price_age_hours_for_freshness) flags.push("stale_price");
|
|
188
|
+
if (marketGapAbs <= 0) flags.push("not_below_market_average");
|
|
189
|
+
|
|
190
|
+
return {
|
|
191
|
+
...row,
|
|
192
|
+
marketGapAbs,
|
|
193
|
+
marketGapPct,
|
|
194
|
+
tags,
|
|
195
|
+
flags
|
|
196
|
+
};
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
const sortedBest = [...enriched].sort((a, b) => {
|
|
200
|
+
const scoreA = a.marketGapAbs + a.anchorSavingsAbs + a.dealScore;
|
|
201
|
+
const scoreB = b.marketGapAbs + b.anchorSavingsAbs + b.dealScore;
|
|
202
|
+
return scoreB - scoreA;
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
const topDiscounts = sortedBest.slice(0, 5).map((row) => ({
|
|
206
|
+
provider: row.provider,
|
|
207
|
+
title: row.title,
|
|
208
|
+
total: round2(row.total),
|
|
209
|
+
market_gap_abs: round2(row.marketGapAbs),
|
|
210
|
+
market_gap_pct: round2(row.marketGapPct),
|
|
211
|
+
anchor_savings_abs: round2(row.anchorSavingsAbs),
|
|
212
|
+
anchor_savings_pct: round2(row.anchorSavingsPct),
|
|
213
|
+
price_age_hours: row.priceAgeHours === null ? null : round2(row.priceAgeHours),
|
|
214
|
+
tags: row.tags,
|
|
215
|
+
flags: row.flags,
|
|
216
|
+
url: row.url
|
|
217
|
+
}));
|
|
218
|
+
|
|
219
|
+
const best = [...enriched].sort((a, b) => a.total - b.total || b.dealScore - a.dealScore)[0];
|
|
220
|
+
const savingsVsAvgAbs = avg - best.total;
|
|
221
|
+
const savingsVsAvgPct = avg > 0 ? (savingsVsAvgAbs / avg) * 100 : 0;
|
|
222
|
+
|
|
223
|
+
const anchorCoverage = enriched.filter((row) => row.anchor > 0).length / enriched.length;
|
|
224
|
+
const freshCoverage = enriched.filter((row) => row.priceAgeHours !== null && row.priceAgeHours <= thresholds.max_price_age_hours_for_freshness).length / enriched.length;
|
|
225
|
+
|
|
226
|
+
const sampleScore = Math.min(enriched.length / thresholds.min_offer_count_for_confidence, 1);
|
|
227
|
+
const anchorScore = thresholds.min_anchor_coverage_for_confidence === 0
|
|
228
|
+
? 1
|
|
229
|
+
: Math.min(anchorCoverage / thresholds.min_anchor_coverage_for_confidence, 1);
|
|
230
|
+
const freshnessScore = freshCoverage;
|
|
231
|
+
|
|
232
|
+
const confidenceScore = (sampleScore * 0.4) + (anchorScore * 0.3) + (freshnessScore * 0.3);
|
|
233
|
+
const warnings = [];
|
|
234
|
+
if (enriched.length < thresholds.min_offer_count_for_confidence) warnings.push("low_sample_size");
|
|
235
|
+
if (anchorCoverage < thresholds.min_anchor_coverage_for_confidence) warnings.push("low_anchor_coverage");
|
|
236
|
+
if (freshCoverage < 0.5) warnings.push("stale_or_missing_prices");
|
|
237
|
+
|
|
238
|
+
let tier = "low";
|
|
239
|
+
if (confidenceScore >= 0.75) tier = "high";
|
|
240
|
+
else if (confidenceScore >= 0.5) tier = "medium";
|
|
241
|
+
|
|
242
|
+
currencySummaries.push({
|
|
243
|
+
currency,
|
|
244
|
+
offer_count: enriched.length,
|
|
245
|
+
market_average_total: round2(avg),
|
|
246
|
+
market_median_total: round2(med),
|
|
247
|
+
best_offer: {
|
|
248
|
+
provider: best.provider,
|
|
249
|
+
title: best.title,
|
|
250
|
+
total: round2(best.total)
|
|
251
|
+
},
|
|
252
|
+
confidence: {
|
|
253
|
+
score: round2(confidenceScore),
|
|
254
|
+
tier,
|
|
255
|
+
sample_size: enriched.length,
|
|
256
|
+
anchor_coverage: round2(anchorCoverage),
|
|
257
|
+
fresh_price_coverage: round2(freshCoverage),
|
|
258
|
+
warnings
|
|
259
|
+
},
|
|
260
|
+
savings_vs_market_average: {
|
|
261
|
+
absolute: round2(savingsVsAvgAbs),
|
|
262
|
+
percent: round2(savingsVsAvgPct)
|
|
263
|
+
},
|
|
264
|
+
top_discounts: topDiscounts
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const summary = {
|
|
269
|
+
generated_at: new Date().toISOString(),
|
|
270
|
+
offers_count: rows.length,
|
|
271
|
+
thresholds_used: thresholds,
|
|
272
|
+
currency_summaries: currencySummaries
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
if (mode === "md") {
|
|
276
|
+
const lines = [
|
|
277
|
+
"# Market Deal Analysis",
|
|
278
|
+
"",
|
|
279
|
+
`Offers analyzed: ${summary.offers_count}`,
|
|
280
|
+
""
|
|
281
|
+
];
|
|
282
|
+
|
|
283
|
+
for (const group of summary.currency_summaries) {
|
|
284
|
+
lines.push(`## ${group.currency}`);
|
|
285
|
+
lines.push(`- Market average total: ${group.market_average_total.toFixed(2)}`);
|
|
286
|
+
lines.push(`- Market median total: ${group.market_median_total.toFixed(2)}`);
|
|
287
|
+
lines.push(`- Best offer: ${group.best_offer.provider} (${group.best_offer.total.toFixed(2)})`);
|
|
288
|
+
lines.push(`- Savings vs average: ${group.savings_vs_market_average.absolute.toFixed(2)} (${group.savings_vs_market_average.percent.toFixed(2)}%)`);
|
|
289
|
+
lines.push(`- Confidence: ${group.confidence.tier} (${group.confidence.score.toFixed(2)})`);
|
|
290
|
+
if (group.confidence.warnings.length > 0) {
|
|
291
|
+
lines.push(`- Warnings: ${group.confidence.warnings.join(", ")}`);
|
|
292
|
+
}
|
|
293
|
+
lines.push("");
|
|
294
|
+
lines.push("| Provider | Product | Total | Market Gap | Anchor Discount | Age(h) | Tags | Flags |");
|
|
295
|
+
lines.push("|---|---|---:|---:|---:|---:|---|---|");
|
|
296
|
+
for (const offer of group.top_discounts) {
|
|
297
|
+
const age = offer.price_age_hours === null ? "n/a" : offer.price_age_hours.toFixed(2);
|
|
298
|
+
lines.push(`| ${offer.provider} | ${offer.title} | ${offer.total.toFixed(2)} | ${offer.market_gap_abs.toFixed(2)} (${offer.market_gap_pct.toFixed(2)}%) | ${offer.anchor_savings_abs.toFixed(2)} (${offer.anchor_savings_pct.toFixed(2)}%) | ${age} | ${offer.tags.join(", ")} | ${offer.flags.join(", ")} |`);
|
|
299
|
+
}
|
|
300
|
+
lines.push("");
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
process.stdout.write(lines.join("\n"));
|
|
304
|
+
} else {
|
|
305
|
+
process.stdout.write(JSON.stringify(summary, null, 2));
|
|
306
|
+
}
|
|
307
|
+
NODE
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
if [[ $# -lt 1 ]]; then
|
|
5
|
+
echo "Usage: normalize-offers.sh <query> [providers]" >&2
|
|
6
|
+
exit 1
|
|
7
|
+
fi
|
|
8
|
+
|
|
9
|
+
query="$1"
|
|
10
|
+
providers="${2:-}"
|
|
11
|
+
|
|
12
|
+
cmd=(opendevbrowser shopping run --query "$query" --mode json --output-format json)
|
|
13
|
+
if [[ -n "$providers" ]]; then
|
|
14
|
+
cmd+=(--providers "$providers")
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
raw="$(${cmd[@]})"
|
|
18
|
+
printf '%s\n' "$raw" | node -e '
|
|
19
|
+
const fs=require("fs");
|
|
20
|
+
const input=fs.readFileSync(0,"utf8");
|
|
21
|
+
const payload=JSON.parse(input);
|
|
22
|
+
const offers=Array.isArray(payload.offers)?payload.offers
|
|
23
|
+
: Array.isArray(payload?.data?.offers)?payload.data.offers
|
|
24
|
+
: Array.isArray(payload?.context?.offers)?payload.context.offers
|
|
25
|
+
: Array.isArray(payload?.data?.context?.offers)?payload.data.context.offers
|
|
26
|
+
: [];
|
|
27
|
+
process.stdout.write(JSON.stringify({offers}, null, 2));
|
|
28
|
+
'
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
if [[ $# -lt 1 ]]; then
|
|
5
|
+
echo "Usage: render-deals.sh <shopping-json-file> [json|md]" >&2
|
|
6
|
+
exit 1
|
|
7
|
+
fi
|
|
8
|
+
|
|
9
|
+
input="$1"
|
|
10
|
+
mode="${2:-md}"
|
|
11
|
+
|
|
12
|
+
script_root="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
13
|
+
"$script_root/analyze-market.sh" "$input" "$mode"
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
if [[ $# -lt 1 ]]; then
|
|
5
|
+
echo "Usage: run-deal-hunt.sh <query> [providers] [output-dir]" >&2
|
|
6
|
+
exit 1
|
|
7
|
+
fi
|
|
8
|
+
|
|
9
|
+
query="$1"
|
|
10
|
+
providers="${2:-}"
|
|
11
|
+
outdir="${3:-/tmp/odb-deals-$(date +%s)}"
|
|
12
|
+
mkdir -p "$outdir"
|
|
13
|
+
|
|
14
|
+
raw_json="$outdir/shopping.raw.json"
|
|
15
|
+
analysis_json="$outdir/market-analysis.json"
|
|
16
|
+
analysis_md="$outdir/market-analysis.md"
|
|
17
|
+
|
|
18
|
+
cmd=(opendevbrowser shopping run --query "$query" --mode json --output-format json)
|
|
19
|
+
if [[ -n "$providers" ]]; then
|
|
20
|
+
cmd+=(--providers "$providers")
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
"${cmd[@]}" > "$raw_json"
|
|
24
|
+
|
|
25
|
+
script_root="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
26
|
+
"$script_root/analyze-market.sh" "$raw_json" json > "$analysis_json"
|
|
27
|
+
"$script_root/analyze-market.sh" "$raw_json" md > "$analysis_md"
|
|
28
|
+
|
|
29
|
+
echo "Deal hunt complete"
|
|
30
|
+
echo "- raw: $raw_json"
|
|
31
|
+
echo "- json analysis: $analysis_json"
|
|
32
|
+
echo "- markdown analysis: $analysis_md"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
if [[ $# -lt 1 ]]; then
|
|
5
|
+
echo "Usage: run-shopping.sh <query> [mode] [sort] [providers]" >&2
|
|
6
|
+
exit 1
|
|
7
|
+
fi
|
|
8
|
+
|
|
9
|
+
query="$1"
|
|
10
|
+
mode="${2:-context}"
|
|
11
|
+
sort="${3:-best_deal}"
|
|
12
|
+
providers="${4:-}"
|
|
13
|
+
|
|
14
|
+
cmd=(opendevbrowser shopping run --query "$query" --mode "$mode" --sort "$sort")
|
|
15
|
+
if [[ -n "$providers" ]]; then
|
|
16
|
+
cmd+=(--providers "$providers")
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
"${cmd[@]}"
|