browxai 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +139 -0
- package/THIRD_PARTY_NOTICES.md +45 -0
- package/dist/cli/chrome.d.ts +1 -0
- package/dist/cli/chrome.js +130 -0
- package/dist/cli/command-registry.d.ts +15 -0
- package/dist/cli/command-registry.js +35 -0
- package/dist/cli/doctor-plugins.d.ts +18 -0
- package/dist/cli/doctor-plugins.js +338 -0
- package/dist/cli/doctor.d.ts +9 -0
- package/dist/cli/doctor.js +407 -0
- package/dist/cli/init.d.ts +1 -0
- package/dist/cli/init.js +200 -0
- package/dist/cli/register-commands.d.ts +1 -0
- package/dist/cli/register-commands.js +22 -0
- package/dist/cli/serve.d.ts +14 -0
- package/dist/cli/serve.js +151 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +129 -0
- package/dist/engine/adapters/adb.d.ts +72 -0
- package/dist/engine/adapters/adb.js +200 -0
- package/dist/engine/adapters/android-cdp.d.ts +54 -0
- package/dist/engine/adapters/android-cdp.js +110 -0
- package/dist/engine/adapters/android.engine.d.ts +1 -0
- package/dist/engine/adapters/android.engine.js +31 -0
- package/dist/engine/adapters/chromium.engine.d.ts +1 -0
- package/dist/engine/adapters/chromium.engine.js +44 -0
- package/dist/engine/adapters/firefox.engine.d.ts +1 -0
- package/dist/engine/adapters/firefox.engine.js +43 -0
- package/dist/engine/adapters/playwright-chromium.d.ts +43 -0
- package/dist/engine/adapters/playwright-chromium.js +56 -0
- package/dist/engine/adapters/playwright-firefox.d.ts +52 -0
- package/dist/engine/adapters/playwright-firefox.js +97 -0
- package/dist/engine/adapters/playwright-webkit.d.ts +40 -0
- package/dist/engine/adapters/playwright-webkit.js +79 -0
- package/dist/engine/adapters/safari/bidi-client.d.ts +46 -0
- package/dist/engine/adapters/safari/bidi-client.js +130 -0
- package/dist/engine/adapters/safari/launch.d.ts +56 -0
- package/dist/engine/adapters/safari/launch.js +104 -0
- package/dist/engine/adapters/safari/webdriver-client.d.ts +102 -0
- package/dist/engine/adapters/safari/webdriver-client.js +175 -0
- package/dist/engine/adapters/safari.engine.d.ts +1 -0
- package/dist/engine/adapters/safari.engine.js +52 -0
- package/dist/engine/adapters/safaridriver-hybrid.d.ts +56 -0
- package/dist/engine/adapters/safaridriver-hybrid.js +127 -0
- package/dist/engine/adapters/webkit.engine.d.ts +1 -0
- package/dist/engine/adapters/webkit.engine.js +47 -0
- package/dist/engine/capabilities.d.ts +53 -0
- package/dist/engine/capabilities.js +122 -0
- package/dist/engine/capability-registry.d.ts +9 -0
- package/dist/engine/capability-registry.js +20 -0
- package/dist/engine/index.d.ts +18 -0
- package/dist/engine/index.js +14 -0
- package/dist/engine/register-engines.d.ts +5 -0
- package/dist/engine/register-engines.js +16 -0
- package/dist/engine/registry.d.ts +145 -0
- package/dist/engine/registry.js +67 -0
- package/dist/engine/select.d.ts +48 -0
- package/dist/engine/select.js +128 -0
- package/dist/engine/session-cdp.d.ts +13 -0
- package/dist/engine/session-cdp.js +22 -0
- package/dist/engine/tool-gate.d.ts +19 -0
- package/dist/engine/tool-gate.js +226 -0
- package/dist/engine/types.d.ts +71 -0
- package/dist/engine/types.js +16 -0
- package/dist/helper/bridge.d.ts +48 -0
- package/dist/helper/bridge.js +200 -0
- package/dist/helper/browx-page.d.ts +1 -0
- package/dist/helper/browx-page.js +47 -0
- package/dist/helper/overlay-hide.d.ts +9 -0
- package/dist/helper/overlay-hide.js +49 -0
- package/dist/helper/stealth.d.ts +10 -0
- package/dist/helper/stealth.js +88 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +15 -0
- package/dist/page/a11y.d.ts +81 -0
- package/dist/page/a11y.js +219 -0
- package/dist/page/action-substrate.d.ts +64 -0
- package/dist/page/action-substrate.js +118 -0
- package/dist/page/actionresult-blocks.d.ts +99 -0
- package/dist/page/actionresult-blocks.js +144 -0
- package/dist/page/actionresult-shape.d.ts +48 -0
- package/dist/page/actionresult-shape.js +155 -0
- package/dist/page/actionresult-types.d.ts +368 -0
- package/dist/page/actionresult-types.js +4 -0
- package/dist/page/actionresult.d.ts +4 -0
- package/dist/page/actionresult.js +299 -0
- package/dist/page/actions-probe.d.ts +32 -0
- package/dist/page/actions-probe.js +294 -0
- package/dist/page/actions-scroll.d.ts +40 -0
- package/dist/page/actions-scroll.js +53 -0
- package/dist/page/actions.d.ts +132 -0
- package/dist/page/actions.js +453 -0
- package/dist/page/archive-assets.d.ts +39 -0
- package/dist/page/archive-assets.js +187 -0
- package/dist/page/archive.d.ts +47 -0
- package/dist/page/archive.js +349 -0
- package/dist/page/asset-export.d.ts +122 -0
- package/dist/page/asset-export.js +376 -0
- package/dist/page/await_network.d.ts +16 -0
- package/dist/page/await_network.js +23 -0
- package/dist/page/bbox.d.ts +37 -0
- package/dist/page/bbox.js +115 -0
- package/dist/page/canvas-capture.d.ts +82 -0
- package/dist/page/canvas-capture.js +257 -0
- package/dist/page/canvas-diff.d.ts +51 -0
- package/dist/page/canvas-diff.js +131 -0
- package/dist/page/canvas-gesture.d.ts +53 -0
- package/dist/page/canvas-gesture.js +167 -0
- package/dist/page/canvas-transform.d.ts +96 -0
- package/dist/page/canvas-transform.js +150 -0
- package/dist/page/canvas.d.ts +8 -0
- package/dist/page/canvas.js +50 -0
- package/dist/page/capture-substrate.d.ts +111 -0
- package/dist/page/capture-substrate.js +139 -0
- package/dist/page/clipboard.d.ts +25 -0
- package/dist/page/clipboard.js +50 -0
- package/dist/page/clock.d.ts +36 -0
- package/dist/page/clock.js +167 -0
- package/dist/page/compose.d.ts +55 -0
- package/dist/page/compose.js +169 -0
- package/dist/page/console.d.ts +39 -0
- package/dist/page/console.js +73 -0
- package/dist/page/coverage.d.ts +97 -0
- package/dist/page/coverage.js +280 -0
- package/dist/page/dom-export.d.ts +41 -0
- package/dist/page/dom-export.js +193 -0
- package/dist/page/dom-walk.d.ts +91 -0
- package/dist/page/dom-walk.js +267 -0
- package/dist/page/dom_diff.d.ts +48 -0
- package/dist/page/dom_diff.js +121 -0
- package/dist/page/downloads.d.ts +80 -0
- package/dist/page/downloads.js +244 -0
- package/dist/page/drop-files.d.ts +78 -0
- package/dist/page/drop-files.js +310 -0
- package/dist/page/element-export-discovery.d.ts +64 -0
- package/dist/page/element-export-discovery.js +346 -0
- package/dist/page/element-export.d.ts +46 -0
- package/dist/page/element-export.js +251 -0
- package/dist/page/emulation-substrate.d.ts +53 -0
- package/dist/page/emulation-substrate.js +87 -0
- package/dist/page/emulation.d.ts +60 -0
- package/dist/page/emulation.js +162 -0
- package/dist/page/export-playwright-script.d.ts +47 -0
- package/dist/page/export-playwright-script.js +304 -0
- package/dist/page/extract-resolve.d.ts +22 -0
- package/dist/page/extract-resolve.js +341 -0
- package/dist/page/extract-schema.d.ts +20 -0
- package/dist/page/extract-schema.js +200 -0
- package/dist/page/extract-types.d.ts +127 -0
- package/dist/page/extract-types.js +8 -0
- package/dist/page/extract-warnings.d.ts +8 -0
- package/dist/page/extract-warnings.js +56 -0
- package/dist/page/extract.d.ts +9 -0
- package/dist/page/extract.js +174 -0
- package/dist/page/fill-form.d.ts +58 -0
- package/dist/page/fill-form.js +261 -0
- package/dist/page/find.d.ts +158 -0
- package/dist/page/find.js +470 -0
- package/dist/page/frames.d.ts +45 -0
- package/dist/page/frames.js +133 -0
- package/dist/page/generate-locator.d.ts +57 -0
- package/dist/page/generate-locator.js +136 -0
- package/dist/page/gestures.d.ts +128 -0
- package/dist/page/gestures.js +198 -0
- package/dist/page/har.d.ts +91 -0
- package/dist/page/har.js +174 -0
- package/dist/page/heap.d.ts +97 -0
- package/dist/page/heap.js +285 -0
- package/dist/page/inspect.d.ts +34 -0
- package/dist/page/inspect.js +75 -0
- package/dist/page/layout-thrash.d.ts +34 -0
- package/dist/page/layout-thrash.js +232 -0
- package/dist/page/learning.d.ts +21 -0
- package/dist/page/learning.js +84 -0
- package/dist/page/locator.d.ts +54 -0
- package/dist/page/locator.js +142 -0
- package/dist/page/memory-diff.d.ts +48 -0
- package/dist/page/memory-diff.js +105 -0
- package/dist/page/network-mask.d.ts +8 -0
- package/dist/page/network-mask.js +18 -0
- package/dist/page/network-playwright.d.ts +96 -0
- package/dist/page/network-playwright.js +353 -0
- package/dist/page/network-substrate-select.d.ts +18 -0
- package/dist/page/network-substrate-select.js +32 -0
- package/dist/page/network-substrate.d.ts +109 -0
- package/dist/page/network-substrate.js +161 -0
- package/dist/page/network-ws.d.ts +46 -0
- package/dist/page/network-ws.js +113 -0
- package/dist/page/network.d.ts +194 -0
- package/dist/page/network.js +415 -0
- package/dist/page/overflow-detect.d.ts +102 -0
- package/dist/page/overflow-detect.js +449 -0
- package/dist/page/pdf.d.ts +69 -0
- package/dist/page/pdf.js +109 -0
- package/dist/page/perf-audit-analysers.d.ts +40 -0
- package/dist/page/perf-audit-analysers.js +369 -0
- package/dist/page/perf-audit-runner.d.ts +20 -0
- package/dist/page/perf-audit-runner.js +195 -0
- package/dist/page/perf-audit-types.d.ts +41 -0
- package/dist/page/perf-audit-types.js +5 -0
- package/dist/page/perf-audit.d.ts +37 -0
- package/dist/page/perf-audit.js +377 -0
- package/dist/page/perf.d.ts +127 -0
- package/dist/page/perf.js +373 -0
- package/dist/page/plan.d.ts +192 -0
- package/dist/page/plan.js +308 -0
- package/dist/page/point_probe.d.ts +46 -0
- package/dist/page/point_probe.js +99 -0
- package/dist/page/recording.d.ts +67 -0
- package/dist/page/recording.js +172 -0
- package/dist/page/refs.d.ts +92 -0
- package/dist/page/refs.js +134 -0
- package/dist/page/regions.d.ts +23 -0
- package/dist/page/regions.js +32 -0
- package/dist/page/routes.d.ts +40 -0
- package/dist/page/routes.js +87 -0
- package/dist/page/safari-actions.d.ts +12 -0
- package/dist/page/safari-actions.js +144 -0
- package/dist/page/sample.d.ts +64 -0
- package/dist/page/sample.js +216 -0
- package/dist/page/screenshot-on.d.ts +51 -0
- package/dist/page/screenshot-on.js +150 -0
- package/dist/page/screenshot-save.d.ts +36 -0
- package/dist/page/screenshot-save.js +53 -0
- package/dist/page/screenshot-schedule.d.ts +50 -0
- package/dist/page/screenshot-schedule.js +155 -0
- package/dist/page/script-substrate.d.ts +32 -0
- package/dist/page/script-substrate.js +47 -0
- package/dist/page/seed-random.d.ts +45 -0
- package/dist/page/seed-random.js +144 -0
- package/dist/page/set-of-marks.d.ts +96 -0
- package/dist/page/set-of-marks.js +245 -0
- package/dist/page/shadow.d.ts +136 -0
- package/dist/page/shadow.js +400 -0
- package/dist/page/shortcut.d.ts +50 -0
- package/dist/page/shortcut.js +147 -0
- package/dist/page/snapshot-substrate-safari.d.ts +30 -0
- package/dist/page/snapshot-substrate-safari.js +84 -0
- package/dist/page/snapshot-substrate-select.d.ts +24 -0
- package/dist/page/snapshot-substrate-select.js +34 -0
- package/dist/page/snapshot-substrate.d.ts +58 -0
- package/dist/page/snapshot-substrate.js +135 -0
- package/dist/page/snapshot.d.ts +24 -0
- package/dist/page/snapshot.js +162 -0
- package/dist/page/solve-captcha.d.ts +76 -0
- package/dist/page/solve-captcha.js +286 -0
- package/dist/page/storage-substrate-types.d.ts +221 -0
- package/dist/page/storage-substrate-types.js +6 -0
- package/dist/page/storage-substrate.d.ts +215 -0
- package/dist/page/storage-substrate.js +280 -0
- package/dist/page/structural.d.ts +9 -0
- package/dist/page/structural.js +152 -0
- package/dist/page/substrate-bundle-safari.d.ts +8 -0
- package/dist/page/substrate-bundle-safari.js +42 -0
- package/dist/page/substrate-bundle.d.ts +6 -0
- package/dist/page/substrate-bundle.js +53 -0
- package/dist/page/text_search.d.ts +44 -0
- package/dist/page/text_search.js +90 -0
- package/dist/page/upload.d.ts +28 -0
- package/dist/page/upload.js +62 -0
- package/dist/page/verify.d.ts +63 -0
- package/dist/page/verify.js +451 -0
- package/dist/page/video.d.ts +115 -0
- package/dist/page/video.js +169 -0
- package/dist/page/visibility.d.ts +22 -0
- package/dist/page/visibility.js +94 -0
- package/dist/page/watch.d.ts +29 -0
- package/dist/page/watch.js +99 -0
- package/dist/page/workers.d.ts +126 -0
- package/dist/page/workers.js +490 -0
- package/dist/page/ws-interactive.d.ts +82 -0
- package/dist/page/ws-interactive.js +318 -0
- package/dist/plugin/cli.d.ts +45 -0
- package/dist/plugin/cli.js +496 -0
- package/dist/plugin/command-registry.d.ts +9 -0
- package/dist/plugin/command-registry.js +23 -0
- package/dist/plugin/depgraph.d.ts +37 -0
- package/dist/plugin/depgraph.js +186 -0
- package/dist/plugin/manifest.d.ts +182 -0
- package/dist/plugin/manifest.js +219 -0
- package/dist/plugin/package-manager.d.ts +22 -0
- package/dist/plugin/package-manager.js +40 -0
- package/dist/plugin/resolver.d.ts +85 -0
- package/dist/plugin/resolver.js +166 -0
- package/dist/plugin/runtime.d.ts +77 -0
- package/dist/plugin/runtime.js +402 -0
- package/dist/plugin/types.d.ts +113 -0
- package/dist/plugin/types.js +4 -0
- package/dist/policy/confirm.d.ts +76 -0
- package/dist/policy/confirm.js +162 -0
- package/dist/policy/origin.d.ts +17 -0
- package/dist/policy/origin.js +79 -0
- package/dist/sdk/client.d.ts +21 -0
- package/dist/sdk/client.js +174 -0
- package/dist/sdk/index.d.ts +32 -0
- package/dist/sdk/index.js +61 -0
- package/dist/sdk/plugin-types.d.ts +33 -0
- package/dist/sdk/plugin-types.js +22 -0
- package/dist/sdk/registry.d.ts +17 -0
- package/dist/sdk/registry.js +94 -0
- package/dist/sdk/socket-transport.d.ts +20 -0
- package/dist/sdk/socket-transport.js +90 -0
- package/dist/sdk/tool-types.d.ts +634 -0
- package/dist/sdk/tool-types.js +28 -0
- package/dist/sdk/transport-in-process.d.ts +21 -0
- package/dist/sdk/transport-in-process.js +44 -0
- package/dist/sdk/transport-registry.d.ts +19 -0
- package/dist/sdk/transport-registry.js +31 -0
- package/dist/sdk/transport-socket.d.ts +12 -0
- package/dist/sdk/transport-socket.js +77 -0
- package/dist/sdk/transport-stdio-child.d.ts +10 -0
- package/dist/sdk/transport-stdio-child.js +47 -0
- package/dist/sdk/transport.d.ts +10 -0
- package/dist/sdk/transport.js +35 -0
- package/dist/sdk/types.d.ts +176 -0
- package/dist/sdk/types.js +10 -0
- package/dist/server.d.ts +33 -0
- package/dist/server.js +327 -0
- package/dist/session/artifacts.d.ts +52 -0
- package/dist/session/artifacts.js +177 -0
- package/dist/session/byob-attach.d.ts +26 -0
- package/dist/session/byob-attach.js +187 -0
- package/dist/session/byob.d.ts +8 -0
- package/dist/session/byob.js +20 -0
- package/dist/session/cache-storage.d.ts +100 -0
- package/dist/session/cache-storage.js +166 -0
- package/dist/session/device-emu.d.ts +149 -0
- package/dist/session/device-emu.js +545 -0
- package/dist/session/device.d.ts +14 -0
- package/dist/session/device.js +44 -0
- package/dist/session/dialog.d.ts +62 -0
- package/dist/session/dialog.js +164 -0
- package/dist/session/emulation.d.ts +69 -0
- package/dist/session/emulation.js +168 -0
- package/dist/session/extensions.d.ts +113 -0
- package/dist/session/extensions.js +237 -0
- package/dist/session/fs-picker.d.ts +144 -0
- package/dist/session/fs-picker.js +666 -0
- package/dist/session/idb-storage.d.ts +86 -0
- package/dist/session/idb-storage.js +229 -0
- package/dist/session/incognito.d.ts +3 -0
- package/dist/session/incognito.js +20 -0
- package/dist/session/launch-options.d.ts +41 -0
- package/dist/session/launch-options.js +200 -0
- package/dist/session/managed.d.ts +3 -0
- package/dist/session/managed.js +16 -0
- package/dist/session/metrics.d.ts +45 -0
- package/dist/session/metrics.js +75 -0
- package/dist/session/notification.d.ts +122 -0
- package/dist/session/notification.js +426 -0
- package/dist/session/permission.d.ts +144 -0
- package/dist/session/permission.js +600 -0
- package/dist/session/playwright-post-wire.d.ts +8 -0
- package/dist/session/playwright-post-wire.js +148 -0
- package/dist/session/policy-buffer.d.ts +21 -0
- package/dist/session/policy-buffer.js +47 -0
- package/dist/session/profile-snapshot.d.ts +11 -0
- package/dist/session/profile-snapshot.js +53 -0
- package/dist/session/registry.d.ts +365 -0
- package/dist/session/registry.js +98 -0
- package/dist/session/safari-post-wire.d.ts +8 -0
- package/dist/session/safari-post-wire.js +28 -0
- package/dist/session/safari-session.d.ts +10 -0
- package/dist/session/safari-session.js +39 -0
- package/dist/session/storage.d.ts +148 -0
- package/dist/session/storage.js +350 -0
- package/dist/session/types.d.ts +113 -0
- package/dist/session/types.js +5 -0
- package/dist/session/wedge.d.ts +15 -0
- package/dist/session/wedge.js +41 -0
- package/dist/tools/action-core-tools.d.ts +13 -0
- package/dist/tools/action-core-tools.js +156 -0
- package/dist/tools/action-form-tools.d.ts +12 -0
- package/dist/tools/action-form-tools.js +179 -0
- package/dist/tools/action-gesture-tools.d.ts +9 -0
- package/dist/tools/action-gesture-tools.js +115 -0
- package/dist/tools/action-history-tools.d.ts +8 -0
- package/dist/tools/action-history-tools.js +67 -0
- package/dist/tools/action-tool.d.ts +42 -0
- package/dist/tools/action-tool.js +58 -0
- package/dist/tools/action-tools.d.ts +20 -0
- package/dist/tools/action-tools.js +28 -0
- package/dist/tools/batch-act-tools.d.ts +10 -0
- package/dist/tools/batch-act-tools.js +276 -0
- package/dist/tools/batch-human-tools.d.ts +8 -0
- package/dist/tools/batch-human-tools.js +148 -0
- package/dist/tools/canvas-tools.d.ts +40 -0
- package/dist/tools/canvas-tools.js +368 -0
- package/dist/tools/capture-report-diagnostics-tools.d.ts +7 -0
- package/dist/tools/capture-report-diagnostics-tools.js +318 -0
- package/dist/tools/capture-report-element-export-tools.d.ts +8 -0
- package/dist/tools/capture-report-element-export-tools.js +197 -0
- package/dist/tools/capture-report-export-tools.d.ts +8 -0
- package/dist/tools/capture-report-export-tools.js +246 -0
- package/dist/tools/capture-report-marks-tools.d.ts +9 -0
- package/dist/tools/capture-report-marks-tools.js +221 -0
- package/dist/tools/capture-report-upload-tools.d.ts +8 -0
- package/dist/tools/capture-report-upload-tools.js +277 -0
- package/dist/tools/config-approval-tools.d.ts +8 -0
- package/dist/tools/config-approval-tools.js +166 -0
- package/dist/tools/deep-coverage-tools.d.ts +8 -0
- package/dist/tools/deep-coverage-tools.js +325 -0
- package/dist/tools/deep-determinism-tools.d.ts +8 -0
- package/dist/tools/deep-determinism-tools.js +276 -0
- package/dist/tools/deep-perf-tools.d.ts +19 -0
- package/dist/tools/deep-perf-tools.js +324 -0
- package/dist/tools/device-emulation-tools.d.ts +9 -0
- package/dist/tools/device-emulation-tools.js +137 -0
- package/dist/tools/extensions-batch-tools.d.ts +18 -0
- package/dist/tools/extensions-batch-tools.js +24 -0
- package/dist/tools/extensions-rebuild.d.ts +22 -0
- package/dist/tools/extensions-rebuild.js +208 -0
- package/dist/tools/extensions-tools.d.ts +2 -0
- package/dist/tools/extensions-tools.js +331 -0
- package/dist/tools/forms-fill-tools.d.ts +8 -0
- package/dist/tools/forms-fill-tools.js +109 -0
- package/dist/tools/forms-plan-tools.d.ts +7 -0
- package/dist/tools/forms-plan-tools.js +159 -0
- package/dist/tools/forms-recording-mode-tools.d.ts +8 -0
- package/dist/tools/forms-recording-mode-tools.js +71 -0
- package/dist/tools/forms-recording-tools.d.ts +14 -0
- package/dist/tools/forms-recording-tools.js +22 -0
- package/dist/tools/forms-refs-tools.d.ts +8 -0
- package/dist/tools/forms-refs-tools.js +90 -0
- package/dist/tools/gesture-coord-tools.d.ts +8 -0
- package/dist/tools/gesture-coord-tools.js +168 -0
- package/dist/tools/gesture-emulation-tools.d.ts +8 -0
- package/dist/tools/gesture-emulation-tools.js +135 -0
- package/dist/tools/gesture-network-tools.d.ts +17 -0
- package/dist/tools/gesture-network-tools.js +27 -0
- package/dist/tools/gesture-route-tools.d.ts +8 -0
- package/dist/tools/gesture-route-tools.js +142 -0
- package/dist/tools/gesture-websocket-tools.d.ts +8 -0
- package/dist/tools/gesture-websocket-tools.js +122 -0
- package/dist/tools/gesture-worker-tools.d.ts +9 -0
- package/dist/tools/gesture-worker-tools.js +200 -0
- package/dist/tools/host-build.d.ts +76 -0
- package/dist/tools/host-build.js +516 -0
- package/dist/tools/host.d.ts +287 -0
- package/dist/tools/host.js +1 -0
- package/dist/tools/input-tools.d.ts +10 -0
- package/dist/tools/input-tools.js +176 -0
- package/dist/tools/live-emulation-tools.d.ts +9 -0
- package/dist/tools/live-emulation-tools.js +353 -0
- package/dist/tools/plugin-runtime.d.ts +36 -0
- package/dist/tools/plugin-runtime.js +274 -0
- package/dist/tools/read-observe-buffer-tools.d.ts +9 -0
- package/dist/tools/read-observe-buffer-tools.js +385 -0
- package/dist/tools/read-observe-capture-tools.d.ts +12 -0
- package/dist/tools/read-observe-capture-tools.js +376 -0
- package/dist/tools/read-observe-dom-tools.d.ts +8 -0
- package/dist/tools/read-observe-dom-tools.js +308 -0
- package/dist/tools/read-observe-extract-tools.d.ts +8 -0
- package/dist/tools/read-observe-extract-tools.js +232 -0
- package/dist/tools/read-observe-verify-tools.d.ts +8 -0
- package/dist/tools/read-observe-verify-tools.js +316 -0
- package/dist/tools/schemas.d.ts +29 -0
- package/dist/tools/schemas.js +58 -0
- package/dist/tools/secrets-captcha-tools.d.ts +9 -0
- package/dist/tools/secrets-captcha-tools.js +231 -0
- package/dist/tools/session-dialog-permission-tools.d.ts +9 -0
- package/dist/tools/session-dialog-permission-tools.js +287 -0
- package/dist/tools/session-lifecycle-tools.d.ts +8 -0
- package/dist/tools/session-lifecycle-tools.js +314 -0
- package/dist/tools/session-notification-device-tools.d.ts +9 -0
- package/dist/tools/session-notification-device-tools.js +156 -0
- package/dist/tools/session-policy-tools.d.ts +16 -0
- package/dist/tools/session-policy-tools.js +22 -0
- package/dist/tools/session-registry.d.ts +28 -0
- package/dist/tools/session-registry.js +427 -0
- package/dist/tools/storage-artifact-har-video-tools.d.ts +8 -0
- package/dist/tools/storage-artifact-har-video-tools.js +311 -0
- package/dist/tools/storage-cache-idb-tools.d.ts +8 -0
- package/dist/tools/storage-cache-idb-tools.js +347 -0
- package/dist/tools/storage-state-cookies-tools.d.ts +8 -0
- package/dist/tools/storage-state-cookies-tools.js +223 -0
- package/dist/tools/storage-tools.d.ts +17 -0
- package/dist/tools/storage-tools.js +25 -0
- package/dist/tools/storage-web-auth-tools.d.ts +10 -0
- package/dist/tools/storage-web-auth-tools.js +230 -0
- package/dist/tools/tool-metadata.d.ts +8 -0
- package/dist/tools/tool-metadata.js +185 -0
- package/dist/util/batch.d.ts +83 -0
- package/dist/util/batch.js +191 -0
- package/dist/util/capabilities.d.ts +504 -0
- package/dist/util/capabilities.js +254 -0
- package/dist/util/config-store.d.ts +103 -0
- package/dist/util/config-store.js +206 -0
- package/dist/util/config.d.ts +11 -0
- package/dist/util/config.js +28 -0
- package/dist/util/credentials.d.ts +136 -0
- package/dist/util/credentials.js +622 -0
- package/dist/util/deadline.d.ts +22 -0
- package/dist/util/deadline.js +62 -0
- package/dist/util/diagnostics.d.ts +161 -0
- package/dist/util/diagnostics.js +579 -0
- package/dist/util/egress-sanitiser.d.ts +29 -0
- package/dist/util/egress-sanitiser.js +52 -0
- package/dist/util/failure.d.ts +8 -0
- package/dist/util/failure.js +50 -0
- package/dist/util/flake-check.d.ts +109 -0
- package/dist/util/flake-check.js +342 -0
- package/dist/util/invariant.d.ts +25 -0
- package/dist/util/invariant.js +66 -0
- package/dist/util/logging.d.ts +6 -0
- package/dist/util/logging.js +12 -0
- package/dist/util/predicates.d.ts +62 -0
- package/dist/util/predicates.js +340 -0
- package/dist/util/secrets.d.ts +104 -0
- package/dist/util/secrets.js +219 -0
- package/dist/util/tokens.d.ts +6 -0
- package/dist/util/tokens.js +24 -0
- package/dist/util/url-sanitizer.d.ts +19 -0
- package/dist/util/url-sanitizer.js +70 -0
- package/dist/util/version.d.ts +2 -0
- package/dist/util/version.js +21 -0
- package/dist/util/workspace.d.ts +7 -0
- package/dist/util/workspace.js +22 -0
- package/package.json +120 -0
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
// Shadow DOM deep piercing.
|
|
2
|
+
//
|
|
3
|
+
// Two layers:
|
|
4
|
+
// 1. Open shadow — reachable from page-side JS via `Element.shadowRoot`.
|
|
5
|
+
// A `Runtime.evaluate`-driven walker covers this case identically to the
|
|
6
|
+
// one in `dom-export.ts`'s jsonl path.
|
|
7
|
+
// 2. Closed shadow — `Element.shadowRoot === null` for any closed-mode
|
|
8
|
+
// web component, but DevTools-level access via `DOM.getDocument({pierce:
|
|
9
|
+
// true, depth: -1})` returns the closed-shadow subtree in each node's
|
|
10
|
+
// `shadowRoots[]` array (CDP exposes both open + closed; the page-side
|
|
11
|
+
// JS only ever sees open).
|
|
12
|
+
//
|
|
13
|
+
// Best-effort by design:
|
|
14
|
+
// - CDP `pierce` is a Chromium DevTools facility, not a web-platform
|
|
15
|
+
// guarantee. Older Chrome builds, non-Chromium browsers, and pages whose
|
|
16
|
+
// renderer is throttled / detached will fall back to the open-only view
|
|
17
|
+
// and surface a `closedShadowAvailable: false` flag.
|
|
18
|
+
// - Closed shadow piercing is intentionally one-way: we read what CDP
|
|
19
|
+
// exposes. We never reach in via the page itself (which would require
|
|
20
|
+
// patching `attachShadow` before the page loaded — out of scope; the
|
|
21
|
+
// `stealth` capability already covers that direction for adjacent reasons).
|
|
22
|
+
//
|
|
23
|
+
// Everything in this file is read-only.
|
|
24
|
+
/**
|
|
25
|
+
* Read the full pierced DOM. Returns the root node and a "closed shadow root
|
|
26
|
+
* exists somewhere" flag. Falls back to an open-only document when CDP refuses
|
|
27
|
+
* the `pierce` parameter (older Chromium, attached BYOB endpoints whose CDP
|
|
28
|
+
* vintage differs from the launcher's). Caller is responsible for treating a
|
|
29
|
+
* `null` result as "shadow walk unavailable" — no exception is thrown so the
|
|
30
|
+
* outer tool can still emit a partial result.
|
|
31
|
+
*/
|
|
32
|
+
export async function fetchPiercedDocument(cdp) {
|
|
33
|
+
// depth: -1 = walk full subtree. pierce: true = traverse shadow + iframes.
|
|
34
|
+
try {
|
|
35
|
+
const { root } = (await cdp.send("DOM.getDocument", {
|
|
36
|
+
depth: -1,
|
|
37
|
+
pierce: true,
|
|
38
|
+
}));
|
|
39
|
+
return { root, closedAvailable: hasClosedShadow(root) };
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
43
|
+
return {
|
|
44
|
+
root: null,
|
|
45
|
+
closedAvailable: false,
|
|
46
|
+
warning: `CDP DOM.getDocument({pierce:true}) failed (${msg}); ` +
|
|
47
|
+
`closed-shadow piercing unavailable on this browser/page. ` +
|
|
48
|
+
`Open shadow roots are still reachable via the standard walk.`,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function hasClosedShadow(root) {
|
|
53
|
+
// Iterative DFS to avoid stack blow-up on large documents.
|
|
54
|
+
const stack = [root];
|
|
55
|
+
while (stack.length) {
|
|
56
|
+
const n = stack.pop();
|
|
57
|
+
for (const sr of n.shadowRoots ?? []) {
|
|
58
|
+
if (sr.shadowRootType === "closed")
|
|
59
|
+
return true;
|
|
60
|
+
stack.push(sr);
|
|
61
|
+
}
|
|
62
|
+
for (const c of n.children ?? [])
|
|
63
|
+
stack.push(c);
|
|
64
|
+
if (n.contentDocument)
|
|
65
|
+
stack.push(n.contentDocument);
|
|
66
|
+
}
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Walk a CDP-pierced document and collect shadow-root entries. When
|
|
71
|
+
* `rootBackendNodeId` is set, only the subtree rooted at that backend id
|
|
72
|
+
* contributes. When omitted, the entire document is walked.
|
|
73
|
+
*/
|
|
74
|
+
export function collectShadowTrees(root, opts) {
|
|
75
|
+
const cap = opts.maxHosts ?? 200;
|
|
76
|
+
let subtree = root;
|
|
77
|
+
if (opts.rootBackendNodeId !== undefined) {
|
|
78
|
+
subtree = findByBackendId(root, opts.rootBackendNodeId);
|
|
79
|
+
if (!subtree)
|
|
80
|
+
return { entries: [] };
|
|
81
|
+
}
|
|
82
|
+
const entries = [];
|
|
83
|
+
walkForShadowHosts(subtree, entries, cap);
|
|
84
|
+
if (entries.length >= cap)
|
|
85
|
+
return { entries, cappedAt: cap };
|
|
86
|
+
return { entries };
|
|
87
|
+
}
|
|
88
|
+
function findByBackendId(root, target) {
|
|
89
|
+
const stack = [root];
|
|
90
|
+
while (stack.length) {
|
|
91
|
+
const n = stack.pop();
|
|
92
|
+
if (n.backendNodeId === target)
|
|
93
|
+
return n;
|
|
94
|
+
for (const c of n.children ?? [])
|
|
95
|
+
stack.push(c);
|
|
96
|
+
for (const sr of n.shadowRoots ?? [])
|
|
97
|
+
stack.push(sr);
|
|
98
|
+
if (n.contentDocument)
|
|
99
|
+
stack.push(n.contentDocument);
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
/** Summarise the element children of one shadow root (tag + child count + direct
|
|
104
|
+
* text), skipping non-element nodes. */
|
|
105
|
+
function summariseShadowChildren(sr) {
|
|
106
|
+
const children = [];
|
|
107
|
+
for (const c of sr.children ?? []) {
|
|
108
|
+
if (c.nodeType !== 1)
|
|
109
|
+
continue;
|
|
110
|
+
const summary = {
|
|
111
|
+
tag: (c.localName ?? c.nodeName ?? "").toLowerCase(),
|
|
112
|
+
childCount: countElementChildren(c),
|
|
113
|
+
};
|
|
114
|
+
const txt = directText(c);
|
|
115
|
+
if (txt)
|
|
116
|
+
summary.text = txt;
|
|
117
|
+
children.push(summary);
|
|
118
|
+
}
|
|
119
|
+
return children;
|
|
120
|
+
}
|
|
121
|
+
/** Build the `ShadowTreeEntry` for one host node + shadow root (non-user-agent). */
|
|
122
|
+
function buildShadowEntry(host, sr) {
|
|
123
|
+
return {
|
|
124
|
+
hostRef: `backend:${host.backendNodeId ?? 0}`,
|
|
125
|
+
hostTag: (host.localName ?? host.nodeName ?? "").toLowerCase(),
|
|
126
|
+
mode: sr.shadowRootType === "closed" ? "closed" : "open",
|
|
127
|
+
children: summariseShadowChildren(sr),
|
|
128
|
+
descendantCount: countDescendantElements(sr),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function walkForShadowHosts(node, out, cap) {
|
|
132
|
+
// BFS so we surface hosts in document order — easier for an agent to reason
|
|
133
|
+
// about than DFS's reverse traversal.
|
|
134
|
+
const queue = [node];
|
|
135
|
+
while (queue.length && out.length < cap) {
|
|
136
|
+
const n = queue.shift();
|
|
137
|
+
for (const sr of n.shadowRoots ?? []) {
|
|
138
|
+
if (out.length >= cap)
|
|
139
|
+
break;
|
|
140
|
+
// user-agent shadow roots (e.g. <video> internals) aren't the adopter's
|
|
141
|
+
// app — not what an agent means by "the shadow root under this component."
|
|
142
|
+
if (sr.shadowRootType === "user-agent")
|
|
143
|
+
continue;
|
|
144
|
+
out.push(buildShadowEntry(n, sr));
|
|
145
|
+
for (const c of sr.children ?? [])
|
|
146
|
+
queue.push(c); // descend for nested hosts
|
|
147
|
+
}
|
|
148
|
+
for (const c of n.children ?? [])
|
|
149
|
+
queue.push(c);
|
|
150
|
+
if (n.contentDocument)
|
|
151
|
+
queue.push(n.contentDocument);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
function directText(node) {
|
|
155
|
+
for (const c of node.children ?? []) {
|
|
156
|
+
if (c.nodeType === 3 && c.nodeValue) {
|
|
157
|
+
const t = c.nodeValue.replace(/\s+/g, " ").trim();
|
|
158
|
+
if (t)
|
|
159
|
+
return t.length > 80 ? `${t.slice(0, 79)}…` : t;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return undefined;
|
|
163
|
+
}
|
|
164
|
+
function countElementChildren(node) {
|
|
165
|
+
let n = 0;
|
|
166
|
+
for (const c of node.children ?? [])
|
|
167
|
+
if (c.nodeType === 1)
|
|
168
|
+
n++;
|
|
169
|
+
return n;
|
|
170
|
+
}
|
|
171
|
+
function countDescendantElements(node) {
|
|
172
|
+
let n = 0;
|
|
173
|
+
const stack = [...(node.children ?? [])];
|
|
174
|
+
while (stack.length) {
|
|
175
|
+
const c = stack.pop();
|
|
176
|
+
if (c.nodeType === 1) {
|
|
177
|
+
n++;
|
|
178
|
+
for (const cc of c.children ?? [])
|
|
179
|
+
stack.push(cc);
|
|
180
|
+
for (const sr of c.shadowRoots ?? [])
|
|
181
|
+
stack.push(sr);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return n;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* In-page walker for the OPEN-shadow case. This is the fast path used when
|
|
188
|
+
* `pierce: "open"` is requested — no CDP `pierce:true` call needed,
|
|
189
|
+
* Chromium-version-independent. Returns the same `ShadowTreeEntry[]` shape as
|
|
190
|
+
* the closed-aware walker so the tool surface is uniform.
|
|
191
|
+
*
|
|
192
|
+
* Run as a `Runtime.evaluate` — kept ES5-ish so it survives every Chromium
|
|
193
|
+
* vintage the project supports.
|
|
194
|
+
*/
|
|
195
|
+
const OPEN_SHADOW_WALK = `function(rootSel, max) {
|
|
196
|
+
var roots = [];
|
|
197
|
+
var queue = [];
|
|
198
|
+
if (rootSel) {
|
|
199
|
+
try {
|
|
200
|
+
var seed = document.querySelector(rootSel);
|
|
201
|
+
if (seed) queue.push(seed);
|
|
202
|
+
} catch (_) { return { trees: [] }; }
|
|
203
|
+
} else if (document.documentElement) {
|
|
204
|
+
queue.push(document.documentElement);
|
|
205
|
+
}
|
|
206
|
+
function directText(el) {
|
|
207
|
+
var t = '';
|
|
208
|
+
var kids = el.childNodes;
|
|
209
|
+
for (var i = 0; i < kids.length; i++) {
|
|
210
|
+
if (kids[i].nodeType === 3) t += kids[i].nodeValue || '';
|
|
211
|
+
}
|
|
212
|
+
t = t.replace(/\\s+/g, ' ').trim();
|
|
213
|
+
if (!t) return null;
|
|
214
|
+
return t.length > 80 ? t.slice(0, 79) + '…' : t;
|
|
215
|
+
}
|
|
216
|
+
function descendantCount(root) {
|
|
217
|
+
var n = 0;
|
|
218
|
+
var stack = [];
|
|
219
|
+
for (var i = 0; i < root.children.length; i++) stack.push(root.children[i]);
|
|
220
|
+
while (stack.length) {
|
|
221
|
+
var c = stack.pop();
|
|
222
|
+
n++;
|
|
223
|
+
for (var j = 0; j < c.children.length; j++) stack.push(c.children[j]);
|
|
224
|
+
if (c.shadowRoot) {
|
|
225
|
+
var skids = c.shadowRoot.children;
|
|
226
|
+
for (var k = 0; k < skids.length; k++) stack.push(skids[k]);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return n;
|
|
230
|
+
}
|
|
231
|
+
while (queue.length && roots.length < max) {
|
|
232
|
+
var n = queue.shift();
|
|
233
|
+
if (n.nodeType !== 1) continue;
|
|
234
|
+
if (n.shadowRoot) {
|
|
235
|
+
var children = [];
|
|
236
|
+
var skids = n.shadowRoot.children;
|
|
237
|
+
for (var i = 0; i < skids.length; i++) {
|
|
238
|
+
var c = skids[i];
|
|
239
|
+
var txt = directText(c);
|
|
240
|
+
var entry = { tag: c.tagName.toLowerCase(), childCount: c.children.length };
|
|
241
|
+
if (txt) entry.text = txt;
|
|
242
|
+
children.push(entry);
|
|
243
|
+
}
|
|
244
|
+
roots.push({
|
|
245
|
+
hostTag: n.tagName.toLowerCase(),
|
|
246
|
+
mode: 'open',
|
|
247
|
+
children: children,
|
|
248
|
+
descendantCount: descendantCount(n.shadowRoot)
|
|
249
|
+
});
|
|
250
|
+
var sk = n.shadowRoot.children;
|
|
251
|
+
for (var j = 0; j < sk.length; j++) queue.push(sk[j]);
|
|
252
|
+
}
|
|
253
|
+
var kids = n.children;
|
|
254
|
+
for (var m = 0; m < kids.length; m++) queue.push(kids[m]);
|
|
255
|
+
}
|
|
256
|
+
return { trees: roots };
|
|
257
|
+
}`;
|
|
258
|
+
/** Page-side counterpart for `shadow_trees` when only open shadow piercing
|
|
259
|
+
* is needed. Cheaper than the CDP `pierce:true` path (no full-document
|
|
260
|
+
* serialisation) and entirely Chromium-version-agnostic. The `hostRef`
|
|
261
|
+
* field is filled in by the caller (the registry is server-side). */
|
|
262
|
+
export async function runOpenShadowWalk(cdp, rootSelector, max) {
|
|
263
|
+
const rootArg = rootSelector ? JSON.stringify(rootSelector) : "null";
|
|
264
|
+
const expr = `(${OPEN_SHADOW_WALK})(${rootArg}, ${max})`;
|
|
265
|
+
try {
|
|
266
|
+
const { result } = (await cdp.send("Runtime.evaluate", {
|
|
267
|
+
expression: expr,
|
|
268
|
+
returnByValue: true,
|
|
269
|
+
awaitPromise: false,
|
|
270
|
+
}));
|
|
271
|
+
return result.value?.trees ?? [];
|
|
272
|
+
}
|
|
273
|
+
catch {
|
|
274
|
+
return [];
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Harvest interactive / test-attr-bearing elements from CLOSED shadow roots
|
|
279
|
+
* only. Open-shadow elements are skipped (the page-side `runDomWalk` already
|
|
280
|
+
* covers them when `pierce: "open"` or `"closed"`). Returns an empty list +
|
|
281
|
+
* no warning when CDP's `pierce` path is unavailable.
|
|
282
|
+
*
|
|
283
|
+
* The walker reads the CDP-pierced DOM tree and identifies closed-mode
|
|
284
|
+
* shadow roots; for each, it harvests element-shaped descendants and
|
|
285
|
+
* extracts the same fields the page-side walker would. Doesn't fetch
|
|
286
|
+
* computed style / `getBoundingClientRect` — closed shadow can't be
|
|
287
|
+
* resolved to a Playwright locator anyway, so a bbox would be a lie.
|
|
288
|
+
*/
|
|
289
|
+
export async function harvestClosedShadowElements(cdp, testAttrs, maxEntries) {
|
|
290
|
+
const { root, warning } = await fetchPiercedDocument(cdp);
|
|
291
|
+
if (!root)
|
|
292
|
+
return { entries: [], ...(warning ? { warning } : {}) };
|
|
293
|
+
const entries = [];
|
|
294
|
+
// Traverse: find every closed shadow root, then walk its descendants.
|
|
295
|
+
// We're explicit about NOT entering open shadow roots from CDP because
|
|
296
|
+
// the page-side walker has already covered them — entering twice would
|
|
297
|
+
// produce duplicate entries that the registry's element-key would then
|
|
298
|
+
// collapse, masking which path discovered what (the `[from-dom]` /
|
|
299
|
+
// `[from-both]` evidence loses its meaning).
|
|
300
|
+
const stack = [root];
|
|
301
|
+
while (stack.length && entries.length < maxEntries) {
|
|
302
|
+
const n = stack.pop();
|
|
303
|
+
for (const sr of n.shadowRoots ?? []) {
|
|
304
|
+
if (sr.shadowRootType === "closed") {
|
|
305
|
+
harvestSubtree(sr, testAttrs, entries, maxEntries);
|
|
306
|
+
}
|
|
307
|
+
// Don't descend further into closed shadow via `stack` here — the
|
|
308
|
+
// recursive harvest already covered nested closed-in-closed cases.
|
|
309
|
+
// Open shadow inside closed shadow IS picked up by harvestSubtree's
|
|
310
|
+
// recursion (it walks all element children).
|
|
311
|
+
}
|
|
312
|
+
for (const c of n.children ?? [])
|
|
313
|
+
stack.push(c);
|
|
314
|
+
if (n.contentDocument)
|
|
315
|
+
stack.push(n.contentDocument);
|
|
316
|
+
}
|
|
317
|
+
return { entries };
|
|
318
|
+
}
|
|
319
|
+
const INTERACTIVE_TAGS = new Set(["button", "a", "input", "select", "textarea"]);
|
|
320
|
+
/** Predicate mirroring PAGE_SCRIPT in dom-walk.ts: a node with a role, a standard
|
|
321
|
+
* interactive tag, or an interaction attribute is interactive. */
|
|
322
|
+
function isInteractiveNode(tag, attrMap) {
|
|
323
|
+
return (attrMap.has("role") ||
|
|
324
|
+
INTERACTIVE_TAGS.has(tag) ||
|
|
325
|
+
(tag === "a" && attrMap.has("href")) ||
|
|
326
|
+
attrMap.has("onclick") ||
|
|
327
|
+
attrMap.has("tabindex") ||
|
|
328
|
+
attrMap.get("contenteditable") === "true");
|
|
329
|
+
}
|
|
330
|
+
/** Build a closed-shadow entry. Closed shadow has no addressable selector from
|
|
331
|
+
* the page side, so the synthetic `structuralPath` documents the boundary (the
|
|
332
|
+
* selectorHint then emits `tier 5` role-only and the agent sees why it isn't
|
|
333
|
+
* actionable). */
|
|
334
|
+
function buildClosedShadowEntry(n, tag, attrMap, testIdEntry, index) {
|
|
335
|
+
return {
|
|
336
|
+
role: attrMap.get("role") || tag,
|
|
337
|
+
name: nameFromAttrs(attrMap),
|
|
338
|
+
testId: testIdEntry?.value ?? "",
|
|
339
|
+
testIdAttr: testIdEntry?.attr ?? "",
|
|
340
|
+
tag,
|
|
341
|
+
id: attrMap.get("id") ?? "",
|
|
342
|
+
structuralPath: `closed-shadow/${tag}[${index}]`,
|
|
343
|
+
cssPath: "",
|
|
344
|
+
closedShadow: true,
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
function harvestSubtree(root, testAttrs, out, max) {
|
|
348
|
+
const stack = [...(root.children ?? [])];
|
|
349
|
+
while (stack.length && out.length < max) {
|
|
350
|
+
const n = stack.pop();
|
|
351
|
+
if (n.nodeType !== 1)
|
|
352
|
+
continue;
|
|
353
|
+
const tag = (n.localName ?? n.nodeName ?? "").toLowerCase();
|
|
354
|
+
const attrMap = readAttrs(n);
|
|
355
|
+
const testIdEntry = firstTestAttr(attrMap, testAttrs);
|
|
356
|
+
if (isInteractiveNode(tag, attrMap) || testIdEntry) {
|
|
357
|
+
out.push(buildClosedShadowEntry(n, tag, attrMap, testIdEntry, out.length));
|
|
358
|
+
}
|
|
359
|
+
pushHarvestChildren(stack, n);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
/** Push a node's element children + its open/closed shadow-root children onto
|
|
363
|
+
* the harvest stack (user-agent shadow roots are skipped). */
|
|
364
|
+
function pushHarvestChildren(stack, n) {
|
|
365
|
+
for (const c of n.children ?? [])
|
|
366
|
+
stack.push(c);
|
|
367
|
+
for (const sr of n.shadowRoots ?? []) {
|
|
368
|
+
if (sr.shadowRootType === "open" || sr.shadowRootType === "closed") {
|
|
369
|
+
for (const c of sr.children ?? [])
|
|
370
|
+
stack.push(c);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
function readAttrs(n) {
|
|
375
|
+
const m = new Map();
|
|
376
|
+
const a = n.attributes ?? [];
|
|
377
|
+
for (let i = 0; i < a.length; i += 2)
|
|
378
|
+
m.set(a[i], a[i + 1] ?? "");
|
|
379
|
+
return m;
|
|
380
|
+
}
|
|
381
|
+
function firstTestAttr(attrs, testAttrs) {
|
|
382
|
+
for (const a of testAttrs) {
|
|
383
|
+
const v = attrs.get(a);
|
|
384
|
+
if (v)
|
|
385
|
+
return { attr: a, value: v };
|
|
386
|
+
}
|
|
387
|
+
return null;
|
|
388
|
+
}
|
|
389
|
+
function nameFromAttrs(attrs) {
|
|
390
|
+
const aria = attrs.get("aria-label");
|
|
391
|
+
if (aria)
|
|
392
|
+
return aria.trim().slice(0, 120);
|
|
393
|
+
const title = attrs.get("title");
|
|
394
|
+
if (title)
|
|
395
|
+
return title.trim().slice(0, 120);
|
|
396
|
+
const placeholder = attrs.get("placeholder");
|
|
397
|
+
if (placeholder)
|
|
398
|
+
return placeholder.trim().slice(0, 120);
|
|
399
|
+
return "";
|
|
400
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { Page } from "playwright-core";
|
|
2
|
+
import type { RefRegistry } from "./refs.js";
|
|
3
|
+
import { type ActionTarget } from "./locator.js";
|
|
4
|
+
import { ClipboardBuffer, type ClipOp } from "./clipboard.js";
|
|
5
|
+
type ChordKind = "copy" | "cut" | "paste" | "other";
|
|
6
|
+
/** Classify a Playwright chord ("Control+C", "Meta+V", "Control+Shift+K").
|
|
7
|
+
* copy/cut/paste require a Control or Meta modifier on c / x / v. */
|
|
8
|
+
export declare function classifyChord(chord: string): ChordKind;
|
|
9
|
+
interface ElSumm {
|
|
10
|
+
tag: string;
|
|
11
|
+
id?: string;
|
|
12
|
+
testId?: string;
|
|
13
|
+
role?: string;
|
|
14
|
+
name?: string;
|
|
15
|
+
}
|
|
16
|
+
interface KbEvent {
|
|
17
|
+
type: string;
|
|
18
|
+
key: string;
|
|
19
|
+
defaultPrevented: boolean;
|
|
20
|
+
target: ElSumm | null;
|
|
21
|
+
}
|
|
22
|
+
export interface ShortcutArgs {
|
|
23
|
+
keys: string | string[];
|
|
24
|
+
target?: ActionTarget;
|
|
25
|
+
}
|
|
26
|
+
export interface ShortcutResult {
|
|
27
|
+
ok: boolean;
|
|
28
|
+
keys: string[];
|
|
29
|
+
activeElement: ElSumm | null;
|
|
30
|
+
events: KbEvent[];
|
|
31
|
+
/** true when a copy/cut/paste event fired OR the app called preventDefault
|
|
32
|
+
* on a keydown — i.e. the app actually responded to the shortcut. */
|
|
33
|
+
handled: boolean;
|
|
34
|
+
clipboard?: {
|
|
35
|
+
op: ClipOp | "paste";
|
|
36
|
+
/** chars captured into the per-session buffer (copy/cut). */
|
|
37
|
+
capturedChars?: number;
|
|
38
|
+
/** chars written to the OS clipboard from the per-session buffer (paste). */
|
|
39
|
+
chars?: number;
|
|
40
|
+
fromSessionBuffer?: boolean;
|
|
41
|
+
osSync: boolean;
|
|
42
|
+
osTool: string;
|
|
43
|
+
};
|
|
44
|
+
clipboardNote?: string;
|
|
45
|
+
}
|
|
46
|
+
export declare function runShortcut(page: Page, refs: RefRegistry, args: ShortcutArgs, opts: {
|
|
47
|
+
clipboardEnabled: boolean;
|
|
48
|
+
clipboard: ClipboardBuffer;
|
|
49
|
+
}): Promise<ShortcutResult>;
|
|
50
|
+
export {};
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
// `shortcut` — keyboard chord / multi-step sequence with handled-observability.
|
|
2
|
+
//
|
|
3
|
+
// `press` drives one combo, but (a) multi-step shortcuts are unergonomic and
|
|
4
|
+
// (b) the agent can't tell whether the *app* handled the shortcut or what was
|
|
5
|
+
// focused — copy/cut/paste especially are opaque (internal vs OS clipboard).
|
|
6
|
+
// This dispatches a chord or an ordered sequence and returns a structured
|
|
7
|
+
// observability block: the active element, which keydown/copy/cut/paste
|
|
8
|
+
// listeners fired, and whether the app called preventDefault.
|
|
9
|
+
//
|
|
10
|
+
// Clipboard (capability `clipboard`, off by default) is per-session and
|
|
11
|
+
// transactional — see clipboard.ts. Observability works without the
|
|
12
|
+
// capability; only the OS-clipboard read/write + per-session buffer engage
|
|
13
|
+
// when it's enabled. No agent JS (fixed server-injected trace script).
|
|
14
|
+
import { locatorFor } from "./locator.js";
|
|
15
|
+
import { osClipboardWrite } from "./clipboard.js";
|
|
16
|
+
/** Classify a Playwright chord ("Control+C", "Meta+V", "Control+Shift+K").
|
|
17
|
+
* copy/cut/paste require a Control or Meta modifier on c / x / v. */
|
|
18
|
+
export function classifyChord(chord) {
|
|
19
|
+
const parts = chord.split("+").map((s) => s.trim().toLowerCase());
|
|
20
|
+
const key = parts[parts.length - 1];
|
|
21
|
+
const mod = parts.slice(0, -1);
|
|
22
|
+
const accel = mod.includes("control") || mod.includes("meta");
|
|
23
|
+
if (!accel)
|
|
24
|
+
return "other";
|
|
25
|
+
if (key === "c")
|
|
26
|
+
return "copy";
|
|
27
|
+
if (key === "x")
|
|
28
|
+
return "cut";
|
|
29
|
+
if (key === "v")
|
|
30
|
+
return "paste";
|
|
31
|
+
return "other";
|
|
32
|
+
}
|
|
33
|
+
const ELSUMM = `function (el) {
|
|
34
|
+
if (!el || !el.tagName) return null;
|
|
35
|
+
return {
|
|
36
|
+
tag: el.tagName.toLowerCase(),
|
|
37
|
+
id: el.id || undefined,
|
|
38
|
+
testId: el.getAttribute ? (el.getAttribute('data-testid') || undefined) : undefined,
|
|
39
|
+
role: el.getAttribute ? (el.getAttribute('role') || undefined) : undefined,
|
|
40
|
+
name: (el.getAttribute && el.getAttribute('aria-label')) ||
|
|
41
|
+
(el.textContent ? el.textContent.trim().slice(0, 40) : undefined) || undefined,
|
|
42
|
+
};
|
|
43
|
+
}`;
|
|
44
|
+
const INSTALL_TRACE = `(() => {
|
|
45
|
+
var summ = ${ELSUMM};
|
|
46
|
+
var W = window;
|
|
47
|
+
var st = { events: [], active: summ(document.activeElement) };
|
|
48
|
+
W.__browx_kbt = st;
|
|
49
|
+
var rec = function (type) {
|
|
50
|
+
return function (e) {
|
|
51
|
+
st.events.push({ type: type, key: e.key, defaultPrevented: !!e.defaultPrevented, target: summ(e.target) });
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
var L = { keydown: rec('keydown'), copy: rec('copy'), cut: rec('cut'), paste: rec('paste') };
|
|
55
|
+
W.__browx_kbt_l = L;
|
|
56
|
+
// bubble phase on document: runs after element/app handlers, so
|
|
57
|
+
// defaultPrevented reflects whether the app handled the event.
|
|
58
|
+
document.addEventListener('keydown', L.keydown, false);
|
|
59
|
+
document.addEventListener('copy', L.copy, false);
|
|
60
|
+
document.addEventListener('cut', L.cut, false);
|
|
61
|
+
document.addEventListener('paste', L.paste, false);
|
|
62
|
+
})()`;
|
|
63
|
+
const READ_TRACE = `(() => {
|
|
64
|
+
var s = window.__browx_kbt || { events: [], active: null };
|
|
65
|
+
return { events: s.events, active: s.active };
|
|
66
|
+
})()`;
|
|
67
|
+
const CLEANUP_TRACE = `(() => {
|
|
68
|
+
var L = window.__browx_kbt_l;
|
|
69
|
+
if (L) {
|
|
70
|
+
document.removeEventListener('keydown', L.keydown, false);
|
|
71
|
+
document.removeEventListener('copy', L.copy, false);
|
|
72
|
+
document.removeEventListener('cut', L.cut, false);
|
|
73
|
+
document.removeEventListener('paste', L.paste, false);
|
|
74
|
+
}
|
|
75
|
+
delete window.__browx_kbt; delete window.__browx_kbt_l;
|
|
76
|
+
})()`;
|
|
77
|
+
const READ_SELECTION = `(() => {
|
|
78
|
+
var a = document.activeElement;
|
|
79
|
+
if (a && (a.tagName === 'INPUT' || a.tagName === 'TEXTAREA') && typeof a.selectionStart === 'number') {
|
|
80
|
+
return a.value.substring(a.selectionStart, a.selectionEnd) || a.value || '';
|
|
81
|
+
}
|
|
82
|
+
var s = window.getSelection && window.getSelection();
|
|
83
|
+
return s ? s.toString() : '';
|
|
84
|
+
})()`;
|
|
85
|
+
export async function runShortcut(page, refs, args, opts) {
|
|
86
|
+
const chords = Array.isArray(args.keys) ? args.keys : [args.keys];
|
|
87
|
+
if (args.target) {
|
|
88
|
+
try {
|
|
89
|
+
await locatorFor(page, refs, args.target).focus({ timeout: 2000 });
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
/* best-effort focus; page-level shortcut still valid */
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
await page.evaluate(INSTALL_TRACE).catch(() => undefined);
|
|
96
|
+
let clip;
|
|
97
|
+
for (const chord of chords) {
|
|
98
|
+
if (classifyChord(chord) === "paste" && opts.clipboardEnabled) {
|
|
99
|
+
const buf = opts.clipboard.get();
|
|
100
|
+
if (buf) {
|
|
101
|
+
// transactional: set the OS clipboard from THIS session's buffer
|
|
102
|
+
// immediately before the paste keystroke, so the app pastes this
|
|
103
|
+
// session's content regardless of concurrent sessions.
|
|
104
|
+
const w = await osClipboardWrite(buf.text);
|
|
105
|
+
clip = {
|
|
106
|
+
op: "paste",
|
|
107
|
+
chars: buf.text.length,
|
|
108
|
+
fromSessionBuffer: true,
|
|
109
|
+
osSync: w.ok,
|
|
110
|
+
osTool: w.tool,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
await page.keyboard.press(chord).catch(() => undefined);
|
|
115
|
+
}
|
|
116
|
+
const copyChord = chords.find((c) => classifyChord(c) === "copy" || classifyChord(c) === "cut");
|
|
117
|
+
if (copyChord && opts.clipboardEnabled) {
|
|
118
|
+
// READ_SELECTION returns a string by construction (see definition above);
|
|
119
|
+
// narrow before coercion so we don't `[object Object]` if the page eval
|
|
120
|
+
// ever returns a non-primitive.
|
|
121
|
+
const raw = await page.evaluate(READ_SELECTION).catch(() => "");
|
|
122
|
+
const sel = typeof raw === "string" ? raw : "";
|
|
123
|
+
const op = classifyChord(copyChord);
|
|
124
|
+
opts.clipboard.set(sel, op);
|
|
125
|
+
const w = await osClipboardWrite(sel);
|
|
126
|
+
clip = { op, capturedChars: sel.length, osSync: w.ok, osTool: w.tool };
|
|
127
|
+
}
|
|
128
|
+
const trace = (await page.evaluate(READ_TRACE).catch(() => ({ events: [], active: null })));
|
|
129
|
+
await page.evaluate(CLEANUP_TRACE).catch(() => undefined);
|
|
130
|
+
const handled = trace.events.some((e) => e.type === "copy" ||
|
|
131
|
+
e.type === "cut" ||
|
|
132
|
+
e.type === "paste" ||
|
|
133
|
+
(e.type === "keydown" && e.defaultPrevented));
|
|
134
|
+
return {
|
|
135
|
+
ok: true,
|
|
136
|
+
keys: chords,
|
|
137
|
+
activeElement: trace.active,
|
|
138
|
+
events: trace.events,
|
|
139
|
+
handled,
|
|
140
|
+
...(clip ? { clipboard: clip } : {}),
|
|
141
|
+
...(opts.clipboardEnabled || !chords.some((c) => classifyChord(c) !== "other")
|
|
142
|
+
? {}
|
|
143
|
+
: {
|
|
144
|
+
clipboardNote: "clipboard capability disabled — keys dispatched and observed, but no OS clipboard read/write and no per-session buffer update (enable BROWX_CAPABILITIES=…,clipboard)",
|
|
145
|
+
}),
|
|
146
|
+
};
|
|
147
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { A11yNode } from "./a11y.js";
|
|
2
|
+
import type { RefRegistry } from "./refs.js";
|
|
3
|
+
import type { ComposedSnapshot, ComposeOptions } from "./compose.js";
|
|
4
|
+
import type { SnapshotSubstrate } from "./snapshot-substrate.js";
|
|
5
|
+
/** The minimal IO the Safari substrate needs — run a page-context script
|
|
6
|
+
* (`execute/sync` body + args → value) and read the current document URL. The
|
|
7
|
+
* SafaridriverHybridAdapter supplies this over its `SafariWebDriverClient`. */
|
|
8
|
+
export interface SafariSnapshotIO {
|
|
9
|
+
/** Run a function-BODY script with args mapped to `arguments`, returning its
|
|
10
|
+
* value (the WebDriver `execute/sync` contract). */
|
|
11
|
+
exec(scriptBody: string, args: unknown[]): Promise<unknown>;
|
|
12
|
+
/** The current document URL (the Classic substitute for `page.url()`). */
|
|
13
|
+
currentUrl(): Promise<string>;
|
|
14
|
+
}
|
|
15
|
+
/** Safari substrate — the page-side DOM-walk over WebDriver Classic
|
|
16
|
+
* `execute/sync`. No CDP, no Playwright Frame. Mirrors PlaywrightSnapshotSubstrate
|
|
17
|
+
* (synthetic `WebArea` root + DOM-walk leaves), with the same documented
|
|
18
|
+
* fidelity tradeoff: refs + find-ranking signal (role/name/[testid]) are present;
|
|
19
|
+
* the deep CDP a11y nesting and closed-shadow piercing are not (no off-Chromium
|
|
20
|
+
* protocol reaches them). */
|
|
21
|
+
export declare class SafariClassicSnapshotSubstrate implements SnapshotSubstrate {
|
|
22
|
+
private readonly io;
|
|
23
|
+
readonly engine = "safari";
|
|
24
|
+
constructor(io: SafariSnapshotIO);
|
|
25
|
+
compose(refs: RefRegistry, testAttributes: string[], opts?: ComposeOptions): Promise<ComposedSnapshot>;
|
|
26
|
+
a11yTree(refs: RefRegistry, testAttributes: string[]): Promise<A11yNode | null>;
|
|
27
|
+
/** The synthetic main-frame root — keyed/stable so its ref persists across
|
|
28
|
+
* snapshots, identical to the Playwright substrate's root. */
|
|
29
|
+
private makeRoot;
|
|
30
|
+
}
|