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,49 @@
|
|
|
1
|
+
// Server-side overlay neutraliser. Dev-build chrome (HMR widgets, devtools
|
|
2
|
+
// iframes), cookie/consent banners and similar overlays intercept coordinate
|
|
3
|
+
// clicks and pollute the snapshot. Rather than have every agent hand-roll
|
|
4
|
+
// node removal in `eval_js` each session, the operator declares the offending
|
|
5
|
+
// selectors once (config `hideOverlaySelectors`) and the server injects a
|
|
6
|
+
// CSS-only init script that neutralises them on every navigation.
|
|
7
|
+
//
|
|
8
|
+
// Non-destructive by design: a `<style>` rule sets `pointer-events:none;
|
|
9
|
+
// display:none` — no node removal, no agent-supplied JS. The selectors come
|
|
10
|
+
// from operator-managed config (config.json / set_config), never the page.
|
|
11
|
+
import { log } from "../util/logging.js";
|
|
12
|
+
const STYLE_ID = "__browx_overlay_hide";
|
|
13
|
+
/** Build the init-script body for the given selectors. Selectors are embedded
|
|
14
|
+
* as JSON string literals (no expression interpolation) and written via
|
|
15
|
+
* `style.textContent` (not parsed as HTML), so a hostile selector can at
|
|
16
|
+
* worst break its own CSS rule — it cannot escape into script. */
|
|
17
|
+
export function buildOverlayHideScript(selectors) {
|
|
18
|
+
return `(() => {
|
|
19
|
+
var SELS = ${JSON.stringify(selectors)};
|
|
20
|
+
if (!SELS.length) return;
|
|
21
|
+
var css = SELS.map(function (s) {
|
|
22
|
+
return s + "{pointer-events:none !important;display:none !important;}";
|
|
23
|
+
}).join("\\n");
|
|
24
|
+
var ID = ${JSON.stringify(STYLE_ID)};
|
|
25
|
+
var inject = function () {
|
|
26
|
+
if (document.getElementById(ID)) return;
|
|
27
|
+
var st = document.createElement("style");
|
|
28
|
+
st.id = ID;
|
|
29
|
+
st.textContent = css;
|
|
30
|
+
(document.head || document.documentElement).appendChild(st);
|
|
31
|
+
};
|
|
32
|
+
inject();
|
|
33
|
+
if (document.readyState === "loading") {
|
|
34
|
+
document.addEventListener("DOMContentLoaded", inject);
|
|
35
|
+
}
|
|
36
|
+
})();`;
|
|
37
|
+
}
|
|
38
|
+
/** Register the overlay-hide init script on a context and apply it to any
|
|
39
|
+
* already-open pages. No-op when `selectors` is empty (feature off). */
|
|
40
|
+
export async function applyOverlayHide(context, selectors) {
|
|
41
|
+
if (!selectors.length)
|
|
42
|
+
return;
|
|
43
|
+
const script = buildOverlayHideScript(selectors);
|
|
44
|
+
await context.addInitScript({ content: script });
|
|
45
|
+
for (const page of context.pages()) {
|
|
46
|
+
await page.evaluate(script).catch(() => undefined);
|
|
47
|
+
}
|
|
48
|
+
log.info("overlay-hide: active", { count: selectors.length });
|
|
49
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { BrowserContext } from "playwright-core";
|
|
2
|
+
/** Build the page-side init script that applies the stealth patches. Pure —
|
|
3
|
+
* takes no input, returns the script string. Wrapped in an IIFE so the
|
|
4
|
+
* helpers don't leak into the page's globals. Idempotent: an early-return
|
|
5
|
+
* guard skips re-application if it ran in the same realm. */
|
|
6
|
+
export declare function buildStealthScript(): string;
|
|
7
|
+
/** Register the stealth init script on a context and apply it to any
|
|
8
|
+
* already-open pages. Mirrors the overlay-hide pattern: `addInitScript`
|
|
9
|
+
* for future navigations + `page.evaluate` for the currently-loaded page. */
|
|
10
|
+
export declare function applyStealth(context: BrowserContext): Promise<void>;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// Stealth-mode init-script patches (capability `stealth`).
|
|
2
|
+
//
|
|
3
|
+
// Many sites detect Playwright/Puppeteer-driven browsers via a small set of
|
|
4
|
+
// well-known fingerprint giveaways the automation framework leaves on the
|
|
5
|
+
// page-side `navigator` / `window` objects. The most commonly-checked surface:
|
|
6
|
+
//
|
|
7
|
+
// - `navigator.webdriver === true` — the WebDriver protocol flag
|
|
8
|
+
// - `navigator.plugins.length === 0` — headless / fresh-profile tell
|
|
9
|
+
// - `window.chrome` undefined / missing `runtime` — non-Chrome user-agent tell
|
|
10
|
+
// - `navigator.languages` empty — headless Chromium default
|
|
11
|
+
//
|
|
12
|
+
// What this module does: registers a per-context `addInitScript` that overrides
|
|
13
|
+
// the above accessors BEFORE any page script runs. We do NOT bundle a
|
|
14
|
+
// general-purpose anti-fingerprinting library (e.g. puppeteer-extra-stealth) —
|
|
15
|
+
// that surface is vast and an arms race; the four patches above cover the
|
|
16
|
+
// observed default detectors and are the conservative minimum.
|
|
17
|
+
//
|
|
18
|
+
// Posture: same class as `eval` / `network-body` / `secrets` / `extensions` —
|
|
19
|
+
// off-by-default capability, loud-warned at boot. Legal/ToS exposure is real:
|
|
20
|
+
// many sites' terms of service explicitly prohibit "circumventing automated-
|
|
21
|
+
// access detection". The loud warning names that explicitly.
|
|
22
|
+
//
|
|
23
|
+
// Non-destructive within the running page: `Object.defineProperty` with
|
|
24
|
+
// `configurable:true` so a page that wants to inspect or replace the override
|
|
25
|
+
// still can (we're spoofing detection, not lying to legitimate code).
|
|
26
|
+
import { log } from "../util/logging.js";
|
|
27
|
+
const SCRIPT_TAG = "__browx_stealth";
|
|
28
|
+
/** Build the page-side init script that applies the stealth patches. Pure —
|
|
29
|
+
* takes no input, returns the script string. Wrapped in an IIFE so the
|
|
30
|
+
* helpers don't leak into the page's globals. Idempotent: an early-return
|
|
31
|
+
* guard skips re-application if it ran in the same realm. */
|
|
32
|
+
export function buildStealthScript() {
|
|
33
|
+
return `(() => {
|
|
34
|
+
if (window.${SCRIPT_TAG}) return;
|
|
35
|
+
Object.defineProperty(window, ${JSON.stringify(SCRIPT_TAG)}, { value: true, configurable: true });
|
|
36
|
+
// 1. navigator.webdriver — the load-bearing Playwright fingerprint.
|
|
37
|
+
try {
|
|
38
|
+
Object.defineProperty(navigator, "webdriver", {
|
|
39
|
+
get: function () { return false; },
|
|
40
|
+
configurable: true,
|
|
41
|
+
});
|
|
42
|
+
} catch (e) { /* best-effort */ }
|
|
43
|
+
// 2. navigator.plugins — headless / fresh-profile tell. Surface a
|
|
44
|
+
// plausible non-empty PluginArray-like (length 1 with a "Chrome PDF
|
|
45
|
+
// Viewer" entry mirrors real Chrome defaults).
|
|
46
|
+
try {
|
|
47
|
+
var fake = [{ name: "Chrome PDF Viewer", filename: "internal-pdf-viewer", description: "Portable Document Format" }];
|
|
48
|
+
Object.defineProperty(navigator, "plugins", {
|
|
49
|
+
get: function () { return fake; },
|
|
50
|
+
configurable: true,
|
|
51
|
+
});
|
|
52
|
+
} catch (e) { /* best-effort */ }
|
|
53
|
+
// 3. navigator.languages — headless Chromium emits []; real browsers
|
|
54
|
+
// populate at least the page-locale entry.
|
|
55
|
+
try {
|
|
56
|
+
if (!navigator.languages || navigator.languages.length === 0) {
|
|
57
|
+
Object.defineProperty(navigator, "languages", {
|
|
58
|
+
get: function () { return ["en-US", "en"]; },
|
|
59
|
+
configurable: true,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
} catch (e) { /* best-effort */ }
|
|
63
|
+
// 4. window.chrome — non-Chrome UA tell. Many detectors check
|
|
64
|
+
// \`typeof window.chrome === "object" && !!window.chrome.runtime\`.
|
|
65
|
+
try {
|
|
66
|
+
if (!window.chrome) {
|
|
67
|
+
Object.defineProperty(window, "chrome", {
|
|
68
|
+
value: { runtime: {} },
|
|
69
|
+
configurable: true,
|
|
70
|
+
writable: true,
|
|
71
|
+
});
|
|
72
|
+
} else if (!window.chrome.runtime) {
|
|
73
|
+
try { window.chrome.runtime = {}; } catch (e) { /* best-effort */ }
|
|
74
|
+
}
|
|
75
|
+
} catch (e) { /* best-effort */ }
|
|
76
|
+
})();`;
|
|
77
|
+
}
|
|
78
|
+
/** Register the stealth init script on a context and apply it to any
|
|
79
|
+
* already-open pages. Mirrors the overlay-hide pattern: `addInitScript`
|
|
80
|
+
* for future navigations + `page.evaluate` for the currently-loaded page. */
|
|
81
|
+
export async function applyStealth(context) {
|
|
82
|
+
const script = buildStealthScript();
|
|
83
|
+
await context.addInitScript({ content: script });
|
|
84
|
+
for (const page of context.pages()) {
|
|
85
|
+
await page.evaluate(script).catch(() => undefined);
|
|
86
|
+
}
|
|
87
|
+
log.info("stealth: active (navigator.webdriver / plugins / languages / chrome patches engaged)");
|
|
88
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import "./tools/tool-metadata.js";
|
|
2
|
+
export { createServer, NAME, VERSION } from "./server.js";
|
|
3
|
+
export type { StartOptions } from "./server.js";
|
|
4
|
+
export { resolveWorkspace } from "./util/workspace.js";
|
|
5
|
+
export type { BrowserSession, SessionOptions, SessionMode } from "./session/types.js";
|
|
6
|
+
export { createBrowxai, NOT_EXPOSED_ERROR, resolveEndpointPath } from "./sdk/index.js";
|
|
7
|
+
export type { BrowxaiArgs, BrowxaiClient, BrowxaiContentItem, BrowxaiResult, BrowxaiSdkOptions, } from "./sdk/index.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Public exports. Most users want the CLI (`browxai` bin) — see cli.ts. This module
|
|
2
|
+
// is for embedding the MCP server programmatically or pulling in types.
|
|
3
|
+
// RFC 0004 P2: install the tool-metadata collector so the derived `TOOL_CAPABILITY`
|
|
4
|
+
// / `DEEP_TOOLS` maps populate for any package consumer (notably the SDK client's
|
|
5
|
+
// capability gate, which reads `TOOL_CAPABILITY` without first building a server).
|
|
6
|
+
// Importing this side-effecting module is the composition-root install point; the
|
|
7
|
+
// collection is cached, so loading it here is cheap and idempotent.
|
|
8
|
+
import "./tools/tool-metadata.js";
|
|
9
|
+
export { createServer, NAME, VERSION } from "./server.js";
|
|
10
|
+
export { resolveWorkspace } from "./util/workspace.js";
|
|
11
|
+
// Typed SDK surface — see src/sdk/types.ts. Importing this from
|
|
12
|
+
// `browxai` gives consumers a programmatic driver over the same
|
|
13
|
+
// tool registry the MCP path exposes, with identical capability gating and
|
|
14
|
+
// identical egress hygiene.
|
|
15
|
+
export { createBrowxai, NOT_EXPOSED_ERROR, resolveEndpointPath } from "./sdk/index.js";
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { CDPSession } from "playwright-core";
|
|
2
|
+
import { RefRegistry } from "./refs.js";
|
|
3
|
+
export declare const MAX_WALK_DEPTH = 2000;
|
|
4
|
+
export interface A11yNode {
|
|
5
|
+
ref: string;
|
|
6
|
+
role: string;
|
|
7
|
+
name?: string;
|
|
8
|
+
value?: string;
|
|
9
|
+
/** CDP node IDs to resolve back into actions / element handles. */
|
|
10
|
+
backendDOMNodeId?: number;
|
|
11
|
+
/** Test-attribute value if we found one (`data-testid` etc.). */
|
|
12
|
+
testId?: string;
|
|
13
|
+
/** Attribute *name* that yielded `testId` — preserves which convention matched. */
|
|
14
|
+
testIdAttr?: string;
|
|
15
|
+
/** Where this node came from. Default = "a11y" for the CDP-a11y path; "dom" for the
|
|
16
|
+
* DOM-walk fallback (see dom-walk.ts) and "both" when a node was independently
|
|
17
|
+
* discovered by both paths. #7 / #8 plumbing. */
|
|
18
|
+
source?: "a11y" | "dom" | "both";
|
|
19
|
+
/** Tag name (DOM-walk only — informational for the agent). */
|
|
20
|
+
tag?: string;
|
|
21
|
+
/** selectorHint tier-4 source: HTML `id=` attribute if present. */
|
|
22
|
+
id?: string;
|
|
23
|
+
/** selectorHint tier-3 source: trimmed text content (truncated, single-line),
|
|
24
|
+
* set when distinct from `name` and stable-looking. DOM-walk fills this in. */
|
|
25
|
+
text?: string;
|
|
26
|
+
/** State flags as reported by CDP (selected subset — see fmtState). */
|
|
27
|
+
disabled?: boolean;
|
|
28
|
+
checked?: boolean | "mixed";
|
|
29
|
+
pressed?: boolean | "mixed";
|
|
30
|
+
selected?: boolean;
|
|
31
|
+
expanded?: boolean;
|
|
32
|
+
focused?: boolean;
|
|
33
|
+
/** Structural neighbourhood when this node lives inside a repeated container
|
|
34
|
+
* (table row, listitem, repeated card). Populated by `annotateStructuralContext`
|
|
35
|
+
* during snapshot composition; null when the node isn't in a recognised
|
|
36
|
+
* repeated structure. */
|
|
37
|
+
context?: StructuralContext;
|
|
38
|
+
children: A11yNode[];
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Structural neighbourhood metadata for nodes living in repeated layouts.
|
|
42
|
+
* Lets callers answer "what row/column is this in?" without re-walking the
|
|
43
|
+
* tree themselves. Detection is generic — driven by semantic ARIA roles
|
|
44
|
+
* (`table` / `row` / `cell` / `columnheader`, `list` / `listitem`, etc.),
|
|
45
|
+
* not by app-specific markers.
|
|
46
|
+
*/
|
|
47
|
+
export interface StructuralContext {
|
|
48
|
+
/** Role of the collection this node sits inside. Typical values: `table`,
|
|
49
|
+
* `grid`, `list`, `feed`, or `<row-role>-list` when the parent role isn't
|
|
50
|
+
* one of the canonical collection roles. */
|
|
51
|
+
collection: string;
|
|
52
|
+
/** Best-effort identifier for the row/item — the first non-empty visible
|
|
53
|
+
* text within the row, capped. Stable enough to disambiguate sibling rows
|
|
54
|
+
* by display label. */
|
|
55
|
+
rowKey?: string;
|
|
56
|
+
/** Column header text (from the table's header row, aligned by cell index).
|
|
57
|
+
* Populated only for semantic-table / grid descendants. */
|
|
58
|
+
column?: string;
|
|
59
|
+
/** Concatenated visible text of the entire row, capped at 200 chars.
|
|
60
|
+
* Cheap "what does this row say overall?" probe for the caller. */
|
|
61
|
+
rowText?: string;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Get the cleaned a11y tree for the current page, with refs assigned through `refs`.
|
|
65
|
+
* Refs are *stable* across calls: a node that persists keeps its `eN`.
|
|
66
|
+
*
|
|
67
|
+
* `testIdAttributes` is the list of HTML attributes to read off the DOM node as
|
|
68
|
+
* the node's `testId` (preference-order-friendly for `find()`'s selectorHint).
|
|
69
|
+
* Sourced from `BROWX_TEST_ATTRIBUTES` via `resolveConfig()`; defaults to
|
|
70
|
+
* `["data-testid", "data-test", "data-cy", "data-qa"]`. Order-sensitive: the
|
|
71
|
+
* **first** match on a node wins. The matched attribute *name* is preserved on
|
|
72
|
+
* the node as `testIdAttr` so selectorHint can emit the right selector.
|
|
73
|
+
*/
|
|
74
|
+
export declare function getA11yTree(cdp: CDPSession, refs: RefRegistry, testIdAttributes?: string[]): Promise<A11yNode | null>;
|
|
75
|
+
/**
|
|
76
|
+
* Walk a tree depth-first, yielding (node, depth) pairs. Used by serialiser + find().
|
|
77
|
+
*/
|
|
78
|
+
export declare function walk(root: A11yNode): Generator<{
|
|
79
|
+
node: A11yNode;
|
|
80
|
+
depth: number;
|
|
81
|
+
}>;
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
// CDP-backed accessibility-tree extraction. playwright-core dropped page.accessibility
|
|
2
|
+
// so we go via CDP (Accessibility.getFullAXTree) directly. The shape we expose is
|
|
3
|
+
// agentic-first: a tidy tree with role/name/value/state and refs assigned by stable
|
|
4
|
+
// element key (see refs.ts), plus a `walk()` helper for serialiser/find() reuse.
|
|
5
|
+
import { elementKey } from "./refs.js";
|
|
6
|
+
// L7 (bounded everything) — the a11y tree-walk depth cap. The audit flagged
|
|
7
|
+
// `walk` as iterative (an explicit stack, so no native stack-overflow risk) but
|
|
8
|
+
// carrying NO declared depth cap: a pathological tree was bounded only by memory.
|
|
9
|
+
// This makes the bound explicit and tested. 2000 is far beyond any real
|
|
10
|
+
// accessibility tree (a deeply-nested SPA is rarely past ~60 levels), so it never
|
|
11
|
+
// trips in practice — it is a containment ceiling against an adversarial /
|
|
12
|
+
// malformed tree, matching the `secrets.ts` `depth > 8` exemplar one layer up.
|
|
13
|
+
// Nodes BELOW the cap are simply not descended into (the tree is truncated, not
|
|
14
|
+
// rejected), so the walk always terminates within `MAX_WALK_DEPTH` levels.
|
|
15
|
+
export const MAX_WALK_DEPTH = 2000;
|
|
16
|
+
/**
|
|
17
|
+
* CDP returns AX node values as `{ type, value: unknown }`. In practice the
|
|
18
|
+
* `value` is a primitive (string | number | boolean | null), but the CDP type
|
|
19
|
+
* is `any` and downstream code consumes a `string | undefined`. Coerce by
|
|
20
|
+
* type so a hypothetical structured value renders as JSON rather than
|
|
21
|
+
* `[object Object]`.
|
|
22
|
+
*/
|
|
23
|
+
/** Map the CDP AX boolean/tri-state properties onto the node. The two tri-state
|
|
24
|
+
* props (`checked`/`pressed`) carry `boolean | "mixed"`; the rest are plain
|
|
25
|
+
* booleans. Each property is independent, so a lookup table keeps the cyclomatic
|
|
26
|
+
* complexity flat. */
|
|
27
|
+
const BOOL_AX_PROPS = ["disabled", "selected", "expanded", "focused"];
|
|
28
|
+
const TRISTATE_AX_PROPS = ["checked", "pressed"];
|
|
29
|
+
function applyAxProperties(node, properties) {
|
|
30
|
+
for (const p of properties) {
|
|
31
|
+
const v = p.value?.value;
|
|
32
|
+
if (BOOL_AX_PROPS.includes(p.name)) {
|
|
33
|
+
node[p.name] = !!v;
|
|
34
|
+
}
|
|
35
|
+
else if (TRISTATE_AX_PROPS.includes(p.name)) {
|
|
36
|
+
node[p.name] = v;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function stringifyAxValue(v) {
|
|
41
|
+
if (v === undefined)
|
|
42
|
+
return undefined;
|
|
43
|
+
if (v === null)
|
|
44
|
+
return "null";
|
|
45
|
+
switch (typeof v) {
|
|
46
|
+
case "string":
|
|
47
|
+
return v;
|
|
48
|
+
case "number":
|
|
49
|
+
case "boolean":
|
|
50
|
+
case "bigint":
|
|
51
|
+
return String(v);
|
|
52
|
+
case "symbol":
|
|
53
|
+
return v.toString();
|
|
54
|
+
default:
|
|
55
|
+
return JSON.stringify(v);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get the cleaned a11y tree for the current page, with refs assigned through `refs`.
|
|
60
|
+
* Refs are *stable* across calls: a node that persists keeps its `eN`.
|
|
61
|
+
*
|
|
62
|
+
* `testIdAttributes` is the list of HTML attributes to read off the DOM node as
|
|
63
|
+
* the node's `testId` (preference-order-friendly for `find()`'s selectorHint).
|
|
64
|
+
* Sourced from `BROWX_TEST_ATTRIBUTES` via `resolveConfig()`; defaults to
|
|
65
|
+
* `["data-testid", "data-test", "data-cy", "data-qa"]`. Order-sensitive: the
|
|
66
|
+
* **first** match on a node wins. The matched attribute *name* is preserved on
|
|
67
|
+
* the node as `testIdAttr` so selectorHint can emit the right selector.
|
|
68
|
+
*/
|
|
69
|
+
export async function getA11yTree(cdp, refs, testIdAttributes = ["data-testid", "data-test", "data-cy", "data-qa"]) {
|
|
70
|
+
// Enable is idempotent; safe to call repeatedly.
|
|
71
|
+
await cdp.send("Accessibility.enable");
|
|
72
|
+
const { nodes } = (await cdp.send("Accessibility.getFullAXTree"));
|
|
73
|
+
if (!nodes.length)
|
|
74
|
+
return null;
|
|
75
|
+
const byId = new Map(nodes.map((n) => [n.nodeId, n]));
|
|
76
|
+
const root = nodes.find((n) => !n.parentId || !byId.has(n.parentId)) ?? nodes[0];
|
|
77
|
+
// We resolve testId attributes per-node lazily — only the ones that have a
|
|
78
|
+
// backendDOMNodeId and are roles we care about (interactives). For we
|
|
79
|
+
// hold off on a batched DOM.getAttributes call and just attach testIds when
|
|
80
|
+
// they show up as CDP properties; a future cycle can switch to a batch fetch
|
|
81
|
+
// if the attribute coverage isn't enough.
|
|
82
|
+
const convert = (raw, path) => {
|
|
83
|
+
if (raw.ignored)
|
|
84
|
+
return null;
|
|
85
|
+
const role = raw.role?.value ?? "generic";
|
|
86
|
+
const name = raw.name?.value;
|
|
87
|
+
const node = {
|
|
88
|
+
ref: "", // filled in below
|
|
89
|
+
role,
|
|
90
|
+
name,
|
|
91
|
+
value: stringifyAxValue(raw.value?.value),
|
|
92
|
+
backendDOMNodeId: raw.backendDOMNodeId,
|
|
93
|
+
children: [],
|
|
94
|
+
};
|
|
95
|
+
applyAxProperties(node, raw.properties ?? []);
|
|
96
|
+
// testId attaches later in enrichTestIds if we batch-fetch attributes.
|
|
97
|
+
node.ref = refs.forKey(elementKey({ role, name, path, testId: node.testId }), {
|
|
98
|
+
role,
|
|
99
|
+
name,
|
|
100
|
+
testId: node.testId,
|
|
101
|
+
source: "a11y",
|
|
102
|
+
});
|
|
103
|
+
let i = 0;
|
|
104
|
+
for (const cid of raw.childIds ?? []) {
|
|
105
|
+
const c = byId.get(cid);
|
|
106
|
+
if (!c)
|
|
107
|
+
continue;
|
|
108
|
+
const cv = convert(c, `${path}/${c.role?.value ?? "generic"}[${i}]`);
|
|
109
|
+
if (cv)
|
|
110
|
+
node.children.push(cv);
|
|
111
|
+
i++;
|
|
112
|
+
}
|
|
113
|
+
return node;
|
|
114
|
+
};
|
|
115
|
+
const tree = convert(root, root.role?.value ?? "root");
|
|
116
|
+
if (!tree)
|
|
117
|
+
return null;
|
|
118
|
+
await enrichTestIds(cdp, tree, testIdAttributes, refs);
|
|
119
|
+
return tree;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Walk a tree depth-first, yielding (node, depth) pairs. Used by serialiser + find().
|
|
123
|
+
*/
|
|
124
|
+
export function* walk(root) {
|
|
125
|
+
const stack = [{ node: root, depth: 0 }];
|
|
126
|
+
while (stack.length) {
|
|
127
|
+
const next = stack.pop();
|
|
128
|
+
yield next;
|
|
129
|
+
// L7: bounded depth — children below MAX_WALK_DEPTH are not pushed, so a
|
|
130
|
+
// pathological tree is truncated at the cap rather than walked to exhaustion.
|
|
131
|
+
// Real trees are orders of magnitude shallower, so this never truncates in
|
|
132
|
+
// practice; it is the containment ceiling the bounded-resource test pins.
|
|
133
|
+
if (next.depth >= MAX_WALK_DEPTH)
|
|
134
|
+
continue;
|
|
135
|
+
for (let i = next.node.children.length - 1; i >= 0; i--) {
|
|
136
|
+
stack.push({ node: next.node.children[i], depth: next.depth + 1 });
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* For nodes with a `backendDOMNodeId`, read off the configured test-attribute(s) in
|
|
142
|
+
* preference order via CDP, attaching the first match to `node.testId`. Also
|
|
143
|
+
* re-keys the node's ref through `refs` so the testId is part of the stable key
|
|
144
|
+
* (testId-bearing nodes keep their refs across snapshots even if neighbourhood text
|
|
145
|
+
* shifts).
|
|
146
|
+
*
|
|
147
|
+
* Batched in one `DOM.getDocument` walk would be cheaper, but per-node
|
|
148
|
+
* `DOM.resolveNode`+`DOM.describeNode` is simpler and doesn't need to be
|
|
149
|
+
* perf-tuned. If this dominates snapshot latency, switch to a batched approach.
|
|
150
|
+
*/
|
|
151
|
+
async function enrichTestIds(cdp, root, attrs, refs) {
|
|
152
|
+
for (const { node } of walk(root)) {
|
|
153
|
+
if (node.backendDOMNodeId === undefined)
|
|
154
|
+
continue;
|
|
155
|
+
// Only enrich roles the agent's likely to act on (interactive / structural).
|
|
156
|
+
if (!INTERACTIVE_ROLES.has(node.role) && !STRUCTURAL_ROLES.has(node.role))
|
|
157
|
+
continue;
|
|
158
|
+
try {
|
|
159
|
+
const { attributes } = await cdp.send("DOM.getAttributes", {
|
|
160
|
+
nodeId: node.backendDOMNodeId,
|
|
161
|
+
});
|
|
162
|
+
// attributes is a flat ["name", "value", "name", "value", ...] array.
|
|
163
|
+
const attrMap = new Map();
|
|
164
|
+
for (let i = 0; i < attributes.length; i += 2) {
|
|
165
|
+
attrMap.set(attributes[i], attributes[i + 1] ?? "");
|
|
166
|
+
}
|
|
167
|
+
for (const a of attrs) {
|
|
168
|
+
const v = attrMap.get(a);
|
|
169
|
+
if (v) {
|
|
170
|
+
node.testId = v;
|
|
171
|
+
node.testIdAttr = a;
|
|
172
|
+
// Refresh the registry's locator inputs so action tools can resolve
|
|
173
|
+
// the ref back to a data-testid-bearing Playwright locator.
|
|
174
|
+
refs.augmentLocator(node.ref, { testId: node.testId, testIdAttr: a });
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
// Node may be detached / not in DOM tree; that's fine, no testId then.
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
const INTERACTIVE_ROLES = new Set([
|
|
185
|
+
"button",
|
|
186
|
+
"link",
|
|
187
|
+
"textbox",
|
|
188
|
+
"searchbox",
|
|
189
|
+
"combobox",
|
|
190
|
+
"checkbox",
|
|
191
|
+
"radio",
|
|
192
|
+
"switch",
|
|
193
|
+
"slider",
|
|
194
|
+
"spinbutton",
|
|
195
|
+
"menuitem",
|
|
196
|
+
"menuitemcheckbox",
|
|
197
|
+
"menuitemradio",
|
|
198
|
+
"option",
|
|
199
|
+
"tab",
|
|
200
|
+
"treeitem",
|
|
201
|
+
"listbox",
|
|
202
|
+
]);
|
|
203
|
+
const STRUCTURAL_ROLES = new Set([
|
|
204
|
+
"dialog",
|
|
205
|
+
"alertdialog",
|
|
206
|
+
"navigation",
|
|
207
|
+
"main",
|
|
208
|
+
"form",
|
|
209
|
+
"search",
|
|
210
|
+
"region",
|
|
211
|
+
"tablist",
|
|
212
|
+
"menu",
|
|
213
|
+
"menubar",
|
|
214
|
+
"tree",
|
|
215
|
+
"grid",
|
|
216
|
+
"table",
|
|
217
|
+
"alert",
|
|
218
|
+
"status",
|
|
219
|
+
]);
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { ActionContext, ActionResult } from "./actionresult.js";
|
|
2
|
+
import type { RefRegistry } from "./refs.js";
|
|
3
|
+
import type { SafariSessionHandle } from "../engine/index.js";
|
|
4
|
+
import * as actions from "./actions.js";
|
|
5
|
+
/** The action capability port. One instance wraps one session's engine handle;
|
|
6
|
+
* the methods carry no engine type, so the handlers above this seam are
|
|
7
|
+
* engine-blind. Mirrors the SnapshotSubstrate / NetworkSubstrate shape. */
|
|
8
|
+
export interface ActionSubstrate {
|
|
9
|
+
readonly engine: string;
|
|
10
|
+
navigate(args: actions.NavigateArgs): Promise<ActionResult>;
|
|
11
|
+
click(args: actions.ClickArgs): Promise<ActionResult>;
|
|
12
|
+
fill(args: actions.FillArgs): Promise<ActionResult>;
|
|
13
|
+
press(args: actions.PressArgs): Promise<ActionResult>;
|
|
14
|
+
hover(args: actions.HoverArgs): Promise<ActionResult>;
|
|
15
|
+
select(args: actions.SelectArgs): Promise<ActionResult>;
|
|
16
|
+
scroll(args: actions.ScrollArgs): Promise<ActionResult>;
|
|
17
|
+
goBack(args: actions.GoBackArgs): Promise<ActionResult>;
|
|
18
|
+
goForward(args: actions.GoForwardArgs): Promise<ActionResult>;
|
|
19
|
+
chooseOption(args: actions.ChooseOptionArgs): Promise<ActionResult>;
|
|
20
|
+
setViewport(args: actions.SetViewportArgs): Promise<ActionResult>;
|
|
21
|
+
waitFor(args: actions.WaitForArgs): Promise<ActionResult>;
|
|
22
|
+
}
|
|
23
|
+
/** Playwright engines — delegates each action to the existing `actions.*` over a
|
|
24
|
+
* freshly-built ActionContext (the `ctx` thunk captures the session entry, the
|
|
25
|
+
* same per-call construction the handlers did before this seam). No behaviour
|
|
26
|
+
* change. */
|
|
27
|
+
export declare class PlaywrightActionSubstrate implements ActionSubstrate {
|
|
28
|
+
private readonly ctx;
|
|
29
|
+
readonly engine: string;
|
|
30
|
+
constructor(ctx: () => ActionContext, engine?: string);
|
|
31
|
+
navigate(args: actions.NavigateArgs): Promise<ActionResult>;
|
|
32
|
+
click(args: actions.ClickArgs): Promise<ActionResult>;
|
|
33
|
+
fill(args: actions.FillArgs): Promise<ActionResult>;
|
|
34
|
+
press(args: actions.PressArgs): Promise<ActionResult>;
|
|
35
|
+
hover(args: actions.HoverArgs): Promise<ActionResult>;
|
|
36
|
+
select(args: actions.SelectArgs): Promise<ActionResult>;
|
|
37
|
+
scroll(args: actions.ScrollArgs): Promise<ActionResult>;
|
|
38
|
+
goBack(args: actions.GoBackArgs): Promise<ActionResult>;
|
|
39
|
+
goForward(args: actions.GoForwardArgs): Promise<ActionResult>;
|
|
40
|
+
chooseOption(args: actions.ChooseOptionArgs): Promise<ActionResult>;
|
|
41
|
+
setViewport(args: actions.SetViewportArgs): Promise<ActionResult>;
|
|
42
|
+
waitFor(args: actions.WaitForArgs): Promise<ActionResult>;
|
|
43
|
+
}
|
|
44
|
+
/** Safari — the WebDriver-Classic action path. The curated subset is real;
|
|
45
|
+
* everything else refuses cleanly here (the gating is in the adapter, not the
|
|
46
|
+
* handler). */
|
|
47
|
+
export declare class SafariActionSubstrate implements ActionSubstrate {
|
|
48
|
+
private readonly handle;
|
|
49
|
+
private readonly refs;
|
|
50
|
+
readonly engine = "safari";
|
|
51
|
+
constructor(handle: SafariSessionHandle, refs: RefRegistry);
|
|
52
|
+
navigate(args: actions.NavigateArgs): Promise<ActionResult>;
|
|
53
|
+
click(args: actions.ClickArgs): Promise<ActionResult>;
|
|
54
|
+
fill(args: actions.FillArgs): Promise<ActionResult>;
|
|
55
|
+
press(args: actions.PressArgs): Promise<ActionResult>;
|
|
56
|
+
hover(): Promise<ActionResult>;
|
|
57
|
+
select(): Promise<ActionResult>;
|
|
58
|
+
scroll(): Promise<ActionResult>;
|
|
59
|
+
goBack(): Promise<ActionResult>;
|
|
60
|
+
goForward(): Promise<ActionResult>;
|
|
61
|
+
chooseOption(): Promise<ActionResult>;
|
|
62
|
+
setViewport(): Promise<ActionResult>;
|
|
63
|
+
waitFor(): Promise<ActionResult>;
|
|
64
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// The ActionSubstrate interface — the engine-agnostic seam beneath the action
|
|
2
|
+
// tools (navigate / click / fill / press / hover / select / scroll / …). It is
|
|
3
|
+
// the action side of the engine-agnostic seam: a tool handler asks a substrate
|
|
4
|
+
// to perform an action and gets back the universal `ActionResult`; an engine-specific
|
|
5
|
+
// implementation does the work. The handler never names Playwright, CDP, or an
|
|
6
|
+
// engine — it calls `actionsFor(e).click(args)`, the same shape as
|
|
7
|
+
// `snapshotSubstrateFor(e.session).compose(...)`.
|
|
8
|
+
//
|
|
9
|
+
// Dependency direction (architecture doctrine §1): tool handler → ActionSubstrate
|
|
10
|
+
// (this interface) → implementation → Playwright | safaridriver. Two impls today:
|
|
11
|
+
// - PlaywrightActionSubstrate (chromium / firefox / webkit / android): wraps the
|
|
12
|
+
// existing `actions.*` over a Playwright ActionContext — byte-identical to the
|
|
13
|
+
// pre-seam path, so the four engines' keystones stay green unchanged.
|
|
14
|
+
// - SafariActionSubstrate (safari): wraps `safari-actions.*` over the WebDriver
|
|
15
|
+
// Classic client (no Playwright Page). The curated subset (navigate/click/
|
|
16
|
+
// fill/press) is real; the rest refuse cleanly IN THE ADAPTER — so the gating
|
|
17
|
+
// lives here, not as `if (engine === "safari")` branches scattered through the
|
|
18
|
+
// handlers.
|
|
19
|
+
import * as actions from "./actions.js";
|
|
20
|
+
import { safariNavigate, safariClick, safariFill, safariPress, safariUnsupportedAction, } from "./safari-actions.js";
|
|
21
|
+
/** Playwright engines — delegates each action to the existing `actions.*` over a
|
|
22
|
+
* freshly-built ActionContext (the `ctx` thunk captures the session entry, the
|
|
23
|
+
* same per-call construction the handlers did before this seam). No behaviour
|
|
24
|
+
* change. */
|
|
25
|
+
export class PlaywrightActionSubstrate {
|
|
26
|
+
ctx;
|
|
27
|
+
engine;
|
|
28
|
+
constructor(ctx, engine = "chromium") {
|
|
29
|
+
this.ctx = ctx;
|
|
30
|
+
this.engine = engine;
|
|
31
|
+
}
|
|
32
|
+
navigate(args) {
|
|
33
|
+
return actions.navigate(this.ctx(), args);
|
|
34
|
+
}
|
|
35
|
+
click(args) {
|
|
36
|
+
return actions.click(this.ctx(), args);
|
|
37
|
+
}
|
|
38
|
+
fill(args) {
|
|
39
|
+
return actions.fill(this.ctx(), args);
|
|
40
|
+
}
|
|
41
|
+
press(args) {
|
|
42
|
+
return actions.press(this.ctx(), args);
|
|
43
|
+
}
|
|
44
|
+
hover(args) {
|
|
45
|
+
return actions.hover(this.ctx(), args);
|
|
46
|
+
}
|
|
47
|
+
select(args) {
|
|
48
|
+
return actions.select(this.ctx(), args);
|
|
49
|
+
}
|
|
50
|
+
scroll(args) {
|
|
51
|
+
return actions.scroll(this.ctx(), args);
|
|
52
|
+
}
|
|
53
|
+
goBack(args) {
|
|
54
|
+
return actions.goBack(this.ctx(), args);
|
|
55
|
+
}
|
|
56
|
+
goForward(args) {
|
|
57
|
+
return actions.goForward(this.ctx(), args);
|
|
58
|
+
}
|
|
59
|
+
chooseOption(args) {
|
|
60
|
+
return actions.chooseOption(this.ctx(), args);
|
|
61
|
+
}
|
|
62
|
+
setViewport(args) {
|
|
63
|
+
return actions.setViewport(this.ctx(), args);
|
|
64
|
+
}
|
|
65
|
+
waitFor(args) {
|
|
66
|
+
return actions.waitFor(this.ctx(), args);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/** Safari — the WebDriver-Classic action path. The curated subset is real;
|
|
70
|
+
* everything else refuses cleanly here (the gating is in the adapter, not the
|
|
71
|
+
* handler). */
|
|
72
|
+
export class SafariActionSubstrate {
|
|
73
|
+
handle;
|
|
74
|
+
refs;
|
|
75
|
+
engine = "safari";
|
|
76
|
+
constructor(handle, refs) {
|
|
77
|
+
this.handle = handle;
|
|
78
|
+
this.refs = refs;
|
|
79
|
+
}
|
|
80
|
+
navigate(args) {
|
|
81
|
+
return safariNavigate(this.handle, args.url);
|
|
82
|
+
}
|
|
83
|
+
click(args) {
|
|
84
|
+
return safariClick(this.handle, this.refs, args.target);
|
|
85
|
+
}
|
|
86
|
+
fill(args) {
|
|
87
|
+
return safariFill(this.handle, this.refs, args.target, args.value);
|
|
88
|
+
}
|
|
89
|
+
press(args) {
|
|
90
|
+
return args.target
|
|
91
|
+
? safariPress(this.handle, this.refs, args.target, args.key)
|
|
92
|
+
: Promise.resolve(safariUnsupportedAction("press"));
|
|
93
|
+
}
|
|
94
|
+
hover() {
|
|
95
|
+
return Promise.resolve(safariUnsupportedAction("hover"));
|
|
96
|
+
}
|
|
97
|
+
select() {
|
|
98
|
+
return Promise.resolve(safariUnsupportedAction("select"));
|
|
99
|
+
}
|
|
100
|
+
scroll() {
|
|
101
|
+
return Promise.resolve(safariUnsupportedAction("scroll"));
|
|
102
|
+
}
|
|
103
|
+
goBack() {
|
|
104
|
+
return Promise.resolve(safariUnsupportedAction("goBack"));
|
|
105
|
+
}
|
|
106
|
+
goForward() {
|
|
107
|
+
return Promise.resolve(safariUnsupportedAction("goForward"));
|
|
108
|
+
}
|
|
109
|
+
chooseOption() {
|
|
110
|
+
return Promise.resolve(safariUnsupportedAction("chooseOption"));
|
|
111
|
+
}
|
|
112
|
+
setViewport() {
|
|
113
|
+
return Promise.resolve(safariUnsupportedAction("setViewport"));
|
|
114
|
+
}
|
|
115
|
+
waitFor() {
|
|
116
|
+
return Promise.resolve(safariUnsupportedAction("waitFor"));
|
|
117
|
+
}
|
|
118
|
+
}
|