opendevbrowser 0.0.15 → 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 +1 -1
- package/README.md +229 -34
- 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 +2205 -267
- 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 +867 -87
- 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 +867 -87
- 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/background.js +10 -4
- package/extension/dist/ops/ops-runtime.js +506 -4
- package/extension/dist/ops/ops-session-store.js +16 -2
- package/extension/dist/ops/parallelism-governor.js +117 -0
- package/extension/dist/ops/snapshot-shared.js +21 -5
- package/extension/dist/services/CDPRouter.js +70 -5
- package/extension/dist/services/ConnectionManager.js +5 -3
- 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 +1 -1
- package/package.json +25 -16
- 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 +17 -8
- package/skills/opendevbrowser-best-practices/SKILL.md +178 -72
- 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 +10 -0
- 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-JVBMT2O5.js +0 -7173
- package/dist/chunk-JVBMT2O5.js.map +0 -1
- package/skills/data-extraction/SKILL.md +0 -128
- package/skills/form-testing/SKILL.md +0 -106
- package/skills/login-automation/SKILL.md +0 -108
package/dist/cli/index.js
CHANGED
|
@@ -6,9 +6,11 @@ import {
|
|
|
6
6
|
EXIT_USAGE,
|
|
7
7
|
buildAnnotateResult,
|
|
8
8
|
callDaemon,
|
|
9
|
+
cleanupExpiredArtifacts,
|
|
9
10
|
createOpenDevBrowserCore,
|
|
10
11
|
createUsageError,
|
|
11
12
|
extractExtension,
|
|
13
|
+
fetchDaemonStatus,
|
|
12
14
|
fetchDaemonStatusFromMetadata,
|
|
13
15
|
fetchWithTimeout,
|
|
14
16
|
formatErrorPayload,
|
|
@@ -20,9 +22,68 @@ import {
|
|
|
20
22
|
startDaemon,
|
|
21
23
|
toCliError,
|
|
22
24
|
writeFileAtomic
|
|
23
|
-
} from "../chunk-
|
|
25
|
+
} from "../chunk-ST7CO5FA.js";
|
|
26
|
+
import "../chunk-7W3SPXIB.js";
|
|
24
27
|
|
|
25
28
|
// src/cli/args.ts
|
|
29
|
+
var CLI_COMMANDS = [
|
|
30
|
+
"install",
|
|
31
|
+
"update",
|
|
32
|
+
"uninstall",
|
|
33
|
+
"help",
|
|
34
|
+
"version",
|
|
35
|
+
"serve",
|
|
36
|
+
"daemon",
|
|
37
|
+
"native",
|
|
38
|
+
"run",
|
|
39
|
+
"launch",
|
|
40
|
+
"connect",
|
|
41
|
+
"disconnect",
|
|
42
|
+
"status",
|
|
43
|
+
"research",
|
|
44
|
+
"shopping",
|
|
45
|
+
"product-video",
|
|
46
|
+
"artifacts",
|
|
47
|
+
"goto",
|
|
48
|
+
"wait",
|
|
49
|
+
"snapshot",
|
|
50
|
+
"click",
|
|
51
|
+
"hover",
|
|
52
|
+
"press",
|
|
53
|
+
"check",
|
|
54
|
+
"uncheck",
|
|
55
|
+
"type",
|
|
56
|
+
"select",
|
|
57
|
+
"scroll",
|
|
58
|
+
"scroll-into-view",
|
|
59
|
+
"targets-list",
|
|
60
|
+
"target-use",
|
|
61
|
+
"target-new",
|
|
62
|
+
"target-close",
|
|
63
|
+
"page",
|
|
64
|
+
"pages",
|
|
65
|
+
"page-close",
|
|
66
|
+
"dom-html",
|
|
67
|
+
"dom-text",
|
|
68
|
+
"dom-attr",
|
|
69
|
+
"dom-value",
|
|
70
|
+
"dom-visible",
|
|
71
|
+
"dom-enabled",
|
|
72
|
+
"dom-checked",
|
|
73
|
+
"clone-page",
|
|
74
|
+
"clone-component",
|
|
75
|
+
"perf",
|
|
76
|
+
"screenshot",
|
|
77
|
+
"console-poll",
|
|
78
|
+
"network-poll",
|
|
79
|
+
"debug-trace-snapshot",
|
|
80
|
+
"cookie-import",
|
|
81
|
+
"cookie-list",
|
|
82
|
+
"macro-resolve",
|
|
83
|
+
"annotate",
|
|
84
|
+
"rpc"
|
|
85
|
+
];
|
|
86
|
+
var CLI_COMMAND_SET = new Set(CLI_COMMANDS);
|
|
26
87
|
var SHORT_FLAGS = {
|
|
27
88
|
"-g": "--global",
|
|
28
89
|
"-l": "--local",
|
|
@@ -85,12 +146,162 @@ function parseTransport(args) {
|
|
|
85
146
|
}
|
|
86
147
|
throw createUsageError(`Invalid --transport: ${value ?? "missing"}`);
|
|
87
148
|
}
|
|
149
|
+
var VALID_FLAGS = [
|
|
150
|
+
"--global",
|
|
151
|
+
"--local",
|
|
152
|
+
"--update",
|
|
153
|
+
"--uninstall",
|
|
154
|
+
"--help",
|
|
155
|
+
"--version",
|
|
156
|
+
"--with-config",
|
|
157
|
+
"--no-prompt",
|
|
158
|
+
"--no-interactive",
|
|
159
|
+
"--quiet",
|
|
160
|
+
"--output-format",
|
|
161
|
+
"--full",
|
|
162
|
+
"--port",
|
|
163
|
+
"--token",
|
|
164
|
+
"--stop",
|
|
165
|
+
"--script",
|
|
166
|
+
"--headless",
|
|
167
|
+
"--profile",
|
|
168
|
+
"--persist-profile",
|
|
169
|
+
"--chrome-path",
|
|
170
|
+
"--start-url",
|
|
171
|
+
"--flag",
|
|
172
|
+
"--session-id",
|
|
173
|
+
"--close-browser",
|
|
174
|
+
"--ws-endpoint",
|
|
175
|
+
"--host",
|
|
176
|
+
"--cdp-port",
|
|
177
|
+
"--url",
|
|
178
|
+
"--wait-until",
|
|
179
|
+
"--timeout-ms",
|
|
180
|
+
"--ref",
|
|
181
|
+
"--state",
|
|
182
|
+
"--until",
|
|
183
|
+
"--mode",
|
|
184
|
+
"--max-chars",
|
|
185
|
+
"--cursor",
|
|
186
|
+
"--text",
|
|
187
|
+
"--clear",
|
|
188
|
+
"--submit",
|
|
189
|
+
"--values",
|
|
190
|
+
"--dy",
|
|
191
|
+
"--key",
|
|
192
|
+
"--attr",
|
|
193
|
+
"--name",
|
|
194
|
+
"--target-id",
|
|
195
|
+
"--tab-id",
|
|
196
|
+
"--include-urls",
|
|
197
|
+
"--path",
|
|
198
|
+
"--since-seq",
|
|
199
|
+
"--max",
|
|
200
|
+
"--since-console-seq",
|
|
201
|
+
"--since-network-seq",
|
|
202
|
+
"--since-exception-seq",
|
|
203
|
+
"--request-id",
|
|
204
|
+
"--cookies",
|
|
205
|
+
"--cookies-file",
|
|
206
|
+
"--strict",
|
|
207
|
+
"--expression",
|
|
208
|
+
"--default-provider",
|
|
209
|
+
"--include-catalog",
|
|
210
|
+
"--execute",
|
|
211
|
+
"--params",
|
|
212
|
+
"--params-file",
|
|
213
|
+
"--unsafe-internal",
|
|
214
|
+
"--daemon",
|
|
215
|
+
"--transport",
|
|
216
|
+
"--no-extension",
|
|
217
|
+
"--extension-only",
|
|
218
|
+
"--extension-legacy",
|
|
219
|
+
"--wait-for-extension",
|
|
220
|
+
"--wait-timeout-ms",
|
|
221
|
+
"--skills-global",
|
|
222
|
+
"--skills-local",
|
|
223
|
+
"--no-skills",
|
|
224
|
+
"--screenshot-mode",
|
|
225
|
+
"--debug",
|
|
226
|
+
"--context",
|
|
227
|
+
"--topic",
|
|
228
|
+
"--days",
|
|
229
|
+
"--from",
|
|
230
|
+
"--to",
|
|
231
|
+
"--source-selection",
|
|
232
|
+
"--sources",
|
|
233
|
+
"--include-engagement",
|
|
234
|
+
"--limit-per-source",
|
|
235
|
+
"--query",
|
|
236
|
+
"--providers",
|
|
237
|
+
"--budget",
|
|
238
|
+
"--region",
|
|
239
|
+
"--sort",
|
|
240
|
+
"--product-url",
|
|
241
|
+
"--product-name",
|
|
242
|
+
"--provider-hint",
|
|
243
|
+
"--include-screenshots",
|
|
244
|
+
"--include-all-images",
|
|
245
|
+
"--include-copy",
|
|
246
|
+
"--output-dir",
|
|
247
|
+
"--ttl-hours",
|
|
248
|
+
"--expired-only"
|
|
249
|
+
];
|
|
250
|
+
var VALID_FLAG_SET = new Set(VALID_FLAGS);
|
|
251
|
+
var VALID_EQUALS_FLAGS = [
|
|
252
|
+
"--output-format",
|
|
253
|
+
"--transport",
|
|
254
|
+
"--session-id",
|
|
255
|
+
"--url",
|
|
256
|
+
"--screenshot-mode",
|
|
257
|
+
"--context",
|
|
258
|
+
"--timeout-ms",
|
|
259
|
+
"--since-seq",
|
|
260
|
+
"--since-console-seq",
|
|
261
|
+
"--since-network-seq",
|
|
262
|
+
"--since-exception-seq",
|
|
263
|
+
"--max",
|
|
264
|
+
"--target-id",
|
|
265
|
+
"--tab-id",
|
|
266
|
+
"--name",
|
|
267
|
+
"--cookies",
|
|
268
|
+
"--cookies-file",
|
|
269
|
+
"--persist-profile",
|
|
270
|
+
"--expression",
|
|
271
|
+
"--default-provider",
|
|
272
|
+
"--request-id",
|
|
273
|
+
"--strict",
|
|
274
|
+
"--params",
|
|
275
|
+
"--params-file",
|
|
276
|
+
"--topic",
|
|
277
|
+
"--days",
|
|
278
|
+
"--from",
|
|
279
|
+
"--to",
|
|
280
|
+
"--source-selection",
|
|
281
|
+
"--sources",
|
|
282
|
+
"--mode",
|
|
283
|
+
"--limit-per-source",
|
|
284
|
+
"--query",
|
|
285
|
+
"--providers",
|
|
286
|
+
"--budget",
|
|
287
|
+
"--region",
|
|
288
|
+
"--sort",
|
|
289
|
+
"--product-url",
|
|
290
|
+
"--product-name",
|
|
291
|
+
"--provider-hint",
|
|
292
|
+
"--include-screenshots",
|
|
293
|
+
"--include-all-images",
|
|
294
|
+
"--include-copy",
|
|
295
|
+
"--output-dir",
|
|
296
|
+
"--ttl-hours"
|
|
297
|
+
];
|
|
298
|
+
var VALID_EQUALS_FLAG_SET = new Set(VALID_EQUALS_FLAGS);
|
|
88
299
|
function parseArgs(argv) {
|
|
89
300
|
let args = expandShortFlags(argv.slice(2));
|
|
90
301
|
let commandOverride = null;
|
|
91
302
|
if (args[0] && !args[0].startsWith("-")) {
|
|
92
303
|
const candidate = args[0];
|
|
93
|
-
if (candidate
|
|
304
|
+
if (CLI_COMMAND_SET.has(candidate)) {
|
|
94
305
|
commandOverride = candidate;
|
|
95
306
|
args = args.slice(1);
|
|
96
307
|
} else {
|
|
@@ -179,87 +390,11 @@ function parseArgs(argv) {
|
|
|
179
390
|
} else if (noPrompt) {
|
|
180
391
|
mode = "global";
|
|
181
392
|
}
|
|
182
|
-
const validFlags = /* @__PURE__ */ new Set([
|
|
183
|
-
"--global",
|
|
184
|
-
"--local",
|
|
185
|
-
"--update",
|
|
186
|
-
"--uninstall",
|
|
187
|
-
"--help",
|
|
188
|
-
"--version",
|
|
189
|
-
"--with-config",
|
|
190
|
-
"--no-prompt",
|
|
191
|
-
"--no-interactive",
|
|
192
|
-
"--quiet",
|
|
193
|
-
"--output-format",
|
|
194
|
-
"--full",
|
|
195
|
-
"--port",
|
|
196
|
-
"--token",
|
|
197
|
-
"--stop",
|
|
198
|
-
"--script",
|
|
199
|
-
"--headless",
|
|
200
|
-
"--profile",
|
|
201
|
-
"--persist-profile",
|
|
202
|
-
"--chrome-path",
|
|
203
|
-
"--start-url",
|
|
204
|
-
"--flag",
|
|
205
|
-
"--session-id",
|
|
206
|
-
"--close-browser",
|
|
207
|
-
"--ws-endpoint",
|
|
208
|
-
"--host",
|
|
209
|
-
"--cdp-port",
|
|
210
|
-
"--url",
|
|
211
|
-
"--wait-until",
|
|
212
|
-
"--timeout-ms",
|
|
213
|
-
"--ref",
|
|
214
|
-
"--state",
|
|
215
|
-
"--until",
|
|
216
|
-
"--mode",
|
|
217
|
-
"--max-chars",
|
|
218
|
-
"--cursor",
|
|
219
|
-
"--text",
|
|
220
|
-
"--clear",
|
|
221
|
-
"--submit",
|
|
222
|
-
"--values",
|
|
223
|
-
"--dy",
|
|
224
|
-
"--key",
|
|
225
|
-
"--attr",
|
|
226
|
-
"--name",
|
|
227
|
-
"--target-id",
|
|
228
|
-
"--tab-id",
|
|
229
|
-
"--include-urls",
|
|
230
|
-
"--path",
|
|
231
|
-
"--since-seq",
|
|
232
|
-
"--max",
|
|
233
|
-
"--daemon",
|
|
234
|
-
"--transport",
|
|
235
|
-
"--no-extension",
|
|
236
|
-
"--extension-only",
|
|
237
|
-
"--extension-legacy",
|
|
238
|
-
"--wait-for-extension",
|
|
239
|
-
"--wait-timeout-ms",
|
|
240
|
-
"--skills-global",
|
|
241
|
-
"--skills-local",
|
|
242
|
-
"--no-skills",
|
|
243
|
-
"--screenshot-mode",
|
|
244
|
-
"--debug",
|
|
245
|
-
"--context"
|
|
246
|
-
]);
|
|
247
|
-
const validEqualsFlags = /* @__PURE__ */ new Set([
|
|
248
|
-
"--output-format",
|
|
249
|
-
"--transport",
|
|
250
|
-
"--session-id",
|
|
251
|
-
"--url",
|
|
252
|
-
"--screenshot-mode",
|
|
253
|
-
"--context",
|
|
254
|
-
"--timeout-ms",
|
|
255
|
-
"--target-id",
|
|
256
|
-
"--tab-id"
|
|
257
|
-
]);
|
|
258
393
|
for (const arg of args) {
|
|
259
|
-
if (arg.startsWith("--") && !
|
|
394
|
+
if (arg.startsWith("--") && !VALID_FLAG_SET.has(arg)) {
|
|
260
395
|
if (arg.includes("=")) {
|
|
261
396
|
const baseFlag = arg.split("=", 2)[0] ?? "";
|
|
262
|
-
if (
|
|
397
|
+
if (VALID_EQUALS_FLAG_SET.has(baseFlag)) {
|
|
263
398
|
continue;
|
|
264
399
|
}
|
|
265
400
|
}
|
|
@@ -283,94 +418,6 @@ function parseArgs(argv) {
|
|
|
283
418
|
rawArgs: args
|
|
284
419
|
};
|
|
285
420
|
}
|
|
286
|
-
function getHelpText() {
|
|
287
|
-
return `
|
|
288
|
-
OpenDevBrowser CLI - Install and manage the OpenDevBrowser plugin
|
|
289
|
-
|
|
290
|
-
USAGE:
|
|
291
|
-
npx opendevbrowser [command] [options]
|
|
292
|
-
|
|
293
|
-
COMMANDS:
|
|
294
|
-
install Install the plugin (default if no command specified)
|
|
295
|
-
update Clear cached plugin to trigger reinstall
|
|
296
|
-
uninstall Remove plugin from config
|
|
297
|
-
serve Start or stop the local daemon
|
|
298
|
-
daemon Install/uninstall/status daemon auto-start
|
|
299
|
-
native Install/uninstall/status native messaging host
|
|
300
|
-
run Execute a JSON script in a single process
|
|
301
|
-
launch Launch a managed browser session via daemon
|
|
302
|
-
connect Connect to an existing browser via daemon
|
|
303
|
-
disconnect Disconnect a daemon session
|
|
304
|
-
status Get daemon status (or session status with --session-id)
|
|
305
|
-
goto Navigate current session to a URL
|
|
306
|
-
wait Wait for load or a ref to appear
|
|
307
|
-
snapshot Capture a snapshot of the active page
|
|
308
|
-
click Click an element by ref
|
|
309
|
-
hover Hover an element by ref
|
|
310
|
-
press Press a keyboard key
|
|
311
|
-
check Check a checkbox by ref
|
|
312
|
-
uncheck Uncheck a checkbox by ref
|
|
313
|
-
type Type into an element by ref
|
|
314
|
-
select Select values in a select by ref
|
|
315
|
-
scroll Scroll the page or element by ref
|
|
316
|
-
scroll-into-view Scroll an element into view by ref
|
|
317
|
-
targets-list List page targets
|
|
318
|
-
target-use Focus a target by id
|
|
319
|
-
target-new Open a new target
|
|
320
|
-
target-close Close a target by id
|
|
321
|
-
page Open or focus a named page
|
|
322
|
-
pages List named pages
|
|
323
|
-
page-close Close a named page
|
|
324
|
-
dom-html Capture HTML for a ref
|
|
325
|
-
dom-text Capture text for a ref
|
|
326
|
-
dom-attr Capture attribute value for a ref
|
|
327
|
-
dom-value Capture input value for a ref
|
|
328
|
-
dom-visible Check visibility for a ref
|
|
329
|
-
dom-enabled Check enabled state for a ref
|
|
330
|
-
dom-checked Check checked state for a ref
|
|
331
|
-
clone-page Clone the active page to React
|
|
332
|
-
clone-component Clone a component by ref
|
|
333
|
-
perf Capture performance metrics
|
|
334
|
-
screenshot Capture a screenshot
|
|
335
|
-
console-poll Poll console events
|
|
336
|
-
network-poll Poll network events
|
|
337
|
-
annotate Request interactive annotations (direct or relay)
|
|
338
|
-
help Show this help message
|
|
339
|
-
version Show version
|
|
340
|
-
|
|
341
|
-
ALIASES:
|
|
342
|
-
--update, -u Same as update
|
|
343
|
-
--uninstall Same as uninstall
|
|
344
|
-
--help, -h Same as help
|
|
345
|
-
--version, -v Same as version
|
|
346
|
-
|
|
347
|
-
INSTALL OPTIONS:
|
|
348
|
-
--global, -g Install to ~/.config/opencode/opencode.json
|
|
349
|
-
--local, -l Install to ./opencode.json (project-local)
|
|
350
|
-
--with-config Also create opendevbrowser.jsonc with defaults
|
|
351
|
-
--full, -f Create config and pre-extract extension assets
|
|
352
|
-
--no-prompt Skip prompts, use defaults (global install)
|
|
353
|
-
--no-interactive Alias of --no-prompt
|
|
354
|
-
--quiet Suppress non-error output
|
|
355
|
-
--output-format Output format: text (default), json, stream-json
|
|
356
|
-
--transport Transport: relay (default) or native
|
|
357
|
-
--skills-global Install bundled skills to ~/.config/opencode/skill (default)
|
|
358
|
-
--skills-local Install bundled skills to ./.opencode/skill
|
|
359
|
-
--no-skills Skip installing bundled skills
|
|
360
|
-
|
|
361
|
-
EXAMPLES:
|
|
362
|
-
npx opendevbrowser # Interactive install
|
|
363
|
-
npx opendevbrowser --global # Global install
|
|
364
|
-
npx opendevbrowser --local # Project install
|
|
365
|
-
npx opendevbrowser --full # Install + config + extension assets
|
|
366
|
-
npx opendevbrowser -g --with-config # Global + config file
|
|
367
|
-
npx opendevbrowser --skills-local # Install skills locally
|
|
368
|
-
npx opendevbrowser --no-skills # Skip skill installation
|
|
369
|
-
npx opendevbrowser --update # Update plugin
|
|
370
|
-
npx opendevbrowser --uninstall --global # Remove from global config
|
|
371
|
-
npx opendevbrowser native install <extension-id> # Install native host
|
|
372
|
-
`.trim();
|
|
373
|
-
}
|
|
374
421
|
function detectOutputFormat(argv) {
|
|
375
422
|
const args = expandShortFlags(argv.slice(2));
|
|
376
423
|
try {
|
|
@@ -388,6 +435,374 @@ function registerCommand(definition) {
|
|
|
388
435
|
function getCommand(name) {
|
|
389
436
|
return registry.get(name);
|
|
390
437
|
}
|
|
438
|
+
function listCommands() {
|
|
439
|
+
return Array.from(registry.values());
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// src/cli/help.ts
|
|
443
|
+
var LABEL_WIDTH = 42;
|
|
444
|
+
var EXPECTED_TOOL_COUNT = 48;
|
|
445
|
+
var COMMAND_SET = new Set(CLI_COMMANDS);
|
|
446
|
+
var FLAG_SET = new Set(VALID_FLAGS);
|
|
447
|
+
var HELP_COMMAND_GROUPS = [
|
|
448
|
+
{
|
|
449
|
+
title: "Install & Lifecycle",
|
|
450
|
+
summary: "Install, remove, and inspect CLI basics.",
|
|
451
|
+
commands: ["install", "update", "uninstall", "help", "version"]
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
title: "Daemon & Runtime",
|
|
455
|
+
summary: "Run daemon services and single-process scripts.",
|
|
456
|
+
commands: ["serve", "daemon", "native", "run"]
|
|
457
|
+
},
|
|
458
|
+
{
|
|
459
|
+
title: "Session Lifecycle",
|
|
460
|
+
summary: "Launch/connect sessions and manage browser state.",
|
|
461
|
+
commands: ["launch", "connect", "disconnect", "status", "cookie-import", "cookie-list"]
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
title: "Provider Workflows",
|
|
465
|
+
summary: "Run research/shopping/media workflows and macro plans.",
|
|
466
|
+
commands: ["research", "shopping", "product-video", "artifacts", "macro-resolve"]
|
|
467
|
+
},
|
|
468
|
+
{
|
|
469
|
+
title: "Navigation",
|
|
470
|
+
summary: "Move through pages and capture fresh refs.",
|
|
471
|
+
commands: ["goto", "wait", "snapshot"]
|
|
472
|
+
},
|
|
473
|
+
{
|
|
474
|
+
title: "Interaction",
|
|
475
|
+
summary: "Perform ref-based interactions in the active page.",
|
|
476
|
+
commands: ["click", "hover", "press", "check", "uncheck", "type", "select", "scroll", "scroll-into-view"]
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
title: "Targets & Pages",
|
|
480
|
+
summary: "Manage tabs/targets and named pages.",
|
|
481
|
+
commands: ["targets-list", "target-use", "target-new", "target-close", "page", "pages", "page-close"]
|
|
482
|
+
},
|
|
483
|
+
{
|
|
484
|
+
title: "DOM & Export",
|
|
485
|
+
summary: "Read DOM state and export page/component code.",
|
|
486
|
+
commands: ["dom-html", "dom-text", "dom-attr", "dom-value", "dom-visible", "dom-enabled", "dom-checked", "clone-page", "clone-component"]
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
title: "Diagnostics & Annotation",
|
|
490
|
+
summary: "Collect runtime diagnostics and annotation payloads.",
|
|
491
|
+
commands: ["perf", "screenshot", "console-poll", "network-poll", "debug-trace-snapshot", "annotate"]
|
|
492
|
+
},
|
|
493
|
+
{
|
|
494
|
+
title: "Power",
|
|
495
|
+
summary: "Unsafe internal command passthrough.",
|
|
496
|
+
commands: ["rpc"]
|
|
497
|
+
}
|
|
498
|
+
];
|
|
499
|
+
var HELP_FLAG_GROUPS = [
|
|
500
|
+
{
|
|
501
|
+
title: "Install/Global Flags",
|
|
502
|
+
summary: "Control installation scope and setup behavior.",
|
|
503
|
+
flags: [
|
|
504
|
+
{ flag: "--global", alias: "-g", description: "Install into ~/.config/opencode/opencode.json." },
|
|
505
|
+
{ flag: "--local", alias: "-l", description: "Install into ./opencode.json for this project." },
|
|
506
|
+
{ flag: "--update", alias: "-u", description: "Alias for the update command." },
|
|
507
|
+
{ flag: "--uninstall", description: "Alias for the uninstall command." },
|
|
508
|
+
{ flag: "--with-config", description: "Also create opendevbrowser.jsonc defaults." },
|
|
509
|
+
{ flag: "--full", alias: "-f", description: "Install config and pre-extract extension assets." },
|
|
510
|
+
{ flag: "--no-prompt", description: "Run non-interactively using defaults." },
|
|
511
|
+
{ flag: "--no-interactive", description: "Alias of --no-prompt." },
|
|
512
|
+
{ flag: "--quiet", description: "Suppress non-error text output." },
|
|
513
|
+
{ flag: "--skills-global", description: "Install bundled skills into global agent directories." },
|
|
514
|
+
{ flag: "--skills-local", description: "Install bundled skills into local project agent directories." },
|
|
515
|
+
{ flag: "--no-skills", description: "Skip bundled skill installation." }
|
|
516
|
+
]
|
|
517
|
+
},
|
|
518
|
+
{
|
|
519
|
+
title: "Help/Output Flags",
|
|
520
|
+
summary: "Inspect help/version and control output transport.",
|
|
521
|
+
flags: [
|
|
522
|
+
{ flag: "--help", alias: "-h", description: "Show CLI help output." },
|
|
523
|
+
{ flag: "--version", alias: "-v", description: "Show CLI version." },
|
|
524
|
+
{ flag: "--output-format", description: "Output mode: text, json, stream-json." },
|
|
525
|
+
{ flag: "--transport", description: "Annotation transport: relay (default) or native." }
|
|
526
|
+
]
|
|
527
|
+
},
|
|
528
|
+
{
|
|
529
|
+
title: "Daemon/Session/Launch Flags",
|
|
530
|
+
summary: "Control daemon binding, connect, and launch behavior.",
|
|
531
|
+
flags: [
|
|
532
|
+
{ flag: "--port", description: "Daemon or relay port override." },
|
|
533
|
+
{ flag: "--token", description: "Relay/daemon auth token override." },
|
|
534
|
+
{ flag: "--stop", description: "Stop a running daemon." },
|
|
535
|
+
{ flag: "--daemon", description: "Target daemon status mode where supported." },
|
|
536
|
+
{ flag: "--script", description: "Path to a run-script JSON file." },
|
|
537
|
+
{ flag: "--session-id", description: "Target an existing daemon session." },
|
|
538
|
+
{ flag: "--close-browser", description: "Close managed browser on disconnect." },
|
|
539
|
+
{ flag: "--ws-endpoint", description: "Connect using explicit CDP WebSocket endpoint." },
|
|
540
|
+
{ flag: "--host", description: "CDP host for host/port connect mode." },
|
|
541
|
+
{ flag: "--cdp-port", description: "CDP port for host/port connect mode." },
|
|
542
|
+
{ flag: "--headless", description: "Launch managed browser in headless mode." },
|
|
543
|
+
{ flag: "--profile", description: "Use a named browser profile directory." },
|
|
544
|
+
{ flag: "--persist-profile", description: "Keep generated profile directory after exit." },
|
|
545
|
+
{ flag: "--chrome-path", description: "Use a specific Chrome/Chromium binary." },
|
|
546
|
+
{ flag: "--start-url", description: "Open this URL immediately after launch." },
|
|
547
|
+
{ flag: "--flag", description: "Pass one or more extra Chrome CLI flags." },
|
|
548
|
+
{ flag: "--no-extension", description: "Force managed mode without extension relay." },
|
|
549
|
+
{ flag: "--extension-only", description: "Fail unless extension relay is connected." },
|
|
550
|
+
{ flag: "--extension-legacy", description: "Use legacy /cdp relay mode instead of /ops." },
|
|
551
|
+
{ flag: "--wait-for-extension", description: "Wait for extension handshake before returning." },
|
|
552
|
+
{ flag: "--wait-timeout-ms", description: "Handshake wait timeout in milliseconds." }
|
|
553
|
+
]
|
|
554
|
+
},
|
|
555
|
+
{
|
|
556
|
+
title: "Navigation/Interaction/Diagnostics Flags",
|
|
557
|
+
summary: "Command-specific flags for page actions and diagnostics.",
|
|
558
|
+
flags: [
|
|
559
|
+
{ flag: "--url", description: "Target URL for navigation, connect, or workflow commands." },
|
|
560
|
+
{ flag: "--wait-until", description: "Navigation wait strategy (load, domcontentloaded, etc.)." },
|
|
561
|
+
{ flag: "--timeout-ms", description: "Operation timeout in milliseconds (for example goto, wait, screenshot, annotate, rpc, and macro-resolve)." },
|
|
562
|
+
{ flag: "--ref", description: "Snapshot ref id for element-targeted commands." },
|
|
563
|
+
{ flag: "--state", description: "Wait state selector for wait-style commands." },
|
|
564
|
+
{ flag: "--until", description: "Wait condition selector for wait-style commands." },
|
|
565
|
+
{ flag: "--mode", description: "Mode selector for commands that accept variants." },
|
|
566
|
+
{ flag: "--max-chars", description: "Maximum text characters to return for DOM reads." },
|
|
567
|
+
{ flag: "--cursor", description: "Cursor token for paginated list commands." },
|
|
568
|
+
{ flag: "--text", description: "Text payload for type and related commands." },
|
|
569
|
+
{ flag: "--clear", description: "Clear existing input value before typing." },
|
|
570
|
+
{ flag: "--submit", description: "Submit form/input after typing." },
|
|
571
|
+
{ flag: "--values", description: "CSV values for select commands." },
|
|
572
|
+
{ flag: "--dy", description: "Vertical scroll delta for scroll commands." },
|
|
573
|
+
{ flag: "--key", description: "Keyboard key for press command." },
|
|
574
|
+
{ flag: "--attr", description: "DOM attribute name for dom-attr command." },
|
|
575
|
+
{ flag: "--name", description: "Named page identifier for page commands." },
|
|
576
|
+
{ flag: "--target-id", description: "Browser target id for target commands." },
|
|
577
|
+
{ flag: "--tab-id", description: "Browser tab id override for extension/annotation commands." },
|
|
578
|
+
{ flag: "--include-urls", description: "Include page URLs in list output where supported." },
|
|
579
|
+
{ flag: "--path", description: "Filesystem path for command output/artifacts." },
|
|
580
|
+
{ flag: "--since-seq", description: "Poll from sequence id across diagnostics streams." },
|
|
581
|
+
{ flag: "--max", description: "Maximum number of records/items to return." },
|
|
582
|
+
{ flag: "--since-console-seq", description: "Console sequence cursor for debug trace snapshots." },
|
|
583
|
+
{ flag: "--since-network-seq", description: "Network sequence cursor for debug trace snapshots." },
|
|
584
|
+
{ flag: "--since-exception-seq", description: "Exception sequence cursor for debug trace snapshots." },
|
|
585
|
+
{ flag: "--request-id", description: "Attach/lookup request id for correlateable output." },
|
|
586
|
+
{ flag: "--cookies", description: "Inline cookie payload for cookie-import command." },
|
|
587
|
+
{ flag: "--cookies-file", description: "File path containing cookies for cookie-import." },
|
|
588
|
+
{ flag: "--strict", description: "Fail cookie import on invalid entries." },
|
|
589
|
+
{ flag: "--screenshot-mode", description: "Annotation screenshot mode: crop, full, or none." },
|
|
590
|
+
{ flag: "--debug", description: "Enable debug-level annotation capture extras." },
|
|
591
|
+
{ flag: "--context", description: "Free-form annotation context for reviewers/agents." }
|
|
592
|
+
]
|
|
593
|
+
},
|
|
594
|
+
{
|
|
595
|
+
title: "Macro/Provider/Power Flags",
|
|
596
|
+
summary: "Workflow filters, provider selectors, and unsafe RPC options.",
|
|
597
|
+
flags: [
|
|
598
|
+
{ flag: "--expression", description: "Macro expression to resolve/execute." },
|
|
599
|
+
{ flag: "--default-provider", description: "Provider fallback for shorthand macro expressions." },
|
|
600
|
+
{ flag: "--include-catalog", description: "Include macro catalog metadata in response." },
|
|
601
|
+
{ flag: "--execute", description: "Execute resolved macro action after planning (pair with --timeout-ms on slow runs)." },
|
|
602
|
+
{ flag: "--params", description: "Inline JSON params for rpc command." },
|
|
603
|
+
{ flag: "--params-file", description: "Path to JSON params file for rpc command." },
|
|
604
|
+
{ flag: "--unsafe-internal", description: "Required safety gate for rpc command." },
|
|
605
|
+
{ flag: "--topic", description: "Research topic input." },
|
|
606
|
+
{ flag: "--days", description: "Lookback window in days for research commands." },
|
|
607
|
+
{ flag: "--from", description: "Start date boundary for research commands." },
|
|
608
|
+
{ flag: "--to", description: "End date boundary for research commands." },
|
|
609
|
+
{ flag: "--source-selection", description: "Research source-family selector." },
|
|
610
|
+
{ flag: "--sources", description: "Explicit source selectors within a source family." },
|
|
611
|
+
{ flag: "--include-engagement", description: "Include engagement metrics in research output." },
|
|
612
|
+
{ flag: "--limit-per-source", description: "Per-source result cap for research runs." },
|
|
613
|
+
{ flag: "--query", description: "Shopping query input." },
|
|
614
|
+
{ flag: "--providers", description: "Comma-separated provider ids for shopping/artifacts." },
|
|
615
|
+
{ flag: "--budget", description: "Budget filter for shopping workflows." },
|
|
616
|
+
{ flag: "--region", description: "Region/country hint for provider selection." },
|
|
617
|
+
{ flag: "--sort", description: "Sort mode for shopping results." },
|
|
618
|
+
{ flag: "--product-url", description: "Target product URL for product-video/artifacts workflows." },
|
|
619
|
+
{ flag: "--product-name", description: "Product name override for media workflows." },
|
|
620
|
+
{ flag: "--provider-hint", description: "Provider hint override for product workflows." },
|
|
621
|
+
{ flag: "--include-screenshots", description: "Include screenshots in product presentation output." },
|
|
622
|
+
{ flag: "--include-all-images", description: "Include all discovered product images." },
|
|
623
|
+
{ flag: "--include-copy", description: "Include product marketing copy metadata." },
|
|
624
|
+
{ flag: "--output-dir", description: "Directory where generated artifacts are written." },
|
|
625
|
+
{ flag: "--ttl-hours", description: "Artifact cache time-to-live in hours." },
|
|
626
|
+
{ flag: "--expired-only", description: "List only expired artifacts in artifacts commands." }
|
|
627
|
+
]
|
|
628
|
+
}
|
|
629
|
+
];
|
|
630
|
+
var HELP_TOOL_ENTRIES = [
|
|
631
|
+
{ name: "opendevbrowser_launch", description: "Launch a managed browser session." },
|
|
632
|
+
{ name: "opendevbrowser_connect", description: "Connect to an existing browser session." },
|
|
633
|
+
{ name: "opendevbrowser_disconnect", description: "Disconnect a managed or connected session." },
|
|
634
|
+
{ name: "opendevbrowser_status", description: "Inspect session and relay status." },
|
|
635
|
+
{ name: "opendevbrowser_targets_list", description: "List available page targets/tabs." },
|
|
636
|
+
{ name: "opendevbrowser_target_use", description: "Switch active target by id." },
|
|
637
|
+
{ name: "opendevbrowser_target_new", description: "Create a new target/tab." },
|
|
638
|
+
{ name: "opendevbrowser_target_close", description: "Close target/tab by id." },
|
|
639
|
+
{ name: "opendevbrowser_page", description: "Open or focus a named page." },
|
|
640
|
+
{ name: "opendevbrowser_list", description: "List named pages in the session." },
|
|
641
|
+
{ name: "opendevbrowser_close", description: "Close a named page." },
|
|
642
|
+
{ name: "opendevbrowser_goto", description: "Navigate to a URL." },
|
|
643
|
+
{ name: "opendevbrowser_wait", description: "Wait for load/ref/state conditions." },
|
|
644
|
+
{ name: "opendevbrowser_snapshot", description: "Capture AX-tree refs for actions." },
|
|
645
|
+
{ name: "opendevbrowser_click", description: "Click an element by ref." },
|
|
646
|
+
{ name: "opendevbrowser_hover", description: "Hover an element by ref." },
|
|
647
|
+
{ name: "opendevbrowser_press", description: "Send a keyboard key." },
|
|
648
|
+
{ name: "opendevbrowser_check", description: "Check checkbox/radio by ref." },
|
|
649
|
+
{ name: "opendevbrowser_uncheck", description: "Uncheck checkbox/radio by ref." },
|
|
650
|
+
{ name: "opendevbrowser_type", description: "Type text into an input by ref." },
|
|
651
|
+
{ name: "opendevbrowser_select", description: "Set select values by ref." },
|
|
652
|
+
{ name: "opendevbrowser_scroll", description: "Scroll page or element." },
|
|
653
|
+
{ name: "opendevbrowser_scroll_into_view", description: "Scroll target element into view." },
|
|
654
|
+
{ name: "opendevbrowser_dom_get_html", description: "Get HTML for page or ref." },
|
|
655
|
+
{ name: "opendevbrowser_dom_get_text", description: "Get text for page or ref." },
|
|
656
|
+
{ name: "opendevbrowser_get_attr", description: "Read a DOM attribute by ref." },
|
|
657
|
+
{ name: "opendevbrowser_get_value", description: "Read form/control value by ref." },
|
|
658
|
+
{ name: "opendevbrowser_is_visible", description: "Check ref visibility." },
|
|
659
|
+
{ name: "opendevbrowser_is_enabled", description: "Check ref enabled state." },
|
|
660
|
+
{ name: "opendevbrowser_is_checked", description: "Check ref checked state." },
|
|
661
|
+
{ name: "opendevbrowser_run", description: "Execute multi-action automation scripts." },
|
|
662
|
+
{ name: "opendevbrowser_prompting_guide", description: "Return best-practice prompting guidance." },
|
|
663
|
+
{ name: "opendevbrowser_console_poll", description: "Poll redacted console events." },
|
|
664
|
+
{ name: "opendevbrowser_network_poll", description: "Poll redacted network events." },
|
|
665
|
+
{ name: "opendevbrowser_debug_trace_snapshot", description: "Capture page + console + network diagnostics." },
|
|
666
|
+
{ name: "opendevbrowser_cookie_import", description: "Import validated cookies into session." },
|
|
667
|
+
{ name: "opendevbrowser_cookie_list", description: "List cookies in session with optional URL filters." },
|
|
668
|
+
{ name: "opendevbrowser_macro_resolve", description: "Resolve/execute provider macro expressions." },
|
|
669
|
+
{ name: "opendevbrowser_research_run", description: "Run research workflow directly." },
|
|
670
|
+
{ name: "opendevbrowser_shopping_run", description: "Run shopping workflow directly." },
|
|
671
|
+
{ name: "opendevbrowser_product_video_run", description: "Run product-video asset workflow directly." },
|
|
672
|
+
{ name: "opendevbrowser_clone_page", description: "Export active page into React code." },
|
|
673
|
+
{ name: "opendevbrowser_clone_component", description: "Export component by ref into React code." },
|
|
674
|
+
{ name: "opendevbrowser_perf", description: "Collect browser performance metrics." },
|
|
675
|
+
{ name: "opendevbrowser_screenshot", description: "Capture page screenshot." },
|
|
676
|
+
{ name: "opendevbrowser_annotate", description: "Capture interactive annotations." },
|
|
677
|
+
{ name: "opendevbrowser_skill_list", description: "List available skill packs." },
|
|
678
|
+
{ name: "opendevbrowser_skill_load", description: "Load a specific skill pack." }
|
|
679
|
+
];
|
|
680
|
+
var HELP_REFERENCE_ENTRIES = [
|
|
681
|
+
{ label: "docs/CLI.md", description: "Full command docs, flag matrix, and examples." },
|
|
682
|
+
{ label: "docs/SURFACE_REFERENCE.md", description: "Canonical CLI/tool/channel inventory matrix." },
|
|
683
|
+
{ label: "src/tools/index.ts", description: "Code-level tool registry (source of truth)." },
|
|
684
|
+
{ label: "opendevbrowser --help", description: "Always safe first command for quick discovery." }
|
|
685
|
+
];
|
|
686
|
+
function formatRows(rows) {
|
|
687
|
+
return rows.map((row) => ` ${row.label.padEnd(LABEL_WIDTH)} ${row.description}`).join("\n");
|
|
688
|
+
}
|
|
689
|
+
function getCommandDescriptions() {
|
|
690
|
+
const descriptions = /* @__PURE__ */ new Map();
|
|
691
|
+
for (const definition of listCommands()) {
|
|
692
|
+
descriptions.set(definition.name, definition.description);
|
|
693
|
+
}
|
|
694
|
+
return descriptions;
|
|
695
|
+
}
|
|
696
|
+
function assertCommandCoverage(commandDescriptions) {
|
|
697
|
+
const seen = /* @__PURE__ */ new Set();
|
|
698
|
+
for (const group of HELP_COMMAND_GROUPS) {
|
|
699
|
+
for (const command of group.commands) {
|
|
700
|
+
if (!COMMAND_SET.has(command)) {
|
|
701
|
+
throw new Error(`Help references unknown CLI command: ${command}`);
|
|
702
|
+
}
|
|
703
|
+
if (!commandDescriptions.has(command)) {
|
|
704
|
+
throw new Error(`Help references unregistered CLI command: ${command}`);
|
|
705
|
+
}
|
|
706
|
+
if (seen.has(command)) {
|
|
707
|
+
throw new Error(`Help command appears multiple times: ${command}`);
|
|
708
|
+
}
|
|
709
|
+
seen.add(command);
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
if (seen.size !== CLI_COMMANDS.length) {
|
|
713
|
+
const missing = CLI_COMMANDS.filter((command) => !seen.has(command));
|
|
714
|
+
throw new Error(`Help command coverage mismatch; missing: ${missing.join(", ")}`);
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
function assertFlagCoverage() {
|
|
718
|
+
const seen = /* @__PURE__ */ new Set();
|
|
719
|
+
for (const group of HELP_FLAG_GROUPS) {
|
|
720
|
+
for (const entry of group.flags) {
|
|
721
|
+
if (!FLAG_SET.has(entry.flag)) {
|
|
722
|
+
throw new Error(`Help references unknown CLI flag: ${entry.flag}`);
|
|
723
|
+
}
|
|
724
|
+
if (seen.has(entry.flag)) {
|
|
725
|
+
throw new Error(`Help flag appears multiple times: ${entry.flag}`);
|
|
726
|
+
}
|
|
727
|
+
seen.add(entry.flag);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
if (seen.size !== VALID_FLAGS.length) {
|
|
731
|
+
const missing = VALID_FLAGS.filter((flag) => !seen.has(flag));
|
|
732
|
+
throw new Error(`Help flag coverage mismatch; missing: ${missing.join(", ")}`);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
function assertToolCoverage() {
|
|
736
|
+
if (HELP_TOOL_ENTRIES.length !== EXPECTED_TOOL_COUNT) {
|
|
737
|
+
throw new Error(`Help tool inventory must list ${EXPECTED_TOOL_COUNT} tools; got ${HELP_TOOL_ENTRIES.length}`);
|
|
738
|
+
}
|
|
739
|
+
const seen = /* @__PURE__ */ new Set();
|
|
740
|
+
for (const entry of HELP_TOOL_ENTRIES) {
|
|
741
|
+
if (seen.has(entry.name)) {
|
|
742
|
+
throw new Error(`Help tool appears multiple times: ${entry.name}`);
|
|
743
|
+
}
|
|
744
|
+
if (!entry.name.startsWith("opendevbrowser_")) {
|
|
745
|
+
throw new Error(`Invalid tool name in help inventory: ${entry.name}`);
|
|
746
|
+
}
|
|
747
|
+
seen.add(entry.name);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
function formatCommandGroups(commandDescriptions) {
|
|
751
|
+
return HELP_COMMAND_GROUPS.map((group) => {
|
|
752
|
+
const rows = group.commands.map((command) => ({
|
|
753
|
+
label: command,
|
|
754
|
+
description: commandDescriptions.get(command) ?? "Missing command description."
|
|
755
|
+
}));
|
|
756
|
+
return `${group.title}: ${group.summary}
|
|
757
|
+
${formatRows(rows)}`;
|
|
758
|
+
}).join("\n\n");
|
|
759
|
+
}
|
|
760
|
+
function formatFlagGroups() {
|
|
761
|
+
return HELP_FLAG_GROUPS.map((group) => {
|
|
762
|
+
const rows = group.flags.map((entry) => ({
|
|
763
|
+
label: entry.alias ? `${entry.flag} (${entry.alias})` : entry.flag,
|
|
764
|
+
description: entry.description
|
|
765
|
+
}));
|
|
766
|
+
return `${group.title}: ${group.summary}
|
|
767
|
+
${formatRows(rows)}`;
|
|
768
|
+
}).join("\n\n");
|
|
769
|
+
}
|
|
770
|
+
function formatToolEntries() {
|
|
771
|
+
return formatRows(HELP_TOOL_ENTRIES.map((entry) => ({
|
|
772
|
+
label: entry.name,
|
|
773
|
+
description: entry.description
|
|
774
|
+
})));
|
|
775
|
+
}
|
|
776
|
+
function formatReferenceEntries() {
|
|
777
|
+
return formatRows(HELP_REFERENCE_ENTRIES.map((entry) => ({
|
|
778
|
+
label: entry.label,
|
|
779
|
+
description: entry.description
|
|
780
|
+
})));
|
|
781
|
+
}
|
|
782
|
+
function getHelpText() {
|
|
783
|
+
const commandDescriptions = getCommandDescriptions();
|
|
784
|
+
assertCommandCoverage(commandDescriptions);
|
|
785
|
+
assertFlagCoverage();
|
|
786
|
+
assertToolCoverage();
|
|
787
|
+
return [
|
|
788
|
+
"OpenDevBrowser CLI",
|
|
789
|
+
"",
|
|
790
|
+
"Usage:",
|
|
791
|
+
" npx opendevbrowser <command> [options]",
|
|
792
|
+
"",
|
|
793
|
+
`Command Inventory (all ${CLI_COMMANDS.length} commands):`,
|
|
794
|
+
formatCommandGroups(commandDescriptions),
|
|
795
|
+
"",
|
|
796
|
+
"Flag Inventory (all supported flags):",
|
|
797
|
+
formatFlagGroups(),
|
|
798
|
+
"",
|
|
799
|
+
`Tool Inventory (all ${EXPECTED_TOOL_COUNT} opendevbrowser_* tools):`,
|
|
800
|
+
formatToolEntries(),
|
|
801
|
+
"",
|
|
802
|
+
"Reference Pointers:",
|
|
803
|
+
formatReferenceEntries()
|
|
804
|
+
].join("\n");
|
|
805
|
+
}
|
|
391
806
|
|
|
392
807
|
// src/cli/installers/global.ts
|
|
393
808
|
import * as fs3 from "fs";
|
|
@@ -504,7 +919,7 @@ function buildConfigTemplate(relayToken, daemonToken) {
|
|
|
504
919
|
"skills": {
|
|
505
920
|
"nudge": {
|
|
506
921
|
"enabled": true,
|
|
507
|
-
"keywords": ["
|
|
922
|
+
"keywords": ["quick start", "getting started", "launch", "connect", "setup"],
|
|
508
923
|
"maxAgeMs": 60000
|
|
509
924
|
}
|
|
510
925
|
},
|
|
@@ -655,6 +1070,7 @@ import * as os3 from "os";
|
|
|
655
1070
|
import { fileURLToPath } from "url";
|
|
656
1071
|
var PACKAGE_NAME = "opendevbrowser";
|
|
657
1072
|
var SKILL_DIR_NAME = "skill";
|
|
1073
|
+
var SKILLS_DIR_NAME = "skills";
|
|
658
1074
|
var cachedPackageRoot = null;
|
|
659
1075
|
function findPackageRoot(startDir) {
|
|
660
1076
|
let current = startDir;
|
|
@@ -697,33 +1113,108 @@ function getGlobalSkillDir() {
|
|
|
697
1113
|
function getLocalSkillDir() {
|
|
698
1114
|
return path3.join(process.cwd(), ".opencode", SKILL_DIR_NAME);
|
|
699
1115
|
}
|
|
1116
|
+
function getCodexHomeDir() {
|
|
1117
|
+
return process.env.CODEX_HOME || path3.join(os3.homedir(), ".codex");
|
|
1118
|
+
}
|
|
1119
|
+
function getClaudeCodeHomeDir() {
|
|
1120
|
+
return process.env.CLAUDECODE_HOME || process.env.CLAUDE_HOME || path3.join(os3.homedir(), ".claude");
|
|
1121
|
+
}
|
|
1122
|
+
function getAmpHomeDir() {
|
|
1123
|
+
return process.env.AMPCLI_HOME || process.env.AMP_CLI_HOME || process.env.AMP_HOME || path3.join(os3.homedir(), ".amp");
|
|
1124
|
+
}
|
|
1125
|
+
function dedupeTargets(targets) {
|
|
1126
|
+
const deduped = /* @__PURE__ */ new Map();
|
|
1127
|
+
for (const target of targets) {
|
|
1128
|
+
const key = path3.resolve(target.dir);
|
|
1129
|
+
const existing = deduped.get(key);
|
|
1130
|
+
if (existing) {
|
|
1131
|
+
if (!existing.agents.includes(target.agent)) {
|
|
1132
|
+
existing.agents.push(target.agent);
|
|
1133
|
+
}
|
|
1134
|
+
continue;
|
|
1135
|
+
}
|
|
1136
|
+
deduped.set(key, { agents: [target.agent], dir: target.dir });
|
|
1137
|
+
}
|
|
1138
|
+
return Array.from(deduped.values());
|
|
1139
|
+
}
|
|
1140
|
+
function getGlobalSkillTargets() {
|
|
1141
|
+
const claudeSkillsDir = path3.join(getClaudeCodeHomeDir(), SKILLS_DIR_NAME);
|
|
1142
|
+
const ampSkillsDir = path3.join(getAmpHomeDir(), SKILLS_DIR_NAME);
|
|
1143
|
+
return dedupeTargets([
|
|
1144
|
+
{ agent: "opencode", dir: getGlobalSkillDir() },
|
|
1145
|
+
{ agent: "codex", dir: path3.join(getCodexHomeDir(), SKILLS_DIR_NAME) },
|
|
1146
|
+
{ agent: "claudecode", dir: claudeSkillsDir },
|
|
1147
|
+
{ agent: "claude", dir: claudeSkillsDir },
|
|
1148
|
+
{ agent: "ampcli", dir: ampSkillsDir },
|
|
1149
|
+
{ agent: "amp", dir: ampSkillsDir }
|
|
1150
|
+
]);
|
|
1151
|
+
}
|
|
1152
|
+
function getLocalSkillTargets() {
|
|
1153
|
+
const localClaudeSkillsDir = path3.join(process.cwd(), ".claude", SKILLS_DIR_NAME);
|
|
1154
|
+
const localAmpSkillsDir = path3.join(process.cwd(), ".amp", SKILLS_DIR_NAME);
|
|
1155
|
+
return dedupeTargets([
|
|
1156
|
+
{ agent: "opencode", dir: getLocalSkillDir() },
|
|
1157
|
+
{ agent: "codex", dir: path3.join(process.cwd(), ".codex", SKILLS_DIR_NAME) },
|
|
1158
|
+
{ agent: "claudecode", dir: localClaudeSkillsDir },
|
|
1159
|
+
{ agent: "claude", dir: localClaudeSkillsDir },
|
|
1160
|
+
{ agent: "ampcli", dir: localAmpSkillsDir },
|
|
1161
|
+
{ agent: "amp", dir: localAmpSkillsDir }
|
|
1162
|
+
]);
|
|
1163
|
+
}
|
|
700
1164
|
|
|
701
1165
|
// src/cli/installers/skills.ts
|
|
702
1166
|
function installSkills(mode) {
|
|
703
|
-
const
|
|
704
|
-
const
|
|
705
|
-
const skipped = [];
|
|
1167
|
+
const targets = mode === "global" ? getGlobalSkillTargets() : getLocalSkillTargets();
|
|
1168
|
+
const targetResults = [];
|
|
706
1169
|
try {
|
|
707
1170
|
const sourceDir = getBundledSkillsDir();
|
|
708
1171
|
const entries = fs6.readdirSync(sourceDir, { withFileTypes: true });
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
1172
|
+
for (const target of targets) {
|
|
1173
|
+
const installed2 = [];
|
|
1174
|
+
const skipped2 = [];
|
|
1175
|
+
try {
|
|
1176
|
+
ensureDir(target.dir);
|
|
1177
|
+
for (const entry of entries) {
|
|
1178
|
+
if (!entry.isDirectory()) continue;
|
|
1179
|
+
const skillName = entry.name;
|
|
1180
|
+
const sourcePath = path4.join(sourceDir, skillName);
|
|
1181
|
+
const targetPath = path4.join(target.dir, skillName);
|
|
1182
|
+
if (fs6.existsSync(targetPath)) {
|
|
1183
|
+
skipped2.push(skillName);
|
|
1184
|
+
continue;
|
|
1185
|
+
}
|
|
1186
|
+
fs6.cpSync(sourcePath, targetPath, { recursive: true });
|
|
1187
|
+
installed2.push(skillName);
|
|
1188
|
+
}
|
|
1189
|
+
targetResults.push({
|
|
1190
|
+
agents: target.agents,
|
|
1191
|
+
targetDir: target.dir,
|
|
1192
|
+
installed: installed2,
|
|
1193
|
+
skipped: skipped2,
|
|
1194
|
+
success: true
|
|
1195
|
+
});
|
|
1196
|
+
} catch (error) {
|
|
1197
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1198
|
+
targetResults.push({
|
|
1199
|
+
agents: target.agents,
|
|
1200
|
+
targetDir: target.dir,
|
|
1201
|
+
installed: installed2,
|
|
1202
|
+
skipped: skipped2,
|
|
1203
|
+
success: false,
|
|
1204
|
+
error: message
|
|
1205
|
+
});
|
|
718
1206
|
}
|
|
719
|
-
fs6.cpSync(sourcePath, targetPath, { recursive: true });
|
|
720
|
-
installed.push(skillName);
|
|
721
1207
|
}
|
|
722
|
-
const
|
|
1208
|
+
const installed = targetResults.flatMap((result) => result.installed);
|
|
1209
|
+
const skipped = targetResults.flatMap((result) => result.skipped);
|
|
1210
|
+
const failures = targetResults.filter((result) => !result.success);
|
|
1211
|
+
const failedSummary = failures.length > 0 ? `, ${failures.length} failed` : "";
|
|
1212
|
+
const summary = `Skills ${mode} install: ${installed.length} installed${skipped.length ? `, ${skipped.length} skipped` : ""}${failedSummary} across ${targetResults.length} targets`;
|
|
723
1213
|
return {
|
|
724
|
-
success:
|
|
1214
|
+
success: failures.length === 0,
|
|
725
1215
|
message: summary,
|
|
726
|
-
|
|
1216
|
+
mode,
|
|
1217
|
+
targets: targetResults,
|
|
727
1218
|
installed,
|
|
728
1219
|
skipped
|
|
729
1220
|
};
|
|
@@ -732,9 +1223,10 @@ function installSkills(mode) {
|
|
|
732
1223
|
return {
|
|
733
1224
|
success: false,
|
|
734
1225
|
message: `Failed to install skills (${mode}): ${message}`,
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
1226
|
+
mode,
|
|
1227
|
+
targets: targetResults,
|
|
1228
|
+
installed: targetResults.flatMap((result) => result.installed),
|
|
1229
|
+
skipped: targetResults.flatMap((result) => result.skipped)
|
|
738
1230
|
};
|
|
739
1231
|
}
|
|
740
1232
|
}
|
|
@@ -866,6 +1358,9 @@ function findInstalledConfigs() {
|
|
|
866
1358
|
return { global, local };
|
|
867
1359
|
}
|
|
868
1360
|
|
|
1361
|
+
// src/cli/commands/serve.ts
|
|
1362
|
+
import { spawnSync } from "child_process";
|
|
1363
|
+
|
|
869
1364
|
// src/cli/utils/parse.ts
|
|
870
1365
|
function parseNumberFlag(value, flag, options = {}) {
|
|
871
1366
|
const parsed = Number(value);
|
|
@@ -1175,7 +1670,7 @@ function discoverExtensionId() {
|
|
|
1175
1670
|
return { extensionId: match.id, matchedBy: match.matchedBy };
|
|
1176
1671
|
}
|
|
1177
1672
|
if (!nameFallback) {
|
|
1178
|
-
nameFallback = match;
|
|
1673
|
+
nameFallback = { id: match.id, matchedBy: "name" };
|
|
1179
1674
|
}
|
|
1180
1675
|
}
|
|
1181
1676
|
if (!commandFallback) {
|
|
@@ -1259,6 +1754,19 @@ async function runNativeCommand(args) {
|
|
|
1259
1754
|
|
|
1260
1755
|
// src/cli/commands/serve.ts
|
|
1261
1756
|
var daemonHandle = null;
|
|
1757
|
+
var PS_MAX_BUFFER = 8 * 1024 * 1024;
|
|
1758
|
+
function resolveTokenCandidates(requestedToken, metadataToken, configToken) {
|
|
1759
|
+
return Array.from(new Set([requestedToken, metadataToken, configToken].filter((token) => typeof token === "string" && token.trim().length > 0)));
|
|
1760
|
+
}
|
|
1761
|
+
async function resolveExistingDaemon(port, tokens) {
|
|
1762
|
+
for (const token of tokens) {
|
|
1763
|
+
const status = await fetchDaemonStatus(port, token);
|
|
1764
|
+
if (status?.ok) {
|
|
1765
|
+
return { token, status };
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
return null;
|
|
1769
|
+
}
|
|
1262
1770
|
function parseServeArgs(rawArgs) {
|
|
1263
1771
|
const parsed = { stop: false };
|
|
1264
1772
|
for (let i = 0; i < rawArgs.length; i += 1) {
|
|
@@ -1304,11 +1812,64 @@ function parseServeArgs(rawArgs) {
|
|
|
1304
1812
|
}
|
|
1305
1813
|
return parsed;
|
|
1306
1814
|
}
|
|
1815
|
+
function listServeProcessPids() {
|
|
1816
|
+
const result = spawnSync("ps", ["-ax", "-o", "pid=,command="], {
|
|
1817
|
+
encoding: "utf-8",
|
|
1818
|
+
maxBuffer: PS_MAX_BUFFER
|
|
1819
|
+
});
|
|
1820
|
+
if ((result.status ?? 1) !== 0) {
|
|
1821
|
+
return [];
|
|
1822
|
+
}
|
|
1823
|
+
const servePattern = /\b(opendevbrowser|dist\/cli\/index\.js)\b.*\bserve\b/;
|
|
1824
|
+
const lines = String(result.stdout ?? "").split(/\r?\n/);
|
|
1825
|
+
const pids = /* @__PURE__ */ new Set();
|
|
1826
|
+
for (const line of lines) {
|
|
1827
|
+
const trimmed = line.trim();
|
|
1828
|
+
if (!trimmed) continue;
|
|
1829
|
+
const match = trimmed.match(/^(\d+)\s+(.+)$/);
|
|
1830
|
+
if (!match) continue;
|
|
1831
|
+
const pidText = match[1];
|
|
1832
|
+
if (!pidText) continue;
|
|
1833
|
+
const pid = Number.parseInt(pidText, 10);
|
|
1834
|
+
const command = match[2] ?? "";
|
|
1835
|
+
if (!Number.isInteger(pid) || pid <= 0) continue;
|
|
1836
|
+
if (pid === process.pid || pid === process.ppid) continue;
|
|
1837
|
+
if (!servePattern.test(command)) continue;
|
|
1838
|
+
pids.add(pid);
|
|
1839
|
+
}
|
|
1840
|
+
return [...pids];
|
|
1841
|
+
}
|
|
1842
|
+
function terminateProcess(pid) {
|
|
1843
|
+
if (!Number.isInteger(pid) || pid <= 0 || pid === process.pid || pid === process.ppid) {
|
|
1844
|
+
return false;
|
|
1845
|
+
}
|
|
1846
|
+
try {
|
|
1847
|
+
process.kill(pid, "SIGTERM");
|
|
1848
|
+
} catch {
|
|
1849
|
+
return false;
|
|
1850
|
+
}
|
|
1851
|
+
try {
|
|
1852
|
+
process.kill(pid, "SIGKILL");
|
|
1853
|
+
} catch {
|
|
1854
|
+
}
|
|
1855
|
+
return true;
|
|
1856
|
+
}
|
|
1857
|
+
function cleanupStaleServeProcesses(keepPid) {
|
|
1858
|
+
const candidates = listServeProcessPids();
|
|
1859
|
+
let cleaned = 0;
|
|
1860
|
+
for (const pid of candidates) {
|
|
1861
|
+
if (Number.isInteger(keepPid) && pid === keepPid) continue;
|
|
1862
|
+
if (terminateProcess(pid)) {
|
|
1863
|
+
cleaned += 1;
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
return cleaned;
|
|
1867
|
+
}
|
|
1307
1868
|
async function runServe(args) {
|
|
1308
1869
|
const serveArgs = parseServeArgs(args.rawArgs);
|
|
1309
1870
|
if (serveArgs.stop) {
|
|
1310
|
-
const
|
|
1311
|
-
if (!
|
|
1871
|
+
const metadata2 = readDaemonMetadata();
|
|
1872
|
+
if (!metadata2) {
|
|
1312
1873
|
if (daemonHandle) {
|
|
1313
1874
|
await daemonHandle.stop();
|
|
1314
1875
|
daemonHandle = null;
|
|
@@ -1317,9 +1878,9 @@ async function runServe(args) {
|
|
|
1317
1878
|
return { success: false, message: "Daemon not running.", exitCode: EXIT_DISCONNECTED };
|
|
1318
1879
|
}
|
|
1319
1880
|
try {
|
|
1320
|
-
const response = await fetchWithTimeout(`http://127.0.0.1:${
|
|
1881
|
+
const response = await fetchWithTimeout(`http://127.0.0.1:${metadata2.port}/stop`, {
|
|
1321
1882
|
method: "POST",
|
|
1322
|
-
headers: { Authorization: `Bearer ${
|
|
1883
|
+
headers: { Authorization: `Bearer ${metadata2.token}` }
|
|
1323
1884
|
});
|
|
1324
1885
|
if (!response.ok) {
|
|
1325
1886
|
throw new Error(`Stop failed (${response.status})`);
|
|
@@ -1331,6 +1892,29 @@ async function runServe(args) {
|
|
|
1331
1892
|
}
|
|
1332
1893
|
}
|
|
1333
1894
|
const config = loadGlobalConfig();
|
|
1895
|
+
const requestedPort = serveArgs.port ?? config.daemonPort;
|
|
1896
|
+
const metadata = readDaemonMetadata();
|
|
1897
|
+
const metadataToken = metadata?.port === requestedPort ? metadata.token : void 0;
|
|
1898
|
+
const tokenCandidates = resolveTokenCandidates(serveArgs.token, metadataToken, config.daemonToken);
|
|
1899
|
+
const existingDaemon = await resolveExistingDaemon(requestedPort, tokenCandidates);
|
|
1900
|
+
const staleCleared = cleanupStaleServeProcesses(existingDaemon?.status.pid);
|
|
1901
|
+
if (existingDaemon) {
|
|
1902
|
+
const relayPort = existingDaemon.status.relay.port ?? config.relayPort;
|
|
1903
|
+
const staleNote2 = staleCleared > 0 ? ` Cleared ${staleCleared} stale daemon process${staleCleared === 1 ? "" : "es"}.` : "";
|
|
1904
|
+
return {
|
|
1905
|
+
success: true,
|
|
1906
|
+
message: `Daemon already running on 127.0.0.1:${requestedPort} (pid=${existingDaemon.status.pid}, relay ${relayPort}).${staleNote2}`,
|
|
1907
|
+
data: {
|
|
1908
|
+
port: requestedPort,
|
|
1909
|
+
pid: existingDaemon.status.pid,
|
|
1910
|
+
relayPort,
|
|
1911
|
+
alreadyRunning: true,
|
|
1912
|
+
staleDaemonsCleared: staleCleared,
|
|
1913
|
+
relay: existingDaemon.status.relay
|
|
1914
|
+
},
|
|
1915
|
+
exitCode: null
|
|
1916
|
+
};
|
|
1917
|
+
}
|
|
1334
1918
|
let nativeStatus = getNativeStatusSnapshot();
|
|
1335
1919
|
let nativeMessage = null;
|
|
1336
1920
|
if (!nativeStatus.installed) {
|
|
@@ -1350,20 +1934,55 @@ async function runServe(args) {
|
|
|
1350
1934
|
nativeMessage = "Native host not installed. Set nativeExtensionId in opendevbrowser.jsonc to auto-install.";
|
|
1351
1935
|
}
|
|
1352
1936
|
}
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1937
|
+
let handle;
|
|
1938
|
+
try {
|
|
1939
|
+
handle = await startDaemon({
|
|
1940
|
+
port: serveArgs.port,
|
|
1941
|
+
token: serveArgs.token,
|
|
1942
|
+
config
|
|
1943
|
+
});
|
|
1944
|
+
} catch (error) {
|
|
1945
|
+
const message2 = error instanceof Error ? error.message : String(error);
|
|
1946
|
+
if (message2.includes("EADDRINUSE") || message2.includes("in use")) {
|
|
1947
|
+
const runningDaemon = await resolveExistingDaemon(requestedPort, tokenCandidates);
|
|
1948
|
+
if (runningDaemon) {
|
|
1949
|
+
const relayPort = runningDaemon.status.relay.port ?? config.relayPort;
|
|
1950
|
+
return {
|
|
1951
|
+
success: true,
|
|
1952
|
+
message: `Daemon already running on 127.0.0.1:${requestedPort} (pid=${runningDaemon.status.pid}, relay ${relayPort}).`,
|
|
1953
|
+
data: {
|
|
1954
|
+
port: requestedPort,
|
|
1955
|
+
pid: runningDaemon.status.pid,
|
|
1956
|
+
relayPort,
|
|
1957
|
+
alreadyRunning: true,
|
|
1958
|
+
relay: runningDaemon.status.relay
|
|
1959
|
+
},
|
|
1960
|
+
exitCode: null
|
|
1961
|
+
};
|
|
1962
|
+
}
|
|
1963
|
+
return {
|
|
1964
|
+
success: false,
|
|
1965
|
+
message: `Daemon port ${requestedPort} is already in use by another process. If this is an existing daemon, run \`opendevbrowser status --daemon\` or \`opendevbrowser serve --stop\`.`,
|
|
1966
|
+
exitCode: EXIT_EXECUTION
|
|
1967
|
+
};
|
|
1968
|
+
}
|
|
1969
|
+
return {
|
|
1970
|
+
success: false,
|
|
1971
|
+
message: `Failed to start daemon: ${message2}`,
|
|
1972
|
+
exitCode: EXIT_EXECUTION
|
|
1973
|
+
};
|
|
1974
|
+
}
|
|
1358
1975
|
daemonHandle = handle;
|
|
1359
1976
|
const { state } = handle;
|
|
1360
1977
|
const baseMessage = `Daemon running on 127.0.0.1:${state.port} (relay ${state.relayPort})`;
|
|
1978
|
+
const staleNote = staleCleared > 0 ? `
|
|
1979
|
+
Cleared ${staleCleared} stale daemon process${staleCleared === 1 ? "" : "es"}.` : "";
|
|
1361
1980
|
const message = nativeMessage ? `${baseMessage}
|
|
1362
|
-
${nativeMessage}` : baseMessage
|
|
1981
|
+
${nativeMessage}${staleNote}` : `${baseMessage}${staleNote}`;
|
|
1363
1982
|
return {
|
|
1364
1983
|
success: true,
|
|
1365
1984
|
message,
|
|
1366
|
-
data: { port: state.port, pid: state.pid, relayPort: state.relayPort, native: nativeStatus },
|
|
1985
|
+
data: { port: state.port, pid: state.pid, relayPort: state.relayPort, native: nativeStatus, staleDaemonsCleared: staleCleared },
|
|
1367
1986
|
exitCode: null
|
|
1368
1987
|
};
|
|
1369
1988
|
}
|
|
@@ -1372,7 +1991,7 @@ ${nativeMessage}` : baseMessage;
|
|
|
1372
1991
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
1373
1992
|
import { existsSync as existsSync8, mkdirSync as mkdirSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync4 } from "fs";
|
|
1374
1993
|
import { homedir as homedir7 } from "os";
|
|
1375
|
-
import { dirname as dirname5, join as join8, resolve as
|
|
1994
|
+
import { dirname as dirname5, join as join8, resolve as resolve4 } from "path";
|
|
1376
1995
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
1377
1996
|
var MAC_LABEL = "com.opendevbrowser.daemon";
|
|
1378
1997
|
var WIN_TASK_NAME = "OpenDevBrowser Daemon";
|
|
@@ -1390,7 +2009,7 @@ var defaultDeps = () => ({
|
|
|
1390
2009
|
});
|
|
1391
2010
|
var resolveCliPathFromModule = (moduleUrl, exists) => {
|
|
1392
2011
|
const modulePath = fileURLToPath3(moduleUrl);
|
|
1393
|
-
const candidate =
|
|
2012
|
+
const candidate = resolve4(dirname5(modulePath), "..", "index.js");
|
|
1394
2013
|
if (!exists(candidate)) {
|
|
1395
2014
|
throw new Error(`CLI entrypoint not found at ${candidate}`);
|
|
1396
2015
|
}
|
|
@@ -1401,7 +2020,7 @@ var resolveCliEntrypoint = (deps = {}) => {
|
|
|
1401
2020
|
const exists = resolved.existsSync;
|
|
1402
2021
|
let cliPath = null;
|
|
1403
2022
|
if (resolved.argv1) {
|
|
1404
|
-
const candidate =
|
|
2023
|
+
const candidate = resolve4(resolved.argv1);
|
|
1405
2024
|
if (exists(candidate)) {
|
|
1406
2025
|
cliPath = candidate;
|
|
1407
2026
|
}
|
|
@@ -1687,6 +2306,75 @@ async function runDaemonCommand(args) {
|
|
|
1687
2306
|
};
|
|
1688
2307
|
}
|
|
1689
2308
|
|
|
2309
|
+
// src/cli/commands/artifacts.ts
|
|
2310
|
+
import { join as join9, resolve as resolve5 } from "path";
|
|
2311
|
+
import { tmpdir } from "os";
|
|
2312
|
+
var usageError = () => {
|
|
2313
|
+
throw createUsageError("Usage: opendevbrowser artifacts cleanup --expired-only [--output-dir <path>]");
|
|
2314
|
+
};
|
|
2315
|
+
var requireValue = (rawArgs, index, flag) => {
|
|
2316
|
+
const value = rawArgs[index + 1];
|
|
2317
|
+
if (!value) {
|
|
2318
|
+
throw createUsageError(`Missing value for ${flag}`);
|
|
2319
|
+
}
|
|
2320
|
+
return value;
|
|
2321
|
+
};
|
|
2322
|
+
var parseArtifactsArgs = (rawArgs) => {
|
|
2323
|
+
const [candidate, ...rest] = rawArgs;
|
|
2324
|
+
if (candidate !== "cleanup") {
|
|
2325
|
+
usageError();
|
|
2326
|
+
}
|
|
2327
|
+
const subcommand = "cleanup";
|
|
2328
|
+
let expiredOnly = false;
|
|
2329
|
+
let outputDir;
|
|
2330
|
+
for (let index = 0; index < rest.length; index += 1) {
|
|
2331
|
+
const arg = rest[index];
|
|
2332
|
+
if (arg === "--expired-only") {
|
|
2333
|
+
expiredOnly = true;
|
|
2334
|
+
continue;
|
|
2335
|
+
}
|
|
2336
|
+
if (arg === "--output-dir") {
|
|
2337
|
+
outputDir = requireValue(rest, index, "--output-dir");
|
|
2338
|
+
index += 1;
|
|
2339
|
+
continue;
|
|
2340
|
+
}
|
|
2341
|
+
if (arg?.startsWith("--output-dir=")) {
|
|
2342
|
+
const value = arg.split("=", 2)[1];
|
|
2343
|
+
if (!value) {
|
|
2344
|
+
throw createUsageError("Missing value for --output-dir");
|
|
2345
|
+
}
|
|
2346
|
+
outputDir = value;
|
|
2347
|
+
continue;
|
|
2348
|
+
}
|
|
2349
|
+
throw createUsageError(`Unknown artifacts flag: ${arg}`);
|
|
2350
|
+
}
|
|
2351
|
+
if (!expiredOnly) {
|
|
2352
|
+
usageError();
|
|
2353
|
+
}
|
|
2354
|
+
return {
|
|
2355
|
+
subcommand,
|
|
2356
|
+
expiredOnly,
|
|
2357
|
+
outputDir
|
|
2358
|
+
};
|
|
2359
|
+
};
|
|
2360
|
+
async function runArtifactsCommand(args) {
|
|
2361
|
+
const parsed = parseArtifactsArgs(args.rawArgs);
|
|
2362
|
+
const rootDir = parsed.outputDir ? resolve5(parsed.outputDir) : join9(tmpdir(), "opendevbrowser");
|
|
2363
|
+
const cleaned = await cleanupExpiredArtifacts(rootDir);
|
|
2364
|
+
return {
|
|
2365
|
+
success: true,
|
|
2366
|
+
message: `Artifact cleanup completed. Removed ${cleaned.removed.length} expired run(s).`,
|
|
2367
|
+
data: {
|
|
2368
|
+
rootDir,
|
|
2369
|
+
expiredOnly: parsed.expiredOnly,
|
|
2370
|
+
removed: cleaned.removed,
|
|
2371
|
+
skipped: cleaned.skipped,
|
|
2372
|
+
removedCount: cleaned.removed.length,
|
|
2373
|
+
skippedCount: cleaned.skipped.length
|
|
2374
|
+
}
|
|
2375
|
+
};
|
|
2376
|
+
}
|
|
2377
|
+
|
|
1690
2378
|
// src/cli/commands/run.ts
|
|
1691
2379
|
import { readFileSync as readFileSync4 } from "fs";
|
|
1692
2380
|
|
|
@@ -1790,13 +2478,13 @@ function parseRunArgs(rawArgs) {
|
|
|
1790
2478
|
return parsed;
|
|
1791
2479
|
}
|
|
1792
2480
|
function readScriptFromStdin() {
|
|
1793
|
-
return new Promise((
|
|
2481
|
+
return new Promise((resolve6, reject) => {
|
|
1794
2482
|
let data = "";
|
|
1795
2483
|
process.stdin.setEncoding("utf8");
|
|
1796
2484
|
process.stdin.on("data", (chunk) => {
|
|
1797
2485
|
data += chunk;
|
|
1798
2486
|
});
|
|
1799
|
-
process.stdin.on("end", () =>
|
|
2487
|
+
process.stdin.on("end", () => resolve6(data));
|
|
1800
2488
|
process.stdin.on("error", reject);
|
|
1801
2489
|
});
|
|
1802
2490
|
}
|
|
@@ -1851,6 +2539,14 @@ async function runScriptCommand(args) {
|
|
|
1851
2539
|
}
|
|
1852
2540
|
|
|
1853
2541
|
// src/cli/commands/session/launch.ts
|
|
2542
|
+
var MIN_LAUNCH_CALL_TIMEOUT_MS = 3e4;
|
|
2543
|
+
var LAUNCH_CALL_TIMEOUT_BUFFER_MS = 5e3;
|
|
2544
|
+
var parseBooleanFlag = (value, flag) => {
|
|
2545
|
+
const normalized = value.trim().toLowerCase();
|
|
2546
|
+
if (normalized === "true" || normalized === "1") return true;
|
|
2547
|
+
if (normalized === "false" || normalized === "0") return false;
|
|
2548
|
+
throw createUsageError(`Invalid ${flag}: ${value}`);
|
|
2549
|
+
};
|
|
1854
2550
|
function parseLaunchArgs(rawArgs) {
|
|
1855
2551
|
const parsed = { flags: [] };
|
|
1856
2552
|
for (let i = 0; i < rawArgs.length; i += 1) {
|
|
@@ -1893,7 +2589,19 @@ function parseLaunchArgs(rawArgs) {
|
|
|
1893
2589
|
continue;
|
|
1894
2590
|
}
|
|
1895
2591
|
if (arg === "--persist-profile") {
|
|
1896
|
-
|
|
2592
|
+
const value = rawArgs[i + 1];
|
|
2593
|
+
if (value && !value.startsWith("--")) {
|
|
2594
|
+
parsed.persistProfile = parseBooleanFlag(value, "--persist-profile");
|
|
2595
|
+
i += 1;
|
|
2596
|
+
} else {
|
|
2597
|
+
parsed.persistProfile = true;
|
|
2598
|
+
}
|
|
2599
|
+
continue;
|
|
2600
|
+
}
|
|
2601
|
+
if (arg?.startsWith("--persist-profile=")) {
|
|
2602
|
+
const value = arg.split("=", 2)[1];
|
|
2603
|
+
if (!value) throw createUsageError("Missing value for --persist-profile");
|
|
2604
|
+
parsed.persistProfile = parseBooleanFlag(value, "--persist-profile");
|
|
1897
2605
|
continue;
|
|
1898
2606
|
}
|
|
1899
2607
|
if (arg === "--no-extension") {
|
|
@@ -1941,10 +2649,15 @@ function parseLaunchArgs(rawArgs) {
|
|
|
1941
2649
|
}
|
|
1942
2650
|
return parsed;
|
|
1943
2651
|
}
|
|
2652
|
+
function deriveLaunchCallTimeoutMs(launchArgs) {
|
|
2653
|
+
const waitHintMs = typeof launchArgs.waitTimeoutMs === "number" ? launchArgs.waitTimeoutMs + LAUNCH_CALL_TIMEOUT_BUFFER_MS : 0;
|
|
2654
|
+
return Math.max(MIN_LAUNCH_CALL_TIMEOUT_MS, waitHintMs);
|
|
2655
|
+
}
|
|
1944
2656
|
async function runSessionLaunch(args) {
|
|
1945
2657
|
const launchArgs = parseLaunchArgs(args.rawArgs);
|
|
2658
|
+
const launchCallTimeoutMs = deriveLaunchCallTimeoutMs(launchArgs);
|
|
1946
2659
|
try {
|
|
1947
|
-
const result = await callDaemon("session.launch", launchArgs);
|
|
2660
|
+
const result = await callDaemon("session.launch", launchArgs, { timeoutMs: launchCallTimeoutMs });
|
|
1948
2661
|
return {
|
|
1949
2662
|
success: true,
|
|
1950
2663
|
message: `Session launched: ${result.sessionId}`,
|
|
@@ -1966,7 +2679,8 @@ async function runSessionLaunch(args) {
|
|
|
1966
2679
|
);
|
|
1967
2680
|
if (retry) {
|
|
1968
2681
|
try {
|
|
1969
|
-
const
|
|
2682
|
+
const retryArgs = { ...launchArgs, waitForExtension: true };
|
|
2683
|
+
const result = await callDaemon("session.launch", retryArgs, { timeoutMs: deriveLaunchCallTimeoutMs(retryArgs) });
|
|
1970
2684
|
return {
|
|
1971
2685
|
success: true,
|
|
1972
2686
|
message: `Session launched: ${result.sessionId}`,
|
|
@@ -1979,11 +2693,12 @@ async function runSessionLaunch(args) {
|
|
|
1979
2693
|
const proceedManaged = await promptYesNo("Proceed with a managed session (headed)?", false);
|
|
1980
2694
|
if (proceedManaged) {
|
|
1981
2695
|
const useHeadless = await promptYesNo("Run headless instead?", false);
|
|
1982
|
-
const
|
|
2696
|
+
const managedArgs = {
|
|
1983
2697
|
...launchArgs,
|
|
1984
2698
|
noExtension: true,
|
|
1985
2699
|
headless: useHeadless ? true : false
|
|
1986
|
-
}
|
|
2700
|
+
};
|
|
2701
|
+
const result = await callDaemon("session.launch", managedArgs, { timeoutMs: deriveLaunchCallTimeoutMs(managedArgs) });
|
|
1987
2702
|
return {
|
|
1988
2703
|
success: true,
|
|
1989
2704
|
message: `Session launched: ${result.sessionId}`,
|
|
@@ -2007,16 +2722,16 @@ function promptYesNo(question, defaultYes) {
|
|
|
2007
2722
|
return Promise.resolve(false);
|
|
2008
2723
|
}
|
|
2009
2724
|
const suffix = defaultYes ? " [Y/n] " : " [y/N] ";
|
|
2010
|
-
return new Promise((
|
|
2725
|
+
return new Promise((resolve6) => {
|
|
2011
2726
|
process.stdout.write(`${question}${suffix}`);
|
|
2012
2727
|
process.stdin.setEncoding("utf8");
|
|
2013
2728
|
process.stdin.once("data", (data) => {
|
|
2014
2729
|
const input = data.toString().trim().toLowerCase();
|
|
2015
2730
|
if (!input) {
|
|
2016
|
-
|
|
2731
|
+
resolve6(defaultYes);
|
|
2017
2732
|
return;
|
|
2018
2733
|
}
|
|
2019
|
-
|
|
2734
|
+
resolve6(input === "y" || input === "yes");
|
|
2020
2735
|
});
|
|
2021
2736
|
});
|
|
2022
2737
|
}
|
|
@@ -2067,6 +2782,10 @@ function parseConnectArgs(rawArgs) {
|
|
|
2067
2782
|
parsed.extensionLegacy = true;
|
|
2068
2783
|
continue;
|
|
2069
2784
|
}
|
|
2785
|
+
if (arg === "--headless") {
|
|
2786
|
+
parsed.headless = true;
|
|
2787
|
+
continue;
|
|
2788
|
+
}
|
|
2070
2789
|
}
|
|
2071
2790
|
return parsed;
|
|
2072
2791
|
}
|
|
@@ -2404,7 +3123,7 @@ async function runSnapshot(args) {
|
|
|
2404
3123
|
}
|
|
2405
3124
|
|
|
2406
3125
|
// src/cli/commands/annotate.ts
|
|
2407
|
-
var
|
|
3126
|
+
var requireValue2 = (value, flag) => {
|
|
2408
3127
|
if (!value) throw createUsageError(`Missing value for ${flag}`);
|
|
2409
3128
|
return value;
|
|
2410
3129
|
};
|
|
@@ -2425,68 +3144,68 @@ var parseAnnotateArgs = (rawArgs) => {
|
|
|
2425
3144
|
for (let i = 0; i < rawArgs.length; i += 1) {
|
|
2426
3145
|
const arg = rawArgs[i];
|
|
2427
3146
|
if (arg === "--session-id") {
|
|
2428
|
-
const value =
|
|
3147
|
+
const value = requireValue2(rawArgs[i + 1], "--session-id");
|
|
2429
3148
|
parsed.sessionId = value;
|
|
2430
3149
|
i += 1;
|
|
2431
3150
|
continue;
|
|
2432
3151
|
}
|
|
2433
3152
|
if (arg?.startsWith("--session-id=")) {
|
|
2434
|
-
const value =
|
|
3153
|
+
const value = requireValue2(arg.split("=", 2)[1], "--session-id");
|
|
2435
3154
|
parsed.sessionId = value;
|
|
2436
3155
|
continue;
|
|
2437
3156
|
}
|
|
2438
3157
|
if (arg === "--url") {
|
|
2439
|
-
const value =
|
|
3158
|
+
const value = requireValue2(rawArgs[i + 1], "--url");
|
|
2440
3159
|
parsed.url = value;
|
|
2441
3160
|
i += 1;
|
|
2442
3161
|
continue;
|
|
2443
3162
|
}
|
|
2444
3163
|
if (arg?.startsWith("--url=")) {
|
|
2445
|
-
const value =
|
|
3164
|
+
const value = requireValue2(arg.split("=", 2)[1], "--url");
|
|
2446
3165
|
parsed.url = value;
|
|
2447
3166
|
continue;
|
|
2448
3167
|
}
|
|
2449
3168
|
if (arg === "--screenshot-mode") {
|
|
2450
|
-
const value =
|
|
3169
|
+
const value = requireValue2(rawArgs[i + 1], "--screenshot-mode");
|
|
2451
3170
|
parsed.screenshotMode = requireScreenshotMode(value);
|
|
2452
3171
|
i += 1;
|
|
2453
3172
|
continue;
|
|
2454
3173
|
}
|
|
2455
3174
|
if (arg?.startsWith("--screenshot-mode=")) {
|
|
2456
|
-
const value =
|
|
3175
|
+
const value = requireValue2(arg.split("=", 2)[1], "--screenshot-mode");
|
|
2457
3176
|
parsed.screenshotMode = requireScreenshotMode(value);
|
|
2458
3177
|
continue;
|
|
2459
3178
|
}
|
|
2460
3179
|
if (arg === "--transport") {
|
|
2461
|
-
const value =
|
|
3180
|
+
const value = requireValue2(rawArgs[i + 1], "--transport");
|
|
2462
3181
|
parsed.transport = requireTransport(value);
|
|
2463
3182
|
i += 1;
|
|
2464
3183
|
continue;
|
|
2465
3184
|
}
|
|
2466
3185
|
if (arg?.startsWith("--transport=")) {
|
|
2467
|
-
const value =
|
|
3186
|
+
const value = requireValue2(arg.split("=", 2)[1], "--transport");
|
|
2468
3187
|
parsed.transport = requireTransport(value);
|
|
2469
3188
|
continue;
|
|
2470
3189
|
}
|
|
2471
3190
|
if (arg === "--target-id") {
|
|
2472
|
-
const value =
|
|
3191
|
+
const value = requireValue2(rawArgs[i + 1], "--target-id");
|
|
2473
3192
|
parsed.targetId = value;
|
|
2474
3193
|
i += 1;
|
|
2475
3194
|
continue;
|
|
2476
3195
|
}
|
|
2477
3196
|
if (arg?.startsWith("--target-id=")) {
|
|
2478
|
-
const value =
|
|
3197
|
+
const value = requireValue2(arg.split("=", 2)[1], "--target-id");
|
|
2479
3198
|
parsed.targetId = value;
|
|
2480
3199
|
continue;
|
|
2481
3200
|
}
|
|
2482
3201
|
if (arg === "--tab-id") {
|
|
2483
|
-
const value =
|
|
3202
|
+
const value = requireValue2(rawArgs[i + 1], "--tab-id");
|
|
2484
3203
|
parsed.tabId = parseNumberFlag(value, "--tab-id", { min: 1 });
|
|
2485
3204
|
i += 1;
|
|
2486
3205
|
continue;
|
|
2487
3206
|
}
|
|
2488
3207
|
if (arg?.startsWith("--tab-id=")) {
|
|
2489
|
-
const value =
|
|
3208
|
+
const value = requireValue2(arg.split("=", 2)[1], "--tab-id");
|
|
2490
3209
|
parsed.tabId = parseNumberFlag(value, "--tab-id", { min: 1 });
|
|
2491
3210
|
continue;
|
|
2492
3211
|
}
|
|
@@ -2495,24 +3214,24 @@ var parseAnnotateArgs = (rawArgs) => {
|
|
|
2495
3214
|
continue;
|
|
2496
3215
|
}
|
|
2497
3216
|
if (arg === "--context") {
|
|
2498
|
-
const value =
|
|
3217
|
+
const value = requireValue2(rawArgs[i + 1], "--context");
|
|
2499
3218
|
parsed.context = value;
|
|
2500
3219
|
i += 1;
|
|
2501
3220
|
continue;
|
|
2502
3221
|
}
|
|
2503
3222
|
if (arg?.startsWith("--context=")) {
|
|
2504
|
-
const value =
|
|
3223
|
+
const value = requireValue2(arg.split("=", 2)[1], "--context");
|
|
2505
3224
|
parsed.context = value;
|
|
2506
3225
|
continue;
|
|
2507
3226
|
}
|
|
2508
3227
|
if (arg === "--timeout-ms") {
|
|
2509
|
-
const value =
|
|
3228
|
+
const value = requireValue2(rawArgs[i + 1], "--timeout-ms");
|
|
2510
3229
|
parsed.timeoutMs = parseNumberFlag(value, "--timeout-ms", { min: 1 });
|
|
2511
3230
|
i += 1;
|
|
2512
3231
|
continue;
|
|
2513
3232
|
}
|
|
2514
3233
|
if (arg?.startsWith("--timeout-ms=")) {
|
|
2515
|
-
const value =
|
|
3234
|
+
const value = requireValue2(arg.split("=", 2)[1], "--timeout-ms");
|
|
2516
3235
|
parsed.timeoutMs = parseNumberFlag(value, "--timeout-ms", { min: 1 });
|
|
2517
3236
|
continue;
|
|
2518
3237
|
}
|
|
@@ -2548,6 +3267,131 @@ async function runAnnotate(args) {
|
|
|
2548
3267
|
}
|
|
2549
3268
|
}
|
|
2550
3269
|
|
|
3270
|
+
// src/cli/commands/rpc.ts
|
|
3271
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
3272
|
+
var requireValue3 = (value, flag) => {
|
|
3273
|
+
if (!value) throw createUsageError(`Missing value for ${flag}`);
|
|
3274
|
+
return value;
|
|
3275
|
+
};
|
|
3276
|
+
var parseJsonObject = (raw, source) => {
|
|
3277
|
+
let parsed;
|
|
3278
|
+
try {
|
|
3279
|
+
parsed = JSON.parse(raw);
|
|
3280
|
+
} catch (error) {
|
|
3281
|
+
const message = error instanceof Error ? error.message : "Invalid JSON";
|
|
3282
|
+
throw createUsageError(`Invalid JSON from ${source}: ${message}`);
|
|
3283
|
+
}
|
|
3284
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
3285
|
+
throw createUsageError(`Invalid JSON from ${source}: expected object`);
|
|
3286
|
+
}
|
|
3287
|
+
return parsed;
|
|
3288
|
+
};
|
|
3289
|
+
var parseRpcArgs = (rawArgs) => {
|
|
3290
|
+
const parsed = {};
|
|
3291
|
+
for (let i = 0; i < rawArgs.length; i += 1) {
|
|
3292
|
+
const arg = rawArgs[i];
|
|
3293
|
+
if (arg === "--unsafe-internal") {
|
|
3294
|
+
parsed.unsafeInternal = true;
|
|
3295
|
+
continue;
|
|
3296
|
+
}
|
|
3297
|
+
if (arg === "--name") {
|
|
3298
|
+
parsed.name = requireValue3(rawArgs[i + 1], "--name");
|
|
3299
|
+
i += 1;
|
|
3300
|
+
continue;
|
|
3301
|
+
}
|
|
3302
|
+
if (arg?.startsWith("--name=")) {
|
|
3303
|
+
parsed.name = requireValue3(arg.split("=", 2)[1], "--name");
|
|
3304
|
+
continue;
|
|
3305
|
+
}
|
|
3306
|
+
if (arg === "--params") {
|
|
3307
|
+
parsed.params = requireValue3(rawArgs[i + 1], "--params");
|
|
3308
|
+
i += 1;
|
|
3309
|
+
continue;
|
|
3310
|
+
}
|
|
3311
|
+
if (arg?.startsWith("--params=")) {
|
|
3312
|
+
parsed.params = requireValue3(arg.split("=", 2)[1], "--params");
|
|
3313
|
+
continue;
|
|
3314
|
+
}
|
|
3315
|
+
if (arg === "--params-file") {
|
|
3316
|
+
parsed.paramsFile = requireValue3(rawArgs[i + 1], "--params-file");
|
|
3317
|
+
i += 1;
|
|
3318
|
+
continue;
|
|
3319
|
+
}
|
|
3320
|
+
if (arg?.startsWith("--params-file=")) {
|
|
3321
|
+
parsed.paramsFile = requireValue3(arg.split("=", 2)[1], "--params-file");
|
|
3322
|
+
continue;
|
|
3323
|
+
}
|
|
3324
|
+
if (arg === "--timeout-ms") {
|
|
3325
|
+
const value = requireValue3(rawArgs[i + 1], "--timeout-ms");
|
|
3326
|
+
parsed.timeoutMs = parseNumberFlag(value, "--timeout-ms", { min: 1 });
|
|
3327
|
+
i += 1;
|
|
3328
|
+
continue;
|
|
3329
|
+
}
|
|
3330
|
+
if (arg?.startsWith("--timeout-ms=")) {
|
|
3331
|
+
const value = requireValue3(arg.split("=", 2)[1], "--timeout-ms");
|
|
3332
|
+
parsed.timeoutMs = parseNumberFlag(value, "--timeout-ms", { min: 1 });
|
|
3333
|
+
continue;
|
|
3334
|
+
}
|
|
3335
|
+
}
|
|
3336
|
+
return parsed;
|
|
3337
|
+
};
|
|
3338
|
+
var resolveRpcParams = (rpcArgs) => {
|
|
3339
|
+
const hasParamsArg = typeof rpcArgs.params === "string";
|
|
3340
|
+
const hasParamsFile = typeof rpcArgs.paramsFile === "string";
|
|
3341
|
+
const inputCount = Number(hasParamsArg) + Number(hasParamsFile);
|
|
3342
|
+
if (inputCount > 1) {
|
|
3343
|
+
throw createUsageError("Provide only one params source: --params or --params-file.");
|
|
3344
|
+
}
|
|
3345
|
+
if (hasParamsArg) {
|
|
3346
|
+
return parseJsonObject(rpcArgs.params ?? "", "--params");
|
|
3347
|
+
}
|
|
3348
|
+
if (hasParamsFile) {
|
|
3349
|
+
let raw = "";
|
|
3350
|
+
try {
|
|
3351
|
+
raw = readFileSync5(rpcArgs.paramsFile ?? "", "utf8");
|
|
3352
|
+
} catch (error) {
|
|
3353
|
+
const message = error instanceof Error ? error.message : "Unable to read file";
|
|
3354
|
+
throw createUsageError(`Invalid --params-file: ${message}`);
|
|
3355
|
+
}
|
|
3356
|
+
if (!raw.trim()) {
|
|
3357
|
+
throw createUsageError("Invalid JSON from --params-file: empty input");
|
|
3358
|
+
}
|
|
3359
|
+
return parseJsonObject(raw, "--params-file");
|
|
3360
|
+
}
|
|
3361
|
+
return {};
|
|
3362
|
+
};
|
|
3363
|
+
async function runRpc(args) {
|
|
3364
|
+
const rpcArgs = parseRpcArgs(args.rawArgs);
|
|
3365
|
+
if (!rpcArgs.unsafeInternal) {
|
|
3366
|
+
throw createUsageError(
|
|
3367
|
+
"Missing --unsafe-internal. rpc is a power-user command that executes internal daemon commands and can mutate session state."
|
|
3368
|
+
);
|
|
3369
|
+
}
|
|
3370
|
+
if (!rpcArgs.name) {
|
|
3371
|
+
throw createUsageError("Missing --name");
|
|
3372
|
+
}
|
|
3373
|
+
const params = resolveRpcParams(rpcArgs);
|
|
3374
|
+
const client = new DaemonClient({ autoRenew: true });
|
|
3375
|
+
try {
|
|
3376
|
+
const result = await client.call(rpcArgs.name, params, { timeoutMs: rpcArgs.timeoutMs });
|
|
3377
|
+
if (args.outputFormat === "text") {
|
|
3378
|
+
const output = typeof result === "string" ? result : JSON.stringify(result, null, 2);
|
|
3379
|
+
return { success: true, message: output };
|
|
3380
|
+
}
|
|
3381
|
+
return {
|
|
3382
|
+
success: true,
|
|
3383
|
+
message: `RPC executed: ${rpcArgs.name}`,
|
|
3384
|
+
data: {
|
|
3385
|
+
name: rpcArgs.name,
|
|
3386
|
+
result
|
|
3387
|
+
}
|
|
3388
|
+
};
|
|
3389
|
+
} finally {
|
|
3390
|
+
await client.releaseBinding().catch(() => {
|
|
3391
|
+
});
|
|
3392
|
+
}
|
|
3393
|
+
}
|
|
3394
|
+
|
|
2551
3395
|
// src/cli/commands/interact/click.ts
|
|
2552
3396
|
function parseClickArgs(rawArgs) {
|
|
2553
3397
|
const parsed = {};
|
|
@@ -3592,39 +4436,49 @@ async function runPerf(args) {
|
|
|
3592
4436
|
}
|
|
3593
4437
|
|
|
3594
4438
|
// src/cli/commands/devtools/screenshot.ts
|
|
4439
|
+
var requireValue4 = (value, flag) => {
|
|
4440
|
+
if (!value) throw createUsageError(`Missing value for ${flag}`);
|
|
4441
|
+
return value;
|
|
4442
|
+
};
|
|
3595
4443
|
function parseScreenshotArgs(rawArgs) {
|
|
3596
4444
|
const parsed = {};
|
|
3597
4445
|
for (let i = 0; i < rawArgs.length; i += 1) {
|
|
3598
4446
|
const arg = rawArgs[i];
|
|
3599
4447
|
if (arg === "--session-id") {
|
|
3600
|
-
|
|
3601
|
-
if (!value) throw createUsageError("Missing value for --session-id");
|
|
3602
|
-
parsed.sessionId = value;
|
|
4448
|
+
parsed.sessionId = requireValue4(rawArgs[i + 1], "--session-id");
|
|
3603
4449
|
i += 1;
|
|
3604
4450
|
continue;
|
|
3605
4451
|
}
|
|
3606
4452
|
if (arg?.startsWith("--session-id=")) {
|
|
3607
|
-
parsed.sessionId = arg.split("=", 2)[1];
|
|
4453
|
+
parsed.sessionId = requireValue4(arg.split("=", 2)[1], "--session-id");
|
|
3608
4454
|
continue;
|
|
3609
4455
|
}
|
|
3610
4456
|
if (arg === "--path") {
|
|
3611
|
-
|
|
3612
|
-
if (!value) throw createUsageError("Missing value for --path");
|
|
3613
|
-
parsed.path = value;
|
|
4457
|
+
parsed.path = requireValue4(rawArgs[i + 1], "--path");
|
|
3614
4458
|
i += 1;
|
|
3615
4459
|
continue;
|
|
3616
4460
|
}
|
|
3617
4461
|
if (arg?.startsWith("--path=")) {
|
|
3618
|
-
parsed.path = arg.split("=", 2)[1];
|
|
4462
|
+
parsed.path = requireValue4(arg.split("=", 2)[1], "--path");
|
|
4463
|
+
continue;
|
|
4464
|
+
}
|
|
4465
|
+
if (arg === "--timeout-ms") {
|
|
4466
|
+
parsed.timeoutMs = parseNumberFlag(requireValue4(rawArgs[i + 1], "--timeout-ms"), "--timeout-ms", { min: 1 });
|
|
4467
|
+
i += 1;
|
|
4468
|
+
continue;
|
|
4469
|
+
}
|
|
4470
|
+
if (arg?.startsWith("--timeout-ms=")) {
|
|
4471
|
+
parsed.timeoutMs = parseNumberFlag(requireValue4(arg.split("=", 2)[1], "--timeout-ms"), "--timeout-ms", { min: 1 });
|
|
3619
4472
|
continue;
|
|
3620
4473
|
}
|
|
3621
4474
|
}
|
|
3622
4475
|
return parsed;
|
|
3623
4476
|
}
|
|
3624
4477
|
async function runScreenshot(args) {
|
|
3625
|
-
const { sessionId, path: path8 } = parseScreenshotArgs(args.rawArgs);
|
|
4478
|
+
const { sessionId, path: path8, timeoutMs } = parseScreenshotArgs(args.rawArgs);
|
|
3626
4479
|
if (!sessionId) throw createUsageError("Missing --session-id");
|
|
3627
|
-
const
|
|
4480
|
+
const params = { sessionId, path: path8 };
|
|
4481
|
+
const result = typeof timeoutMs === "number" ? await callDaemon("page.screenshot", params, { timeoutMs }) : await callDaemon("page.screenshot", params);
|
|
3628
4482
|
return { success: true, message: "Screenshot captured.", data: result };
|
|
3629
4483
|
}
|
|
3630
4484
|
|
|
@@ -3724,23 +4578,1062 @@ async function runNetworkPoll(args) {
|
|
|
3724
4578
|
return { success: true, message: "Network events polled.", data: result };
|
|
3725
4579
|
}
|
|
3726
4580
|
|
|
3727
|
-
// src/cli/
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
4581
|
+
// src/cli/commands/devtools/debug-trace-snapshot.ts
|
|
4582
|
+
function parseDebugTraceSnapshotArgs(rawArgs) {
|
|
4583
|
+
const parsed = {};
|
|
4584
|
+
for (let index = 0; index < rawArgs.length; index += 1) {
|
|
4585
|
+
const arg = rawArgs[index];
|
|
4586
|
+
if (arg === "--session-id") {
|
|
4587
|
+
const value = rawArgs[index + 1];
|
|
4588
|
+
if (!value) throw createUsageError("Missing value for --session-id");
|
|
4589
|
+
parsed.sessionId = value;
|
|
4590
|
+
index += 1;
|
|
4591
|
+
continue;
|
|
4592
|
+
}
|
|
4593
|
+
if (arg?.startsWith("--session-id=")) {
|
|
4594
|
+
parsed.sessionId = arg.split("=", 2)[1];
|
|
4595
|
+
continue;
|
|
4596
|
+
}
|
|
4597
|
+
if (arg === "--since-console-seq") {
|
|
4598
|
+
const value = rawArgs[index + 1];
|
|
4599
|
+
if (!value) throw createUsageError("Missing value for --since-console-seq");
|
|
4600
|
+
parsed.sinceConsoleSeq = parseNumberFlag(value, "--since-console-seq", { min: 0 });
|
|
4601
|
+
index += 1;
|
|
4602
|
+
continue;
|
|
4603
|
+
}
|
|
4604
|
+
if (arg?.startsWith("--since-console-seq=")) {
|
|
4605
|
+
const value = arg.split("=", 2)[1];
|
|
4606
|
+
if (!value) throw createUsageError("Missing value for --since-console-seq");
|
|
4607
|
+
parsed.sinceConsoleSeq = parseNumberFlag(value, "--since-console-seq", { min: 0 });
|
|
4608
|
+
continue;
|
|
4609
|
+
}
|
|
4610
|
+
if (arg === "--since-network-seq") {
|
|
4611
|
+
const value = rawArgs[index + 1];
|
|
4612
|
+
if (!value) throw createUsageError("Missing value for --since-network-seq");
|
|
4613
|
+
parsed.sinceNetworkSeq = parseNumberFlag(value, "--since-network-seq", { min: 0 });
|
|
4614
|
+
index += 1;
|
|
4615
|
+
continue;
|
|
4616
|
+
}
|
|
4617
|
+
if (arg?.startsWith("--since-network-seq=")) {
|
|
4618
|
+
const value = arg.split("=", 2)[1];
|
|
4619
|
+
if (!value) throw createUsageError("Missing value for --since-network-seq");
|
|
4620
|
+
parsed.sinceNetworkSeq = parseNumberFlag(value, "--since-network-seq", { min: 0 });
|
|
4621
|
+
continue;
|
|
4622
|
+
}
|
|
4623
|
+
if (arg === "--since-exception-seq") {
|
|
4624
|
+
const value = rawArgs[index + 1];
|
|
4625
|
+
if (!value) throw createUsageError("Missing value for --since-exception-seq");
|
|
4626
|
+
parsed.sinceExceptionSeq = parseNumberFlag(value, "--since-exception-seq", { min: 0 });
|
|
4627
|
+
index += 1;
|
|
4628
|
+
continue;
|
|
4629
|
+
}
|
|
4630
|
+
if (arg?.startsWith("--since-exception-seq=")) {
|
|
4631
|
+
const value = arg.split("=", 2)[1];
|
|
4632
|
+
if (!value) throw createUsageError("Missing value for --since-exception-seq");
|
|
4633
|
+
parsed.sinceExceptionSeq = parseNumberFlag(value, "--since-exception-seq", { min: 0 });
|
|
4634
|
+
continue;
|
|
4635
|
+
}
|
|
4636
|
+
if (arg === "--max") {
|
|
4637
|
+
const value = rawArgs[index + 1];
|
|
4638
|
+
if (!value) throw createUsageError("Missing value for --max");
|
|
4639
|
+
parsed.max = parseNumberFlag(value, "--max", { min: 1 });
|
|
4640
|
+
index += 1;
|
|
4641
|
+
continue;
|
|
4642
|
+
}
|
|
4643
|
+
if (arg?.startsWith("--max=")) {
|
|
4644
|
+
const value = arg.split("=", 2)[1];
|
|
4645
|
+
if (!value) throw createUsageError("Missing value for --max");
|
|
4646
|
+
parsed.max = parseNumberFlag(value, "--max", { min: 1 });
|
|
4647
|
+
continue;
|
|
4648
|
+
}
|
|
4649
|
+
if (arg === "--request-id") {
|
|
4650
|
+
const value = rawArgs[index + 1];
|
|
4651
|
+
if (!value) throw createUsageError("Missing value for --request-id");
|
|
4652
|
+
parsed.requestId = value;
|
|
4653
|
+
index += 1;
|
|
4654
|
+
continue;
|
|
4655
|
+
}
|
|
4656
|
+
if (arg?.startsWith("--request-id=")) {
|
|
4657
|
+
const value = arg.split("=", 2)[1];
|
|
4658
|
+
if (!value) throw createUsageError("Missing value for --request-id");
|
|
4659
|
+
parsed.requestId = value;
|
|
4660
|
+
continue;
|
|
4661
|
+
}
|
|
4662
|
+
}
|
|
4663
|
+
return parsed;
|
|
4664
|
+
}
|
|
4665
|
+
async function runDebugTraceSnapshot(args) {
|
|
4666
|
+
const parsed = parseDebugTraceSnapshotArgs(args.rawArgs);
|
|
4667
|
+
if (!parsed.sessionId) {
|
|
4668
|
+
throw createUsageError("Missing --session-id");
|
|
4669
|
+
}
|
|
4670
|
+
const result = await callDaemon("devtools.debugTraceSnapshot", {
|
|
4671
|
+
sessionId: parsed.sessionId,
|
|
4672
|
+
sinceConsoleSeq: parsed.sinceConsoleSeq,
|
|
4673
|
+
sinceNetworkSeq: parsed.sinceNetworkSeq,
|
|
4674
|
+
sinceExceptionSeq: parsed.sinceExceptionSeq,
|
|
4675
|
+
max: parsed.max,
|
|
4676
|
+
requestId: parsed.requestId
|
|
4677
|
+
});
|
|
4678
|
+
return {
|
|
4679
|
+
success: true,
|
|
4680
|
+
message: "Debug trace snapshot captured.",
|
|
4681
|
+
data: result
|
|
4682
|
+
};
|
|
4683
|
+
}
|
|
4684
|
+
|
|
4685
|
+
// src/cli/commands/session/cookie-import.ts
|
|
4686
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
4687
|
+
var requireValue5 = (value, flag) => {
|
|
4688
|
+
if (!value) {
|
|
4689
|
+
throw createUsageError(`Missing value for ${flag}`);
|
|
4690
|
+
}
|
|
4691
|
+
return value;
|
|
4692
|
+
};
|
|
4693
|
+
var parseStrictValue = (value, flag) => {
|
|
4694
|
+
const normalized = value.trim().toLowerCase();
|
|
4695
|
+
if (normalized === "true") return true;
|
|
4696
|
+
if (normalized === "false") return false;
|
|
4697
|
+
throw createUsageError(`Invalid ${flag}: ${value}`);
|
|
4698
|
+
};
|
|
4699
|
+
var parseCookieImportArgs = (rawArgs) => {
|
|
4700
|
+
const parsed = {};
|
|
4701
|
+
for (let index = 0; index < rawArgs.length; index += 1) {
|
|
4702
|
+
const arg = rawArgs[index];
|
|
4703
|
+
if (arg === "--session-id") {
|
|
4704
|
+
parsed.sessionId = requireValue5(rawArgs[index + 1], "--session-id");
|
|
4705
|
+
index += 1;
|
|
4706
|
+
continue;
|
|
4707
|
+
}
|
|
4708
|
+
if (arg?.startsWith("--session-id=")) {
|
|
4709
|
+
parsed.sessionId = requireValue5(arg.split("=", 2)[1], "--session-id");
|
|
4710
|
+
continue;
|
|
4711
|
+
}
|
|
4712
|
+
if (arg === "--cookies") {
|
|
4713
|
+
parsed.cookies = requireValue5(rawArgs[index + 1], "--cookies");
|
|
4714
|
+
index += 1;
|
|
4715
|
+
continue;
|
|
4716
|
+
}
|
|
4717
|
+
if (arg?.startsWith("--cookies=")) {
|
|
4718
|
+
parsed.cookies = requireValue5(arg.split("=", 2)[1], "--cookies");
|
|
4719
|
+
continue;
|
|
4720
|
+
}
|
|
4721
|
+
if (arg === "--cookies-file") {
|
|
4722
|
+
parsed.cookiesFile = requireValue5(rawArgs[index + 1], "--cookies-file");
|
|
4723
|
+
index += 1;
|
|
4724
|
+
continue;
|
|
4725
|
+
}
|
|
4726
|
+
if (arg?.startsWith("--cookies-file=")) {
|
|
4727
|
+
parsed.cookiesFile = requireValue5(arg.split("=", 2)[1], "--cookies-file");
|
|
4728
|
+
continue;
|
|
4729
|
+
}
|
|
4730
|
+
if (arg === "--strict") {
|
|
4731
|
+
parsed.strict = true;
|
|
4732
|
+
continue;
|
|
4733
|
+
}
|
|
4734
|
+
if (arg?.startsWith("--strict=")) {
|
|
4735
|
+
parsed.strict = parseStrictValue(requireValue5(arg.split("=", 2)[1], "--strict"), "--strict");
|
|
4736
|
+
continue;
|
|
4737
|
+
}
|
|
4738
|
+
if (arg === "--request-id") {
|
|
4739
|
+
parsed.requestId = requireValue5(rawArgs[index + 1], "--request-id");
|
|
4740
|
+
index += 1;
|
|
4741
|
+
continue;
|
|
4742
|
+
}
|
|
4743
|
+
if (arg?.startsWith("--request-id=")) {
|
|
4744
|
+
parsed.requestId = requireValue5(arg.split("=", 2)[1], "--request-id");
|
|
4745
|
+
continue;
|
|
4746
|
+
}
|
|
4747
|
+
}
|
|
4748
|
+
return parsed;
|
|
4749
|
+
};
|
|
4750
|
+
var parseCookiesJson = (raw, source) => {
|
|
4751
|
+
let parsed;
|
|
4752
|
+
try {
|
|
4753
|
+
parsed = JSON.parse(raw);
|
|
4754
|
+
} catch (error) {
|
|
4755
|
+
const message = error instanceof Error ? error.message : "Invalid JSON";
|
|
4756
|
+
throw createUsageError(`Invalid JSON from ${source}: ${message}`);
|
|
4757
|
+
}
|
|
4758
|
+
if (!Array.isArray(parsed)) {
|
|
4759
|
+
throw createUsageError(`Invalid JSON from ${source}: expected array`);
|
|
4760
|
+
}
|
|
4761
|
+
const cookies = [];
|
|
4762
|
+
for (const entry of parsed) {
|
|
4763
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
|
|
4764
|
+
throw createUsageError(`Invalid JSON from ${source}: expected cookie object entries`);
|
|
4765
|
+
}
|
|
4766
|
+
const cookie = entry;
|
|
4767
|
+
if (typeof cookie.name !== "string" || typeof cookie.value !== "string") {
|
|
4768
|
+
throw createUsageError(`Invalid JSON from ${source}: each cookie requires string name and value`);
|
|
4769
|
+
}
|
|
4770
|
+
if (typeof cookie.sameSite !== "undefined" && cookie.sameSite !== "Strict" && cookie.sameSite !== "Lax" && cookie.sameSite !== "None") {
|
|
4771
|
+
throw createUsageError(`Invalid JSON from ${source}: sameSite must be Strict, Lax, or None`);
|
|
4772
|
+
}
|
|
4773
|
+
cookies.push({
|
|
4774
|
+
name: cookie.name,
|
|
4775
|
+
value: cookie.value,
|
|
4776
|
+
...typeof cookie.url === "string" ? { url: cookie.url } : {},
|
|
4777
|
+
...typeof cookie.domain === "string" ? { domain: cookie.domain } : {},
|
|
4778
|
+
...typeof cookie.path === "string" ? { path: cookie.path } : {},
|
|
4779
|
+
...typeof cookie.expires === "number" ? { expires: cookie.expires } : {},
|
|
4780
|
+
...typeof cookie.httpOnly === "boolean" ? { httpOnly: cookie.httpOnly } : {},
|
|
4781
|
+
...typeof cookie.secure === "boolean" ? { secure: cookie.secure } : {},
|
|
4782
|
+
...cookie.sameSite ? { sameSite: cookie.sameSite } : {}
|
|
4783
|
+
});
|
|
4784
|
+
}
|
|
4785
|
+
return cookies;
|
|
4786
|
+
};
|
|
4787
|
+
var resolveCookies = (parsed) => {
|
|
4788
|
+
const hasInline = typeof parsed.cookies === "string";
|
|
4789
|
+
const hasFile = typeof parsed.cookiesFile === "string";
|
|
4790
|
+
if (!hasInline && !hasFile) {
|
|
4791
|
+
throw createUsageError("Missing --cookies or --cookies-file");
|
|
4792
|
+
}
|
|
4793
|
+
if (hasInline && hasFile) {
|
|
4794
|
+
throw createUsageError("Provide only one cookies source: --cookies or --cookies-file.");
|
|
4795
|
+
}
|
|
4796
|
+
if (hasInline) {
|
|
4797
|
+
return parseCookiesJson(parsed.cookies ?? "", "--cookies");
|
|
4798
|
+
}
|
|
4799
|
+
let raw = "";
|
|
4800
|
+
try {
|
|
4801
|
+
raw = readFileSync6(parsed.cookiesFile ?? "", "utf8");
|
|
4802
|
+
} catch (error) {
|
|
4803
|
+
const message = error instanceof Error ? error.message : "Unable to read file";
|
|
4804
|
+
throw createUsageError(`Invalid --cookies-file: ${message}`);
|
|
4805
|
+
}
|
|
4806
|
+
if (!raw.trim()) {
|
|
4807
|
+
throw createUsageError("Invalid JSON from --cookies-file: empty input");
|
|
4808
|
+
}
|
|
4809
|
+
return parseCookiesJson(raw, "--cookies-file");
|
|
4810
|
+
};
|
|
4811
|
+
async function runCookieImport(args) {
|
|
4812
|
+
const parsed = parseCookieImportArgs(args.rawArgs);
|
|
4813
|
+
if (!parsed.sessionId) {
|
|
4814
|
+
throw createUsageError("Missing --session-id");
|
|
4815
|
+
}
|
|
4816
|
+
const cookies = resolveCookies(parsed);
|
|
4817
|
+
const result = await callDaemon("session.cookieImport", {
|
|
4818
|
+
sessionId: parsed.sessionId,
|
|
4819
|
+
cookies,
|
|
4820
|
+
strict: parsed.strict ?? true,
|
|
4821
|
+
requestId: parsed.requestId
|
|
4822
|
+
});
|
|
4823
|
+
const imported = typeof result.imported === "number" ? result.imported : cookies.length;
|
|
4824
|
+
return {
|
|
4825
|
+
success: true,
|
|
4826
|
+
message: `Cookies imported: ${imported}`,
|
|
4827
|
+
data: result
|
|
4828
|
+
};
|
|
4829
|
+
}
|
|
4830
|
+
|
|
4831
|
+
// src/cli/commands/session/cookie-list.ts
|
|
4832
|
+
var requireValue6 = (value, flag) => {
|
|
4833
|
+
if (!value) {
|
|
4834
|
+
throw createUsageError(`Missing value for ${flag}`);
|
|
4835
|
+
}
|
|
4836
|
+
return value;
|
|
4837
|
+
};
|
|
4838
|
+
var normalizeCookieUrls = (values) => {
|
|
4839
|
+
const normalized = [];
|
|
4840
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4841
|
+
for (const value of values) {
|
|
4842
|
+
const trimmed = value.trim();
|
|
4843
|
+
if (!trimmed) {
|
|
4844
|
+
continue;
|
|
4845
|
+
}
|
|
4846
|
+
let parsedUrl;
|
|
4847
|
+
try {
|
|
4848
|
+
parsedUrl = new URL(trimmed);
|
|
4849
|
+
} catch {
|
|
4850
|
+
throw createUsageError(`Invalid --url value: ${trimmed}`);
|
|
4851
|
+
}
|
|
4852
|
+
if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") {
|
|
4853
|
+
throw createUsageError(`Invalid --url protocol: ${trimmed}`);
|
|
4854
|
+
}
|
|
4855
|
+
const normalizedUrl = parsedUrl.toString();
|
|
4856
|
+
if (seen.has(normalizedUrl)) {
|
|
4857
|
+
continue;
|
|
4858
|
+
}
|
|
4859
|
+
seen.add(normalizedUrl);
|
|
4860
|
+
normalized.push(normalizedUrl);
|
|
4861
|
+
}
|
|
4862
|
+
return normalized;
|
|
4863
|
+
};
|
|
4864
|
+
var parseCookieListArgs = (rawArgs) => {
|
|
4865
|
+
const parsed = { urls: [] };
|
|
4866
|
+
for (let index = 0; index < rawArgs.length; index += 1) {
|
|
4867
|
+
const arg = rawArgs[index];
|
|
4868
|
+
if (arg === "--session-id") {
|
|
4869
|
+
parsed.sessionId = requireValue6(rawArgs[index + 1], "--session-id");
|
|
4870
|
+
index += 1;
|
|
4871
|
+
continue;
|
|
4872
|
+
}
|
|
4873
|
+
if (arg?.startsWith("--session-id=")) {
|
|
4874
|
+
parsed.sessionId = requireValue6(arg.split("=", 2)[1], "--session-id");
|
|
4875
|
+
continue;
|
|
4876
|
+
}
|
|
4877
|
+
if (arg === "--url") {
|
|
4878
|
+
const rawValue = requireValue6(rawArgs[index + 1], "--url");
|
|
4879
|
+
parsed.urls.push(...rawValue.split(","));
|
|
4880
|
+
index += 1;
|
|
4881
|
+
continue;
|
|
4882
|
+
}
|
|
4883
|
+
if (arg?.startsWith("--url=")) {
|
|
4884
|
+
parsed.urls.push(...requireValue6(arg.split("=", 2)[1], "--url").split(","));
|
|
4885
|
+
continue;
|
|
4886
|
+
}
|
|
4887
|
+
if (arg === "--request-id") {
|
|
4888
|
+
parsed.requestId = requireValue6(rawArgs[index + 1], "--request-id");
|
|
4889
|
+
index += 1;
|
|
4890
|
+
continue;
|
|
4891
|
+
}
|
|
4892
|
+
if (arg?.startsWith("--request-id=")) {
|
|
4893
|
+
parsed.requestId = requireValue6(arg.split("=", 2)[1], "--request-id");
|
|
4894
|
+
continue;
|
|
4895
|
+
}
|
|
4896
|
+
}
|
|
4897
|
+
parsed.urls = normalizeCookieUrls(parsed.urls);
|
|
4898
|
+
return parsed;
|
|
4899
|
+
};
|
|
4900
|
+
async function runCookieList(args) {
|
|
4901
|
+
const parsed = parseCookieListArgs(args.rawArgs);
|
|
4902
|
+
if (!parsed.sessionId) {
|
|
4903
|
+
throw createUsageError("Missing --session-id");
|
|
4904
|
+
}
|
|
4905
|
+
const result = await callDaemon("session.cookieList", {
|
|
4906
|
+
sessionId: parsed.sessionId,
|
|
4907
|
+
...parsed.urls.length > 0 ? { urls: parsed.urls } : {},
|
|
4908
|
+
requestId: parsed.requestId
|
|
4909
|
+
});
|
|
4910
|
+
const count = typeof result.count === "number" ? result.count : Array.isArray(result.cookies) ? result.cookies.length : 0;
|
|
4911
|
+
return {
|
|
4912
|
+
success: true,
|
|
4913
|
+
message: `Cookies listed: ${count}`,
|
|
4914
|
+
data: result
|
|
4915
|
+
};
|
|
4916
|
+
}
|
|
4917
|
+
|
|
4918
|
+
// src/cli/commands/macro-resolve.ts
|
|
4919
|
+
var requireValue7 = (value, flag) => {
|
|
4920
|
+
if (!value) {
|
|
4921
|
+
throw createUsageError(`Missing value for ${flag}`);
|
|
4922
|
+
}
|
|
4923
|
+
return value;
|
|
4924
|
+
};
|
|
4925
|
+
var parseMacroResolveArgs = (rawArgs) => {
|
|
4926
|
+
const parsed = {};
|
|
4927
|
+
for (let index = 0; index < rawArgs.length; index += 1) {
|
|
4928
|
+
const arg = rawArgs[index];
|
|
4929
|
+
if (arg === "--expression") {
|
|
4930
|
+
parsed.expression = requireValue7(rawArgs[index + 1], "--expression");
|
|
4931
|
+
index += 1;
|
|
4932
|
+
continue;
|
|
4933
|
+
}
|
|
4934
|
+
if (arg?.startsWith("--expression=")) {
|
|
4935
|
+
parsed.expression = requireValue7(arg.split("=", 2)[1], "--expression");
|
|
4936
|
+
continue;
|
|
4937
|
+
}
|
|
4938
|
+
if (arg === "--default-provider") {
|
|
4939
|
+
parsed.defaultProvider = requireValue7(rawArgs[index + 1], "--default-provider");
|
|
4940
|
+
index += 1;
|
|
4941
|
+
continue;
|
|
4942
|
+
}
|
|
4943
|
+
if (arg?.startsWith("--default-provider=")) {
|
|
4944
|
+
parsed.defaultProvider = requireValue7(arg.split("=", 2)[1], "--default-provider");
|
|
4945
|
+
continue;
|
|
4946
|
+
}
|
|
4947
|
+
if (arg === "--include-catalog") {
|
|
4948
|
+
parsed.includeCatalog = true;
|
|
4949
|
+
continue;
|
|
4950
|
+
}
|
|
4951
|
+
if (arg === "--execute") {
|
|
4952
|
+
parsed.execute = true;
|
|
4953
|
+
continue;
|
|
4954
|
+
}
|
|
4955
|
+
if (arg === "--timeout-ms") {
|
|
4956
|
+
const value = requireValue7(rawArgs[index + 1], "--timeout-ms");
|
|
4957
|
+
parsed.timeoutMs = parseNumberFlag(value, "--timeout-ms", { min: 1 });
|
|
4958
|
+
index += 1;
|
|
4959
|
+
continue;
|
|
4960
|
+
}
|
|
4961
|
+
if (arg?.startsWith("--timeout-ms=")) {
|
|
4962
|
+
parsed.timeoutMs = parseNumberFlag(requireValue7(arg.split("=", 2)[1], "--timeout-ms"), "--timeout-ms", { min: 1 });
|
|
4963
|
+
continue;
|
|
4964
|
+
}
|
|
4965
|
+
}
|
|
4966
|
+
return parsed;
|
|
4967
|
+
};
|
|
4968
|
+
async function runMacroResolve(args) {
|
|
4969
|
+
const parsed = parseMacroResolveArgs(args.rawArgs);
|
|
4970
|
+
if (!parsed.expression) {
|
|
4971
|
+
throw createUsageError("Missing --expression");
|
|
4972
|
+
}
|
|
4973
|
+
const params = {
|
|
4974
|
+
expression: parsed.expression,
|
|
4975
|
+
defaultProvider: parsed.defaultProvider,
|
|
4976
|
+
includeCatalog: parsed.includeCatalog ?? false,
|
|
4977
|
+
execute: parsed.execute ?? false
|
|
4978
|
+
};
|
|
4979
|
+
const result = typeof parsed.timeoutMs === "number" ? await callDaemon("macro.resolve", params, { timeoutMs: parsed.timeoutMs }) : await callDaemon("macro.resolve", params);
|
|
4980
|
+
return {
|
|
4981
|
+
success: true,
|
|
4982
|
+
message: parsed.execute ? "Macro resolved and executed." : "Macro resolved.",
|
|
4983
|
+
data: result
|
|
4984
|
+
};
|
|
4985
|
+
}
|
|
4986
|
+
|
|
4987
|
+
// src/cli/commands/research.ts
|
|
4988
|
+
var SOURCE_VALUES = /* @__PURE__ */ new Set(["web", "community", "social", "shopping"]);
|
|
4989
|
+
var SOURCE_SELECTION_VALUES = /* @__PURE__ */ new Set(["auto", "web", "community", "social", "shopping", "all"]);
|
|
4990
|
+
var MODE_VALUES = /* @__PURE__ */ new Set(["compact", "json", "md", "context", "path"]);
|
|
4991
|
+
var COOKIE_POLICY_VALUES = /* @__PURE__ */ new Set(["off", "auto", "required"]);
|
|
4992
|
+
var requireValue8 = (rawArgs, index, flag) => {
|
|
4993
|
+
const value = rawArgs[index + 1];
|
|
4994
|
+
if (!value) {
|
|
4995
|
+
throw createUsageError(`Missing value for ${flag}`);
|
|
4996
|
+
}
|
|
4997
|
+
return value;
|
|
4998
|
+
};
|
|
4999
|
+
var parseBoolean = (value, flag) => {
|
|
5000
|
+
if (value === "true") return true;
|
|
5001
|
+
if (value === "false") return false;
|
|
5002
|
+
throw createUsageError(`Invalid ${flag}: ${value}`);
|
|
5003
|
+
};
|
|
5004
|
+
var parseSources = (raw) => {
|
|
5005
|
+
const parsed = raw.split(",").map((entry) => entry.trim().toLowerCase()).filter(Boolean);
|
|
5006
|
+
if (parsed.length === 0) {
|
|
5007
|
+
throw createUsageError("--sources requires at least one source");
|
|
5008
|
+
}
|
|
5009
|
+
const deduped = [...new Set(parsed)];
|
|
5010
|
+
for (const source of deduped) {
|
|
5011
|
+
if (!SOURCE_VALUES.has(source)) {
|
|
5012
|
+
throw createUsageError(`Invalid --sources value: ${source}`);
|
|
5013
|
+
}
|
|
5014
|
+
}
|
|
5015
|
+
return deduped;
|
|
5016
|
+
};
|
|
5017
|
+
var parseResearchRunArgs = (rawArgs) => {
|
|
5018
|
+
const parsed = {};
|
|
5019
|
+
for (let index = 0; index < rawArgs.length; index += 1) {
|
|
5020
|
+
const arg = rawArgs[index];
|
|
5021
|
+
if (arg === "--topic") {
|
|
5022
|
+
parsed.topic = requireValue8(rawArgs, index, "--topic");
|
|
5023
|
+
index += 1;
|
|
5024
|
+
continue;
|
|
5025
|
+
}
|
|
5026
|
+
if (arg?.startsWith("--topic=")) {
|
|
5027
|
+
parsed.topic = arg.split("=", 2)[1];
|
|
5028
|
+
continue;
|
|
5029
|
+
}
|
|
5030
|
+
if (arg === "--days") {
|
|
5031
|
+
parsed.days = parseNumberFlag(requireValue8(rawArgs, index, "--days"), "--days", { min: 1, max: 365 });
|
|
5032
|
+
index += 1;
|
|
5033
|
+
continue;
|
|
5034
|
+
}
|
|
5035
|
+
if (arg?.startsWith("--days=")) {
|
|
5036
|
+
parsed.days = parseNumberFlag(arg.split("=", 2)[1] ?? "", "--days", { min: 1, max: 365 });
|
|
5037
|
+
continue;
|
|
5038
|
+
}
|
|
5039
|
+
if (arg === "--from") {
|
|
5040
|
+
parsed.from = requireValue8(rawArgs, index, "--from");
|
|
5041
|
+
index += 1;
|
|
5042
|
+
continue;
|
|
5043
|
+
}
|
|
5044
|
+
if (arg?.startsWith("--from=")) {
|
|
5045
|
+
parsed.from = arg.split("=", 2)[1];
|
|
5046
|
+
continue;
|
|
5047
|
+
}
|
|
5048
|
+
if (arg === "--to") {
|
|
5049
|
+
parsed.to = requireValue8(rawArgs, index, "--to");
|
|
5050
|
+
index += 1;
|
|
5051
|
+
continue;
|
|
5052
|
+
}
|
|
5053
|
+
if (arg?.startsWith("--to=")) {
|
|
5054
|
+
parsed.to = arg.split("=", 2)[1];
|
|
5055
|
+
continue;
|
|
5056
|
+
}
|
|
5057
|
+
if (arg === "--source-selection") {
|
|
5058
|
+
const value = requireValue8(rawArgs, index, "--source-selection").toLowerCase();
|
|
5059
|
+
if (!SOURCE_SELECTION_VALUES.has(value)) {
|
|
5060
|
+
throw createUsageError(`Invalid --source-selection: ${value}`);
|
|
5061
|
+
}
|
|
5062
|
+
parsed.sourceSelection = value;
|
|
5063
|
+
index += 1;
|
|
5064
|
+
continue;
|
|
5065
|
+
}
|
|
5066
|
+
if (arg?.startsWith("--source-selection=")) {
|
|
5067
|
+
const value = (arg.split("=", 2)[1] ?? "").toLowerCase();
|
|
5068
|
+
if (!SOURCE_SELECTION_VALUES.has(value)) {
|
|
5069
|
+
throw createUsageError(`Invalid --source-selection: ${value}`);
|
|
5070
|
+
}
|
|
5071
|
+
parsed.sourceSelection = value;
|
|
5072
|
+
continue;
|
|
5073
|
+
}
|
|
5074
|
+
if (arg === "--sources") {
|
|
5075
|
+
parsed.sources = parseSources(requireValue8(rawArgs, index, "--sources"));
|
|
5076
|
+
index += 1;
|
|
5077
|
+
continue;
|
|
5078
|
+
}
|
|
5079
|
+
if (arg?.startsWith("--sources=")) {
|
|
5080
|
+
parsed.sources = parseSources(arg.split("=", 2)[1] ?? "");
|
|
5081
|
+
continue;
|
|
5082
|
+
}
|
|
5083
|
+
if (arg === "--mode") {
|
|
5084
|
+
const value = requireValue8(rawArgs, index, "--mode").toLowerCase();
|
|
5085
|
+
if (!MODE_VALUES.has(value)) {
|
|
5086
|
+
throw createUsageError(`Invalid --mode: ${value}`);
|
|
5087
|
+
}
|
|
5088
|
+
parsed.mode = value;
|
|
5089
|
+
index += 1;
|
|
5090
|
+
continue;
|
|
5091
|
+
}
|
|
5092
|
+
if (arg?.startsWith("--mode=")) {
|
|
5093
|
+
const value = (arg.split("=", 2)[1] ?? "").toLowerCase();
|
|
5094
|
+
if (!MODE_VALUES.has(value)) {
|
|
5095
|
+
throw createUsageError(`Invalid --mode: ${value}`);
|
|
5096
|
+
}
|
|
5097
|
+
parsed.mode = value;
|
|
5098
|
+
continue;
|
|
5099
|
+
}
|
|
5100
|
+
if (arg === "--include-engagement") {
|
|
5101
|
+
parsed.includeEngagement = true;
|
|
5102
|
+
continue;
|
|
5103
|
+
}
|
|
5104
|
+
if (arg === "--limit-per-source") {
|
|
5105
|
+
parsed.limitPerSource = parseNumberFlag(requireValue8(rawArgs, index, "--limit-per-source"), "--limit-per-source", { min: 1, max: 100 });
|
|
5106
|
+
index += 1;
|
|
5107
|
+
continue;
|
|
5108
|
+
}
|
|
5109
|
+
if (arg?.startsWith("--limit-per-source=")) {
|
|
5110
|
+
parsed.limitPerSource = parseNumberFlag(arg.split("=", 2)[1] ?? "", "--limit-per-source", { min: 1, max: 100 });
|
|
5111
|
+
continue;
|
|
5112
|
+
}
|
|
5113
|
+
if (arg === "--output-dir") {
|
|
5114
|
+
parsed.outputDir = requireValue8(rawArgs, index, "--output-dir");
|
|
5115
|
+
index += 1;
|
|
5116
|
+
continue;
|
|
5117
|
+
}
|
|
5118
|
+
if (arg?.startsWith("--output-dir=")) {
|
|
5119
|
+
parsed.outputDir = arg.split("=", 2)[1];
|
|
5120
|
+
continue;
|
|
5121
|
+
}
|
|
5122
|
+
if (arg === "--ttl-hours") {
|
|
5123
|
+
parsed.ttlHours = parseNumberFlag(requireValue8(rawArgs, index, "--ttl-hours"), "--ttl-hours", { min: 1, max: 168 });
|
|
5124
|
+
index += 1;
|
|
5125
|
+
continue;
|
|
5126
|
+
}
|
|
5127
|
+
if (arg?.startsWith("--ttl-hours=")) {
|
|
5128
|
+
parsed.ttlHours = parseNumberFlag(arg.split("=", 2)[1] ?? "", "--ttl-hours", { min: 1, max: 168 });
|
|
5129
|
+
continue;
|
|
5130
|
+
}
|
|
5131
|
+
if (arg === "--use-cookies") {
|
|
5132
|
+
parsed.useCookies = true;
|
|
5133
|
+
continue;
|
|
5134
|
+
}
|
|
5135
|
+
if (arg?.startsWith("--use-cookies=")) {
|
|
5136
|
+
parsed.useCookies = parseBoolean(arg.split("=", 2)[1] ?? "", "--use-cookies");
|
|
5137
|
+
continue;
|
|
5138
|
+
}
|
|
5139
|
+
if (arg === "--cookie-policy-override" || arg === "--cookie-policy") {
|
|
5140
|
+
const value = requireValue8(rawArgs, index, arg).toLowerCase();
|
|
5141
|
+
if (!COOKIE_POLICY_VALUES.has(value)) {
|
|
5142
|
+
throw createUsageError(`Invalid ${arg}: ${value}`);
|
|
5143
|
+
}
|
|
5144
|
+
parsed.cookiePolicyOverride = value;
|
|
5145
|
+
index += 1;
|
|
5146
|
+
continue;
|
|
5147
|
+
}
|
|
5148
|
+
if (arg?.startsWith("--cookie-policy-override=") || arg?.startsWith("--cookie-policy=")) {
|
|
5149
|
+
const value = (arg.split("=", 2)[1] ?? "").toLowerCase();
|
|
5150
|
+
if (!COOKIE_POLICY_VALUES.has(value)) {
|
|
5151
|
+
throw createUsageError(`Invalid --cookie-policy-override: ${value}`);
|
|
5152
|
+
}
|
|
5153
|
+
parsed.cookiePolicyOverride = value;
|
|
5154
|
+
continue;
|
|
5155
|
+
}
|
|
5156
|
+
}
|
|
5157
|
+
return parsed;
|
|
5158
|
+
};
|
|
5159
|
+
async function runResearchCommand(args) {
|
|
5160
|
+
const [subcommand, ...rest] = args.rawArgs;
|
|
5161
|
+
if (subcommand !== "run") {
|
|
5162
|
+
throw createUsageError("Usage: opendevbrowser research run --topic <value> [options]");
|
|
5163
|
+
}
|
|
5164
|
+
const parsed = parseResearchRunArgs(rest);
|
|
5165
|
+
if (!parsed.topic?.trim()) {
|
|
5166
|
+
throw createUsageError("Missing --topic");
|
|
5167
|
+
}
|
|
5168
|
+
const data = await callDaemon("research.run", {
|
|
5169
|
+
topic: parsed.topic,
|
|
5170
|
+
days: parsed.days,
|
|
5171
|
+
from: parsed.from,
|
|
5172
|
+
to: parsed.to,
|
|
5173
|
+
sourceSelection: parsed.sourceSelection,
|
|
5174
|
+
sources: parsed.sources,
|
|
5175
|
+
mode: parsed.mode ?? "compact",
|
|
5176
|
+
includeEngagement: parsed.includeEngagement ?? false,
|
|
5177
|
+
limitPerSource: parsed.limitPerSource,
|
|
5178
|
+
outputDir: parsed.outputDir,
|
|
5179
|
+
ttlHours: parsed.ttlHours,
|
|
5180
|
+
useCookies: parsed.useCookies,
|
|
5181
|
+
cookiePolicyOverride: parsed.cookiePolicyOverride
|
|
5182
|
+
});
|
|
5183
|
+
return {
|
|
5184
|
+
success: true,
|
|
5185
|
+
message: "Research workflow completed.",
|
|
5186
|
+
data
|
|
5187
|
+
};
|
|
5188
|
+
}
|
|
5189
|
+
|
|
5190
|
+
// src/cli/commands/shopping.ts
|
|
5191
|
+
var SORT_VALUES = /* @__PURE__ */ new Set(["best_deal", "lowest_price", "highest_rating", "fastest_shipping"]);
|
|
5192
|
+
var MODE_VALUES2 = /* @__PURE__ */ new Set(["compact", "json", "md", "context", "path"]);
|
|
5193
|
+
var COOKIE_POLICY_VALUES2 = /* @__PURE__ */ new Set(["off", "auto", "required"]);
|
|
5194
|
+
var requireValue9 = (rawArgs, index, flag) => {
|
|
5195
|
+
const value = rawArgs[index + 1];
|
|
5196
|
+
if (!value) {
|
|
5197
|
+
throw createUsageError(`Missing value for ${flag}`);
|
|
5198
|
+
}
|
|
5199
|
+
return value;
|
|
5200
|
+
};
|
|
5201
|
+
var parseBoolean2 = (value, flag) => {
|
|
5202
|
+
if (value === "true") return true;
|
|
5203
|
+
if (value === "false") return false;
|
|
5204
|
+
throw createUsageError(`Invalid ${flag}: ${value}`);
|
|
5205
|
+
};
|
|
5206
|
+
var parseProviders = (raw) => {
|
|
5207
|
+
const providers = raw.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
5208
|
+
if (providers.length === 0) {
|
|
5209
|
+
throw createUsageError("--providers requires at least one provider");
|
|
5210
|
+
}
|
|
5211
|
+
return [...new Set(providers)];
|
|
5212
|
+
};
|
|
5213
|
+
var parseShoppingRunArgs = (rawArgs) => {
|
|
5214
|
+
const parsed = {};
|
|
5215
|
+
for (let index = 0; index < rawArgs.length; index += 1) {
|
|
5216
|
+
const arg = rawArgs[index];
|
|
5217
|
+
if (arg === "--query") {
|
|
5218
|
+
parsed.query = requireValue9(rawArgs, index, "--query");
|
|
5219
|
+
index += 1;
|
|
5220
|
+
continue;
|
|
5221
|
+
}
|
|
5222
|
+
if (arg?.startsWith("--query=")) {
|
|
5223
|
+
parsed.query = arg.split("=", 2)[1];
|
|
5224
|
+
continue;
|
|
5225
|
+
}
|
|
5226
|
+
if (arg === "--providers") {
|
|
5227
|
+
parsed.providers = parseProviders(requireValue9(rawArgs, index, "--providers"));
|
|
5228
|
+
index += 1;
|
|
5229
|
+
continue;
|
|
5230
|
+
}
|
|
5231
|
+
if (arg?.startsWith("--providers=")) {
|
|
5232
|
+
parsed.providers = parseProviders(arg.split("=", 2)[1] ?? "");
|
|
5233
|
+
continue;
|
|
5234
|
+
}
|
|
5235
|
+
if (arg === "--budget") {
|
|
5236
|
+
parsed.budget = parseNumberFlag(requireValue9(rawArgs, index, "--budget"), "--budget", { min: 1, integer: false });
|
|
5237
|
+
index += 1;
|
|
5238
|
+
continue;
|
|
5239
|
+
}
|
|
5240
|
+
if (arg?.startsWith("--budget=")) {
|
|
5241
|
+
parsed.budget = parseNumberFlag(arg.split("=", 2)[1] ?? "", "--budget", { min: 1, integer: false });
|
|
5242
|
+
continue;
|
|
5243
|
+
}
|
|
5244
|
+
if (arg === "--region") {
|
|
5245
|
+
parsed.region = requireValue9(rawArgs, index, "--region");
|
|
5246
|
+
index += 1;
|
|
5247
|
+
continue;
|
|
5248
|
+
}
|
|
5249
|
+
if (arg?.startsWith("--region=")) {
|
|
5250
|
+
parsed.region = arg.split("=", 2)[1];
|
|
5251
|
+
continue;
|
|
5252
|
+
}
|
|
5253
|
+
if (arg === "--sort") {
|
|
5254
|
+
const value = requireValue9(rawArgs, index, "--sort").toLowerCase();
|
|
5255
|
+
if (!SORT_VALUES.has(value)) {
|
|
5256
|
+
throw createUsageError(`Invalid --sort: ${value}`);
|
|
5257
|
+
}
|
|
5258
|
+
parsed.sort = value;
|
|
5259
|
+
index += 1;
|
|
5260
|
+
continue;
|
|
5261
|
+
}
|
|
5262
|
+
if (arg?.startsWith("--sort=")) {
|
|
5263
|
+
const value = (arg.split("=", 2)[1] ?? "").toLowerCase();
|
|
5264
|
+
if (!SORT_VALUES.has(value)) {
|
|
5265
|
+
throw createUsageError(`Invalid --sort: ${value}`);
|
|
5266
|
+
}
|
|
5267
|
+
parsed.sort = value;
|
|
5268
|
+
continue;
|
|
5269
|
+
}
|
|
5270
|
+
if (arg === "--mode") {
|
|
5271
|
+
const value = requireValue9(rawArgs, index, "--mode").toLowerCase();
|
|
5272
|
+
if (!MODE_VALUES2.has(value)) {
|
|
5273
|
+
throw createUsageError(`Invalid --mode: ${value}`);
|
|
5274
|
+
}
|
|
5275
|
+
parsed.mode = value;
|
|
5276
|
+
index += 1;
|
|
5277
|
+
continue;
|
|
5278
|
+
}
|
|
5279
|
+
if (arg?.startsWith("--mode=")) {
|
|
5280
|
+
const value = (arg.split("=", 2)[1] ?? "").toLowerCase();
|
|
5281
|
+
if (!MODE_VALUES2.has(value)) {
|
|
5282
|
+
throw createUsageError(`Invalid --mode: ${value}`);
|
|
5283
|
+
}
|
|
5284
|
+
parsed.mode = value;
|
|
5285
|
+
continue;
|
|
5286
|
+
}
|
|
5287
|
+
if (arg === "--timeout-ms") {
|
|
5288
|
+
parsed.timeoutMs = parseNumberFlag(requireValue9(rawArgs, index, "--timeout-ms"), "--timeout-ms", { min: 1 });
|
|
5289
|
+
index += 1;
|
|
5290
|
+
continue;
|
|
5291
|
+
}
|
|
5292
|
+
if (arg?.startsWith("--timeout-ms=")) {
|
|
5293
|
+
parsed.timeoutMs = parseNumberFlag(arg.split("=", 2)[1] ?? "", "--timeout-ms", { min: 1 });
|
|
5294
|
+
continue;
|
|
5295
|
+
}
|
|
5296
|
+
if (arg === "--output-dir") {
|
|
5297
|
+
parsed.outputDir = requireValue9(rawArgs, index, "--output-dir");
|
|
5298
|
+
index += 1;
|
|
5299
|
+
continue;
|
|
5300
|
+
}
|
|
5301
|
+
if (arg?.startsWith("--output-dir=")) {
|
|
5302
|
+
parsed.outputDir = arg.split("=", 2)[1];
|
|
5303
|
+
continue;
|
|
5304
|
+
}
|
|
5305
|
+
if (arg === "--ttl-hours") {
|
|
5306
|
+
parsed.ttlHours = parseNumberFlag(requireValue9(rawArgs, index, "--ttl-hours"), "--ttl-hours", { min: 1, max: 168 });
|
|
5307
|
+
index += 1;
|
|
5308
|
+
continue;
|
|
5309
|
+
}
|
|
5310
|
+
if (arg?.startsWith("--ttl-hours=")) {
|
|
5311
|
+
parsed.ttlHours = parseNumberFlag(arg.split("=", 2)[1] ?? "", "--ttl-hours", { min: 1, max: 168 });
|
|
5312
|
+
continue;
|
|
5313
|
+
}
|
|
5314
|
+
if (arg === "--use-cookies") {
|
|
5315
|
+
parsed.useCookies = true;
|
|
5316
|
+
continue;
|
|
5317
|
+
}
|
|
5318
|
+
if (arg?.startsWith("--use-cookies=")) {
|
|
5319
|
+
parsed.useCookies = parseBoolean2(arg.split("=", 2)[1] ?? "", "--use-cookies");
|
|
5320
|
+
continue;
|
|
5321
|
+
}
|
|
5322
|
+
if (arg === "--cookie-policy-override" || arg === "--cookie-policy") {
|
|
5323
|
+
const value = requireValue9(rawArgs, index, arg).toLowerCase();
|
|
5324
|
+
if (!COOKIE_POLICY_VALUES2.has(value)) {
|
|
5325
|
+
throw createUsageError(`Invalid ${arg}: ${value}`);
|
|
5326
|
+
}
|
|
5327
|
+
parsed.cookiePolicyOverride = value;
|
|
5328
|
+
index += 1;
|
|
5329
|
+
continue;
|
|
5330
|
+
}
|
|
5331
|
+
if (arg?.startsWith("--cookie-policy-override=") || arg?.startsWith("--cookie-policy=")) {
|
|
5332
|
+
const value = (arg.split("=", 2)[1] ?? "").toLowerCase();
|
|
5333
|
+
if (!COOKIE_POLICY_VALUES2.has(value)) {
|
|
5334
|
+
throw createUsageError(`Invalid --cookie-policy-override: ${value}`);
|
|
5335
|
+
}
|
|
5336
|
+
parsed.cookiePolicyOverride = value;
|
|
5337
|
+
continue;
|
|
5338
|
+
}
|
|
5339
|
+
}
|
|
5340
|
+
return parsed;
|
|
5341
|
+
};
|
|
5342
|
+
async function runShoppingCommand(args) {
|
|
5343
|
+
const [subcommand, ...rest] = args.rawArgs;
|
|
5344
|
+
if (subcommand !== "run") {
|
|
5345
|
+
throw createUsageError("Usage: opendevbrowser shopping run --query <value> [options]");
|
|
5346
|
+
}
|
|
5347
|
+
const parsed = parseShoppingRunArgs(rest);
|
|
5348
|
+
if (!parsed.query?.trim()) {
|
|
5349
|
+
throw createUsageError("Missing --query");
|
|
5350
|
+
}
|
|
5351
|
+
const payload = {
|
|
5352
|
+
query: parsed.query,
|
|
5353
|
+
providers: parsed.providers,
|
|
5354
|
+
budget: parsed.budget,
|
|
5355
|
+
region: parsed.region,
|
|
5356
|
+
sort: parsed.sort,
|
|
5357
|
+
mode: parsed.mode ?? "compact",
|
|
5358
|
+
...typeof parsed.timeoutMs === "number" ? { timeoutMs: parsed.timeoutMs } : {},
|
|
5359
|
+
outputDir: parsed.outputDir,
|
|
5360
|
+
ttlHours: parsed.ttlHours,
|
|
5361
|
+
useCookies: parsed.useCookies,
|
|
5362
|
+
cookiePolicyOverride: parsed.cookiePolicyOverride
|
|
5363
|
+
};
|
|
5364
|
+
const data = typeof parsed.timeoutMs === "number" ? await callDaemon("shopping.run", payload, { timeoutMs: parsed.timeoutMs }) : await callDaemon("shopping.run", payload);
|
|
5365
|
+
return {
|
|
5366
|
+
success: true,
|
|
5367
|
+
message: "Shopping workflow completed.",
|
|
5368
|
+
data
|
|
5369
|
+
};
|
|
5370
|
+
}
|
|
5371
|
+
|
|
5372
|
+
// src/cli/commands/product-video.ts
|
|
5373
|
+
var requireValue10 = (rawArgs, index, flag) => {
|
|
5374
|
+
const value = rawArgs[index + 1];
|
|
5375
|
+
if (!value) {
|
|
5376
|
+
throw createUsageError(`Missing value for ${flag}`);
|
|
5377
|
+
}
|
|
5378
|
+
return value;
|
|
5379
|
+
};
|
|
5380
|
+
var parseBoolean3 = (value, flag) => {
|
|
5381
|
+
if (value === "true") return true;
|
|
5382
|
+
if (value === "false") return false;
|
|
5383
|
+
throw createUsageError(`Invalid ${flag}: ${value}`);
|
|
5384
|
+
};
|
|
5385
|
+
var COOKIE_POLICY_VALUES3 = /* @__PURE__ */ new Set(["off", "auto", "required"]);
|
|
5386
|
+
var parseProductVideoArgs = (rawArgs) => {
|
|
5387
|
+
const parsed = {};
|
|
5388
|
+
for (let index = 0; index < rawArgs.length; index += 1) {
|
|
5389
|
+
const arg = rawArgs[index];
|
|
5390
|
+
if (arg === "--product-url") {
|
|
5391
|
+
parsed.productUrl = requireValue10(rawArgs, index, "--product-url");
|
|
5392
|
+
index += 1;
|
|
5393
|
+
continue;
|
|
5394
|
+
}
|
|
5395
|
+
if (arg?.startsWith("--product-url=")) {
|
|
5396
|
+
parsed.productUrl = arg.split("=", 2)[1];
|
|
5397
|
+
continue;
|
|
5398
|
+
}
|
|
5399
|
+
if (arg === "--product-name") {
|
|
5400
|
+
parsed.productName = requireValue10(rawArgs, index, "--product-name");
|
|
5401
|
+
index += 1;
|
|
5402
|
+
continue;
|
|
5403
|
+
}
|
|
5404
|
+
if (arg?.startsWith("--product-name=")) {
|
|
5405
|
+
parsed.productName = arg.split("=", 2)[1];
|
|
5406
|
+
continue;
|
|
5407
|
+
}
|
|
5408
|
+
if (arg === "--provider-hint") {
|
|
5409
|
+
parsed.providerHint = requireValue10(rawArgs, index, "--provider-hint");
|
|
5410
|
+
index += 1;
|
|
5411
|
+
continue;
|
|
5412
|
+
}
|
|
5413
|
+
if (arg?.startsWith("--provider-hint=")) {
|
|
5414
|
+
parsed.providerHint = arg.split("=", 2)[1];
|
|
5415
|
+
continue;
|
|
5416
|
+
}
|
|
5417
|
+
if (arg === "--include-screenshots") {
|
|
5418
|
+
parsed.includeScreenshots = true;
|
|
5419
|
+
continue;
|
|
5420
|
+
}
|
|
5421
|
+
if (arg?.startsWith("--include-screenshots=")) {
|
|
5422
|
+
parsed.includeScreenshots = parseBoolean3(arg.split("=", 2)[1] ?? "", "--include-screenshots");
|
|
5423
|
+
continue;
|
|
5424
|
+
}
|
|
5425
|
+
if (arg === "--include-all-images") {
|
|
5426
|
+
parsed.includeAllImages = true;
|
|
5427
|
+
continue;
|
|
5428
|
+
}
|
|
5429
|
+
if (arg?.startsWith("--include-all-images=")) {
|
|
5430
|
+
parsed.includeAllImages = parseBoolean3(arg.split("=", 2)[1] ?? "", "--include-all-images");
|
|
5431
|
+
continue;
|
|
5432
|
+
}
|
|
5433
|
+
if (arg === "--include-copy") {
|
|
5434
|
+
parsed.includeCopy = true;
|
|
5435
|
+
continue;
|
|
5436
|
+
}
|
|
5437
|
+
if (arg?.startsWith("--include-copy=")) {
|
|
5438
|
+
parsed.includeCopy = parseBoolean3(arg.split("=", 2)[1] ?? "", "--include-copy");
|
|
5439
|
+
continue;
|
|
5440
|
+
}
|
|
5441
|
+
if (arg === "--output-dir") {
|
|
5442
|
+
parsed.outputDir = requireValue10(rawArgs, index, "--output-dir");
|
|
5443
|
+
index += 1;
|
|
5444
|
+
continue;
|
|
5445
|
+
}
|
|
5446
|
+
if (arg?.startsWith("--output-dir=")) {
|
|
5447
|
+
parsed.outputDir = arg.split("=", 2)[1];
|
|
5448
|
+
continue;
|
|
5449
|
+
}
|
|
5450
|
+
if (arg === "--ttl-hours") {
|
|
5451
|
+
parsed.ttlHours = parseNumberFlag(requireValue10(rawArgs, index, "--ttl-hours"), "--ttl-hours", { min: 1, max: 168 });
|
|
5452
|
+
index += 1;
|
|
5453
|
+
continue;
|
|
5454
|
+
}
|
|
5455
|
+
if (arg?.startsWith("--ttl-hours=")) {
|
|
5456
|
+
parsed.ttlHours = parseNumberFlag(arg.split("=", 2)[1] ?? "", "--ttl-hours", { min: 1, max: 168 });
|
|
5457
|
+
continue;
|
|
5458
|
+
}
|
|
5459
|
+
if (arg === "--timeout-ms") {
|
|
5460
|
+
parsed.timeoutMs = parseNumberFlag(requireValue10(rawArgs, index, "--timeout-ms"), "--timeout-ms", { min: 1 });
|
|
5461
|
+
index += 1;
|
|
5462
|
+
continue;
|
|
5463
|
+
}
|
|
5464
|
+
if (arg?.startsWith("--timeout-ms=")) {
|
|
5465
|
+
parsed.timeoutMs = parseNumberFlag(arg.split("=", 2)[1] ?? "", "--timeout-ms", { min: 1 });
|
|
5466
|
+
continue;
|
|
5467
|
+
}
|
|
5468
|
+
if (arg === "--use-cookies") {
|
|
5469
|
+
parsed.useCookies = true;
|
|
5470
|
+
continue;
|
|
5471
|
+
}
|
|
5472
|
+
if (arg?.startsWith("--use-cookies=")) {
|
|
5473
|
+
parsed.useCookies = parseBoolean3(arg.split("=", 2)[1] ?? "", "--use-cookies");
|
|
5474
|
+
continue;
|
|
5475
|
+
}
|
|
5476
|
+
if (arg === "--cookie-policy-override" || arg === "--cookie-policy") {
|
|
5477
|
+
const value = requireValue10(rawArgs, index, arg).toLowerCase();
|
|
5478
|
+
if (!COOKIE_POLICY_VALUES3.has(value)) {
|
|
5479
|
+
throw createUsageError(`Invalid ${arg}: ${value}`);
|
|
5480
|
+
}
|
|
5481
|
+
parsed.cookiePolicyOverride = value;
|
|
5482
|
+
index += 1;
|
|
5483
|
+
continue;
|
|
5484
|
+
}
|
|
5485
|
+
if (arg?.startsWith("--cookie-policy-override=") || arg?.startsWith("--cookie-policy=")) {
|
|
5486
|
+
const value = (arg.split("=", 2)[1] ?? "").toLowerCase();
|
|
5487
|
+
if (!COOKIE_POLICY_VALUES3.has(value)) {
|
|
5488
|
+
throw createUsageError(`Invalid --cookie-policy-override: ${value}`);
|
|
5489
|
+
}
|
|
5490
|
+
parsed.cookiePolicyOverride = value;
|
|
5491
|
+
continue;
|
|
5492
|
+
}
|
|
5493
|
+
}
|
|
5494
|
+
return parsed;
|
|
5495
|
+
};
|
|
5496
|
+
async function runProductVideoCommand(args) {
|
|
5497
|
+
const [subcommand, ...rest] = args.rawArgs;
|
|
5498
|
+
if (subcommand !== "run") {
|
|
5499
|
+
throw createUsageError("Usage: opendevbrowser product-video run --product-url <url> | --product-name <name>");
|
|
5500
|
+
}
|
|
5501
|
+
const parsed = parseProductVideoArgs(rest);
|
|
5502
|
+
if (!parsed.productUrl && !parsed.productName) {
|
|
5503
|
+
throw createUsageError("Missing --product-url or --product-name");
|
|
5504
|
+
}
|
|
5505
|
+
const timeoutMs = parsed.timeoutMs ?? 12e4;
|
|
5506
|
+
const data = await callDaemon("product.video.run", {
|
|
5507
|
+
product_url: parsed.productUrl,
|
|
5508
|
+
product_name: parsed.productName,
|
|
5509
|
+
provider_hint: parsed.providerHint,
|
|
5510
|
+
include_screenshots: parsed.includeScreenshots,
|
|
5511
|
+
include_all_images: parsed.includeAllImages,
|
|
5512
|
+
include_copy: parsed.includeCopy,
|
|
5513
|
+
output_dir: parsed.outputDir,
|
|
5514
|
+
ttl_hours: parsed.ttlHours,
|
|
5515
|
+
useCookies: parsed.useCookies,
|
|
5516
|
+
cookiePolicyOverride: parsed.cookiePolicyOverride
|
|
5517
|
+
}, { timeoutMs });
|
|
5518
|
+
return {
|
|
5519
|
+
success: true,
|
|
5520
|
+
message: "Product video asset workflow completed.",
|
|
5521
|
+
data
|
|
5522
|
+
};
|
|
5523
|
+
}
|
|
5524
|
+
|
|
5525
|
+
// package.json
|
|
5526
|
+
var package_default = {
|
|
5527
|
+
name: "opendevbrowser",
|
|
5528
|
+
version: "0.0.16",
|
|
5529
|
+
description: "OpenCode plugin for browser automation via CDP with snapshot-refs-actions workflow",
|
|
5530
|
+
type: "module",
|
|
5531
|
+
main: "dist/index.js",
|
|
5532
|
+
types: "dist/index.d.ts",
|
|
5533
|
+
bin: {
|
|
5534
|
+
opendevbrowser: "dist/cli/index.js"
|
|
5535
|
+
},
|
|
5536
|
+
files: [
|
|
5537
|
+
"dist",
|
|
5538
|
+
"skills",
|
|
5539
|
+
"scripts/native",
|
|
5540
|
+
"extension/manifest.json",
|
|
5541
|
+
"extension/popup.html",
|
|
5542
|
+
"extension/dist",
|
|
5543
|
+
"extension/icons"
|
|
5544
|
+
],
|
|
5545
|
+
keywords: [
|
|
5546
|
+
"opencode",
|
|
5547
|
+
"plugin",
|
|
5548
|
+
"browser",
|
|
5549
|
+
"automation",
|
|
5550
|
+
"cdp",
|
|
5551
|
+
"playwright",
|
|
5552
|
+
"testing",
|
|
5553
|
+
"web-scraping",
|
|
5554
|
+
"chrome"
|
|
5555
|
+
],
|
|
5556
|
+
license: "MIT",
|
|
5557
|
+
repository: {
|
|
5558
|
+
type: "git",
|
|
5559
|
+
url: "git+https://github.com/freshtechbro/opendevbrowser.git"
|
|
5560
|
+
},
|
|
5561
|
+
engines: {
|
|
5562
|
+
node: ">=18"
|
|
5563
|
+
},
|
|
5564
|
+
scripts: {
|
|
5565
|
+
build: `tsup src/index.ts src/cli/index.ts --format esm --clean --sourcemap && tsc --emitDeclarationOnly --declaration --declarationMap -p tsconfig.json && node --input-type=module -e "import { copyFileSync, existsSync } from 'node:fs';
|
|
5566
|
+
import { resolve } from 'node:path';
|
|
5567
|
+
const dist = resolve('dist');
|
|
5568
|
+
const pairs = [
|
|
5569
|
+
['index.js', 'opendevbrowser.js'],
|
|
5570
|
+
['index.js.map', 'opendevbrowser.js.map'],
|
|
5571
|
+
['index.d.ts', 'opendevbrowser.d.ts'],
|
|
5572
|
+
['index.d.ts.map', 'opendevbrowser.d.ts.map'],
|
|
5573
|
+
];
|
|
5574
|
+
for (const [src, dst] of pairs) {
|
|
5575
|
+
const from = resolve(dist, src);
|
|
5576
|
+
const to = resolve(dist, dst);
|
|
5577
|
+
if (existsSync(from)) copyFileSync(from, to);
|
|
5578
|
+
}"`,
|
|
5579
|
+
dev: "tsup src/index.ts src/cli/index.ts --format esm --dts --watch",
|
|
5580
|
+
lint: 'eslint "src/**/*.ts" "tests/**/*.ts"',
|
|
5581
|
+
typecheck: "tsc --noEmit -p tsconfig.json",
|
|
5582
|
+
test: "vitest run --coverage",
|
|
5583
|
+
"test:release-gate": "node scripts/release-gate-test-groups.mjs",
|
|
5584
|
+
"test:release-gate:g1": "node scripts/release-gate-test-groups.mjs --group 1",
|
|
5585
|
+
"test:release-gate:g2": "node scripts/release-gate-test-groups.mjs --group 2",
|
|
5586
|
+
"test:release-gate:g3": "node scripts/release-gate-test-groups.mjs --group 3",
|
|
5587
|
+
"test:release-gate:g4": "node scripts/release-gate-test-groups.mjs --group 4",
|
|
5588
|
+
"test:release-gate:g5": "node scripts/release-gate-test-groups.mjs --group 5",
|
|
5589
|
+
"extension:sync": "node scripts/sync-extension-version.mjs",
|
|
5590
|
+
"extension:build": "npm run extension:sync && tsc -p extension/tsconfig.json && node scripts/copy-extension-assets.mjs",
|
|
5591
|
+
"extension:pack": "cd extension && zip -r ../opendevbrowser-extension.zip manifest.json popup.html dist/ icons/",
|
|
5592
|
+
"extension:store": "node scripts/chrome-store-publish.mjs",
|
|
5593
|
+
"version:check": "node scripts/verify-versions.mjs",
|
|
5594
|
+
prepack: "npm run version:check && npm run build && npm run extension:build"
|
|
5595
|
+
},
|
|
5596
|
+
dependencies: {
|
|
5597
|
+
"@opencode-ai/plugin": "^1.2.11",
|
|
5598
|
+
"@puppeteer/browsers": "^2.13.0",
|
|
5599
|
+
"async-mutex": "^0.5.0",
|
|
5600
|
+
"jsonc-parser": "^3.2.0",
|
|
5601
|
+
"playwright-core": "^1.58.2",
|
|
5602
|
+
ws: "^8.19.0",
|
|
5603
|
+
zod: "^3.25.76"
|
|
5604
|
+
},
|
|
5605
|
+
devDependencies: {
|
|
5606
|
+
"@types/chrome": "^0.1.37",
|
|
5607
|
+
"@types/node": "^20.19.35",
|
|
5608
|
+
"@types/ws": "^8.18.1",
|
|
5609
|
+
"@typescript-eslint/eslint-plugin": "^8.56.1",
|
|
5610
|
+
"@typescript-eslint/parser": "^8.56.1",
|
|
5611
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
5612
|
+
eslint: "^9.39.3",
|
|
5613
|
+
"happy-dom": "^20.7.0",
|
|
5614
|
+
tsup: "^8.5.1",
|
|
5615
|
+
typescript: "^5.9.3",
|
|
5616
|
+
vitest: "^4.0.18"
|
|
5617
|
+
}
|
|
5618
|
+
};
|
|
5619
|
+
|
|
5620
|
+
// src/cli/index.ts
|
|
5621
|
+
var VERSION = typeof package_default.version === "string" ? package_default.version : "0.0.0";
|
|
5622
|
+
async function promptInstallMode() {
|
|
5623
|
+
if (!process.stdin.isTTY) {
|
|
5624
|
+
console.log("Non-interactive mode detected. Using global install.");
|
|
5625
|
+
return "global";
|
|
5626
|
+
}
|
|
5627
|
+
return new Promise((resolve6) => {
|
|
5628
|
+
console.log("\nWhere would you like to install opendevbrowser?\n");
|
|
5629
|
+
console.log(" 1. Global (~/.config/opencode/opencode.json)");
|
|
5630
|
+
console.log(" 2. Local (./opencode.json in this project)\n");
|
|
5631
|
+
process.stdout.write("Enter choice [1]: ");
|
|
5632
|
+
process.stdin.setEncoding("utf8");
|
|
5633
|
+
let resolved = false;
|
|
5634
|
+
let timeoutId = null;
|
|
5635
|
+
const cleanup = () => {
|
|
5636
|
+
if (timeoutId !== null) {
|
|
3744
5637
|
clearTimeout(timeoutId);
|
|
3745
5638
|
timeoutId = null;
|
|
3746
5639
|
}
|
|
@@ -3751,23 +5644,23 @@ async function promptInstallMode() {
|
|
|
3751
5644
|
resolved = true;
|
|
3752
5645
|
const input = data.toString().trim();
|
|
3753
5646
|
if (input === "2") {
|
|
3754
|
-
|
|
5647
|
+
resolve6("local");
|
|
3755
5648
|
} else {
|
|
3756
|
-
|
|
5649
|
+
resolve6("global");
|
|
3757
5650
|
}
|
|
3758
5651
|
});
|
|
3759
5652
|
process.stdin.once("close", () => {
|
|
3760
5653
|
cleanup();
|
|
3761
5654
|
if (resolved) return;
|
|
3762
5655
|
resolved = true;
|
|
3763
|
-
|
|
5656
|
+
resolve6("global");
|
|
3764
5657
|
});
|
|
3765
5658
|
timeoutId = setTimeout(() => {
|
|
3766
5659
|
timeoutId = null;
|
|
3767
5660
|
if (resolved) return;
|
|
3768
5661
|
resolved = true;
|
|
3769
5662
|
console.log("\nTimeout - using global install.");
|
|
3770
|
-
|
|
5663
|
+
resolve6("global");
|
|
3771
5664
|
}, 3e4);
|
|
3772
5665
|
});
|
|
3773
5666
|
}
|
|
@@ -3787,7 +5680,7 @@ async function promptUninstallMode() {
|
|
|
3787
5680
|
console.log("Plugin found in both global and local configs. Use --global or --local flag.");
|
|
3788
5681
|
return null;
|
|
3789
5682
|
}
|
|
3790
|
-
return new Promise((
|
|
5683
|
+
return new Promise((resolve6) => {
|
|
3791
5684
|
console.log("\nopendevbrowser is installed in multiple locations:\n");
|
|
3792
5685
|
console.log(" 1. Global (~/.config/opencode/opencode.json)");
|
|
3793
5686
|
console.log(" 2. Local (./opencode.json)");
|
|
@@ -3797,15 +5690,15 @@ async function promptUninstallMode() {
|
|
|
3797
5690
|
process.stdin.once("data", (data) => {
|
|
3798
5691
|
const input = data.toString().trim();
|
|
3799
5692
|
if (input === "1") {
|
|
3800
|
-
|
|
5693
|
+
resolve6("global");
|
|
3801
5694
|
} else if (input === "2") {
|
|
3802
|
-
|
|
5695
|
+
resolve6("local");
|
|
3803
5696
|
} else {
|
|
3804
|
-
|
|
5697
|
+
resolve6(null);
|
|
3805
5698
|
}
|
|
3806
5699
|
});
|
|
3807
5700
|
process.stdin.once("close", () => {
|
|
3808
|
-
|
|
5701
|
+
resolve6(null);
|
|
3809
5702
|
});
|
|
3810
5703
|
});
|
|
3811
5704
|
}
|
|
@@ -4046,6 +5939,11 @@ async function main() {
|
|
|
4046
5939
|
description: "Request interactive annotations (extension relay)",
|
|
4047
5940
|
run: async () => runAnnotate(args)
|
|
4048
5941
|
});
|
|
5942
|
+
registerCommand({
|
|
5943
|
+
name: "rpc",
|
|
5944
|
+
description: "Execute an internal daemon RPC command (power-user)",
|
|
5945
|
+
run: async () => runRpc(args)
|
|
5946
|
+
});
|
|
4049
5947
|
registerCommand({
|
|
4050
5948
|
name: "click",
|
|
4051
5949
|
description: "Click an element by ref",
|
|
@@ -4191,6 +6089,46 @@ async function main() {
|
|
|
4191
6089
|
description: "Poll network events",
|
|
4192
6090
|
run: async () => runNetworkPoll(args)
|
|
4193
6091
|
});
|
|
6092
|
+
registerCommand({
|
|
6093
|
+
name: "debug-trace-snapshot",
|
|
6094
|
+
description: "Capture page + console + network + exception diagnostics",
|
|
6095
|
+
run: async () => runDebugTraceSnapshot(args)
|
|
6096
|
+
});
|
|
6097
|
+
registerCommand({
|
|
6098
|
+
name: "cookie-import",
|
|
6099
|
+
description: "Import validated cookies into a session",
|
|
6100
|
+
run: async () => runCookieImport(args)
|
|
6101
|
+
});
|
|
6102
|
+
registerCommand({
|
|
6103
|
+
name: "cookie-list",
|
|
6104
|
+
description: "List cookies for a session (optionally filtered by URL)",
|
|
6105
|
+
run: async () => runCookieList(args)
|
|
6106
|
+
});
|
|
6107
|
+
registerCommand({
|
|
6108
|
+
name: "macro-resolve",
|
|
6109
|
+
description: "Resolve or execute a macro expression via provider actions",
|
|
6110
|
+
run: async () => runMacroResolve(args)
|
|
6111
|
+
});
|
|
6112
|
+
registerCommand({
|
|
6113
|
+
name: "research",
|
|
6114
|
+
description: "Run research workflows",
|
|
6115
|
+
run: async () => runResearchCommand(args)
|
|
6116
|
+
});
|
|
6117
|
+
registerCommand({
|
|
6118
|
+
name: "shopping",
|
|
6119
|
+
description: "Run shopping workflows",
|
|
6120
|
+
run: async () => runShoppingCommand(args)
|
|
6121
|
+
});
|
|
6122
|
+
registerCommand({
|
|
6123
|
+
name: "product-video",
|
|
6124
|
+
description: "Run product presentation asset workflows",
|
|
6125
|
+
run: async () => runProductVideoCommand(args)
|
|
6126
|
+
});
|
|
6127
|
+
registerCommand({
|
|
6128
|
+
name: "artifacts",
|
|
6129
|
+
description: "Manage workflow artifact lifecycle",
|
|
6130
|
+
run: async () => runArtifactsCommand(args)
|
|
6131
|
+
});
|
|
4194
6132
|
const command = getCommand(args.command);
|
|
4195
6133
|
if (!command) {
|
|
4196
6134
|
throw new Error(`Unknown command: ${args.command}`);
|