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,34 @@
|
|
|
1
|
+
import type { CDPSession } from "playwright-core";
|
|
2
|
+
import type { TraceEvent } from "./perf.js";
|
|
3
|
+
/** Default categories for the focused trace — same set DevTools uses when
|
|
4
|
+
* it highlights "Forced Reflow" + "Layout Shift" lanes. */
|
|
5
|
+
export declare const LAYOUT_THRASH_CATEGORIES: string[];
|
|
6
|
+
/** Per-origin aggregate: how many events fired from this call-stack + total
|
|
7
|
+
* cumulative time, plus a top-N representative origin string. */
|
|
8
|
+
export interface LayoutThrashOrigin {
|
|
9
|
+
/** Topmost frame: `${functionName}@${url}:${lineNumber}:${columnNumber}` —
|
|
10
|
+
* or `"<anonymous>"` if no stack was attached. */
|
|
11
|
+
originatingStack: string;
|
|
12
|
+
count: number;
|
|
13
|
+
totalDurationMs: number;
|
|
14
|
+
}
|
|
15
|
+
export interface LayoutThrashResult {
|
|
16
|
+
forcedLayoutsCount: number;
|
|
17
|
+
layoutShiftsCount: number;
|
|
18
|
+
/** Sorted by count desc. Capped at 50. */
|
|
19
|
+
eventsByOrigin: LayoutThrashOrigin[];
|
|
20
|
+
/** Workspace-rooted path the trace was written to. */
|
|
21
|
+
tracePath: string;
|
|
22
|
+
durationMs: number;
|
|
23
|
+
}
|
|
24
|
+
export interface LayoutThrashOptions {
|
|
25
|
+
durationMs?: number;
|
|
26
|
+
}
|
|
27
|
+
/** Default trace filename under `<workspace>/perf/<sessionId>-layout-thrash-<ts>.json`. */
|
|
28
|
+
export declare function defaultLayoutThrashPath(workspaceRoot: string, sessionId: string): string;
|
|
29
|
+
export declare function runLayoutThrashTrace(cdp: CDPSession, workspaceRoot: string, sessionId: string, opts?: LayoutThrashOptions): Promise<LayoutThrashResult>;
|
|
30
|
+
export declare function aggregateLayoutThrash(events: TraceEvent[]): {
|
|
31
|
+
forcedLayoutsCount: number;
|
|
32
|
+
layoutShiftsCount: number;
|
|
33
|
+
eventsByOrigin: LayoutThrashOrigin[];
|
|
34
|
+
};
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
// Layout-thrash trace — capability `read`. Focused CDP trace just for
|
|
2
|
+
// forced-synchronous-layout + layout-shift events, with origin-of-event
|
|
3
|
+
// stacks aggregated so the agent sees "this rAF loop is causing 200 forced
|
|
4
|
+
// layouts" at a glance instead of paging through a 100MB chromium trace.
|
|
5
|
+
//
|
|
6
|
+
// Pattern mirrors `src/page/perf.ts` (same `Tracing.dataCollected` →
|
|
7
|
+
// `Tracing.tracingComplete` flush flow) but the lifecycle is one-shot —
|
|
8
|
+
// caller doesn't manage state, this function arms + waits + parses + writes
|
|
9
|
+
// in one go.
|
|
10
|
+
//
|
|
11
|
+
// CDP `stackTrace` is populated on relevant trace events when DevTools is
|
|
12
|
+
// attached. We pick the topmost frame as `originatingStack` for the
|
|
13
|
+
// aggregation — that's the function name + url:line:col the agent acts on.
|
|
14
|
+
import { writeFileSync, mkdirSync, existsSync } from "node:fs";
|
|
15
|
+
import { dirname, join, resolve, sep } from "node:path";
|
|
16
|
+
/** Default categories for the focused trace — same set DevTools uses when
|
|
17
|
+
* it highlights "Forced Reflow" + "Layout Shift" lanes. */
|
|
18
|
+
export const LAYOUT_THRASH_CATEGORIES = [
|
|
19
|
+
"devtools.timeline",
|
|
20
|
+
"disabled-by-default-devtools.timeline",
|
|
21
|
+
"blink.user_timing",
|
|
22
|
+
];
|
|
23
|
+
const DEFAULT_DURATION_MS = 5_000;
|
|
24
|
+
const MAX_DURATION_MS = 30_000;
|
|
25
|
+
const MAX_ORIGINS = 50;
|
|
26
|
+
/** Workspace-rooted path helper — same shape as `resolvePerfTracePath`. */
|
|
27
|
+
function resolveLayoutThrashPath(workspaceRoot, p, tool) {
|
|
28
|
+
const resolved = resolve(workspaceRoot, p);
|
|
29
|
+
if (resolved !== workspaceRoot && !resolved.startsWith(workspaceRoot + sep)) {
|
|
30
|
+
throw new Error(`${tool}: \`path\` must resolve inside $BROWX_WORKSPACE — got "${p}".`);
|
|
31
|
+
}
|
|
32
|
+
return resolved;
|
|
33
|
+
}
|
|
34
|
+
/** Default trace filename under `<workspace>/perf/<sessionId>-layout-thrash-<ts>.json`. */
|
|
35
|
+
export function defaultLayoutThrashPath(workspaceRoot, sessionId) {
|
|
36
|
+
const safe = (sessionId || "default").replace(/[^A-Za-z0-9._-]/g, "_");
|
|
37
|
+
const ts = new Date().toISOString().replace(/[:.]/g, "-");
|
|
38
|
+
return join(workspaceRoot, "perf", `${safe}-layout-thrash-${ts}.json`);
|
|
39
|
+
}
|
|
40
|
+
/** Run a focused layout-thrash trace. Records for `durationMs`, parses the
|
|
41
|
+
* result, writes the raw events to `<workspace>/perf/...`, returns the
|
|
42
|
+
* aggregated finding. */
|
|
43
|
+
/** Start a layout-thrash CDP trace, record for `durationMs`, then stop and drain
|
|
44
|
+
* the buffered events (bounded by a 30s completion race). Detaches both
|
|
45
|
+
* listeners in `finally` regardless of outcome. */
|
|
46
|
+
async function collectTraceEvents(cdp, durationMs) {
|
|
47
|
+
const events = [];
|
|
48
|
+
let complete = null;
|
|
49
|
+
const onData = (e) => {
|
|
50
|
+
if (Array.isArray(e?.value)) {
|
|
51
|
+
for (const ev of e.value)
|
|
52
|
+
events.push(ev);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
const onComplete = () => {
|
|
56
|
+
if (complete)
|
|
57
|
+
complete();
|
|
58
|
+
};
|
|
59
|
+
cdp.on("Tracing.dataCollected", onData);
|
|
60
|
+
cdp.on("Tracing.tracingComplete", onComplete);
|
|
61
|
+
try {
|
|
62
|
+
await cdp.send("Tracing.start", {
|
|
63
|
+
transferMode: "ReportEvents",
|
|
64
|
+
traceConfig: {
|
|
65
|
+
recordMode: "recordContinuously",
|
|
66
|
+
includedCategories: LAYOUT_THRASH_CATEGORIES,
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
await new Promise((res) => setTimeout(res, durationMs));
|
|
70
|
+
const completionPromise = new Promise((res) => {
|
|
71
|
+
complete = res;
|
|
72
|
+
});
|
|
73
|
+
await cdp.send("Tracing.end").catch(() => undefined);
|
|
74
|
+
await Promise.race([completionPromise, new Promise((res) => setTimeout(res, 30_000))]);
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
try {
|
|
78
|
+
cdp.off("Tracing.dataCollected", onData);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
/* best-effort */
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
cdp.off("Tracing.tracingComplete", onComplete);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
/* best-effort */
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return events;
|
|
91
|
+
}
|
|
92
|
+
export async function runLayoutThrashTrace(cdp, workspaceRoot, sessionId, opts = {}) {
|
|
93
|
+
const durationMs = clampDuration(opts.durationMs);
|
|
94
|
+
const events = await collectTraceEvents(cdp, durationMs);
|
|
95
|
+
// Write the raw trace events file (workspace-rooted) so the agent can
|
|
96
|
+
// re-open it in the DevTools Performance panel if desired.
|
|
97
|
+
const tracePath = defaultLayoutThrashPath(workspaceRoot, sessionId);
|
|
98
|
+
const resolved = resolveLayoutThrashPath(workspaceRoot, tracePath, "layout_thrash_trace");
|
|
99
|
+
const parent = dirname(resolved);
|
|
100
|
+
// ws.sub-style: ensure parent exists under workspace.root.
|
|
101
|
+
if (parent && !existsSync(parent))
|
|
102
|
+
mkdirSync(parent, { recursive: true });
|
|
103
|
+
// ws.root-rooted path — see resolveLayoutThrashPath above for the guard.
|
|
104
|
+
writeFileSync(resolved, JSON.stringify({
|
|
105
|
+
traceEvents: events,
|
|
106
|
+
metadata: {
|
|
107
|
+
source: "browxai",
|
|
108
|
+
sessionId,
|
|
109
|
+
categories: LAYOUT_THRASH_CATEGORIES,
|
|
110
|
+
durationMs,
|
|
111
|
+
eventCount: events.length,
|
|
112
|
+
capturedAt: new Date().toISOString(),
|
|
113
|
+
kind: "layout-thrash",
|
|
114
|
+
},
|
|
115
|
+
}), "utf8");
|
|
116
|
+
const agg = aggregateLayoutThrash(events);
|
|
117
|
+
return {
|
|
118
|
+
forcedLayoutsCount: agg.forcedLayoutsCount,
|
|
119
|
+
layoutShiftsCount: agg.layoutShiftsCount,
|
|
120
|
+
eventsByOrigin: agg.eventsByOrigin,
|
|
121
|
+
tracePath: resolved,
|
|
122
|
+
durationMs,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function clampDuration(d) {
|
|
126
|
+
if (typeof d !== "number" || !Number.isFinite(d) || d <= 0)
|
|
127
|
+
return DEFAULT_DURATION_MS;
|
|
128
|
+
if (d > MAX_DURATION_MS)
|
|
129
|
+
return MAX_DURATION_MS;
|
|
130
|
+
return Math.floor(d);
|
|
131
|
+
}
|
|
132
|
+
/** Aggregate trace events into the result shape. Pure — exported for unit
|
|
133
|
+
* tests against synthetic fixture event blobs. */
|
|
134
|
+
const RECALC_NAMES = new Set(["UpdateLayoutTree", "Recalc Style", "RecalculateStyles"]);
|
|
135
|
+
/** Classify a trace event for the thrash aggregation: a forced/sync layout, a
|
|
136
|
+
* layout shift, or a recalc — `relevant` is true when it should be bucketed by
|
|
137
|
+
* origin. Returns null for non-object / unnamed events. */
|
|
138
|
+
function classifyLayoutEvent(e) {
|
|
139
|
+
if (!e || typeof e !== "object")
|
|
140
|
+
return null;
|
|
141
|
+
const name = typeof e.name === "string" ? e.name : "";
|
|
142
|
+
if (!name)
|
|
143
|
+
return null;
|
|
144
|
+
const forced = (name === "Layout" && hasForcedFlag(e)) || name === "ForcedSyncLayout";
|
|
145
|
+
const shift = name === "LayoutShift";
|
|
146
|
+
const recalc = RECALC_NAMES.has(name);
|
|
147
|
+
return { forced, shift, relevant: forced || shift || recalc };
|
|
148
|
+
}
|
|
149
|
+
export function aggregateLayoutThrash(events) {
|
|
150
|
+
let forcedLayoutsCount = 0;
|
|
151
|
+
let layoutShiftsCount = 0;
|
|
152
|
+
const byOrigin = new Map();
|
|
153
|
+
for (const e of events) {
|
|
154
|
+
const k = classifyLayoutEvent(e);
|
|
155
|
+
if (!k)
|
|
156
|
+
continue;
|
|
157
|
+
if (k.shift)
|
|
158
|
+
layoutShiftsCount++;
|
|
159
|
+
if (k.forced)
|
|
160
|
+
forcedLayoutsCount++;
|
|
161
|
+
if (!k.relevant)
|
|
162
|
+
continue;
|
|
163
|
+
const dur = typeof e.dur === "number" ? e.dur / 1000 : 0;
|
|
164
|
+
const stack = extractOriginStack(e);
|
|
165
|
+
const slot = byOrigin.get(stack);
|
|
166
|
+
if (slot) {
|
|
167
|
+
slot.count++;
|
|
168
|
+
slot.totalDurationMs += dur;
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
byOrigin.set(stack, { count: 1, totalDurationMs: dur });
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
const eventsByOrigin = [];
|
|
175
|
+
for (const [originatingStack, { count, totalDurationMs }] of byOrigin) {
|
|
176
|
+
eventsByOrigin.push({ originatingStack, count, totalDurationMs });
|
|
177
|
+
}
|
|
178
|
+
eventsByOrigin.sort((a, b) => b.count - a.count);
|
|
179
|
+
return {
|
|
180
|
+
forcedLayoutsCount,
|
|
181
|
+
layoutShiftsCount,
|
|
182
|
+
eventsByOrigin: eventsByOrigin.slice(0, MAX_ORIGINS),
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
/** A `Layout` event is "forced sync" when chromium tags it with
|
|
186
|
+
* `args.beginData.frame` indicating a JS-driven layout pass. The reliable
|
|
187
|
+
* signal in the headless trace stream is the event itself — chromium emits
|
|
188
|
+
* `Layout` events on every forced/synchronous layout flush during the
|
|
189
|
+
* recording window. Initial page-load layouts also count; the aggregation
|
|
190
|
+
* by originating stack distinguishes one from the other.
|
|
191
|
+
*
|
|
192
|
+
* Optimistic note: when DevTools is attached chromium DOES sometimes
|
|
193
|
+
* populate `args.data.stackTrace` on the event — we still prefer the
|
|
194
|
+
* flagged path when present, since it lets us split per-callsite. The
|
|
195
|
+
* bare-event fallback ensures the count surfaces even without stacks. */
|
|
196
|
+
function hasForcedFlag(e) {
|
|
197
|
+
// `Layout` with a `beginData.frame` is a real layout flush — chromium
|
|
198
|
+
// emits these on every synchronous layout it does during the recording
|
|
199
|
+
// window. Treat any Layout event with begin/end data as a forced layout
|
|
200
|
+
// for the count. The aggregation by originating stack handles
|
|
201
|
+
// distinguishing per-origin contribution.
|
|
202
|
+
const args = e.args;
|
|
203
|
+
if (!args)
|
|
204
|
+
return false;
|
|
205
|
+
if (args.beginData && typeof args.beginData === "object")
|
|
206
|
+
return true;
|
|
207
|
+
const data = args.data ?? {};
|
|
208
|
+
if (Array.isArray(data.stackTrace) && data.stackTrace.length > 0)
|
|
209
|
+
return true;
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
/** Get the topmost stack frame as a stable origin string. Returns
|
|
213
|
+
* `"<anonymous>"` when no stack is available. */
|
|
214
|
+
function extractOriginStack(e) {
|
|
215
|
+
const args = e.args;
|
|
216
|
+
if (!args)
|
|
217
|
+
return "<anonymous>";
|
|
218
|
+
const data = args.data ?? args.beginData ?? {};
|
|
219
|
+
const stack = data.stackTrace;
|
|
220
|
+
if (!Array.isArray(stack) || stack.length === 0)
|
|
221
|
+
return "<anonymous>";
|
|
222
|
+
const top = stack[0];
|
|
223
|
+
if (!top)
|
|
224
|
+
return "<anonymous>";
|
|
225
|
+
const fn = typeof top.functionName === "string" && top.functionName ? top.functionName : "<anonymous>";
|
|
226
|
+
const url = typeof top.url === "string" ? top.url : "";
|
|
227
|
+
const line = typeof top.lineNumber === "number" ? top.lineNumber : 0;
|
|
228
|
+
const col = typeof top.columnNumber === "number" ? top.columnNumber : 0;
|
|
229
|
+
if (!url)
|
|
230
|
+
return fn;
|
|
231
|
+
return `${fn}@${url}:${line}:${col}`;
|
|
232
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface WinnerIdentity {
|
|
2
|
+
testId?: string;
|
|
3
|
+
testIdAttr?: string;
|
|
4
|
+
role: string;
|
|
5
|
+
name?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class FeedbackMemory {
|
|
8
|
+
private entries;
|
|
9
|
+
private readonly cap;
|
|
10
|
+
constructor(cap?: number);
|
|
11
|
+
record(query: string, winner: WinnerIdentity): void;
|
|
12
|
+
/**
|
|
13
|
+
* Compute a bonus score (≥ 0) for a candidate against the given query, based on
|
|
14
|
+
* prior feedback. The bonus = +5 per matching prior entry whose token-set overlaps
|
|
15
|
+
* the query and whose winner-identity matches the candidate. Capped at +15 per
|
|
16
|
+
* candidate so a single repeated mistake can't dominate.
|
|
17
|
+
*/
|
|
18
|
+
bonusFor(query: string, candidate: WinnerIdentity): number;
|
|
19
|
+
size(): number;
|
|
20
|
+
clear(): void;
|
|
21
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// Learned `find()` ranking — follow-on.
|
|
2
|
+
//
|
|
3
|
+
// Session-scoped, in-memory feedback signal: when the agent calls
|
|
4
|
+
// `find_feedback({ query, ref })` after a successful find→act, we remember that
|
|
5
|
+
// (queryTokenSet → element-identity) pair. On subsequent finds whose query token
|
|
6
|
+
// set overlaps, we boost candidates that match the prior winner's identity.
|
|
7
|
+
//
|
|
8
|
+
// Identity = testId (most stable) or role+name (medium) — the same features the
|
|
9
|
+
// stable-ref scheme uses. So the boost survives snapshots that re-key refs.
|
|
10
|
+
//
|
|
11
|
+
// Cap: 100 entries per session, LRU-evict. Adding more learning sophistication
|
|
12
|
+
// (frequency, decay over wall-clock) is straightforward but work; this
|
|
13
|
+
// minimum-viable version closes the "ranking should adapt" loop without
|
|
14
|
+
// committing to a model.
|
|
15
|
+
export class FeedbackMemory {
|
|
16
|
+
entries = [];
|
|
17
|
+
cap;
|
|
18
|
+
constructor(cap = 100) {
|
|
19
|
+
this.cap = cap;
|
|
20
|
+
}
|
|
21
|
+
record(query, winner) {
|
|
22
|
+
const tokens = tokenise(query);
|
|
23
|
+
if (tokens.size === 0)
|
|
24
|
+
return;
|
|
25
|
+
// De-dupe: drop any prior entry with identical token set + winner identity.
|
|
26
|
+
this.entries = this.entries.filter((e) => !(setsEqual(e.tokens, tokens) && identityEqual(e.winner, winner)));
|
|
27
|
+
this.entries.push({ tokens, winner, ts: Date.now() });
|
|
28
|
+
if (this.entries.length > this.cap)
|
|
29
|
+
this.entries.shift();
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Compute a bonus score (≥ 0) for a candidate against the given query, based on
|
|
33
|
+
* prior feedback. The bonus = +5 per matching prior entry whose token-set overlaps
|
|
34
|
+
* the query and whose winner-identity matches the candidate. Capped at +15 per
|
|
35
|
+
* candidate so a single repeated mistake can't dominate.
|
|
36
|
+
*/
|
|
37
|
+
bonusFor(query, candidate) {
|
|
38
|
+
const qTokens = tokenise(query);
|
|
39
|
+
if (qTokens.size === 0)
|
|
40
|
+
return 0;
|
|
41
|
+
let bonus = 0;
|
|
42
|
+
for (const e of this.entries) {
|
|
43
|
+
if (!hasIntersection(qTokens, e.tokens))
|
|
44
|
+
continue;
|
|
45
|
+
if (identityEqual(e.winner, candidate))
|
|
46
|
+
bonus += 5;
|
|
47
|
+
if (bonus >= 15)
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
return bonus;
|
|
51
|
+
}
|
|
52
|
+
size() {
|
|
53
|
+
return this.entries.length;
|
|
54
|
+
}
|
|
55
|
+
clear() {
|
|
56
|
+
this.entries = [];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function tokenise(query) {
|
|
60
|
+
return new Set(query
|
|
61
|
+
.toLowerCase()
|
|
62
|
+
.split(/[^a-z0-9]+/)
|
|
63
|
+
.filter((t) => t.length >= 2));
|
|
64
|
+
}
|
|
65
|
+
function hasIntersection(a, b) {
|
|
66
|
+
for (const t of a)
|
|
67
|
+
if (b.has(t))
|
|
68
|
+
return true;
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
function setsEqual(a, b) {
|
|
72
|
+
if (a.size !== b.size)
|
|
73
|
+
return false;
|
|
74
|
+
for (const t of a)
|
|
75
|
+
if (!b.has(t))
|
|
76
|
+
return false;
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
function identityEqual(a, b) {
|
|
80
|
+
// testId is the strongest disambiguator; if both sides have one, only that matters.
|
|
81
|
+
if (a.testId && b.testId)
|
|
82
|
+
return (a.testId === b.testId && (a.testIdAttr ?? "data-testid") === (b.testIdAttr ?? "data-testid"));
|
|
83
|
+
return a.role === b.role && (a.name ?? "") === (b.name ?? "");
|
|
84
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { Locator, Page } from "playwright-core";
|
|
2
|
+
import type { RefRegistry } from "./refs.js";
|
|
3
|
+
/**
|
|
4
|
+
* Action target shape. Exactly one of `ref` / `selector` / `coords` is
|
|
5
|
+
* required. `contextRef` optionally scopes a `selector` to the subtree of a
|
|
6
|
+
* prior ref — lets callers say "the [data-testid=...] *inside this row*"
|
|
7
|
+
* without baking positional `:nth` chains into the selector. `coords` is the
|
|
8
|
+
* escape hatch for visually-located targets (canvas, custom-painted UIs,
|
|
9
|
+
* dismiss-empty-space) that ref/selector resolution genuinely can't address.
|
|
10
|
+
*/
|
|
11
|
+
export type ActionTarget = {
|
|
12
|
+
ref: string;
|
|
13
|
+
selector?: undefined;
|
|
14
|
+
contextRef?: undefined;
|
|
15
|
+
coords?: undefined;
|
|
16
|
+
} | {
|
|
17
|
+
selector: string;
|
|
18
|
+
ref?: undefined;
|
|
19
|
+
contextRef?: string;
|
|
20
|
+
coords?: undefined;
|
|
21
|
+
} | {
|
|
22
|
+
coords: {
|
|
23
|
+
x: number;
|
|
24
|
+
y: number;
|
|
25
|
+
};
|
|
26
|
+
ref?: undefined;
|
|
27
|
+
selector?: undefined;
|
|
28
|
+
contextRef?: undefined;
|
|
29
|
+
};
|
|
30
|
+
export type ResolvedTarget = {
|
|
31
|
+
kind: "locator";
|
|
32
|
+
loc: Locator;
|
|
33
|
+
} | {
|
|
34
|
+
kind: "coords";
|
|
35
|
+
x: number;
|
|
36
|
+
y: number;
|
|
37
|
+
};
|
|
38
|
+
export declare function resolveTarget(page: Page, refs: RefRegistry, target: ActionTarget): ResolvedTarget;
|
|
39
|
+
/**
|
|
40
|
+
* Ambiguity-aware target resolution for the *acting* path. A ref built from a
|
|
41
|
+
* signal that is shared across repeated / hover-revealed items (e.g. a
|
|
42
|
+
* `data-testid` reused on every row's edit button) resolves via `.first()` to
|
|
43
|
+
* whatever instance is first in the DOM — which can be a *different* visible
|
|
44
|
+
* element than the one the agent found, so the action silently lands at the
|
|
45
|
+
* wrong visual location. When the primary locator matches more than one node
|
|
46
|
+
* and the ref carries the concrete structural path it was discovered as,
|
|
47
|
+
* re-resolve to that concrete element and surface a warning. Verify-before-
|
|
48
|
+
* dispatch: a loud "I re-resolved" beats a silent wrong-place click.
|
|
49
|
+
*/
|
|
50
|
+
export declare function resolveTargetChecked(page: Page, refs: RefRegistry, target: ActionTarget): Promise<{
|
|
51
|
+
resolved: ResolvedTarget;
|
|
52
|
+
warning?: string;
|
|
53
|
+
}>;
|
|
54
|
+
export declare function locatorFor(page: Page, refs: RefRegistry, target: ActionTarget): Locator;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// Resolve a `ref` (from snapshot()/find()) or a `selector` (raw CSS / Playwright
|
|
2
|
+
// locator string) into a Playwright Locator we can act on. Refs are the preferred
|
|
3
|
+
// path: they're stable across snapshots and built from role+name(+testId), which
|
|
4
|
+
// gives Playwright auto-waiting + strict-match for free.
|
|
5
|
+
export function resolveTarget(page, refs, target) {
|
|
6
|
+
if (target.coords) {
|
|
7
|
+
return { kind: "coords", x: target.coords.x, y: target.coords.y };
|
|
8
|
+
}
|
|
9
|
+
return { kind: "locator", loc: locatorFor(page, refs, target) };
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Ambiguity-aware target resolution for the *acting* path. A ref built from a
|
|
13
|
+
* signal that is shared across repeated / hover-revealed items (e.g. a
|
|
14
|
+
* `data-testid` reused on every row's edit button) resolves via `.first()` to
|
|
15
|
+
* whatever instance is first in the DOM — which can be a *different* visible
|
|
16
|
+
* element than the one the agent found, so the action silently lands at the
|
|
17
|
+
* wrong visual location. When the primary locator matches more than one node
|
|
18
|
+
* and the ref carries the concrete structural path it was discovered as,
|
|
19
|
+
* re-resolve to that concrete element and surface a warning. Verify-before-
|
|
20
|
+
* dispatch: a loud "I re-resolved" beats a silent wrong-place click.
|
|
21
|
+
*/
|
|
22
|
+
export async function resolveTargetChecked(page, refs, target) {
|
|
23
|
+
if (target.coords || !target.ref) {
|
|
24
|
+
return { resolved: resolveTarget(page, refs, target) };
|
|
25
|
+
}
|
|
26
|
+
const primary = locatorFor(page, refs, target);
|
|
27
|
+
const inputs = refs.locatorOf(target.ref);
|
|
28
|
+
if (!inputs?.cssPath)
|
|
29
|
+
return { resolved: { kind: "locator", loc: primary } };
|
|
30
|
+
let count;
|
|
31
|
+
try {
|
|
32
|
+
count = await primary.count();
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
count = 1; // can't tell → don't second-guess the primary path
|
|
36
|
+
}
|
|
37
|
+
if (count <= 1)
|
|
38
|
+
return { resolved: { kind: "locator", loc: primary } };
|
|
39
|
+
const concrete = page.locator(inputs.cssPath).first();
|
|
40
|
+
let concreteCount;
|
|
41
|
+
try {
|
|
42
|
+
concreteCount = await concrete.count();
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
concreteCount = 0;
|
|
46
|
+
}
|
|
47
|
+
if (concreteCount >= 1) {
|
|
48
|
+
return {
|
|
49
|
+
resolved: { kind: "locator", loc: concrete },
|
|
50
|
+
warning: `ref "${target.ref}": the primary locator matched ${count} nodes ` +
|
|
51
|
+
`(ambiguous — likely a shared test-id across repeated/overlay items). ` +
|
|
52
|
+
`Re-resolved to the concrete element captured when the ref was found, ` +
|
|
53
|
+
`to avoid acting at the wrong visual location.`,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
resolved: { kind: "locator", loc: primary },
|
|
58
|
+
warning: `ref "${target.ref}": the primary locator is ambiguous (${count} matches) ` +
|
|
59
|
+
`and the concrete path captured at discovery no longer resolves; acting ` +
|
|
60
|
+
`on .first() — verify the result, the element may have moved or re-rendered.`,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
export function locatorFor(page, refs, target) {
|
|
64
|
+
if (target.coords) {
|
|
65
|
+
throw new Error("locatorFor: coords target has no Locator — use resolveTarget() and switch on kind");
|
|
66
|
+
}
|
|
67
|
+
if (target.ref) {
|
|
68
|
+
const inputs = refs.locatorOf(target.ref);
|
|
69
|
+
if (!inputs) {
|
|
70
|
+
throw new Error(`unknown ref "${target.ref}"; call snapshot() or find() first to populate refs, or pass a selector instead`);
|
|
71
|
+
}
|
|
72
|
+
// Frame-aware resolution: refs minted inside a child frame
|
|
73
|
+
// carry a bound Frame handle; route through it so `frame.locator(...)`
|
|
74
|
+
// crosses the OOPIF / same-origin iframe boundary transparently. Main-
|
|
75
|
+
// frame refs (no binding) resolve against the page — byte-identical to
|
|
76
|
+
// pre-v0.5.0 behaviour.
|
|
77
|
+
const frame = refs.frameOf(target.ref);
|
|
78
|
+
return locatorFromInputs(frame ?? page, inputs);
|
|
79
|
+
}
|
|
80
|
+
if (target.selector) {
|
|
81
|
+
if (target.contextRef) {
|
|
82
|
+
const ctxInputs = refs.locatorOf(target.contextRef);
|
|
83
|
+
if (!ctxInputs) {
|
|
84
|
+
throw new Error(`unknown contextRef "${target.contextRef}"; call snapshot() or find() first to populate refs`);
|
|
85
|
+
}
|
|
86
|
+
const ctxFrame = refs.frameOf(target.contextRef);
|
|
87
|
+
const ctxLoc = locatorFromInputs(ctxFrame ?? page, ctxInputs);
|
|
88
|
+
return parseSelectorHint(ctxLoc, target.selector);
|
|
89
|
+
}
|
|
90
|
+
return parseSelectorHint(page, target.selector);
|
|
91
|
+
}
|
|
92
|
+
throw new Error("locatorFor: requires { ref } or { selector } (with optional { contextRef } for scoped selectors) or { coords }");
|
|
93
|
+
}
|
|
94
|
+
function locatorFromInputs(root, inputs) {
|
|
95
|
+
// Tier 1: testId — strongest signal, works for any provenance. CSS attribute
|
|
96
|
+
// form rather than Playwright's `getByTestId` so non-standard test attributes
|
|
97
|
+
// (`data-type`, `data-cy`, etc.) work without per-context plumbing.
|
|
98
|
+
if (inputs.testId) {
|
|
99
|
+
const attr = inputs.testIdAttr ?? "data-testid";
|
|
100
|
+
return root.locator(`[${attr}=${JSON.stringify(inputs.testId)}]`).first();
|
|
101
|
+
}
|
|
102
|
+
// Provenance-aware routing: refs discovered exclusively via the DOM walk
|
|
103
|
+
// typically carry bare-tag roles (`td`, `div`, `generic`) whose role-locators
|
|
104
|
+
// are ambiguous or don't actually resolve. Prefer the structural CSS path
|
|
105
|
+
// captured at walk time.
|
|
106
|
+
if (inputs.source === "dom" && inputs.cssPath) {
|
|
107
|
+
return root.locator(inputs.cssPath).first();
|
|
108
|
+
}
|
|
109
|
+
// Tier 2: role + name — strong when the a11y pass saw it.
|
|
110
|
+
if (inputs.name) {
|
|
111
|
+
return root
|
|
112
|
+
.getByRole(inputs.role, { name: inputs.name })
|
|
113
|
+
.first();
|
|
114
|
+
}
|
|
115
|
+
// Fallback: structural path (covers `source: "both"` refs where the a11y
|
|
116
|
+
// pass produced no name, plus the rare migration case of legacy refs that
|
|
117
|
+
// never got a name).
|
|
118
|
+
if (inputs.cssPath) {
|
|
119
|
+
return root.locator(inputs.cssPath).first();
|
|
120
|
+
}
|
|
121
|
+
// Last resort: role only. Often ambiguous; the agent saw stability=low.
|
|
122
|
+
return root.getByRole(inputs.role).first();
|
|
123
|
+
}
|
|
124
|
+
function parseSelectorHint(root, sel) {
|
|
125
|
+
const s = sel.trim();
|
|
126
|
+
const attrMatch = s.match(/^\[([a-zA-Z][a-zA-Z0-9-]*)=("([^"]*)"|'([^']*)')\]$/);
|
|
127
|
+
if (attrMatch) {
|
|
128
|
+
return root.locator(s).first();
|
|
129
|
+
}
|
|
130
|
+
const roleWithNameMatch = s.match(/^role=([a-zA-Z][a-zA-Z0-9-]*)\[name=("((?:\\.|[^"\\])*)"|'((?:\\.|[^'\\])*)')\]$/);
|
|
131
|
+
if (roleWithNameMatch) {
|
|
132
|
+
const role = roleWithNameMatch[1];
|
|
133
|
+
const raw = roleWithNameMatch[3] ?? roleWithNameMatch[4] ?? "";
|
|
134
|
+
const name = raw.replace(/\\"/g, '"').replace(/\\'/g, "'").replace(/\\\\/g, "\\");
|
|
135
|
+
return root.getByRole(role, { name }).first();
|
|
136
|
+
}
|
|
137
|
+
const roleOnlyMatch = s.match(/^role=([a-zA-Z][a-zA-Z0-9-]*)$/);
|
|
138
|
+
if (roleOnlyMatch) {
|
|
139
|
+
return root.getByRole(roleOnlyMatch[1]).first();
|
|
140
|
+
}
|
|
141
|
+
return root.locator(s).first();
|
|
142
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { parseHeapSnapshot } from "./heap.js";
|
|
2
|
+
/** One row in the retainer-growth report. */
|
|
3
|
+
export interface RetainerGrowthRow {
|
|
4
|
+
/** Display name of the grouped nodes: `${type}:${name}` or just `name`. */
|
|
5
|
+
node: string;
|
|
6
|
+
/** V8 node-type (closure, object, hidden, …). */
|
|
7
|
+
type: string;
|
|
8
|
+
sizeBefore: number;
|
|
9
|
+
sizeAfter: number;
|
|
10
|
+
deltaBytes: number;
|
|
11
|
+
/** Percent change. `sizeBefore:0` reports `deltaPercent: Infinity` →
|
|
12
|
+
* surfaced as the string `"+inf"` for JSON serialisability. */
|
|
13
|
+
deltaPercent: number | "+inf";
|
|
14
|
+
}
|
|
15
|
+
export interface MemoryDiffSummary {
|
|
16
|
+
totalGrowth: number;
|
|
17
|
+
top3Growers: Array<{
|
|
18
|
+
node: string;
|
|
19
|
+
deltaBytes: number;
|
|
20
|
+
deltaPercent: number | "+inf";
|
|
21
|
+
}>;
|
|
22
|
+
}
|
|
23
|
+
export interface MemoryDiffResult {
|
|
24
|
+
retainerGrowth: RetainerGrowthRow[];
|
|
25
|
+
summary: MemoryDiffSummary;
|
|
26
|
+
}
|
|
27
|
+
/** Workspace-rooted path helper — same shape as `resolvePerfTracePath`. */
|
|
28
|
+
export declare function resolveHeapPath(workspaceRoot: string, p: string, tool: string): string;
|
|
29
|
+
/** Pure aggregator — group nodes by `${type}:${name}` and sum self_size.
|
|
30
|
+
* Exported for unit tests against tiny in-memory snapshot JSON values. */
|
|
31
|
+
export declare function aggregateNodeSizes(parsed: ReturnType<typeof parseHeapSnapshot>): Map<string, {
|
|
32
|
+
type: string;
|
|
33
|
+
name: string;
|
|
34
|
+
size: number;
|
|
35
|
+
}>;
|
|
36
|
+
/** Pure diff helper — given two aggregator maps, return the growth report.
|
|
37
|
+
* Exported for unit tests. */
|
|
38
|
+
export declare function diffSizeMaps(before: Map<string, {
|
|
39
|
+
type: string;
|
|
40
|
+
name: string;
|
|
41
|
+
size: number;
|
|
42
|
+
}>, after: Map<string, {
|
|
43
|
+
type: string;
|
|
44
|
+
name: string;
|
|
45
|
+
size: number;
|
|
46
|
+
}>): MemoryDiffResult;
|
|
47
|
+
/** Diff two heap snapshots at the given workspace-rooted paths. */
|
|
48
|
+
export declare function diffHeapSnapshots(workspaceRoot: string, beforePath: string, afterPath: string, tool?: string): MemoryDiffResult;
|