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,53 @@
|
|
|
1
|
+
// `screenshot` — workspace-rooted file-write extension.
|
|
2
|
+
//
|
|
3
|
+
// The `screenshot` tool's default mode returns inline base64 image bytes (an
|
|
4
|
+
// MCP `image` content part). When the caller supplies a `path`, the bytes are
|
|
5
|
+
// written to a workspace-rooted file instead, and the result swaps the inline
|
|
6
|
+
// image for a `{ ok, path, bytes, format, fullPage }` JSON envelope.
|
|
7
|
+
//
|
|
8
|
+
// This module owns the disk-write side only — buffer encoding stays with the
|
|
9
|
+
// tool layer (Playwright's `page.screenshot()` / `locator.screenshot()` already
|
|
10
|
+
// produced the buffer by the time we're called). Mirrors the `pdf_save` split:
|
|
11
|
+
// the consequential write goes through `resolveWorkspacePath` so a path
|
|
12
|
+
// escaping `$BROWX_WORKSPACE` is rejected before any byte hits disk.
|
|
13
|
+
//
|
|
14
|
+
// Capability gating happens at the tool layer (see `src/server.ts`): when
|
|
15
|
+
// `path` is set, `file-io` is required in addition to the screenshot tool's
|
|
16
|
+
// own `read` gate. Default (no `path`) behaviour is unchanged — no capability
|
|
17
|
+
// change, no disk write.
|
|
18
|
+
import { resolve as resolvePath, dirname } from "node:path";
|
|
19
|
+
import { statSync, mkdirSync, writeFileSync } from "node:fs";
|
|
20
|
+
import { resolveWorkspacePath } from "../session/storage.js";
|
|
21
|
+
/** Write screenshot bytes to a workspace-rooted path. The caller has already
|
|
22
|
+
* encoded the buffer (via Playwright `page.screenshot()` /
|
|
23
|
+
* `locator.screenshot()`); this layer resolves the path safely, ensures the
|
|
24
|
+
* parent directory exists, and writes the bytes synchronously.
|
|
25
|
+
*
|
|
26
|
+
* Throws on:
|
|
27
|
+
* - `path` escaping `$BROWX_WORKSPACE` (via `resolveWorkspacePath`).
|
|
28
|
+
* - Underlying `writeFileSync` failure (re-thrown with original message). */
|
|
29
|
+
export function screenshotSave(buf, workspaceRoot, args) {
|
|
30
|
+
const resolved = resolveWorkspacePath(workspaceRoot, args.path, "screenshot");
|
|
31
|
+
// Ensure parent dir exists — `resolved` is rooted in BROWX_WORKSPACE by
|
|
32
|
+
// construction (resolveWorkspacePath rejects escapes); `writeFileSync`
|
|
33
|
+
// fails if the dir is missing. Same pattern as `pdfSave`.
|
|
34
|
+
mkdirSync(dirname(resolved), { recursive: true });
|
|
35
|
+
writeFileSync(resolved, buf);
|
|
36
|
+
let bytes = 0;
|
|
37
|
+
try {
|
|
38
|
+
bytes = statSync(resolved).size;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
/* best-effort */
|
|
42
|
+
}
|
|
43
|
+
// Belt-and-braces: re-run resolve to surface the absolute path (the input
|
|
44
|
+
// may have been a workspace-relative path).
|
|
45
|
+
const absolute = resolvePath(resolved);
|
|
46
|
+
return {
|
|
47
|
+
ok: true,
|
|
48
|
+
path: absolute,
|
|
49
|
+
bytes,
|
|
50
|
+
format: args.format,
|
|
51
|
+
fullPage: args.fullPage,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export declare const MIN_INTERVAL_MS = 100;
|
|
2
|
+
export declare const MAX_INTERVAL_MS = 60000;
|
|
3
|
+
/** Hard cap on captures-per-call. The schedule is already bounded by
|
|
4
|
+
* count/durationMs; this is a belt-and-braces ceiling so a 100ms cadence over
|
|
5
|
+
* the 1h action-timeout ceiling can't blow up disk space in one call. */
|
|
6
|
+
export declare const MAX_CAPTURES_PER_CALL = 1000;
|
|
7
|
+
export interface ScheduleArgs {
|
|
8
|
+
everyMs: number;
|
|
9
|
+
/** Mutually exclusive with `durationMs`. */
|
|
10
|
+
count?: number;
|
|
11
|
+
/** Mutually exclusive with `count`. */
|
|
12
|
+
durationMs?: number;
|
|
13
|
+
/** Destination directory (workspace-rooted). Defaulted by the server
|
|
14
|
+
* handler before this layer ever sees it (so the controller's contract
|
|
15
|
+
* stays "give me a resolved dir"). */
|
|
16
|
+
intoDir: string;
|
|
17
|
+
/** Image format — `"png"` (default) or `"jpeg"`. Recorded in each file's
|
|
18
|
+
* extension so the caller can spot the format from the dir alone. */
|
|
19
|
+
format?: "png" | "jpeg";
|
|
20
|
+
}
|
|
21
|
+
export interface ScheduleResult {
|
|
22
|
+
intoDir: string;
|
|
23
|
+
count: number;
|
|
24
|
+
capturedAt: number[];
|
|
25
|
+
paths: string[];
|
|
26
|
+
warnings: string[];
|
|
27
|
+
}
|
|
28
|
+
/** Validate the shape; throw early so the MCP handler can return a structured
|
|
29
|
+
* error before any disk write. */
|
|
30
|
+
export declare function validateScheduleArgs(args: ScheduleArgs): void;
|
|
31
|
+
/** Inject a `snap()` for tests; the real wiring passes a closure over
|
|
32
|
+
* Playwright's `page.screenshot()`. Returns the encoded bytes. */
|
|
33
|
+
export type SnapFn = () => Promise<Buffer>;
|
|
34
|
+
/** Injectable timing seam (real impl uses `setTimeout` + `Date.now`). */
|
|
35
|
+
export interface ScheduleClock {
|
|
36
|
+
now(): number;
|
|
37
|
+
/** Sleep for `ms`. Returns when the timer fires; never rejects. */
|
|
38
|
+
sleep(ms: number): Promise<void>;
|
|
39
|
+
}
|
|
40
|
+
export declare function runSchedule(snap: SnapFn, args: ScheduleArgs, workspaceRoot: string, clock?: ScheduleClock): Promise<ScheduleResult>;
|
|
41
|
+
/** Default `intoDir` shape — `screenshots/<sessionId>-<isoTs>/`. The MCP
|
|
42
|
+
* handler joins this against `$BROWX_WORKSPACE` via `resolveWorkspacePath`,
|
|
43
|
+
* same as a user-supplied path. ISO timestamp uses `:` / `.` → `-` so the
|
|
44
|
+
* path is filesystem-friendly on every platform. */
|
|
45
|
+
export declare function defaultScheduleDir(sessionId: string, now?: Date): string;
|
|
46
|
+
/** Shared dir-creation helper — re-used by `screenshot_on`. Rooted inside
|
|
47
|
+
* $BROWX_WORKSPACE (path escape is rejected by `resolveWorkspacePath`). */
|
|
48
|
+
export declare function ensureWorkspaceDir(workspaceRoot: string, intoDir: string, tool: string): string;
|
|
49
|
+
/** Stat helper used by the result envelope — best-effort byte count per file. */
|
|
50
|
+
export declare function fileBytes(path: string): number;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
// `screenshot_schedule` — periodic screenshot captures at a fixed interval,
|
|
2
|
+
// stopped by a hard count or a wall-clock duration. Sibling of
|
|
3
|
+
// `screenshot_on` (event-driven). The controller itself is browser-agnostic:
|
|
4
|
+
// the *snap* function is injected, so the policy (cadence + stop) and the
|
|
5
|
+
// path-write side stay independently unit-testable.
|
|
6
|
+
//
|
|
7
|
+
// Anti-wedge: every call is bounded — either `count` OR `durationMs` must be
|
|
8
|
+
// supplied (mutually exclusive), so an unbounded interval-fire-forever loop
|
|
9
|
+
// can't exist. The outer MCP handler additionally wraps the controller in
|
|
10
|
+
// `withDeadline` against the action-timeout so the call returns even if a
|
|
11
|
+
// single `snap` wedges. Capability `file-io` (the bytes hit disk).
|
|
12
|
+
import { mkdirSync, statSync, writeFileSync } from "node:fs";
|
|
13
|
+
import { join, resolve as resolvePath } from "node:path";
|
|
14
|
+
import { resolveWorkspacePath } from "../session/storage.js";
|
|
15
|
+
export const MIN_INTERVAL_MS = 100;
|
|
16
|
+
export const MAX_INTERVAL_MS = 60_000;
|
|
17
|
+
/** Hard cap on captures-per-call. The schedule is already bounded by
|
|
18
|
+
* count/durationMs; this is a belt-and-braces ceiling so a 100ms cadence over
|
|
19
|
+
* the 1h action-timeout ceiling can't blow up disk space in one call. */
|
|
20
|
+
export const MAX_CAPTURES_PER_CALL = 1000;
|
|
21
|
+
/** Validate the shape; throw early so the MCP handler can return a structured
|
|
22
|
+
* error before any disk write. */
|
|
23
|
+
export function validateScheduleArgs(args) {
|
|
24
|
+
if (!Number.isFinite(args.everyMs) ||
|
|
25
|
+
args.everyMs < MIN_INTERVAL_MS ||
|
|
26
|
+
args.everyMs > MAX_INTERVAL_MS) {
|
|
27
|
+
throw new Error(`screenshot_schedule: \`everyMs\` must be in [${MIN_INTERVAL_MS}, ${MAX_INTERVAL_MS}] — got ${args.everyMs}`);
|
|
28
|
+
}
|
|
29
|
+
const hasCount = typeof args.count === "number";
|
|
30
|
+
const hasDuration = typeof args.durationMs === "number";
|
|
31
|
+
if (hasCount && hasDuration) {
|
|
32
|
+
throw new Error(`screenshot_schedule: \`count\` and \`durationMs\` are mutually exclusive — pass exactly one`);
|
|
33
|
+
}
|
|
34
|
+
if (!hasCount && !hasDuration) {
|
|
35
|
+
throw new Error(`screenshot_schedule: pass either \`count\` (N captures) or \`durationMs\` (window length, ms) — unbounded schedules are refused`);
|
|
36
|
+
}
|
|
37
|
+
if (hasCount &&
|
|
38
|
+
(!Number.isInteger(args.count) ||
|
|
39
|
+
args.count < 1 ||
|
|
40
|
+
args.count > MAX_CAPTURES_PER_CALL)) {
|
|
41
|
+
throw new Error(`screenshot_schedule: \`count\` must be an integer in [1, ${MAX_CAPTURES_PER_CALL}] — got ${args.count}`);
|
|
42
|
+
}
|
|
43
|
+
if (hasDuration &&
|
|
44
|
+
(!Number.isFinite(args.durationMs) || args.durationMs < args.everyMs)) {
|
|
45
|
+
throw new Error(`screenshot_schedule: \`durationMs\` must be >= \`everyMs\` — got durationMs=${args.durationMs}, everyMs=${args.everyMs}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const REAL_CLOCK = {
|
|
49
|
+
now: () => Date.now(),
|
|
50
|
+
sleep: (ms) => new Promise((r) => setTimeout(r, Math.max(0, ms))),
|
|
51
|
+
};
|
|
52
|
+
/** Run the schedule. The caller is responsible for the outer `withDeadline`
|
|
53
|
+
* wrap (anti-wedge), and supplies `workspaceRoot` so `intoDir` resolves
|
|
54
|
+
* inside `$BROWX_WORKSPACE`. */
|
|
55
|
+
/** Attempt one capture; on failure surface a warning and return null (a single
|
|
56
|
+
* transient hiccup shouldn't poison the whole window). */
|
|
57
|
+
async function tryCapture(snap, i, warnings) {
|
|
58
|
+
try {
|
|
59
|
+
return await snap();
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
warnings.push(`capture ${i}: ${err instanceof Error ? err.message : String(err)}`);
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** Sleep until the next scheduled tick (drift-tolerant: anchored to the capture
|
|
67
|
+
* start, so a slow snap still fires the next tick on-cadence). Returns true when
|
|
68
|
+
* the window has ended (caller should break). */
|
|
69
|
+
async function cadenceSleep(clock, captureStart, everyMs, hasCount, windowEndMs) {
|
|
70
|
+
const sleepMs = Math.max(0, captureStart + everyMs - clock.now());
|
|
71
|
+
if (!hasCount && clock.now() + sleepMs >= windowEndMs) {
|
|
72
|
+
await clock.sleep(Math.max(0, windowEndMs - clock.now()));
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
await clock.sleep(sleepMs);
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
export async function runSchedule(snap, args, workspaceRoot, clock = REAL_CLOCK) {
|
|
79
|
+
validateScheduleArgs(args);
|
|
80
|
+
// Resolve + create the target dir under $BROWX_WORKSPACE. `resolveWorkspacePath`
|
|
81
|
+
// rejects path-escape attempts before any byte hits disk (same chokepoint as
|
|
82
|
+
// `screenshot({path})`).
|
|
83
|
+
const resolvedDir = resolveWorkspacePath(workspaceRoot, args.intoDir, "screenshot_schedule");
|
|
84
|
+
mkdirSync(resolvedDir, { recursive: true });
|
|
85
|
+
const fmt = args.format ?? "png";
|
|
86
|
+
const ext = fmt === "jpeg" ? "jpg" : "png";
|
|
87
|
+
const paths = [];
|
|
88
|
+
const capturedAt = [];
|
|
89
|
+
const warnings = [];
|
|
90
|
+
const tStart = clock.now();
|
|
91
|
+
const hasCount = typeof args.count === "number";
|
|
92
|
+
const targetCount = hasCount ? args.count : MAX_CAPTURES_PER_CALL;
|
|
93
|
+
const windowEndMs = hasCount ? Number.POSITIVE_INFINITY : tStart + args.durationMs;
|
|
94
|
+
let i = 0;
|
|
95
|
+
while (i < targetCount && clock.now() < windowEndMs) {
|
|
96
|
+
// Belt-and-braces ceiling — independent of count/duration. Ensures a
|
|
97
|
+
// 100ms-cadence over the 1h action-timeout ceiling can't blow up disk space.
|
|
98
|
+
if (paths.length >= MAX_CAPTURES_PER_CALL) {
|
|
99
|
+
warnings.push(`reached MAX_CAPTURES_PER_CALL=${MAX_CAPTURES_PER_CALL}; schedule stopped early`);
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
const t = clock.now();
|
|
103
|
+
const buf = await tryCapture(snap, i, warnings);
|
|
104
|
+
if (buf === null) {
|
|
105
|
+
i++;
|
|
106
|
+
// Honour the cadence even on a failed capture.
|
|
107
|
+
if (i < targetCount && clock.now() < windowEndMs)
|
|
108
|
+
await clock.sleep(Math.max(0, args.everyMs));
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
const ts = clock.now() - tStart;
|
|
112
|
+
// `p` inherits its $BROWX_WORKSPACE-rooted dir from `resolvedDir`.
|
|
113
|
+
const p = join(resolvedDir, `${String(i).padStart(4, "0")}-${ts}.${ext}`);
|
|
114
|
+
writeFileSync(p, buf);
|
|
115
|
+
paths.push(p);
|
|
116
|
+
capturedAt.push(ts);
|
|
117
|
+
i++;
|
|
118
|
+
if (i >= targetCount)
|
|
119
|
+
break;
|
|
120
|
+
if (await cadenceSleep(clock, t, args.everyMs, hasCount, windowEndMs))
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
intoDir: resolvePath(resolvedDir),
|
|
125
|
+
count: paths.length,
|
|
126
|
+
capturedAt,
|
|
127
|
+
paths,
|
|
128
|
+
warnings,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/** Default `intoDir` shape — `screenshots/<sessionId>-<isoTs>/`. The MCP
|
|
132
|
+
* handler joins this against `$BROWX_WORKSPACE` via `resolveWorkspacePath`,
|
|
133
|
+
* same as a user-supplied path. ISO timestamp uses `:` / `.` → `-` so the
|
|
134
|
+
* path is filesystem-friendly on every platform. */
|
|
135
|
+
export function defaultScheduleDir(sessionId, now = new Date()) {
|
|
136
|
+
const ts = now.toISOString().replace(/[:.]/g, "-");
|
|
137
|
+
return `screenshots/${sessionId}-${ts}`;
|
|
138
|
+
}
|
|
139
|
+
/** Shared dir-creation helper — re-used by `screenshot_on`. Rooted inside
|
|
140
|
+
* $BROWX_WORKSPACE (path escape is rejected by `resolveWorkspacePath`). */
|
|
141
|
+
export function ensureWorkspaceDir(workspaceRoot, intoDir, tool) {
|
|
142
|
+
const resolved = resolveWorkspacePath(workspaceRoot, intoDir, tool);
|
|
143
|
+
// $BROWX_WORKSPACE-rooted by construction (resolveWorkspacePath above).
|
|
144
|
+
mkdirSync(resolved, { recursive: true });
|
|
145
|
+
return resolved;
|
|
146
|
+
}
|
|
147
|
+
/** Stat helper used by the result envelope — best-effort byte count per file. */
|
|
148
|
+
export function fileBytes(path) {
|
|
149
|
+
try {
|
|
150
|
+
return statSync(path).size;
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return 0;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Page } from "playwright-core";
|
|
2
|
+
import type { SafariSessionHandle } from "../engine/index.js";
|
|
3
|
+
/** The script capability port. One instance wraps one session's engine handle;
|
|
4
|
+
* the method carries no engine type, so the handler above this seam is
|
|
5
|
+
* engine-blind. Mirrors the ActionSubstrate / CaptureSubstrate shape. The
|
|
6
|
+
* returned value is page-controlled (untrusted); the handler treats it the same
|
|
7
|
+
* as snapshot text. The deadline race + error envelope stay in the handler — the
|
|
8
|
+
* substrate only performs the raw evaluation. */
|
|
9
|
+
export interface ScriptSubstrate {
|
|
10
|
+
readonly engine: string;
|
|
11
|
+
evaluate(expr: string): Promise<unknown>;
|
|
12
|
+
}
|
|
13
|
+
/** Playwright engines — delegates to `page.evaluate(expr)` verbatim. `page.evaluate`
|
|
14
|
+
* carries no Playwright timeout (a never-resolving expr would wedge forever), so the
|
|
15
|
+
* handler races the returned promise against the anti-wedge deadline exactly as it
|
|
16
|
+
* did pre-seam. No behaviour change. */
|
|
17
|
+
export declare class PlaywrightScriptSubstrate implements ScriptSubstrate {
|
|
18
|
+
private readonly page;
|
|
19
|
+
readonly engine: string;
|
|
20
|
+
constructor(page: () => Page, engine?: string);
|
|
21
|
+
evaluate(expr: string): Promise<unknown>;
|
|
22
|
+
}
|
|
23
|
+
/** Safari — the WebDriver-Classic eval path. safaridriver has no Playwright Page;
|
|
24
|
+
* `execute/sync` takes a function BODY, so the bare expression is wrapped in
|
|
25
|
+
* `return (…)` to evaluate it and return its value — the verbatim wrapping from the
|
|
26
|
+
* handler's deleted Safari branch. */
|
|
27
|
+
export declare class SafariScriptSubstrate implements ScriptSubstrate {
|
|
28
|
+
private readonly handle;
|
|
29
|
+
readonly engine = "safari";
|
|
30
|
+
constructor(handle: SafariSessionHandle);
|
|
31
|
+
evaluate(expr: string): Promise<unknown>;
|
|
32
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// The ScriptSubstrate interface — the engine-agnostic seam beneath page-side JS
|
|
2
|
+
// evaluation (`eval_js` today; `exposeBinding` / `addInitScript` later). It keeps
|
|
3
|
+
// engine specifics out of the handler: the `eval_js` handler asks a substrate to
|
|
4
|
+
// evaluate an expression and gets back the page-controlled value; an engine-specific
|
|
5
|
+
// implementation does the work. The handler never names Playwright, safaridriver,
|
|
6
|
+
// or an engine — it calls `scriptFor(e).evaluate(expr)`, the same shape as
|
|
7
|
+
// `actionsFor(e).click(args)` / `captureFor(e).screenshot(args)`.
|
|
8
|
+
//
|
|
9
|
+
// Dependency direction (architecture doctrine §1): tool handler → ScriptSubstrate
|
|
10
|
+
// (this interface) → implementation → Playwright | safaridriver. Two impls today:
|
|
11
|
+
// - PlaywrightScriptSubstrate (chromium / firefox / webkit / android): wraps
|
|
12
|
+
// `page.evaluate(expr)` verbatim — byte-identical to the pre-seam handler, so
|
|
13
|
+
// the four engines' keystones stay green unchanged.
|
|
14
|
+
// - SafariScriptSubstrate (safari): wraps `webDriver.executeScript` over the
|
|
15
|
+
// WebDriver Classic `execute/sync` endpoint, wrapping the expression in
|
|
16
|
+
// `return (…)` (an expression, not a statement body) exactly as the handler's
|
|
17
|
+
// deleted `if (sh)` branch did — so the engine specifics live here, not as an
|
|
18
|
+
// engine check in the handler.
|
|
19
|
+
/** Playwright engines — delegates to `page.evaluate(expr)` verbatim. `page.evaluate`
|
|
20
|
+
* carries no Playwright timeout (a never-resolving expr would wedge forever), so the
|
|
21
|
+
* handler races the returned promise against the anti-wedge deadline exactly as it
|
|
22
|
+
* did pre-seam. No behaviour change. */
|
|
23
|
+
export class PlaywrightScriptSubstrate {
|
|
24
|
+
page;
|
|
25
|
+
engine;
|
|
26
|
+
constructor(page, engine = "chromium") {
|
|
27
|
+
this.page = page;
|
|
28
|
+
this.engine = engine;
|
|
29
|
+
}
|
|
30
|
+
evaluate(expr) {
|
|
31
|
+
return this.page().evaluate(expr);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** Safari — the WebDriver-Classic eval path. safaridriver has no Playwright Page;
|
|
35
|
+
* `execute/sync` takes a function BODY, so the bare expression is wrapped in
|
|
36
|
+
* `return (…)` to evaluate it and return its value — the verbatim wrapping from the
|
|
37
|
+
* handler's deleted Safari branch. */
|
|
38
|
+
export class SafariScriptSubstrate {
|
|
39
|
+
handle;
|
|
40
|
+
engine = "safari";
|
|
41
|
+
constructor(handle) {
|
|
42
|
+
this.handle = handle;
|
|
43
|
+
}
|
|
44
|
+
evaluate(expr) {
|
|
45
|
+
return this.handle.webDriver.executeScript(this.handle.sessionId, `return (${expr});`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { BrowserContext, Page } from "playwright-core";
|
|
2
|
+
export interface SeedRandomInput {
|
|
3
|
+
/** Non-negative finite integer seed. 0 is valid. */
|
|
4
|
+
seed: number;
|
|
5
|
+
}
|
|
6
|
+
export interface SeedRandomState {
|
|
7
|
+
seed: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The page-side init script. Defined as a string so Playwright can serialise
|
|
11
|
+
* it intact to every new document. Re-reads `window.__browxSeed` on every
|
|
12
|
+
* call (set by the install-script closure) so a re-seed via the main-frame
|
|
13
|
+
* hook below is picked up by the next `Math.random()` without re-injection.
|
|
14
|
+
*
|
|
15
|
+
* Mulberry32 — small, fast, statistically reasonable for testing flake-repros;
|
|
16
|
+
* not cryptographic and explicitly NOT a `crypto` replacement.
|
|
17
|
+
*/
|
|
18
|
+
declare function buildInitScript(seed: number): string;
|
|
19
|
+
/** Per-session seeded-random controller. One per SessionEntry. */
|
|
20
|
+
export declare class SeededRandomRegistry {
|
|
21
|
+
private state;
|
|
22
|
+
/** Tracks whether we've installed a context-level init script yet. The
|
|
23
|
+
* reference is the BrowserContext so a session-shared context only gets
|
|
24
|
+
* one. */
|
|
25
|
+
private contextInstalled;
|
|
26
|
+
/** Tracks pages we've wired the re-apply hook on. */
|
|
27
|
+
private reattachInstalled;
|
|
28
|
+
/** Apply a seed override and remember it. */
|
|
29
|
+
apply(context: BrowserContext, page: Page, input: SeedRandomInput): Promise<{
|
|
30
|
+
state: SeedRandomState;
|
|
31
|
+
}>;
|
|
32
|
+
/** Test introspection. */
|
|
33
|
+
current(): SeedRandomState | undefined;
|
|
34
|
+
/** Defensive re-apply: `addInitScript` is per-document, but a renderer swap
|
|
35
|
+
* or main-frame nav still benefits from a re-push for symmetry with
|
|
36
|
+
* src/page/emulation.ts + src/page/clock.ts. We push the cached seed back
|
|
37
|
+
* into the main frame on every main-frame `framenavigated`. */
|
|
38
|
+
private installReattach;
|
|
39
|
+
}
|
|
40
|
+
/** Test-only: expose the script-builder so tests can assert determinism by
|
|
41
|
+
* evaluating the produced source in a sandbox without launching a browser. */
|
|
42
|
+
export declare const _internal: {
|
|
43
|
+
buildInitScript: typeof buildInitScript;
|
|
44
|
+
};
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
// Deterministic Math.random — capability `action`.
|
|
2
|
+
//
|
|
3
|
+
// Wraps Playwright `context.addInitScript` to inject a Mulberry32 PRNG that
|
|
4
|
+
// replaces `Math.random` at every realm bootstrap. The seed is captured by
|
|
5
|
+
// closure inside the init script so each navigation (and every iframe /
|
|
6
|
+
// worker that uses an init-script-installed Math.random) gets a fresh
|
|
7
|
+
// deterministic stream starting from the same state. Per-session.
|
|
8
|
+
//
|
|
9
|
+
// Reset semantics:
|
|
10
|
+
// - `seed_random({ seed })` with a finite, non-negative integer seed →
|
|
11
|
+
// installs the override (or replaces the cached seed if already set).
|
|
12
|
+
// - The init script is added ONCE per BrowserContext on first apply; the
|
|
13
|
+
// cached seed lives on a `window.__browxSeed` writeable closure-set by
|
|
14
|
+
// the init script. To re-seed we mutate that closure on the current page
|
|
15
|
+
// AND swap the context's init-script seed for any future page bootstrap.
|
|
16
|
+
//
|
|
17
|
+
// Re-apply on navigation:
|
|
18
|
+
// - Playwright `addInitScript` is a context-level primitive — it runs in
|
|
19
|
+
// every new document. To stay future-proof against renderer-swap edge
|
|
20
|
+
// cases (mirroring src/page/emulation.ts + src/page/clock.ts), we also
|
|
21
|
+
// install a `framenavigated` hook that pushes the cached seed back into
|
|
22
|
+
// the main-frame realm.
|
|
23
|
+
//
|
|
24
|
+
// MVP scope (not touched):
|
|
25
|
+
// - `crypto.randomUUID` / `crypto.getRandomValues` — web-crypto is a much
|
|
26
|
+
// bigger surface to deterministically stub; revisit later.
|
|
27
|
+
// - Workers — `addInitScript` runs in every document realm but not inside
|
|
28
|
+
// Web Workers / Service Workers. Out of scope for v1.
|
|
29
|
+
//
|
|
30
|
+
// BYOB note: the init script is installed on the attached Chrome's context
|
|
31
|
+
// for as long as the context lives. After our session detaches, any tab
|
|
32
|
+
// the human spawns from this context still hits the override on first load
|
|
33
|
+
// — surfaced as a `warning` on the result.
|
|
34
|
+
const MAX_SEED = 0xffffffff; // 2^32 - 1, Mulberry32's state domain
|
|
35
|
+
/**
|
|
36
|
+
* The page-side init script. Defined as a string so Playwright can serialise
|
|
37
|
+
* it intact to every new document. Re-reads `window.__browxSeed` on every
|
|
38
|
+
* call (set by the install-script closure) so a re-seed via the main-frame
|
|
39
|
+
* hook below is picked up by the next `Math.random()` without re-injection.
|
|
40
|
+
*
|
|
41
|
+
* Mulberry32 — small, fast, statistically reasonable for testing flake-repros;
|
|
42
|
+
* not cryptographic and explicitly NOT a `crypto` replacement.
|
|
43
|
+
*/
|
|
44
|
+
function buildInitScript(seed) {
|
|
45
|
+
return `(() => {
|
|
46
|
+
// Idempotent: a refresh that re-runs the init script must not stack overrides.
|
|
47
|
+
if (Object.prototype.hasOwnProperty.call(globalThis, "__browxSeed")) {
|
|
48
|
+
globalThis.__browxSeed = ${seed} >>> 0;
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
let state = ${seed} >>> 0;
|
|
52
|
+
Object.defineProperty(globalThis, "__browxSeed", {
|
|
53
|
+
configurable: true,
|
|
54
|
+
enumerable: false,
|
|
55
|
+
get() { return state; },
|
|
56
|
+
set(v) { state = (v | 0) >>> 0; },
|
|
57
|
+
});
|
|
58
|
+
const mulberry32 = () => {
|
|
59
|
+
state = (state + 0x6D2B79F5) >>> 0;
|
|
60
|
+
let t = state;
|
|
61
|
+
t = Math.imul(t ^ (t >>> 15), t | 1);
|
|
62
|
+
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
|
|
63
|
+
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
64
|
+
};
|
|
65
|
+
try {
|
|
66
|
+
Object.defineProperty(Math, "random", {
|
|
67
|
+
configurable: true,
|
|
68
|
+
writable: true,
|
|
69
|
+
value: mulberry32,
|
|
70
|
+
});
|
|
71
|
+
} catch {
|
|
72
|
+
// Fallback if Math.random is non-configurable in some embedder; assign anyway.
|
|
73
|
+
Math.random = mulberry32;
|
|
74
|
+
}
|
|
75
|
+
})();`;
|
|
76
|
+
}
|
|
77
|
+
function normalize(input) {
|
|
78
|
+
const s = input.seed;
|
|
79
|
+
if (s === undefined ||
|
|
80
|
+
s === null ||
|
|
81
|
+
!Number.isFinite(s) ||
|
|
82
|
+
!Number.isInteger(s) ||
|
|
83
|
+
s < 0 ||
|
|
84
|
+
s > MAX_SEED) {
|
|
85
|
+
throw new Error(`seed_random: seed must be a non-negative integer in [0, ${MAX_SEED}] (got ${JSON.stringify(s)})`);
|
|
86
|
+
}
|
|
87
|
+
return { seed: s };
|
|
88
|
+
}
|
|
89
|
+
/** Per-session seeded-random controller. One per SessionEntry. */
|
|
90
|
+
export class SeededRandomRegistry {
|
|
91
|
+
state;
|
|
92
|
+
/** Tracks whether we've installed a context-level init script yet. The
|
|
93
|
+
* reference is the BrowserContext so a session-shared context only gets
|
|
94
|
+
* one. */
|
|
95
|
+
contextInstalled = new WeakSet();
|
|
96
|
+
/** Tracks pages we've wired the re-apply hook on. */
|
|
97
|
+
reattachInstalled = new WeakSet();
|
|
98
|
+
/** Apply a seed override and remember it. */
|
|
99
|
+
async apply(context, page, input) {
|
|
100
|
+
const state = normalize(input);
|
|
101
|
+
if (!this.contextInstalled.has(context)) {
|
|
102
|
+
// First time: register the init script on the context so every new
|
|
103
|
+
// document (including the current one's NEXT navigation) sees it.
|
|
104
|
+
await context.addInitScript({ content: buildInitScript(state.seed) });
|
|
105
|
+
this.contextInstalled.add(context);
|
|
106
|
+
}
|
|
107
|
+
// Re-seed the CURRENT page's main realm immediately so a caller doesn't
|
|
108
|
+
// have to navigate to see the override take effect. This is best-effort —
|
|
109
|
+
// a closed page or detached frame raises, swallowed.
|
|
110
|
+
await page.evaluate(buildInitScript(state.seed)).catch(() => undefined);
|
|
111
|
+
this.state = state;
|
|
112
|
+
this.installReattach(page);
|
|
113
|
+
return { state };
|
|
114
|
+
}
|
|
115
|
+
/** Test introspection. */
|
|
116
|
+
current() {
|
|
117
|
+
return this.state;
|
|
118
|
+
}
|
|
119
|
+
/** Defensive re-apply: `addInitScript` is per-document, but a renderer swap
|
|
120
|
+
* or main-frame nav still benefits from a re-push for symmetry with
|
|
121
|
+
* src/page/emulation.ts + src/page/clock.ts. We push the cached seed back
|
|
122
|
+
* into the main frame on every main-frame `framenavigated`. */
|
|
123
|
+
installReattach(page) {
|
|
124
|
+
if (this.reattachInstalled.has(page))
|
|
125
|
+
return;
|
|
126
|
+
this.reattachInstalled.add(page);
|
|
127
|
+
const onNav = async (frame) => {
|
|
128
|
+
if (frame.parentFrame())
|
|
129
|
+
return; // main frame only
|
|
130
|
+
if (!this.state)
|
|
131
|
+
return;
|
|
132
|
+
try {
|
|
133
|
+
await page.evaluate(buildInitScript(this.state.seed)).catch(() => undefined);
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
// page may have closed mid-navigation; swallow
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
page.on("framenavigated", onNav);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/** Test-only: expose the script-builder so tests can assert determinism by
|
|
143
|
+
* evaluating the produced source in a sandbox without launching a browser. */
|
|
144
|
+
export const _internal = { buildInitScript };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { CDPSession, Page } from "playwright-core";
|
|
2
|
+
import { type FindCandidate } from "./find.js";
|
|
3
|
+
import type { RefRegistry } from "./refs.js";
|
|
4
|
+
import { type VisibleRect } from "./bbox.js";
|
|
5
|
+
import type { SnapshotSubstrate } from "./snapshot-substrate.js";
|
|
6
|
+
export type LabelMode = "index" | "ref" | "role";
|
|
7
|
+
export interface MarkCandidateRef {
|
|
8
|
+
/** Stable `eN` ref previously surfaced by snapshot/find. */
|
|
9
|
+
ref: string;
|
|
10
|
+
}
|
|
11
|
+
/** A pre-computed `find()` candidate. The caller can pass the full object
|
|
12
|
+
* through — we only consume `ref`, `role`, `name`, `testId`, and `bbox`. */
|
|
13
|
+
export type MarkCandidate = MarkCandidateRef | Pick<FindCandidate, "ref" | "role" | "name" | "testId" | "bbox">;
|
|
14
|
+
export interface SetOfMarksOptions {
|
|
15
|
+
candidates: MarkCandidate[];
|
|
16
|
+
/** How to label each painted box. Default `"index"` — the array-position
|
|
17
|
+
* numbering 1..N (paired with `mapping` so the agent can convert to `eN`).
|
|
18
|
+
* `"ref"` paints the existing `eN` directly. `"role"` paints the candidate's
|
|
19
|
+
* role (useful when the agent already has refs and wants visual grounding
|
|
20
|
+
* on what each box *is*). */
|
|
21
|
+
label?: LabelMode;
|
|
22
|
+
/** Configured test-attribute list — required if any candidate is a bare
|
|
23
|
+
* `{ref}` and we have to resolve its bbox via `find()`'s tree walker.
|
|
24
|
+
* When every candidate already carries `bbox`, unused. */
|
|
25
|
+
testAttributes?: string[];
|
|
26
|
+
}
|
|
27
|
+
export interface MarkEntry {
|
|
28
|
+
/** 1-based array position. Stable for the duration of the call result. */
|
|
29
|
+
index: number;
|
|
30
|
+
/** Existing `eN` ref — the cross-snapshot-stable identity. */
|
|
31
|
+
ref: string;
|
|
32
|
+
role?: string;
|
|
33
|
+
name?: string;
|
|
34
|
+
testId?: string;
|
|
35
|
+
bbox: VisibleRect | null;
|
|
36
|
+
/** True when this candidate was painted on the image. A candidate with a
|
|
37
|
+
* null bbox (fully clipped / off-screen) is reported but not painted. */
|
|
38
|
+
painted: boolean;
|
|
39
|
+
}
|
|
40
|
+
export interface SetOfMarksResult {
|
|
41
|
+
/** base64-encoded PNG of the viewport with the painted overlay. */
|
|
42
|
+
imageBase64: string;
|
|
43
|
+
mimeType: "image/png";
|
|
44
|
+
/** Per-candidate row: array position, ref, role/name/testId, the bbox we
|
|
45
|
+
* painted (or null), and whether it landed on the image. The agent can
|
|
46
|
+
* index 1..N OR address `eN` — same identity. */
|
|
47
|
+
marks: MarkEntry[];
|
|
48
|
+
/** Convenience: `{ "1": "e7", "2": "e3", … }`. Lets the LLM say "click 2"
|
|
49
|
+
* and the harness translate back to `click({ref:"e3"})`. */
|
|
50
|
+
mapping: Record<string, string>;
|
|
51
|
+
/** Non-fatal notes (candidates with no bbox, ref-only inputs we couldn't
|
|
52
|
+
* resolve, etc.). Same convention as `find()`'s `warnings`. */
|
|
53
|
+
warnings: string[];
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Resolve a list of `MarkCandidate`s (mixed `{ref}` and full-candidate shape)
|
|
57
|
+
* into `MarkEntry` rows. For bare `{ref}` inputs that aren't already bound to
|
|
58
|
+
* a locator in the registry, we fall back to `find()` over the existing tree
|
|
59
|
+
* to look up the bbox + role/name. Pure-ish: only does a `find()` walk when
|
|
60
|
+
* a bare ref needs resolving. Exported for unit-test composition.
|
|
61
|
+
*/
|
|
62
|
+
/** The page-side dependencies `resolveCandidates` threads through (bundled so the
|
|
63
|
+
* signature stays within the parameter budget). `cdp` is the chromium-only
|
|
64
|
+
* visible-rect fast path; off Chromium it is undefined and bbox computes via the
|
|
65
|
+
* portable `locatorBoundingBox` fallback. */
|
|
66
|
+
export interface MarksDeps {
|
|
67
|
+
page: Page;
|
|
68
|
+
substrate: SnapshotSubstrate;
|
|
69
|
+
refs: RefRegistry;
|
|
70
|
+
testAttributes: string[];
|
|
71
|
+
cdp?: CDPSession;
|
|
72
|
+
}
|
|
73
|
+
export declare function resolveCandidates(deps: MarksDeps, candidates: MarkCandidate[]): Promise<{
|
|
74
|
+
entries: MarkEntry[];
|
|
75
|
+
warnings: string[];
|
|
76
|
+
}>;
|
|
77
|
+
/** Pure label-builder. Exported for unit-test direct coverage. */
|
|
78
|
+
export declare function labelFor(entry: MarkEntry, mode: LabelMode): string;
|
|
79
|
+
/**
|
|
80
|
+
* Compose a single PNG screenshot of the current viewport with numbered
|
|
81
|
+
* bounding boxes painted over the supplied candidates. The numbering scheme
|
|
82
|
+
* shares the existing `eN` ref namespace (index↔ref mapping returned).
|
|
83
|
+
*
|
|
84
|
+
* `bbox` is honoured exactly as `find()` reported it — visible-rect with
|
|
85
|
+
* ancestor-overflow + viewport intersection applied (see `src/page/bbox.ts`).
|
|
86
|
+
* A candidate with `bbox: null` is **not** painted; it's listed in `marks`
|
|
87
|
+
* with `painted: false` and a `warnings` entry, so the caller knows the
|
|
88
|
+
* mapping still resolves but the box wasn't visible.
|
|
89
|
+
*
|
|
90
|
+
* The overlay is installed for the duration of the screenshot only and
|
|
91
|
+
* removed before this function returns. Failures during removal are
|
|
92
|
+
* best-effort (we still return the image + the warning).
|
|
93
|
+
*/
|
|
94
|
+
export declare function screenshotMarks(page: Page, substrate: SnapshotSubstrate, refs: RefRegistry, opts: SetOfMarksOptions,
|
|
95
|
+
/** CDP handle for the visible-rect bbox fast path — chromium only. */
|
|
96
|
+
cdp?: CDPSession): Promise<SetOfMarksResult>;
|