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,254 @@
|
|
|
1
|
+
// Capability toggles — security model. See `docs/threat-model.md` for the
|
|
2
|
+
// full design. The gist:
|
|
3
|
+
//
|
|
4
|
+
// - Tools group into coarse categories (`read`, `navigation`, `action`, `human`,
|
|
5
|
+
// `eval`, `byob-attach`, `file-io`). Each is independently enable/disable-able at
|
|
6
|
+
// server start.
|
|
7
|
+
// - Default set: read + navigation + action + human. `eval` / `byob-attach` /
|
|
8
|
+
// `file-io` are off-by-default — opt in via `BROWX_CAPABILITIES`.
|
|
9
|
+
// - The server's startup log lists the active set; `browxai doctor` warns when
|
|
10
|
+
// dangerous capabilities are on (`eval`, `byob-attach`).
|
|
11
|
+
//
|
|
12
|
+
// Configuring:
|
|
13
|
+
// BROWX_CAPABILITIES=read,navigation,action,human # the default
|
|
14
|
+
// BROWX_CAPABILITIES=read # read-only server
|
|
15
|
+
// BROWX_CAPABILITIES=read,navigation,action,human,eval # opts in to eval_js
|
|
16
|
+
export const ALL_CAPABILITIES = [
|
|
17
|
+
"read",
|
|
18
|
+
"navigation",
|
|
19
|
+
"action",
|
|
20
|
+
"human",
|
|
21
|
+
"eval",
|
|
22
|
+
"byob-attach",
|
|
23
|
+
"file-io",
|
|
24
|
+
"network-body",
|
|
25
|
+
"clipboard",
|
|
26
|
+
"secrets",
|
|
27
|
+
"extensions",
|
|
28
|
+
"stealth",
|
|
29
|
+
"captcha",
|
|
30
|
+
"credentials",
|
|
31
|
+
"device-emulation",
|
|
32
|
+
"diagnostics",
|
|
33
|
+
"canvas",
|
|
34
|
+
];
|
|
35
|
+
export const DEFAULT_CAPABILITIES = [
|
|
36
|
+
"read",
|
|
37
|
+
"navigation",
|
|
38
|
+
"action",
|
|
39
|
+
"human",
|
|
40
|
+
];
|
|
41
|
+
/**
|
|
42
|
+
* Capabilities that USED to be valid and have since been retired. A retired
|
|
43
|
+
* capability is still ACCEPTED in `BROWX_CAPABILITIES` (and the `capabilities`
|
|
44
|
+
* config key) — it is ignored with a deprecation warning, never an error — so
|
|
45
|
+
* evolving the capability set can't crash an existing adopter's config.
|
|
46
|
+
* Genuine typos (a name that was never a capability) are still rejected loudly.
|
|
47
|
+
* A retired entry may be dropped entirely only in a major version bump.
|
|
48
|
+
* See the "API evolution" rule in CLAUDE.md.
|
|
49
|
+
*
|
|
50
|
+
* The value is the agent/operator-facing reason + what to do instead.
|
|
51
|
+
*/
|
|
52
|
+
export const RETIRED_CAPABILITIES = {
|
|
53
|
+
unstable: "the tools it gated (gestures, route mocking, compound act-and-observe " +
|
|
54
|
+
"tools, visual regions, profile snapshot/restore) were promoted into the " +
|
|
55
|
+
"default stable surface — it no longer gates anything; drop it from " +
|
|
56
|
+
"BROWX_CAPABILITIES",
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* The per-tool capability assignment is DERIVED (RFC 0004 P2 / D2): it lives at
|
|
60
|
+
* each tool's `host.register({ capability })` call (the single source of truth,
|
|
61
|
+
* src/tools/host.ts), not in a hand-maintained list here. This module owns the
|
|
62
|
+
* closed *vocabulary* (`Capability` / `ALL_CAPABILITIES` above); the per-tool
|
|
63
|
+
* rows are populated from the registration metadata via `declareToolCapability`,
|
|
64
|
+
* collected once by the tools-layer bootstrap (`src/tools/tool-metadata.ts`).
|
|
65
|
+
*
|
|
66
|
+
* A tool with no declared capability is treated as `human` (coordination
|
|
67
|
+
* primitive, always safe) — the same permissive default as before, now reachable
|
|
68
|
+
* only for the control-plane primitives that legitimately carry no browser
|
|
69
|
+
* capability (open_session, batch, get_config, …), never by a silent omission
|
|
70
|
+
* (the completeness fitness test asserts every browser tool declares one).
|
|
71
|
+
*/
|
|
72
|
+
const TOOL_CAPABILITY_MAP = new Map();
|
|
73
|
+
/** Record one tool's capability assignment from its colocated
|
|
74
|
+
* `host.register({ capability })` metadata (RFC 0004 P2). Idempotent for an
|
|
75
|
+
* identical re-declaration; a *conflicting* one throws (two registrations cannot
|
|
76
|
+
* disagree on one tool's gate). The only writer of the derived map. */
|
|
77
|
+
export function declareToolCapability(tool, capability) {
|
|
78
|
+
const existing = TOOL_CAPABILITY_MAP.get(tool);
|
|
79
|
+
if (existing !== undefined && existing !== capability) {
|
|
80
|
+
throw new Error(`declareToolCapability: "${tool}" already declared as "${existing}", got "${capability}"`);
|
|
81
|
+
}
|
|
82
|
+
TOOL_CAPABILITY_MAP.set(tool, capability);
|
|
83
|
+
}
|
|
84
|
+
/** Lazy-collection seam (RFC 0004 P2). The tools layer installs a collector that
|
|
85
|
+
* runs the registration metadata once and populates the derived maps;
|
|
86
|
+
* `capabilities.ts` (a leaf) cannot import the tools layer, so the dependency is
|
|
87
|
+
* inverted through this setter. Every real entry point (`createServer`, the SDK
|
|
88
|
+
* client, the CLI, the package entry) reaches the tools-layer bootstrap, which
|
|
89
|
+
* installs the collector AND eagerly populates the map — so in production a gate
|
|
90
|
+
* read always sees the full derived rows. */
|
|
91
|
+
let toolMetadataCollector;
|
|
92
|
+
let toolMetadataLoaded = false;
|
|
93
|
+
/** True while the collector is mid-run. A re-entrant read during collection (the
|
|
94
|
+
* collector's own `resolveCapabilities`/`buildHost` path touches the gate) must
|
|
95
|
+
* tolerate the partially-populated map WITHOUT tripping the fail-safe — the
|
|
96
|
+
* collector is installed and running, so the map is about to be complete. */
|
|
97
|
+
let toolMetadataCollecting = false;
|
|
98
|
+
export function installToolMetadataCollector(collect) {
|
|
99
|
+
toolMetadataCollector = collect;
|
|
100
|
+
// A late install (after the first read already ran the empty map) still takes
|
|
101
|
+
// effect: clear the loaded flag so the next read collects.
|
|
102
|
+
toolMetadataLoaded = false;
|
|
103
|
+
}
|
|
104
|
+
function ensureToolMetadataLoaded() {
|
|
105
|
+
if (toolMetadataLoaded || toolMetadataCollector === undefined)
|
|
106
|
+
return;
|
|
107
|
+
toolMetadataLoaded = true; // set before running so re-entrant declares don't recurse
|
|
108
|
+
toolMetadataCollecting = true;
|
|
109
|
+
try {
|
|
110
|
+
toolMetadataCollector();
|
|
111
|
+
}
|
|
112
|
+
finally {
|
|
113
|
+
toolMetadataCollecting = false;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* D1 fail-safe (RFC 0004 P2, SECURITY-CRITICAL): the capability gate must NEVER
|
|
118
|
+
* fail OPEN. If a reader hits the derived map while it is empty AND no collector
|
|
119
|
+
* was ever installed, the tools-layer bootstrap did not run — `isToolEnabled`
|
|
120
|
+
* would otherwise pass EVERYTHING through the permissive `human` default,
|
|
121
|
+
* silently un-gating `eval_js` / `register_secret` / `network_body` / the engine
|
|
122
|
+
* gate. Rather than fail open we throw a structured, actionable error so the
|
|
123
|
+
* misconfiguration is loud and impossible to ship. The guaranteed bootstrap
|
|
124
|
+
* (`tool-metadata.ts`, imported by every real entry point) is the primary
|
|
125
|
+
* mechanism that keeps this throw from firing in production; this is the backstop.
|
|
126
|
+
*
|
|
127
|
+
* The throw is suppressed only DURING collection (the collector's own gate read
|
|
128
|
+
* legitimately sees a partial map) — at that point a collector is installed and
|
|
129
|
+
* running, so the map is about to be complete.
|
|
130
|
+
*/
|
|
131
|
+
function assertGateBootstrapped() {
|
|
132
|
+
if (TOOL_CAPABILITY_MAP.size > 0 || toolMetadataCollecting)
|
|
133
|
+
return;
|
|
134
|
+
throw new Error("browxai capability gate read before the tool-metadata bootstrap ran: the derived " +
|
|
135
|
+
"TOOL_CAPABILITY map is empty and no collector was installed. Refusing to fail OPEN " +
|
|
136
|
+
"(which would un-gate eval_js / register_secret / network_body). Import the package " +
|
|
137
|
+
'entry ("browxai") or call createServer before reading the capability gate. ' +
|
|
138
|
+
"(RFC 0004 P2 / D1.)");
|
|
139
|
+
}
|
|
140
|
+
/** The derived tool→capability map. Reading drives the lazy collection so the
|
|
141
|
+
* rows declared at registration are present for a standalone caller, then
|
|
142
|
+
* asserts the gate is bootstrapped (fail-safe — never returns an empty
|
|
143
|
+
* un-gated map to a consumer). */
|
|
144
|
+
export function toolCapabilityMap() {
|
|
145
|
+
ensureToolMetadataLoaded();
|
|
146
|
+
assertGateBootstrapped();
|
|
147
|
+
return TOOL_CAPABILITY_MAP;
|
|
148
|
+
}
|
|
149
|
+
/** Back-compat `Record` view of the derived map for the consumers that index it
|
|
150
|
+
* by name (`TOOL_CAPABILITY[tool]`). A `Proxy` so a read both triggers the lazy
|
|
151
|
+
* collection and reflects any registration that ran after a prior read. Every
|
|
152
|
+
* access path that resolves a capability (the by-name `get`, the membership
|
|
153
|
+
* `has`, key enumeration, and the D2 `Symbol.iterator` Map-parity iterator)
|
|
154
|
+
* runs the D1 fail-safe — the gate never answers from an empty unbootstrapped
|
|
155
|
+
* map. */
|
|
156
|
+
export const TOOL_CAPABILITY = new Proxy(Object.create(null), {
|
|
157
|
+
get(_t, key) {
|
|
158
|
+
ensureToolMetadataLoaded();
|
|
159
|
+
// D2: Map-parity iteration — `for (const [tool, cap] of TOOL_CAPABILITY)`
|
|
160
|
+
// and `[...TOOL_CAPABILITY]` delegate to the backing Map's iterator. Bound
|
|
161
|
+
// to the Map so the internal-slot read keeps the right receiver.
|
|
162
|
+
if (key === Symbol.iterator) {
|
|
163
|
+
assertGateBootstrapped();
|
|
164
|
+
return TOOL_CAPABILITY_MAP[Symbol.iterator].bind(TOOL_CAPABILITY_MAP);
|
|
165
|
+
}
|
|
166
|
+
if (typeof key !== "string")
|
|
167
|
+
return undefined;
|
|
168
|
+
assertGateBootstrapped();
|
|
169
|
+
return TOOL_CAPABILITY_MAP.get(key);
|
|
170
|
+
},
|
|
171
|
+
has(_t, key) {
|
|
172
|
+
ensureToolMetadataLoaded();
|
|
173
|
+
assertGateBootstrapped();
|
|
174
|
+
return typeof key === "string" && TOOL_CAPABILITY_MAP.has(key);
|
|
175
|
+
},
|
|
176
|
+
ownKeys() {
|
|
177
|
+
ensureToolMetadataLoaded();
|
|
178
|
+
assertGateBootstrapped();
|
|
179
|
+
return [...TOOL_CAPABILITY_MAP.keys()];
|
|
180
|
+
},
|
|
181
|
+
getOwnPropertyDescriptor(_t, key) {
|
|
182
|
+
ensureToolMetadataLoaded();
|
|
183
|
+
assertGateBootstrapped();
|
|
184
|
+
if (typeof key === "string" && TOOL_CAPABILITY_MAP.has(key)) {
|
|
185
|
+
return { enumerable: true, configurable: true, value: TOOL_CAPABILITY_MAP.get(key) };
|
|
186
|
+
}
|
|
187
|
+
return undefined;
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
export function resolveCapabilities(env = process.env) {
|
|
191
|
+
const raw = env.BROWX_CAPABILITIES?.trim();
|
|
192
|
+
const list = raw
|
|
193
|
+
? raw
|
|
194
|
+
.split(",")
|
|
195
|
+
.map((s) => s.trim())
|
|
196
|
+
.filter(Boolean)
|
|
197
|
+
: [...DEFAULT_CAPABILITIES];
|
|
198
|
+
const warnings = [];
|
|
199
|
+
const live = [];
|
|
200
|
+
const unknown = [];
|
|
201
|
+
for (const c of list) {
|
|
202
|
+
if (ALL_CAPABILITIES.includes(c)) {
|
|
203
|
+
live.push(c);
|
|
204
|
+
}
|
|
205
|
+
else if (Object.prototype.hasOwnProperty.call(RETIRED_CAPABILITIES, c)) {
|
|
206
|
+
// Retired, not unknown — tolerate it so an old config never crashes.
|
|
207
|
+
warnings.push(`BROWX_CAPABILITIES: "${c}" is a retired capability — ${RETIRED_CAPABILITIES[c]}. ` +
|
|
208
|
+
`It is ignored (no effect); the rest of your config is honoured.`);
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
unknown.push(c);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (unknown.length) {
|
|
215
|
+
throw new Error(`BROWX_CAPABILITIES: unknown capability/capabilities ${unknown.map((u) => JSON.stringify(u)).join(", ")}. ` +
|
|
216
|
+
`Valid: ${ALL_CAPABILITIES.join(", ")}.`);
|
|
217
|
+
}
|
|
218
|
+
const enabled = new Set(live);
|
|
219
|
+
const disabledTools = [];
|
|
220
|
+
for (const [tool, cap] of toolCapabilityMap()) {
|
|
221
|
+
if (!enabled.has(cap))
|
|
222
|
+
disabledTools.push({ tool, capability: cap });
|
|
223
|
+
}
|
|
224
|
+
return { enabled, disabledTools, warnings };
|
|
225
|
+
}
|
|
226
|
+
/** Returns true iff the tool is enabled given the active capability set. */
|
|
227
|
+
export function isToolEnabled(tool, caps) {
|
|
228
|
+
const cap = toolCapabilityMap().get(tool);
|
|
229
|
+
if (!cap)
|
|
230
|
+
return true; // unknown tool: pass through (human-coordination default)
|
|
231
|
+
return caps.enabled.has(cap);
|
|
232
|
+
}
|
|
233
|
+
const ALL_CONFIRM_HOOKS = [
|
|
234
|
+
"navigate_off_allowlist",
|
|
235
|
+
"file_download",
|
|
236
|
+
"file_upload",
|
|
237
|
+
"byob_action",
|
|
238
|
+
];
|
|
239
|
+
const DEFAULT_CONFIRM_HOOKS = ["navigate_off_allowlist", "byob_action"];
|
|
240
|
+
export function resolveConfirmHooks(env = process.env) {
|
|
241
|
+
const raw = env.BROWX_CONFIRM_REQUIRED?.trim();
|
|
242
|
+
if (!raw)
|
|
243
|
+
return new Set(DEFAULT_CONFIRM_HOOKS);
|
|
244
|
+
const list = raw
|
|
245
|
+
.split(",")
|
|
246
|
+
.map((s) => s.trim())
|
|
247
|
+
.filter(Boolean);
|
|
248
|
+
const unknown = list.filter((h) => !ALL_CONFIRM_HOOKS.includes(h));
|
|
249
|
+
if (unknown.length) {
|
|
250
|
+
throw new Error(`BROWX_CONFIRM_REQUIRED: unknown hook(s) ${unknown.map((u) => JSON.stringify(u)).join(", ")}. ` +
|
|
251
|
+
`Valid: ${ALL_CONFIRM_HOOKS.join(", ")}.`);
|
|
252
|
+
}
|
|
253
|
+
return new Set(list);
|
|
254
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/** Full resolved view consumed by the server. */
|
|
2
|
+
export interface ResolvedConfig {
|
|
3
|
+
testAttributes: string[];
|
|
4
|
+
capabilities: string[];
|
|
5
|
+
confirmRequired: string[];
|
|
6
|
+
allowedOrigins: string[];
|
|
7
|
+
blockedOrigins: string[];
|
|
8
|
+
headless: boolean;
|
|
9
|
+
/** hard anti-wedge deadline (ms) applied to every action body /
|
|
10
|
+
* `eval_js` / read-CDP path. Default 5000. Per-call `timeoutMs` overrides.
|
|
11
|
+
* Clamped to [1, 3_600_000] at use. A real op completes well under this;
|
|
12
|
+
* raising it as a blanket masks no-ops/wedges. */
|
|
13
|
+
actionTimeoutMs?: number;
|
|
14
|
+
/** when true, `managed` / `incognito` sessions launch with
|
|
15
|
+
* `--disable-web-security --disable-site-isolation-trials` (SOP/CORS OFF
|
|
16
|
+
* browser-wide). Dangerous opt-in — off by default, loud-warned, and
|
|
17
|
+
* deliberately NOT mappable from the legacy env layer (set via MCP
|
|
18
|
+
* `set_config` or the managed config file only). No effect on
|
|
19
|
+
* `attached`/BYOB (externally launched). */
|
|
20
|
+
disableWebSecurity?: boolean;
|
|
21
|
+
/** default device-preset name for new sessions (Playwright device
|
|
22
|
+
* registry, e.g. "iPhone 14"). Overridable per `open_session`. */
|
|
23
|
+
defaultDevice?: string;
|
|
24
|
+
/** default viewport for new sessions. Overrides a preset's viewport
|
|
25
|
+
* when both are set. Overridable per `open_session`. */
|
|
26
|
+
defaultViewport?: {
|
|
27
|
+
width: number;
|
|
28
|
+
height: number;
|
|
29
|
+
};
|
|
30
|
+
/** CSS selectors for chrome/overlay elements (dev-build HMR widgets,
|
|
31
|
+
* devtools iframes, cookie/consent banners) that should be neutralised
|
|
32
|
+
* before the agent interacts with the page. A server-injected init
|
|
33
|
+
* script applies `pointer-events:none; display:none` to matches on every
|
|
34
|
+
* navigation — non-destructive (no node removal), config-driven, no
|
|
35
|
+
* agent JS. Default `[]` (feature off). */
|
|
36
|
+
hideOverlaySelectors: string[];
|
|
37
|
+
/** declarative plugin set. Mirrors what `plugins.json`
|
|
38
|
+
* declares; persisted alongside other config so `set_config({plugins})`
|
|
39
|
+
* and `get_config({scope:"resolved"}).plugins` work without hand-editing
|
|
40
|
+
* the plugins.json file. Plugin lifecycle is RESOLVED ONCE AT SERVER
|
|
41
|
+
* START — `set_config` persists, but takes effect on next restart
|
|
42
|
+
* (mirrors `capabilities`). Empty array = "no plugins declared". */
|
|
43
|
+
plugins: string[];
|
|
44
|
+
/** Experimental / feature-flag knobs. Not stable; shallow-merged across layers. */
|
|
45
|
+
unstable: Record<string, unknown>;
|
|
46
|
+
}
|
|
47
|
+
/** A partial override at one precedence layer. Every key optional. */
|
|
48
|
+
export type ConfigLayer = Partial<Omit<ResolvedConfig, "unstable">> & {
|
|
49
|
+
unstable?: Record<string, unknown>;
|
|
50
|
+
};
|
|
51
|
+
export type PersistentScope = "user" | "project";
|
|
52
|
+
export type ConfigScope = "defaults" | "env" | PersistentScope | "session";
|
|
53
|
+
export declare const BUILTIN_DEFAULTS: ResolvedConfig;
|
|
54
|
+
/** Legacy `BROWX_*` env vars as a low-precedence layer (above defaults). */
|
|
55
|
+
export declare function envLayer(env?: NodeJS.ProcessEnv): ConfigLayer;
|
|
56
|
+
export declare class ConfigStore {
|
|
57
|
+
private filePath;
|
|
58
|
+
private persisted;
|
|
59
|
+
private env;
|
|
60
|
+
constructor(workspaceRoot: string, env?: NodeJS.ProcessEnv);
|
|
61
|
+
private load;
|
|
62
|
+
private save;
|
|
63
|
+
/** Merge one layer onto an accumulator. Arrays replace; unstable shallow-merges. */
|
|
64
|
+
private static apply;
|
|
65
|
+
/** The precedence chain as DATA (RFC 0004 P4 / D6) — replacing the four
|
|
66
|
+
* fixed-order `apply` calls + the `getLayer` switch. The array order IS the
|
|
67
|
+
* precedence, applied lowest → highest: env < user < project < session, atop
|
|
68
|
+
* the built-in defaults base. CRITICAL: reordering this array silently
|
|
69
|
+
* changes which layer wins, so the order is pinned by the config-store unit
|
|
70
|
+
* tests for every layer permutation. `read(store, sessionPatch)` returns the
|
|
71
|
+
* raw pre-merge layer for that scope (the same value the old `getLayer` arm
|
|
72
|
+
* returned). Adding a layer is one entry here, not edits to two methods.
|
|
73
|
+
*
|
|
74
|
+
* `defaults` is NOT in this array: it is the base accumulator, not an
|
|
75
|
+
* override layer (`getLayer("defaults")` returns the resolved base directly).
|
|
76
|
+
* `session` reads `sessionPatch` during `resolve()` but is not held on the
|
|
77
|
+
* store, so its `getLayer` view is `{}` — preserved exactly. */
|
|
78
|
+
private static readonly PRECEDENCE;
|
|
79
|
+
/** Resolve the full config. `sessionPatch` is the highest-precedence layer.
|
|
80
|
+
* Iterates `PRECEDENCE` low → high atop the defaults base — byte-identical to
|
|
81
|
+
* the old fixed `apply(env) → apply(user) → apply(project) → apply(session)`
|
|
82
|
+
* sequence, now data-driven. */
|
|
83
|
+
resolve(sessionPatch?: ConfigLayer): ResolvedConfig;
|
|
84
|
+
/** Inspect one layer (raw, pre-merge) — for `get_config({ scope })`. Reads the
|
|
85
|
+
* same `PRECEDENCE` array `resolve()` iterates, so the inspected layer and the
|
|
86
|
+
* applied layer can never diverge. `defaults` returns the base directly (it is
|
|
87
|
+
* not an override layer); `session` is never held here, so its raw view is
|
|
88
|
+
* `{}` — both preserved exactly. */
|
|
89
|
+
getLayer(scope: ConfigScope): ConfigLayer | ResolvedConfig;
|
|
90
|
+
/** Persist a patch into `user` or `project`. The only writer of config.json. */
|
|
91
|
+
setLayer(scope: PersistentScope, patch: ConfigLayer): void;
|
|
92
|
+
/** Clear a persistent layer entirely. */
|
|
93
|
+
resetLayer(scope: PersistentScope): void;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Adapter: render a `ResolvedConfig` as an env-shaped record so the existing
|
|
97
|
+
* env-driven resolvers (`resolveCapabilities` / `resolveOriginPolicy` /
|
|
98
|
+
* `resolveConfirmHooks` / `resolveConfig`) can consume the *fully resolved*
|
|
99
|
+
* precedence chain without each being rewritten. Precedence is already applied
|
|
100
|
+
* in `ConfigStore.resolve()`; this just re-expresses the result in the shape
|
|
101
|
+
* those functions parse.
|
|
102
|
+
*/
|
|
103
|
+
export declare function resolvedToEnv(c: ResolvedConfig): NodeJS.ProcessEnv;
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
// browxai-managed config store.
|
|
2
|
+
//
|
|
3
|
+
// Precedence (lowest → highest):
|
|
4
|
+
// built-in defaults < env (legacy BROWX_*) < user < project < session patch
|
|
5
|
+
//
|
|
6
|
+
// Persistent layers live in `<workspace>/config.json` as
|
|
7
|
+
// `{ "user": {...}, "project": {...} }` and are mutated ONLY via
|
|
8
|
+
// set_config / reset_config (the MCP tools). The file is machine-managed —
|
|
9
|
+
// a malformed file degrades to "ignore that layer + warn", never a crash.
|
|
10
|
+
//
|
|
11
|
+
// `workspace` (root path) is intentionally NOT config — it's the *location*
|
|
12
|
+
// the store itself lives at, resolved before the store exists.
|
|
13
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
14
|
+
import { join } from "node:path";
|
|
15
|
+
import { log } from "./logging.js";
|
|
16
|
+
import { invariant } from "./invariant.js";
|
|
17
|
+
export const BUILTIN_DEFAULTS = {
|
|
18
|
+
testAttributes: ["data-testid", "data-test", "data-cy", "data-qa"],
|
|
19
|
+
capabilities: ["read", "navigation", "action", "human"],
|
|
20
|
+
confirmRequired: ["navigate_off_allowlist", "byob_action"],
|
|
21
|
+
allowedOrigins: [],
|
|
22
|
+
blockedOrigins: [],
|
|
23
|
+
headless: false,
|
|
24
|
+
hideOverlaySelectors: [],
|
|
25
|
+
plugins: [],
|
|
26
|
+
unstable: {},
|
|
27
|
+
};
|
|
28
|
+
const CONFIG_FILE = "config.json";
|
|
29
|
+
/** Legacy `BROWX_*` env vars as a low-precedence layer (above defaults). */
|
|
30
|
+
export function envLayer(env = process.env) {
|
|
31
|
+
const layer = {};
|
|
32
|
+
const list = (v) => v
|
|
33
|
+
? v
|
|
34
|
+
.split(",")
|
|
35
|
+
.map((s) => s.trim())
|
|
36
|
+
.filter(Boolean)
|
|
37
|
+
: undefined;
|
|
38
|
+
const ta = list(env.BROWX_TEST_ATTRIBUTES?.trim());
|
|
39
|
+
if (ta)
|
|
40
|
+
layer.testAttributes = ta;
|
|
41
|
+
const caps = list(env.BROWX_CAPABILITIES?.trim());
|
|
42
|
+
if (caps)
|
|
43
|
+
layer.capabilities = caps;
|
|
44
|
+
const cr = list(env.BROWX_CONFIRM_REQUIRED?.trim());
|
|
45
|
+
if (cr)
|
|
46
|
+
layer.confirmRequired = cr;
|
|
47
|
+
const ao = list(env.BROWX_ALLOWED_ORIGINS?.trim());
|
|
48
|
+
if (ao)
|
|
49
|
+
layer.allowedOrigins = ao;
|
|
50
|
+
const bo = list(env.BROWX_BLOCKED_ORIGINS?.trim());
|
|
51
|
+
if (bo)
|
|
52
|
+
layer.blockedOrigins = bo;
|
|
53
|
+
const hl = env.BROWX_HEADLESS?.trim();
|
|
54
|
+
if (hl)
|
|
55
|
+
layer.headless = hl === "1" || hl.toLowerCase() === "true";
|
|
56
|
+
const hos = list(env.BROWX_HIDE_OVERLAY_SELECTORS?.trim());
|
|
57
|
+
if (hos)
|
|
58
|
+
layer.hideOverlaySelectors = hos;
|
|
59
|
+
return layer;
|
|
60
|
+
}
|
|
61
|
+
export class ConfigStore {
|
|
62
|
+
filePath;
|
|
63
|
+
persisted = {};
|
|
64
|
+
env;
|
|
65
|
+
constructor(workspaceRoot, env = process.env) {
|
|
66
|
+
this.filePath = join(workspaceRoot, CONFIG_FILE);
|
|
67
|
+
this.env = envLayer(env);
|
|
68
|
+
this.load();
|
|
69
|
+
}
|
|
70
|
+
load() {
|
|
71
|
+
if (!existsSync(this.filePath))
|
|
72
|
+
return;
|
|
73
|
+
try {
|
|
74
|
+
const raw = JSON.parse(readFileSync(this.filePath, "utf8"));
|
|
75
|
+
// Defensive: only accept the two known sections; ignore anything else.
|
|
76
|
+
this.persisted = {
|
|
77
|
+
...(raw.user && typeof raw.user === "object" ? { user: raw.user } : {}),
|
|
78
|
+
...(raw.project && typeof raw.project === "object" ? { project: raw.project } : {}),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
catch (e) {
|
|
82
|
+
log.warn(`config: ${CONFIG_FILE} is malformed — ignoring persistent layers`, {
|
|
83
|
+
error: e instanceof Error ? e.message : String(e),
|
|
84
|
+
});
|
|
85
|
+
this.persisted = {};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
save() {
|
|
89
|
+
try {
|
|
90
|
+
writeFileSync(this.filePath, JSON.stringify(this.persisted, null, 2) + "\n", "utf8");
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
93
|
+
log.warn(`config: failed to write ${CONFIG_FILE}`, {
|
|
94
|
+
error: e instanceof Error ? e.message : String(e),
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/** Merge one layer onto an accumulator. Arrays replace; unstable shallow-merges. */
|
|
99
|
+
static apply(acc, layer) {
|
|
100
|
+
if (!layer)
|
|
101
|
+
return acc;
|
|
102
|
+
return {
|
|
103
|
+
testAttributes: layer.testAttributes ?? acc.testAttributes,
|
|
104
|
+
capabilities: layer.capabilities ?? acc.capabilities,
|
|
105
|
+
confirmRequired: layer.confirmRequired ?? acc.confirmRequired,
|
|
106
|
+
allowedOrigins: layer.allowedOrigins ?? acc.allowedOrigins,
|
|
107
|
+
blockedOrigins: layer.blockedOrigins ?? acc.blockedOrigins,
|
|
108
|
+
headless: layer.headless ?? acc.headless,
|
|
109
|
+
actionTimeoutMs: layer.actionTimeoutMs ?? acc.actionTimeoutMs,
|
|
110
|
+
disableWebSecurity: layer.disableWebSecurity ?? acc.disableWebSecurity,
|
|
111
|
+
defaultDevice: layer.defaultDevice ?? acc.defaultDevice,
|
|
112
|
+
defaultViewport: layer.defaultViewport ?? acc.defaultViewport,
|
|
113
|
+
hideOverlaySelectors: layer.hideOverlaySelectors ?? acc.hideOverlaySelectors,
|
|
114
|
+
plugins: layer.plugins ?? acc.plugins,
|
|
115
|
+
unstable: layer.unstable ? { ...acc.unstable, ...layer.unstable } : acc.unstable,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/** The precedence chain as DATA (RFC 0004 P4 / D6) — replacing the four
|
|
119
|
+
* fixed-order `apply` calls + the `getLayer` switch. The array order IS the
|
|
120
|
+
* precedence, applied lowest → highest: env < user < project < session, atop
|
|
121
|
+
* the built-in defaults base. CRITICAL: reordering this array silently
|
|
122
|
+
* changes which layer wins, so the order is pinned by the config-store unit
|
|
123
|
+
* tests for every layer permutation. `read(store, sessionPatch)` returns the
|
|
124
|
+
* raw pre-merge layer for that scope (the same value the old `getLayer` arm
|
|
125
|
+
* returned). Adding a layer is one entry here, not edits to two methods.
|
|
126
|
+
*
|
|
127
|
+
* `defaults` is NOT in this array: it is the base accumulator, not an
|
|
128
|
+
* override layer (`getLayer("defaults")` returns the resolved base directly).
|
|
129
|
+
* `session` reads `sessionPatch` during `resolve()` but is not held on the
|
|
130
|
+
* store, so its `getLayer` view is `{}` — preserved exactly. */
|
|
131
|
+
static PRECEDENCE = [
|
|
132
|
+
{ scope: "env", read: (s) => s.env },
|
|
133
|
+
{ scope: "user", read: (s) => s.persisted.user },
|
|
134
|
+
{ scope: "project", read: (s) => s.persisted.project },
|
|
135
|
+
{ scope: "session", read: (_s, sessionPatch) => sessionPatch },
|
|
136
|
+
];
|
|
137
|
+
/** Resolve the full config. `sessionPatch` is the highest-precedence layer.
|
|
138
|
+
* Iterates `PRECEDENCE` low → high atop the defaults base — byte-identical to
|
|
139
|
+
* the old fixed `apply(env) → apply(user) → apply(project) → apply(session)`
|
|
140
|
+
* sequence, now data-driven. */
|
|
141
|
+
resolve(sessionPatch) {
|
|
142
|
+
// L8: the precedence chain must be non-empty and `session` must be its
|
|
143
|
+
// highest-precedence (last) layer — the whole contract of `resolve()` is
|
|
144
|
+
// "apply lowest → highest, session wins". A reordering that demoted `session`
|
|
145
|
+
// would silently let a persisted layer override an open_session patch. The
|
|
146
|
+
// PRECEDENCE array is a fixed module constant ending in `session`, so this
|
|
147
|
+
// holds on every call; the invariant pins the ordering contract at the one
|
|
148
|
+
// place it is depended on, complementing the per-permutation unit tests.
|
|
149
|
+
const chain = ConfigStore.PRECEDENCE;
|
|
150
|
+
invariant(chain.length > 0, "config precedence chain is empty");
|
|
151
|
+
invariant(chain[chain.length - 1].scope === "session", "config precedence: `session` must be the highest-precedence layer");
|
|
152
|
+
let acc = { ...BUILTIN_DEFAULTS, unstable: { ...BUILTIN_DEFAULTS.unstable } };
|
|
153
|
+
for (const layer of chain) {
|
|
154
|
+
acc = ConfigStore.apply(acc, layer.read(this, sessionPatch));
|
|
155
|
+
}
|
|
156
|
+
return acc;
|
|
157
|
+
}
|
|
158
|
+
/** Inspect one layer (raw, pre-merge) — for `get_config({ scope })`. Reads the
|
|
159
|
+
* same `PRECEDENCE` array `resolve()` iterates, so the inspected layer and the
|
|
160
|
+
* applied layer can never diverge. `defaults` returns the base directly (it is
|
|
161
|
+
* not an override layer); `session` is never held here, so its raw view is
|
|
162
|
+
* `{}` — both preserved exactly. */
|
|
163
|
+
getLayer(scope) {
|
|
164
|
+
if (scope === "defaults")
|
|
165
|
+
return BUILTIN_DEFAULTS;
|
|
166
|
+
const entry = ConfigStore.PRECEDENCE.find((l) => l.scope === scope);
|
|
167
|
+
// session config isn't held here (it's per open_session), so its raw layer
|
|
168
|
+
// is `{}`; every other scope returns its stored layer (or `{}` when unset).
|
|
169
|
+
return entry?.read(this) ?? {};
|
|
170
|
+
}
|
|
171
|
+
/** Persist a patch into `user` or `project`. The only writer of config.json. */
|
|
172
|
+
setLayer(scope, patch) {
|
|
173
|
+
const current = this.persisted[scope] ?? {};
|
|
174
|
+
this.persisted[scope] = {
|
|
175
|
+
...current,
|
|
176
|
+
...patch,
|
|
177
|
+
...(patch.unstable ? { unstable: { ...(current.unstable ?? {}), ...patch.unstable } } : {}),
|
|
178
|
+
};
|
|
179
|
+
this.save();
|
|
180
|
+
log.info(`config: set scope="${scope}"`, { keys: Object.keys(patch) });
|
|
181
|
+
}
|
|
182
|
+
/** Clear a persistent layer entirely. */
|
|
183
|
+
resetLayer(scope) {
|
|
184
|
+
delete this.persisted[scope];
|
|
185
|
+
this.save();
|
|
186
|
+
log.info(`config: reset scope="${scope}"`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Adapter: render a `ResolvedConfig` as an env-shaped record so the existing
|
|
191
|
+
* env-driven resolvers (`resolveCapabilities` / `resolveOriginPolicy` /
|
|
192
|
+
* `resolveConfirmHooks` / `resolveConfig`) can consume the *fully resolved*
|
|
193
|
+
* precedence chain without each being rewritten. Precedence is already applied
|
|
194
|
+
* in `ConfigStore.resolve()`; this just re-expresses the result in the shape
|
|
195
|
+
* those functions parse.
|
|
196
|
+
*/
|
|
197
|
+
export function resolvedToEnv(c) {
|
|
198
|
+
return {
|
|
199
|
+
BROWX_TEST_ATTRIBUTES: c.testAttributes.join(","),
|
|
200
|
+
BROWX_CAPABILITIES: c.capabilities.join(","),
|
|
201
|
+
BROWX_CONFIRM_REQUIRED: c.confirmRequired.join(","),
|
|
202
|
+
BROWX_ALLOWED_ORIGINS: c.allowedOrigins.join(","),
|
|
203
|
+
BROWX_BLOCKED_ORIGINS: c.blockedOrigins.join(","),
|
|
204
|
+
BROWX_HEADLESS: c.headless ? "1" : "",
|
|
205
|
+
};
|
|
206
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Threshold below which `snapshot()` emits the "low-content" warning (
|
|
3
|
+
* ). Tuned conservatively — most non-trivial pages have well more than 5
|
|
4
|
+
* interactive descendants in the a11y tree; a hydrated page returning fewer is
|
|
5
|
+
* almost always a sparse-a11y SPA where the DOM-walk fallback wins.
|
|
6
|
+
*/
|
|
7
|
+
export declare const LOW_A11Y_THRESHOLD = 5;
|
|
8
|
+
export interface BrowxConfig {
|
|
9
|
+
testAttributes: string[];
|
|
10
|
+
}
|
|
11
|
+
export declare function resolveConfig(env?: NodeJS.ProcessEnv): BrowxConfig;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Runtime configuration sourced from env. Resolved once at startup so behaviour
|
|
2
|
+
// is predictable per-session. Adopters who need to add a project-conventional
|
|
3
|
+
// data-attribute (e.g. some codebases use `data-type`, `data-cy`, `data-qa`)
|
|
4
|
+
// can do so without code changes:
|
|
5
|
+
//
|
|
6
|
+
// BROWX_TEST_ATTRIBUTES=data-testid,data-test,data-cy,data-qa,data-type
|
|
7
|
+
//
|
|
8
|
+
// The list is order-sensitive: the **first** match on a node wins as its `testId`
|
|
9
|
+
// and the matched attribute name flows through to selectorHint so the agent
|
|
10
|
+
// transcribes the right selector ("[data-type=\"foo\"]", not "[data-testid=\"foo\"]").
|
|
11
|
+
const DEFAULT_TEST_ATTRIBUTES = ["data-testid", "data-test", "data-cy", "data-qa"];
|
|
12
|
+
/**
|
|
13
|
+
* Threshold below which `snapshot()` emits the "low-content" warning (
|
|
14
|
+
* ). Tuned conservatively — most non-trivial pages have well more than 5
|
|
15
|
+
* interactive descendants in the a11y tree; a hydrated page returning fewer is
|
|
16
|
+
* almost always a sparse-a11y SPA where the DOM-walk fallback wins.
|
|
17
|
+
*/
|
|
18
|
+
export const LOW_A11Y_THRESHOLD = 5;
|
|
19
|
+
export function resolveConfig(env = process.env) {
|
|
20
|
+
const raw = env.BROWX_TEST_ATTRIBUTES?.trim();
|
|
21
|
+
const list = raw
|
|
22
|
+
? raw
|
|
23
|
+
.split(",")
|
|
24
|
+
.map((s) => s.trim())
|
|
25
|
+
.filter(Boolean)
|
|
26
|
+
: DEFAULT_TEST_ATTRIBUTES;
|
|
27
|
+
return { testAttributes: list };
|
|
28
|
+
}
|