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
package/dist/server.js
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
// MCP server wiring. Tools are registered here; their implementations live in
|
|
2
|
+
// page/* and helper/*. stdout is the MCP channel — all logging goes via util/logging.ts.
|
|
3
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
+
import { resolveCredentialsProvider } from "./util/credentials.js";
|
|
6
|
+
import { resolveConfig } from "./util/config.js";
|
|
7
|
+
import { resolveWorkspace } from "./util/workspace.js";
|
|
8
|
+
import { DiagnosticsRecorder, ensureDiagnosticsRoot, resolveRetentionDays, sweepRetention, } from "./util/diagnostics.js";
|
|
9
|
+
import { ConfigStore, resolvedToEnv } from "./util/config-store.js";
|
|
10
|
+
import { resolveCapabilities, resolveConfirmHooks } from "./util/capabilities.js";
|
|
11
|
+
import { resolveOriginPolicy, describePolicy } from "./policy/origin.js";
|
|
12
|
+
import { ApprovalStore } from "./policy/confirm.js";
|
|
13
|
+
import { log } from "./util/logging.js";
|
|
14
|
+
import { PACKAGE_VERSION } from "./util/version.js";
|
|
15
|
+
import { buildHost } from "./tools/host-build.js";
|
|
16
|
+
import { registerActionTools } from "./tools/action-tools.js";
|
|
17
|
+
import { registerReadObserveDomTools } from "./tools/read-observe-dom-tools.js";
|
|
18
|
+
import { registerReadObserveExtractTools } from "./tools/read-observe-extract-tools.js";
|
|
19
|
+
import { registerReadObserveVerifyTools } from "./tools/read-observe-verify-tools.js";
|
|
20
|
+
import { registerReadObserveCaptureTools } from "./tools/read-observe-capture-tools.js";
|
|
21
|
+
import { registerReadObserveBufferTools } from "./tools/read-observe-buffer-tools.js";
|
|
22
|
+
import { registerGestureNetworkTools } from "./tools/gesture-network-tools.js";
|
|
23
|
+
import { registerDeepPerfTools } from "./tools/deep-perf-tools.js";
|
|
24
|
+
import { registerDeepCoverageTools } from "./tools/deep-coverage-tools.js";
|
|
25
|
+
import { registerDeepDeterminismTools } from "./tools/deep-determinism-tools.js";
|
|
26
|
+
import { registerCaptureReportMarksTools } from "./tools/capture-report-marks-tools.js";
|
|
27
|
+
import { registerCaptureReportDiagnosticsTools } from "./tools/capture-report-diagnostics-tools.js";
|
|
28
|
+
import { registerCaptureReportUploadTools } from "./tools/capture-report-upload-tools.js";
|
|
29
|
+
import { registerCaptureReportExportTools } from "./tools/capture-report-export-tools.js";
|
|
30
|
+
import { registerCaptureReportElementExportTools } from "./tools/capture-report-element-export-tools.js";
|
|
31
|
+
import { registerCanvasTools } from "./tools/canvas-tools.js";
|
|
32
|
+
import { registerStorageTools } from "./tools/storage-tools.js";
|
|
33
|
+
import { registerFormsRecordingTools } from "./tools/forms-recording-tools.js";
|
|
34
|
+
import { registerSessionPolicyTools } from "./tools/session-policy-tools.js";
|
|
35
|
+
import { registerDeviceEmulationTools } from "./tools/device-emulation-tools.js";
|
|
36
|
+
import { registerLiveEmulationTools } from "./tools/live-emulation-tools.js";
|
|
37
|
+
import { registerConfigApprovalTools } from "./tools/config-approval-tools.js";
|
|
38
|
+
import { registerSecretsCaptchaTools } from "./tools/secrets-captcha-tools.js";
|
|
39
|
+
import { registerInputTools } from "./tools/input-tools.js";
|
|
40
|
+
import { registerExtensionsBatchTools } from "./tools/extensions-batch-tools.js";
|
|
41
|
+
import { wirePluginRuntime } from "./tools/plugin-runtime.js";
|
|
42
|
+
import { buildSessionRegistry } from "./tools/session-registry.js";
|
|
43
|
+
// RFC 0004 P2 / D1 (SECURITY-CRITICAL): importing the tool-metadata bootstrap is a
|
|
44
|
+
// side effect that EAGERLY populates the derived `TOOL_CAPABILITY` / `DEEP_TOOLS`
|
|
45
|
+
// maps. `createServer` calls `resolveCapabilities` BEFORE its own tool
|
|
46
|
+
// registrations run; this import guarantees the maps are already populated at that
|
|
47
|
+
// point (and that the gate's fail-safe never trips for a server-built process),
|
|
48
|
+
// independent of whether the consumer reached us via the package entry.
|
|
49
|
+
import "./tools/tool-metadata.js";
|
|
50
|
+
// Shared input-schema fragments live in a leaf module so the per-family tool
|
|
51
|
+
// modules and this composition root depend on them without an import cycle.
|
|
52
|
+
import { SESSION_ARG, TIMEOUT_ARG, ACTION_OPTS, REF_OR_SELECTOR } from "./tools/schemas.js";
|
|
53
|
+
export const NAME = "browxai";
|
|
54
|
+
// Derived from package.json — see src/util/version.ts. Never hand-bump.
|
|
55
|
+
export const VERSION = PACKAGE_VERSION;
|
|
56
|
+
// Re-exported (imported at the top with the other tool modules) to preserve the
|
|
57
|
+
// existing public surface — the definitions now live in `tools/schemas`.
|
|
58
|
+
export { SESSION_ARG, TIMEOUT_ARG, ACTION_OPTS, REF_OR_SELECTOR };
|
|
59
|
+
/** structured one-liner alongside an element screenshot. Skips
|
|
60
|
+
* vision-reading when the agent only needs to confirm "yes the button is there." */
|
|
61
|
+
async function describeTarget(loc, refs, target) {
|
|
62
|
+
const bits = [];
|
|
63
|
+
let inputs;
|
|
64
|
+
if ("ref" in target && target.ref) {
|
|
65
|
+
inputs = refs.locatorOf(target.ref);
|
|
66
|
+
if (inputs) {
|
|
67
|
+
bits.push(inputs.role);
|
|
68
|
+
if (inputs.name)
|
|
69
|
+
bits.push(`"${inputs.name}"`);
|
|
70
|
+
if (inputs.testId)
|
|
71
|
+
bits.push(`[${inputs.testIdAttr ?? "data-testid"}="${inputs.testId}"]`);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
bits.push(`ref=${target.ref}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
else if ("selector" in target && target.selector) {
|
|
78
|
+
bits.push(`selector=${target.selector}`);
|
|
79
|
+
}
|
|
80
|
+
else if ("coords" in target && target.coords) {
|
|
81
|
+
bits.push(`coords=${target.coords.x},${target.coords.y}`);
|
|
82
|
+
return bits.join(" "); // no Locator to probe further for coords targets
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
const box = await loc.boundingBox();
|
|
86
|
+
if (box)
|
|
87
|
+
bits.push(`bbox=${Math.round(box.x)},${Math.round(box.y)} ${Math.round(box.width)}×${Math.round(box.height)}`);
|
|
88
|
+
const visible = await loc.isVisible().catch(() => undefined);
|
|
89
|
+
if (visible === false)
|
|
90
|
+
bits.push("not-visible");
|
|
91
|
+
const enabled = await loc.isEnabled().catch(() => undefined);
|
|
92
|
+
if (enabled === false)
|
|
93
|
+
bits.push("disabled");
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
/* skip — fall back to whatever we have */
|
|
97
|
+
}
|
|
98
|
+
return bits.join(" ");
|
|
99
|
+
}
|
|
100
|
+
function asTarget(args, toolName, refs) {
|
|
101
|
+
const provided = [args.ref, args.selector, args.named, args.coords].filter(Boolean).length;
|
|
102
|
+
if (provided > 1)
|
|
103
|
+
throw new Error(`${toolName}: pass exactly one of \`ref\` / \`selector\` / \`named\` / \`coords\``);
|
|
104
|
+
if (args.ref)
|
|
105
|
+
return { ref: args.ref };
|
|
106
|
+
if (args.named) {
|
|
107
|
+
const resolved = refs.refByNameLookup(args.named);
|
|
108
|
+
if (!resolved)
|
|
109
|
+
throw new Error(`${toolName}: name "${args.named}" not bound. Call name_ref({name, ref}) first.`);
|
|
110
|
+
return { ref: resolved };
|
|
111
|
+
}
|
|
112
|
+
if (args.selector) {
|
|
113
|
+
return args.contextRef
|
|
114
|
+
? { selector: args.selector, contextRef: args.contextRef }
|
|
115
|
+
: { selector: args.selector };
|
|
116
|
+
}
|
|
117
|
+
if (args.coords)
|
|
118
|
+
return { coords: args.coords };
|
|
119
|
+
throw new Error(`${toolName}: requires one of \`ref\` (from find/snapshot), \`selector\`, \`named\`, or \`coords\``);
|
|
120
|
+
}
|
|
121
|
+
export async function createServer(opts = {}) {
|
|
122
|
+
// config flows through the browxai-managed ConfigStore (precedence
|
|
123
|
+
// defaults < env(legacy) < user < project < session). The existing env-driven
|
|
124
|
+
// resolvers consume the *resolved* chain re-expressed as an env shape, so
|
|
125
|
+
// precedence is centralised in the store without rewriting each resolver.
|
|
126
|
+
const workspace = resolveWorkspace();
|
|
127
|
+
const configStore = new ConfigStore(workspace.root);
|
|
128
|
+
const resolvedConfig = configStore.resolve();
|
|
129
|
+
const cfgEnv = resolvedToEnv(resolvedConfig);
|
|
130
|
+
const config = resolveConfig(cfgEnv);
|
|
131
|
+
// approvals are session-independent policy state — server-level.
|
|
132
|
+
const approvals = new ApprovalStore();
|
|
133
|
+
// policy: capabilities, confirm-required hooks, origin allow/blocklist.
|
|
134
|
+
const caps = resolveCapabilities(cfgEnv);
|
|
135
|
+
const confirmHooks = resolveConfirmHooks(cfgEnv);
|
|
136
|
+
const originPolicy = resolveOriginPolicy(cfgEnv);
|
|
137
|
+
const isByob = !!opts.attachCdp;
|
|
138
|
+
log.info("browxai: policy", {
|
|
139
|
+
capabilities: [...caps.enabled],
|
|
140
|
+
confirmHooks: [...confirmHooks],
|
|
141
|
+
origins: describePolicy(originPolicy),
|
|
142
|
+
});
|
|
143
|
+
for (const w of caps.warnings)
|
|
144
|
+
log.warn(`browxai: ${w}`);
|
|
145
|
+
if (caps.enabled.has("eval"))
|
|
146
|
+
log.warn("browxai: eval capability is ENABLED — `eval_js` will execute page-side JS. Return values are page-controlled.");
|
|
147
|
+
if (caps.enabled.has("network-body"))
|
|
148
|
+
log.warn("browxai: network-body capability is ENABLED — `network_body` returns full response bodies, which can carry PII / auth tokens. Off by default for a reason.");
|
|
149
|
+
if (caps.enabled.has("secrets"))
|
|
150
|
+
log.warn("browxai: secrets capability is ENABLED — `register_secret` accepts sensitive values; once a secret is registered the egress masking layer engages on every sink (ActionResult.network, network_read, network_body, ws_read, console_read, snapshot, find). `screenshot` is a partial sink — see docs/tool-reference.md.");
|
|
151
|
+
// Credentials provider: resolved once at server start. The provider object
|
|
152
|
+
// is constructed even when the capability is off so per-deployment config
|
|
153
|
+
// validation (unknown provider name → warn) happens up front. Per-call
|
|
154
|
+
// failures (missing CLI binary, missing seed, etc.) surface as structured
|
|
155
|
+
// refusals on the tool result — never crash startup.
|
|
156
|
+
const credentialsResolved = resolveCredentialsProvider(cfgEnv);
|
|
157
|
+
for (const w of credentialsResolved.config.warnings)
|
|
158
|
+
log.warn(`browxai: ${w}`);
|
|
159
|
+
if (caps.enabled.has("credentials")) {
|
|
160
|
+
log.warn(`browxai: credentials capability is ENABLED — \`get_totp\` / \`get_credential\` will shell out to the configured "${credentialsResolved.config.provider}" backend per call. NEVER bundled, NEVER auto-installed — the operator supplies the CLI / seeds out-of-band. \`get_credential\` ADDITIONALLY requires the \`secrets\` capability so the looked-up password is auto-registered into the per-session secrets registry under \`<PASSWORD_<account>>\` and masked across every egress sink (without \`secrets\`, the lookup refuses rather than leak cleartext). Same posture class as \`eval\` / \`network-body\` / \`secrets\`. See docs/threat-model.md.`);
|
|
161
|
+
}
|
|
162
|
+
if (caps.enabled.has("extensions"))
|
|
163
|
+
log.warn("browxai: extensions capability is ENABLED — `extensions_install` loads unpacked Chromium extensions into managed (headed, persistent) sessions. Loaded extensions can READ every page the session visits and make ARBITRARY network requests; treat the extension code itself as in-scope trust. Headed + persistent only — incognito / attached sessions refuse. install/reload/uninstall REBUILD the underlying browser context, invalidating refs + console/network buffers (profile state on disk survives). Same posture class as `eval` / `network-body` / `secrets` — see docs/threat-model.md.");
|
|
164
|
+
if (caps.enabled.has("stealth"))
|
|
165
|
+
log.warn("browxai: stealth capability is ENABLED — every session's context loads init-script patches that override `navigator.webdriver` / `navigator.plugins` / `navigator.languages` / `window.chrome` to defeat the common Playwright fingerprint surface. CIRCUMVENTING AUTOMATION DETECTION MAY VIOLATE A SITE'S TERMS OF SERVICE; the operator carries the legal exposure. browxai does NOT bundle a full anti-fingerprinting library — only the four well-known patches above. Same posture class as `eval` / `network-body` / `secrets` / `extensions` — see docs/threat-model.md.");
|
|
166
|
+
if (caps.enabled.has("device-emulation"))
|
|
167
|
+
log.warn("browxai: device-emulation capability is ENABLED — `emulate_bluetooth` / `emulate_usb` / `emulate_hid` install init-script wrappers around `navigator.bluetooth.requestDevice` / `navigator.usb.requestDevice` / `navigator.hid.requestDevice` so the page resolves with synthetic device objects the agent staged. THE PAGE WILL BELIEVE IT HAS ACCESS TO PHYSICAL DEVICES THAT DON'T EXIST. v1 covers the picker-clear path only — GATT service emulation (Bluetooth), USB transfer endpoints, and HID input/output reports are stubs (resolve with empty/zero-byte results). Same posture class as `eval` / `network-body` / `secrets` / `extensions` / `stealth` / `captcha` — see docs/threat-model.md.");
|
|
168
|
+
if (caps.enabled.has("canvas"))
|
|
169
|
+
log.warn("browxai: canvas capability is ENABLED — `canvas_capture` reads framebuffer / 2D ImageData pixel bytes off `<canvas>` elements (subject to the platform's canvas-taint rules for cross-origin sources); `gesture_chain` dispatches multi-step pointer programs (custom paint strokes, lasso paths); `canvas_world_to_screen` / `canvas_screen_to_world` probe common app-side globals heuristically (Figma / Tldraw / Excalidraw shapes) when no explicit transform is supplied — confirm on a known landmark before relying on the result. `canvas_query` dispatches to canvas-app adapter plugins; the inner plugin tool's capability is enforced via the plugin call-graph gate. browxai is BYO-vision — `canvas_capture` is the pixel source, not a vision call; composition with the host agent's own multimodal vision is the loop. Same posture class as `eval` / `network-body` / `secrets` / `extensions` / `device-emulation` / `diagnostics` — see docs/threat-model.md.");
|
|
170
|
+
if (caps.enabled.has("captcha"))
|
|
171
|
+
log.warn("browxai: captcha capability is ENABLED — `solve_captcha` will delegate challenges to the provider configured via BROWX_CAPTCHA_PROVIDER + BROWX_CAPTCHA_API_KEY. SOLVING CAPTCHAS MAY VIOLATE THE TARGET SITE'S TERMS OF SERVICE and (depending on jurisdiction) computer-misuse / unauthorised-access law; the operator carries the legal exposure. browxai does NOT bundle a solver and does NOT auto-purchase credits — the operator chooses a provider, funds the account, configures the server. Same posture class as `eval` / `network-body` / `secrets` / `extensions` / `stealth` — see docs/threat-model.md.");
|
|
172
|
+
// diagnostics recorder. Constructed eagerly so the dispatch
|
|
173
|
+
// wrapper can reference it; the `enabled` flag is what gates every
|
|
174
|
+
// actual side-effect. OFF → zero allocations beyond a gate check on
|
|
175
|
+
// every tool call.
|
|
176
|
+
const diagnosticsEnabled = caps.enabled.has("diagnostics");
|
|
177
|
+
const diagRetentionDays = resolveRetentionDays(cfgEnv);
|
|
178
|
+
if (diagnosticsEnabled) {
|
|
179
|
+
log.warn("browxai: diagnostics capability is ENABLED — every MCP tool call is " +
|
|
180
|
+
`recorded as a JSONL line under $BROWX_WORKSPACE/diagnostics/<sessionId>/<ISO>.jsonl ` +
|
|
181
|
+
`(retention: ${diagRetentionDays} days; configure via BROWX_DIAGNOSTICS_RETENTION_DAYS). ` +
|
|
182
|
+
"Args are structurally redacted (large/sensitive payload fields → sha256 + byteLength); " +
|
|
183
|
+
"the recorder runs DOWNSTREAM of the URL sanitiser + secrets-masking egress " +
|
|
184
|
+
"chokepoint, so registered secret values never reach the store raw. The agent " +
|
|
185
|
+
"self-feedback tool `diagnostics_note` ALSO requires this capability; read-side " +
|
|
186
|
+
"queries (`diagnostics_search`, `diagnostics_report`) ride the `read` capability " +
|
|
187
|
+
"so a report can be pulled even when no further notes are being filed. Same posture " +
|
|
188
|
+
"class as `eval` / `network-body` / `secrets` / `extensions` / `stealth` / `captcha` / " +
|
|
189
|
+
"`device-emulation`. See docs/threat-model.md.");
|
|
190
|
+
// Create the diagnostics root + run the retention sweep up-front so a
|
|
191
|
+
// long-idle workspace doesn't keep months of stale JSONL.
|
|
192
|
+
try {
|
|
193
|
+
ensureDiagnosticsRoot(workspace.root);
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
/* best-effort */
|
|
197
|
+
}
|
|
198
|
+
try {
|
|
199
|
+
sweepRetention(workspace.root, diagRetentionDays);
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
/* best-effort */
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
const diagnostics = new DiagnosticsRecorder({
|
|
206
|
+
enabled: diagnosticsEnabled,
|
|
207
|
+
workspaceRoot: workspace.root,
|
|
208
|
+
retentionDays: diagRetentionDays,
|
|
209
|
+
});
|
|
210
|
+
if (resolvedConfig.disableWebSecurity)
|
|
211
|
+
log.warn("browxai: disableWebSecurity is ENABLED — managed/incognito sessions launch with SOP/CORS OFF (--disable-web-security). Use only against test/dev targets.");
|
|
212
|
+
if (process.env.BROWX_EXTRACT_STRICT === "1")
|
|
213
|
+
log.warn("browxai: BROWX_EXTRACT_STRICT=1 — extract() unknown-`x-browx-source`-key warnings are PROMOTED to hard `ok:false` invalid-schema rejections (v0.2.2's partialMisses-only behavior is bypassed). The integer→number coerce and array-`selector`-as-`collection` alias are NOT promoted; only typo-like unknown-key diagnostics are.");
|
|
214
|
+
if (isByob && !caps.enabled.has("byob-attach")) {
|
|
215
|
+
log.warn("browxai: BROWX_ATTACH_CDP is set but `byob-attach` capability is disabled. Add `byob-attach` to BROWX_CAPABILITIES to use it.");
|
|
216
|
+
}
|
|
217
|
+
// per-session state lives in the SessionRegistry. The "default"
|
|
218
|
+
// session is created lazily on the first browser-touching tool call — so
|
|
219
|
+
// list_tools / discovery still don't launch a browser, and every existing
|
|
220
|
+
// caller that omits `session` keeps working unchanged.
|
|
221
|
+
// The engine every session this server opens runs on. Defaults to chromium;
|
|
222
|
+
// firefox + webkit + android are also wired (the launch path drives each via
|
|
223
|
+
// its adapter). A future-declared engine without an adapter is rejected
|
|
224
|
+
// (engine-not-yet-supported) — there is no silent fallback to chromium.
|
|
225
|
+
const serverEngine = opts.browserType ?? "chromium";
|
|
226
|
+
// The server-level launch mode: BYOB when BROWX_ATTACH_CDP is set, else
|
|
227
|
+
// persistent. android is ATTACH-ONLY (the user's real Chrome-on-Android over
|
|
228
|
+
// adb + CDP), so it defaults to "attached" with no BROWX_ATTACH_CDP
|
|
229
|
+
// (the endpoint is DISCOVERED over adb, not configured). This is the default a
|
|
230
|
+
// lazily-created session inherits; an explicit open_session can override per id.
|
|
231
|
+
const serverDefaultMode = serverEngine === "android" || opts.attachCdp ? "attached" : "persistent";
|
|
232
|
+
const registry = buildSessionRegistry({
|
|
233
|
+
opts,
|
|
234
|
+
resolvedConfig,
|
|
235
|
+
configStore,
|
|
236
|
+
caps,
|
|
237
|
+
workspace,
|
|
238
|
+
serverEngine,
|
|
239
|
+
serverDefaultMode,
|
|
240
|
+
});
|
|
241
|
+
const server = new McpServer({ name: NAME, version: VERSION }, { capabilities: { tools: {} } });
|
|
242
|
+
// Side-table of handler functions, populated as we register each tool. Lets
|
|
243
|
+
// the `batch` tool dispatch a whitelist of inner calls without going through
|
|
244
|
+
// the MCP transport. Each handler accepts the inner tool's args and returns
|
|
245
|
+
// the same `{ content: [...] }` shape an MCP call would. `ToolResponse` is the
|
|
246
|
+
// shared seam type (src/tools/host.ts) so extracted tool modules and the
|
|
247
|
+
// composition root agree on the envelope.
|
|
248
|
+
const toolHandlers = {};
|
|
249
|
+
// populated AFTER every core tool registration when the plugin
|
|
250
|
+
// runtime fires. Declared here so `get_config({scope:"resolved"})` can
|
|
251
|
+
// reference it via closure (registered before plugin loading runs).
|
|
252
|
+
let pluginRecords = [];
|
|
253
|
+
// The composition seam: bundle the shared state + helper closures into one
|
|
254
|
+
// host and hand it to each per-family tool module. createServer stays the
|
|
255
|
+
// registry composition root; the closures + host literal live in buildHost.
|
|
256
|
+
const host = buildHost({
|
|
257
|
+
server,
|
|
258
|
+
toolHandlers,
|
|
259
|
+
registry,
|
|
260
|
+
config,
|
|
261
|
+
configStore,
|
|
262
|
+
resolvedConfig,
|
|
263
|
+
caps,
|
|
264
|
+
confirmHooks,
|
|
265
|
+
originPolicy,
|
|
266
|
+
approvals,
|
|
267
|
+
isByob,
|
|
268
|
+
workspace,
|
|
269
|
+
diagnostics,
|
|
270
|
+
credentialsResolved,
|
|
271
|
+
pluginRecords: () => pluginRecords,
|
|
272
|
+
startOptions: opts,
|
|
273
|
+
describeTarget,
|
|
274
|
+
asTarget,
|
|
275
|
+
});
|
|
276
|
+
registerReadObserveDomTools(host);
|
|
277
|
+
registerReadObserveExtractTools(host);
|
|
278
|
+
registerReadObserveVerifyTools(host);
|
|
279
|
+
registerReadObserveCaptureTools(host);
|
|
280
|
+
registerReadObserveBufferTools(host);
|
|
281
|
+
registerActionTools(host);
|
|
282
|
+
registerGestureNetworkTools(host);
|
|
283
|
+
registerDeepPerfTools(host);
|
|
284
|
+
registerDeepCoverageTools(host);
|
|
285
|
+
registerDeepDeterminismTools(host);
|
|
286
|
+
registerCaptureReportMarksTools(host);
|
|
287
|
+
registerCaptureReportDiagnosticsTools(host);
|
|
288
|
+
registerCaptureReportUploadTools(host);
|
|
289
|
+
registerCaptureReportExportTools(host);
|
|
290
|
+
registerCaptureReportElementExportTools(host);
|
|
291
|
+
registerCanvasTools(host);
|
|
292
|
+
registerStorageTools(host);
|
|
293
|
+
registerFormsRecordingTools(host);
|
|
294
|
+
registerSessionPolicyTools(host);
|
|
295
|
+
registerDeviceEmulationTools(host);
|
|
296
|
+
registerLiveEmulationTools(host);
|
|
297
|
+
registerConfigApprovalTools(host);
|
|
298
|
+
registerSecretsCaptchaTools(host);
|
|
299
|
+
registerInputTools(host);
|
|
300
|
+
// The extensions + batch/compound-primitive family registers through the
|
|
301
|
+
// shared ToolHost seam. It MUST run before the coreToolNames capture below
|
|
302
|
+
// so its tools count as core (plugin runtime loads last).
|
|
303
|
+
registerExtensionsBatchTools(host);
|
|
304
|
+
// Plugin runtime wiring — the LAST registration step, run after every core
|
|
305
|
+
// `register*Tools(host)` call so the `coreToolNames` snapshot taken inside
|
|
306
|
+
// counts the full core surface as "core" and plugins load on top of it.
|
|
307
|
+
// Returns the loaded records; assigning them to the createServer `let`
|
|
308
|
+
// keeps `get_config` reporting the live enabled-plugin set via the host
|
|
309
|
+
// getter.
|
|
310
|
+
pluginRecords = await wirePluginRuntime(host, {
|
|
311
|
+
server,
|
|
312
|
+
noteMetrics: host.noteMetrics,
|
|
313
|
+
noteDiagnostics: host.noteDiagnostics,
|
|
314
|
+
});
|
|
315
|
+
return {
|
|
316
|
+
start: async () => {
|
|
317
|
+
const transport = new StdioServerTransport();
|
|
318
|
+
await server.connect(transport);
|
|
319
|
+
log.info("browxai: MCP server up on stdio");
|
|
320
|
+
},
|
|
321
|
+
shutdown: async () => {
|
|
322
|
+
await registry.closeAll();
|
|
323
|
+
await server.close().catch(() => undefined);
|
|
324
|
+
},
|
|
325
|
+
handlers: toolHandlers,
|
|
326
|
+
};
|
|
327
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/** Max number of artifacts kept per session. Oldest-write evicted past this. */
|
|
2
|
+
export declare const ARTIFACT_MAX_ENTRIES = 200;
|
|
3
|
+
/** Max total bytes kept per session (50 MiB). Oldest-write evicted to fit. */
|
|
4
|
+
export declare const ARTIFACT_MAX_BYTES: number;
|
|
5
|
+
export type ArtifactEncoding = "utf8" | "base64";
|
|
6
|
+
/** What `artifact_list` returns per entry. */
|
|
7
|
+
export interface ArtifactInfo {
|
|
8
|
+
name: string;
|
|
9
|
+
/** size on disk, bytes. */
|
|
10
|
+
size: number;
|
|
11
|
+
/** ISO timestamp of last write. */
|
|
12
|
+
mtime: string;
|
|
13
|
+
}
|
|
14
|
+
/** Per-session artifact registry. One instance per SessionEntry. */
|
|
15
|
+
export declare class ArtifactsRegistry {
|
|
16
|
+
/** Per-session storage dir: `$BROWX_WORKSPACE/.artifacts/<sessionId>/`. */
|
|
17
|
+
readonly storageDir: string;
|
|
18
|
+
constructor(
|
|
19
|
+
/** Per-session storage dir: `$BROWX_WORKSPACE/.artifacts/<sessionId>/`. */
|
|
20
|
+
storageDir: string);
|
|
21
|
+
/** Resolve + workspace-escape-check the on-disk path for a name. The name
|
|
22
|
+
* is asserted via `assertSafeName` first (no separators / no `..` — the
|
|
23
|
+
* shared validator from storage.ts) PLUS a no-leading-dot guard added
|
|
24
|
+
* here so we never write a hidden file into the artifacts dir; the path
|
|
25
|
+
* is then re-resolved + checked it stays inside `storageDir` as defence
|
|
26
|
+
* in depth. */
|
|
27
|
+
pathFor(name: string): string;
|
|
28
|
+
/** Write an artifact. Overwrites an existing entry of the same name.
|
|
29
|
+
* Evicts oldest-write entries to stay under the capacity caps. */
|
|
30
|
+
save(name: string, content: string, encoding?: ArtifactEncoding): ArtifactInfo;
|
|
31
|
+
/** Read an artifact's bytes back. Throws if the name is unknown or the
|
|
32
|
+
* file vanished. */
|
|
33
|
+
get(name: string, encoding?: ArtifactEncoding): {
|
|
34
|
+
content: string;
|
|
35
|
+
size: number;
|
|
36
|
+
mtime: string;
|
|
37
|
+
encoding: ArtifactEncoding;
|
|
38
|
+
};
|
|
39
|
+
/** Enumerate every artifact in this session (sorted by name asc).
|
|
40
|
+
* Read-only; never throws on a single bad entry — skip unreadable. */
|
|
41
|
+
list(): ArtifactInfo[];
|
|
42
|
+
/** Best-effort wipe of the entire storage dir. Called on session
|
|
43
|
+
* teardown — every artifact written during the session is removed.
|
|
44
|
+
* Idempotent; ignores missing-dir. */
|
|
45
|
+
clear(): void;
|
|
46
|
+
/** Evict oldest-write entries until both the entry-count and total-byte
|
|
47
|
+
* caps are satisfied. Called after every save. */
|
|
48
|
+
private enforceCaps;
|
|
49
|
+
/** stat every entry, sorted by mtime ascending (oldest first). */
|
|
50
|
+
private statsByMtime;
|
|
51
|
+
private evict;
|
|
52
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
// Per-session artifact KV — session-scoped workspace primitives.
|
|
2
|
+
//
|
|
3
|
+
// First-class `save_artifact(name, content)` / `list_artifacts` /
|
|
4
|
+
// `load_artifact(name)` for the "build your own library over time" loop.
|
|
5
|
+
// Before this lane agents were forced to round-trip scripts/files/blobs
|
|
6
|
+
// through `name_ref`/`name_region` — both ref-typed and a poor fit for
|
|
7
|
+
// raw byte/string payloads.
|
|
8
|
+
//
|
|
9
|
+
// Design notes:
|
|
10
|
+
// - **Per-session.** Each `SessionEntry` owns one registry; entries
|
|
11
|
+
// don't cross sessions. Storage dir is
|
|
12
|
+
// `$BROWX_WORKSPACE/.artifacts/<sessionId>/`.
|
|
13
|
+
// - **Workspace-rooted paths only.** The name is restricted to a safe
|
|
14
|
+
// character set (no path separators, no leading dots, no `..`) — same
|
|
15
|
+
// posture as `assertSafeName` in `src/session/storage.ts`. Even with
|
|
16
|
+
// that, the composed path is re-resolved + workspace-escape-rejected
|
|
17
|
+
// defensively (defence in depth — `path/posix.join` with the workspace
|
|
18
|
+
// prefix).
|
|
19
|
+
// - **Cleared on session close.** Teardown wipes the whole
|
|
20
|
+
// `<sessionId>/` subdir; sessions that never wrote an artifact leave
|
|
21
|
+
// no trace.
|
|
22
|
+
// - **Capacity-bounded.** Max 200 entries AND 50 MiB total. Oldest-write
|
|
23
|
+
// evicted on overflow (per-name `mtime` ordering — LRU-by-write).
|
|
24
|
+
// - **Encoding.** `utf8` (default) treats `content` as text; `base64`
|
|
25
|
+
// decodes binary. Reads return the same encoding the caller wrote
|
|
26
|
+
// with — round-trip-faithful for both text and binary payloads.
|
|
27
|
+
// - **Capability split.** `artifact_save` → `action` (writes a file).
|
|
28
|
+
// `artifact_get` / `artifact_list` → `read`.
|
|
29
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync, } from "node:fs";
|
|
30
|
+
import { join, resolve, sep } from "node:path";
|
|
31
|
+
import { assertSafeName } from "./storage.js";
|
|
32
|
+
/** Max number of artifacts kept per session. Oldest-write evicted past this. */
|
|
33
|
+
export const ARTIFACT_MAX_ENTRIES = 200;
|
|
34
|
+
/** Max total bytes kept per session (50 MiB). Oldest-write evicted to fit. */
|
|
35
|
+
export const ARTIFACT_MAX_BYTES = 50 * 1024 * 1024;
|
|
36
|
+
/** Per-session artifact registry. One instance per SessionEntry. */
|
|
37
|
+
export class ArtifactsRegistry {
|
|
38
|
+
storageDir;
|
|
39
|
+
constructor(
|
|
40
|
+
/** Per-session storage dir: `$BROWX_WORKSPACE/.artifacts/<sessionId>/`. */
|
|
41
|
+
storageDir) {
|
|
42
|
+
this.storageDir = storageDir;
|
|
43
|
+
}
|
|
44
|
+
/** Resolve + workspace-escape-check the on-disk path for a name. The name
|
|
45
|
+
* is asserted via `assertSafeName` first (no separators / no `..` — the
|
|
46
|
+
* shared validator from storage.ts) PLUS a no-leading-dot guard added
|
|
47
|
+
* here so we never write a hidden file into the artifacts dir; the path
|
|
48
|
+
* is then re-resolved + checked it stays inside `storageDir` as defence
|
|
49
|
+
* in depth. */
|
|
50
|
+
pathFor(name) {
|
|
51
|
+
assertSafeName("artifact name", name);
|
|
52
|
+
if (name.startsWith(".")) {
|
|
53
|
+
throw new Error(`artifact name "${name}" invalid — names cannot start with '.'`);
|
|
54
|
+
}
|
|
55
|
+
const target = join(this.storageDir, name);
|
|
56
|
+
const resolved = resolve(target);
|
|
57
|
+
const root = resolve(this.storageDir);
|
|
58
|
+
if (resolved !== root && !resolved.startsWith(root + sep)) {
|
|
59
|
+
throw new Error(`artifact name "${name}" resolved outside its session storage dir — refusing.`);
|
|
60
|
+
}
|
|
61
|
+
return resolved;
|
|
62
|
+
}
|
|
63
|
+
/** Write an artifact. Overwrites an existing entry of the same name.
|
|
64
|
+
* Evicts oldest-write entries to stay under the capacity caps. */
|
|
65
|
+
save(name, content, encoding = "utf8") {
|
|
66
|
+
const dest = this.pathFor(name);
|
|
67
|
+
// `storageDir` is workspace-rooted by construction — the SessionEntry
|
|
68
|
+
// factory sets it via `workspace.sub('.artifacts/<id>')` (see server.ts).
|
|
69
|
+
// `dest` is the asserted-safe-name joined to that storageDir, with the
|
|
70
|
+
// workspace-escape re-check in `pathFor`.
|
|
71
|
+
if (!existsSync(this.storageDir))
|
|
72
|
+
mkdirSync(this.storageDir, { recursive: true });
|
|
73
|
+
const buf = encoding === "base64" ? Buffer.from(content, "base64") : Buffer.from(content, "utf8");
|
|
74
|
+
// workspace.sub-rooted by construction (see comment above).
|
|
75
|
+
writeFileSync(dest, buf);
|
|
76
|
+
this.enforceCaps();
|
|
77
|
+
const st = statSync(dest);
|
|
78
|
+
return { name, size: st.size, mtime: new Date(st.mtimeMs).toISOString() };
|
|
79
|
+
}
|
|
80
|
+
/** Read an artifact's bytes back. Throws if the name is unknown or the
|
|
81
|
+
* file vanished. */
|
|
82
|
+
get(name, encoding = "utf8") {
|
|
83
|
+
const dest = this.pathFor(name);
|
|
84
|
+
if (!existsSync(dest)) {
|
|
85
|
+
throw new Error(`artifact_get: no artifact "${name}" in this session — call artifact_save({ name, content }) first.`);
|
|
86
|
+
}
|
|
87
|
+
const buf = readFileSync(dest);
|
|
88
|
+
const st = statSync(dest);
|
|
89
|
+
return {
|
|
90
|
+
content: encoding === "base64" ? buf.toString("base64") : buf.toString("utf8"),
|
|
91
|
+
size: st.size,
|
|
92
|
+
mtime: new Date(st.mtimeMs).toISOString(),
|
|
93
|
+
encoding,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/** Enumerate every artifact in this session (sorted by name asc).
|
|
97
|
+
* Read-only; never throws on a single bad entry — skip unreadable. */
|
|
98
|
+
list() {
|
|
99
|
+
if (!existsSync(this.storageDir))
|
|
100
|
+
return [];
|
|
101
|
+
const out = [];
|
|
102
|
+
for (const entry of readdirSync(this.storageDir)) {
|
|
103
|
+
const p = join(this.storageDir, entry);
|
|
104
|
+
try {
|
|
105
|
+
const st = statSync(p);
|
|
106
|
+
if (!st.isFile())
|
|
107
|
+
continue;
|
|
108
|
+
out.push({ name: entry, size: st.size, mtime: new Date(st.mtimeMs).toISOString() });
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
/* skip unreadable */
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return out.sort((a, b) => a.name.localeCompare(b.name));
|
|
115
|
+
}
|
|
116
|
+
/** Best-effort wipe of the entire storage dir. Called on session
|
|
117
|
+
* teardown — every artifact written during the session is removed.
|
|
118
|
+
* Idempotent; ignores missing-dir. */
|
|
119
|
+
clear() {
|
|
120
|
+
try {
|
|
121
|
+
if (existsSync(this.storageDir))
|
|
122
|
+
rmSync(this.storageDir, { recursive: true, force: true });
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
/* best-effort cleanup */
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// ---- capacity enforcement -------------------------------------------------
|
|
129
|
+
/** Evict oldest-write entries until both the entry-count and total-byte
|
|
130
|
+
* caps are satisfied. Called after every save. */
|
|
131
|
+
enforceCaps() {
|
|
132
|
+
const entries = this.statsByMtime();
|
|
133
|
+
// entry-count cap
|
|
134
|
+
while (entries.length > ARTIFACT_MAX_ENTRIES) {
|
|
135
|
+
const victim = entries.shift();
|
|
136
|
+
if (!victim)
|
|
137
|
+
break;
|
|
138
|
+
this.evict(victim.path);
|
|
139
|
+
}
|
|
140
|
+
// byte cap
|
|
141
|
+
let totalBytes = entries.reduce((s, e) => s + e.size, 0);
|
|
142
|
+
while (totalBytes > ARTIFACT_MAX_BYTES) {
|
|
143
|
+
const victim = entries.shift();
|
|
144
|
+
if (!victim)
|
|
145
|
+
break;
|
|
146
|
+
this.evict(victim.path);
|
|
147
|
+
totalBytes -= victim.size;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/** stat every entry, sorted by mtime ascending (oldest first). */
|
|
151
|
+
statsByMtime() {
|
|
152
|
+
if (!existsSync(this.storageDir))
|
|
153
|
+
return [];
|
|
154
|
+
const out = [];
|
|
155
|
+
for (const name of readdirSync(this.storageDir)) {
|
|
156
|
+
const p = join(this.storageDir, name);
|
|
157
|
+
try {
|
|
158
|
+
const st = statSync(p);
|
|
159
|
+
if (!st.isFile())
|
|
160
|
+
continue;
|
|
161
|
+
out.push({ path: p, size: st.size, mtimeMs: st.mtimeMs });
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
/* skip */
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return out.sort((a, b) => a.mtimeMs - b.mtimeMs);
|
|
168
|
+
}
|
|
169
|
+
evict(p) {
|
|
170
|
+
try {
|
|
171
|
+
rmSync(p, { force: true });
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
/* best-effort */
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { BrowserSession, SessionOptions } from "./types.js";
|
|
2
|
+
/** Android BYOB — discover real Chrome-on-Android over adb + CDP and attach.
|
|
3
|
+
* Distinct from the desktop URL-attach path: the endpoint is DISCOVERED
|
|
4
|
+
* (adb forward → /json/version → wsUrl), not configured. The forwarded socket is
|
|
5
|
+
* loopback by construction (adb forwards to 127.0.0.1), so the same not-owned
|
|
6
|
+
* policy applies; close additionally removes the adb forward. Full CDP, so the
|
|
7
|
+
* session carries `cdp()` and the substrates pick the CDP path automatically. */
|
|
8
|
+
export declare function openAndroidByobSession(): Promise<BrowserSession>;
|
|
9
|
+
/** Assert the BYOB attach endpoint is present + loopback, returning it as a
|
|
10
|
+
* string. The firefox / webkit engine modules call this before surfacing their
|
|
11
|
+
* structured attach refusal, preserving the EXACT pre-relocation order (the
|
|
12
|
+
* `!attachCdp` throw, then the loopback assertion, then the per-engine refusal).
|
|
13
|
+
* Shared so the loopback policy lives in one place. */
|
|
14
|
+
export declare function assertByobAttach(opts: SessionOptions & {
|
|
15
|
+
attachCdp?: string;
|
|
16
|
+
}): string;
|
|
17
|
+
/** The Chromium CDP-attach (BYOB) lane — the desktop URL-attach path, extracted
|
|
18
|
+
* verbatim from the old `openByobSession` chromium body. Asserts the loopback
|
|
19
|
+
* endpoint, attaches over CDP, ensures a usable viewport, and builds the
|
|
20
|
+
* not-owned `BrowserSession`. The chromium engine module's `makeAdapter` byob
|
|
21
|
+
* branch calls this; firefox/webkit/safari surface their own structured attach
|
|
22
|
+
* refusals from their own engine modules, and android attaches over adb via
|
|
23
|
+
* `openAndroidByobSession` — so no engine-name branch survives here. */
|
|
24
|
+
export declare function attachByobChromium(opts: SessionOptions & {
|
|
25
|
+
attachCdp?: string;
|
|
26
|
+
}): Promise<BrowserSession>;
|