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,516 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { assertEngineSupports } from "../engine/index.js";
|
|
3
|
+
import { DEFAULT_SESSION_ID, } from "../session/registry.js";
|
|
4
|
+
import { clampTimeout, withDeadline, DEFAULT_ACTION_TIMEOUT_MS } from "../util/deadline.js";
|
|
5
|
+
import { estimateTokens } from "../util/tokens.js";
|
|
6
|
+
import { invariant } from "../util/invariant.js";
|
|
7
|
+
import { buildEvalJsCapture, redactArgs, } from "../util/diagnostics.js";
|
|
8
|
+
import { engineEntry } from "../engine/registry.js";
|
|
9
|
+
import { EgressSanitiser } from "../util/egress-sanitiser.js";
|
|
10
|
+
import { screenshotSave } from "../page/screenshot-save.js";
|
|
11
|
+
import { isToolEnabled, declareToolCapability, toolCapabilityMap, } from "../util/capabilities.js";
|
|
12
|
+
import { declareDeepTool } from "../engine/tool-gate.js";
|
|
13
|
+
/**
|
|
14
|
+
* The composition heart: assemble the shared helper closures + the `ToolHost`
|
|
15
|
+
* literal `createServer` hands to each `registerXxxTools(host)` module. Every
|
|
16
|
+
* closure body is byte-identical to the inline `createServer` version; the
|
|
17
|
+
* createServer locals they close over arrive through `deps`, and the
|
|
18
|
+
* intra-block references between closures (register → noteWedgeOutcome, the
|
|
19
|
+
* `*For` ports → ctxFor, …) stay as-is because they all move together.
|
|
20
|
+
*/
|
|
21
|
+
export function buildHost(deps) {
|
|
22
|
+
const { server, toolHandlers, registry, config, configStore, resolvedConfig, caps, confirmHooks, originPolicy, approvals, isByob, workspace, diagnostics, credentialsResolved, pluginRecords, startOptions, describeTarget, asTarget, } = deps;
|
|
23
|
+
const entryFor = (sessionId) => registry.get(sessionId ?? DEFAULT_SESSION_ID);
|
|
24
|
+
const confirmCtxFor = (e) => ({
|
|
25
|
+
hooks: confirmHooks,
|
|
26
|
+
policy: originPolicy,
|
|
27
|
+
bridge: e.bridge,
|
|
28
|
+
isByob,
|
|
29
|
+
approvals,
|
|
30
|
+
});
|
|
31
|
+
/** Disabled-tool early-return shape. Used at the top of each handler:
|
|
32
|
+
* const g = gateCheck("foo"); if (g) return g;
|
|
33
|
+
* Returns null when the tool is enabled (handler proceeds). */
|
|
34
|
+
const gateCheck = (toolName) => {
|
|
35
|
+
if (isToolEnabled(toolName, caps))
|
|
36
|
+
return null;
|
|
37
|
+
return {
|
|
38
|
+
content: [
|
|
39
|
+
{
|
|
40
|
+
type: "text",
|
|
41
|
+
text: JSON.stringify({
|
|
42
|
+
ok: false,
|
|
43
|
+
error: `tool "${toolName}" is disabled — its capability is not in the server's ACTIVE set`,
|
|
44
|
+
requiredCapability: toolCapabilityMap().get(toolName) ?? null,
|
|
45
|
+
activeCapabilities: [...caps.enabled],
|
|
46
|
+
hint: "This tool's capability (`requiredCapability` above) is not in the server's active set. Fix: add it to `BROWX_CAPABILITIES` (or the `capabilities` config), then RESTART the browxai server — capabilities are resolved ONCE at server start, so `set_config` alone won't enable it. Two gotchas if it still doesn't take after a restart: (1) a persisted `set_config({capabilities})` layer REPLACES the BROWX_CAPABILITIES env value entirely (arrays don't merge), so a patch that omits this capability silently overrides the env var — include every capability you want, not just this one; (2) `get_config({scope:\"resolved\"}).capabilities` is the *live enforced* set (what this gate checks). See docs/threat-model.md.",
|
|
47
|
+
}, null, 2),
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
/** Engine-dimension early-return shape — the headline of the multi-engine
|
|
53
|
+
* work. Composes with `gateCheck` (capability dimension): after the tool's
|
|
54
|
+
* capability is confirmed active and the session is resolved, this refuses a
|
|
55
|
+
* CDP-deep tool (audit class B + the live-CDP class-C tools) on an engine
|
|
56
|
+
* that declares no `deep` escape hatch (firefox), with a structured hint —
|
|
57
|
+
* the same refusal-with-hint pattern `pdf_save`-on-BYOB uses. Returns null
|
|
58
|
+
* when the engine supports the tool (the fast path on chromium and for every
|
|
59
|
+
* cross-browser tool).
|
|
60
|
+
*
|
|
61
|
+
* const eg = engineGate("perf_start", e); if (eg) return eg;
|
|
62
|
+
*/
|
|
63
|
+
const engineGate = (toolName, e) => {
|
|
64
|
+
const refusal = assertEngineSupports(toolName, e.session.engine);
|
|
65
|
+
if (!refusal)
|
|
66
|
+
return null;
|
|
67
|
+
const body = {
|
|
68
|
+
ok: false,
|
|
69
|
+
error: refusal.error,
|
|
70
|
+
engine: e.session.engine,
|
|
71
|
+
hint: refusal.hint,
|
|
72
|
+
};
|
|
73
|
+
return {
|
|
74
|
+
content: [
|
|
75
|
+
{
|
|
76
|
+
type: "text",
|
|
77
|
+
text: JSON.stringify({ ...body, tokensEstimate: estimateTokens(JSON.stringify(body)) }, null, 2),
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
/** Confirm-hook early-return helper. Returns the rejection content if denied, else null. */
|
|
83
|
+
const denyContent = (toolName, decision) => ({
|
|
84
|
+
content: [
|
|
85
|
+
{
|
|
86
|
+
type: "text",
|
|
87
|
+
text: JSON.stringify({
|
|
88
|
+
ok: false,
|
|
89
|
+
action: { type: toolName },
|
|
90
|
+
error: `policy: ${decision.reason}`,
|
|
91
|
+
hint: "This is NOT a human-approval wall and NOT a selector failure. As an MCP client, call `approve_actions({ scopes:[…], ttlSeconds })` once at session start to enable action tools for the session (e.g. scopes:[\"byob_action\"]). Alternatives: remove the entry from BROWX_CONFIRM_REQUIRED, or a human responds `true` to the page-side confirm. Don't mark the feature unverified — it's gated, not broken.",
|
|
92
|
+
}, null, 2),
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
});
|
|
96
|
+
/** Reconstruct a `selectorHint` string the recorder can write into a flow file
|
|
97
|
+
* YAML. Mirrors `buildSelectorHint` for `ref`/`named`; passes through `selector`. */
|
|
98
|
+
const hintFromTarget = (e, target) => {
|
|
99
|
+
// Coords targets don't correspond to a stable locator the recorder can replay —
|
|
100
|
+
// skip the hint and let the recording layer omit the step's target metadata.
|
|
101
|
+
if (target.coords)
|
|
102
|
+
return undefined;
|
|
103
|
+
if (target.selector)
|
|
104
|
+
return { selectorHint: target.selector };
|
|
105
|
+
let ref = target.ref;
|
|
106
|
+
if (target.named)
|
|
107
|
+
ref = e.refs.refByNameLookup(target.named);
|
|
108
|
+
if (!ref)
|
|
109
|
+
return undefined;
|
|
110
|
+
const inputs = e.refs.locatorOf(ref);
|
|
111
|
+
if (!inputs)
|
|
112
|
+
return undefined;
|
|
113
|
+
if (inputs.testId) {
|
|
114
|
+
const attr = inputs.testIdAttr ?? "data-testid";
|
|
115
|
+
return { selectorHint: `[${attr}="${inputs.testId}"]`, stability: "high" };
|
|
116
|
+
}
|
|
117
|
+
if (inputs.name)
|
|
118
|
+
return { selectorHint: `role=${inputs.role}[name="${inputs.name}"]`, stability: "medium" };
|
|
119
|
+
return { selectorHint: `role=${inputs.role}`, stability: "low" };
|
|
120
|
+
};
|
|
121
|
+
const ctxFor = (e) => ({
|
|
122
|
+
page: e.session.page(),
|
|
123
|
+
// The action window mints its per-action network tap from this substrate
|
|
124
|
+
// by engine capability: chromium → the CDP NetworkTap; firefox/webkit → the
|
|
125
|
+
// Playwright context-event tap. So the envelope's network slice is real on
|
|
126
|
+
// every engine, not just chromium.
|
|
127
|
+
network: e.networkSubstrate,
|
|
128
|
+
snapshot: e.snapshotSubstrate,
|
|
129
|
+
refs: e.refs,
|
|
130
|
+
console: e.console,
|
|
131
|
+
pages: () => e.session.page().context().pages(),
|
|
132
|
+
testAttributes: config.testAttributes,
|
|
133
|
+
originPolicy,
|
|
134
|
+
recorder: e.recorder,
|
|
135
|
+
ws: e.ws,
|
|
136
|
+
dialog: e.dialog,
|
|
137
|
+
permission: e.permission,
|
|
138
|
+
notification: e.notification,
|
|
139
|
+
fsPicker: e.fsPicker,
|
|
140
|
+
// pass the secrets registry only when the capability is on; the
|
|
141
|
+
// registry exists per-session regardless (kept on SessionEntry so
|
|
142
|
+
// setters wired at creation can reference it), but the action layer
|
|
143
|
+
// only consults it when the capability gate is open.
|
|
144
|
+
...(caps.enabled.has("secrets") ? { secrets: e.secrets } : {}),
|
|
145
|
+
// pass the downloads registry only when `file-io` is on. The registry
|
|
146
|
+
// exists per-session regardless (off-by-default state on SessionEntry),
|
|
147
|
+
// but the action-window only consults it when the capability gate is
|
|
148
|
+
// open so a server without `file-io` can never surface a downloads
|
|
149
|
+
// block.
|
|
150
|
+
...(caps.enabled.has("file-io") ? { downloads: e.downloads } : {}),
|
|
151
|
+
});
|
|
152
|
+
// The five capability ports (actions / capture / storage / script / emulation)
|
|
153
|
+
// are now folded into the engine's `SubstrateBundle` (RFC 0004 D1): the
|
|
154
|
+
// Safari-vs-Playwright choice each selector used to make inline is the engine's
|
|
155
|
+
// own concern, declared once in its `makeSubstrates(deps)`. The Playwright bundle
|
|
156
|
+
// needs the host config the old `actionsFor`/`captureFor` closures closed over
|
|
157
|
+
// (`ctxFor` for the ActionContext; `describeTarget` + the screenshot `save` sink
|
|
158
|
+
// for capture). These deps close over THIS server's boundary — `ctxFor` carries
|
|
159
|
+
// the server's originPolicy / config.testAttributes / caps gating, `save` writes
|
|
160
|
+
// under the server's `workspace.root` — so the composition root threads its OWN
|
|
161
|
+
// per-server set at the `makeSubstrates(deps)` call site (a closure-owned local,
|
|
162
|
+
// NEVER a module-global, so a second `createServer()` in the same process can
|
|
163
|
+
// never overwrite this server's substrate deps). The five host ports then resolve
|
|
164
|
+
// through the bundle keyed on `e.session.engine`, byte-identical to the pre-fold
|
|
165
|
+
// closures.
|
|
166
|
+
const serverSubstrateDeps = {
|
|
167
|
+
ctxFor,
|
|
168
|
+
describeTarget,
|
|
169
|
+
save: (buf, args) => screenshotSave(buf, workspace.root, args),
|
|
170
|
+
};
|
|
171
|
+
const substratesFor = (e) => engineEntry(e.session.engine).makeSubstrates(serverSubstrateDeps);
|
|
172
|
+
const actionsFor = (e) => substratesFor(e).actions(e);
|
|
173
|
+
const captureFor = (e) => substratesFor(e).capture(e);
|
|
174
|
+
const storageFor = (e) => substratesFor(e).storage(e);
|
|
175
|
+
const scriptFor = (e) => substratesFor(e).script(e);
|
|
176
|
+
const emulationFor = (e) => substratesFor(e).emulation(e);
|
|
177
|
+
// The egress-masking chokepoint (RFC 0004 P3 / D4). The `secrets`-capability
|
|
178
|
+
// decision is made ONCE here: a `secrets`-off server hands every sink a
|
|
179
|
+
// sanitiser holding a null registry (URL-sanitisation still applies; deep/text
|
|
180
|
+
// secrets-masking is a no-op) — byte-identical to the prior per-sink
|
|
181
|
+
// `caps.enabled.has("secrets") ? e.secrets.applyMaskDeep(x) : x` hand-call.
|
|
182
|
+
const egressFor = (e) => new EgressSanitiser(caps.enabled.has("secrets") ? e.secrets : null);
|
|
183
|
+
// resolve the effective anti-wedge deadline for a call —
|
|
184
|
+
// per-call `timeoutMs` over config `actionTimeoutMs` over the 5000 default,
|
|
185
|
+
// clamped to [1, 3_600_000]. `warning` is non-empty when the caller asked
|
|
186
|
+
// for an over-ceiling (insane) value.
|
|
187
|
+
const cfgActionTimeout = () => {
|
|
188
|
+
const v = configStore.resolve().actionTimeoutMs;
|
|
189
|
+
return typeof v === "number" && v > 0 ? v : DEFAULT_ACTION_TIMEOUT_MS;
|
|
190
|
+
};
|
|
191
|
+
const actionTimeout = (args) => clampTimeout(args.timeoutMs, cfgActionTimeout());
|
|
192
|
+
// Wedge tracking. Only tools that actually exercise the page can
|
|
193
|
+
// wedge a session; session-management / config / coordination tools are
|
|
194
|
+
// excluded so their (always fast) results don't reset the streak.
|
|
195
|
+
const WEDGE_TRACKED_CAPABILITIES = new Set([
|
|
196
|
+
"read",
|
|
197
|
+
"navigation",
|
|
198
|
+
"action",
|
|
199
|
+
"eval",
|
|
200
|
+
"network-body",
|
|
201
|
+
"file-io",
|
|
202
|
+
]);
|
|
203
|
+
/** First text item of a result, parsed as a JSON object — or null when the
|
|
204
|
+
* result has no leading JSON object (a plain-text snapshot, an image). */
|
|
205
|
+
const firstJsonResult = (res) => {
|
|
206
|
+
for (let i = 0; i < res.content.length; i++) {
|
|
207
|
+
const item = res.content[i];
|
|
208
|
+
if (item && item.type === "text") {
|
|
209
|
+
try {
|
|
210
|
+
const parsed = JSON.parse(item.text);
|
|
211
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
212
|
+
return { obj: parsed, idx: i };
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
/* not JSON — a plain-text result, e.g. a snapshot tree */
|
|
217
|
+
}
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return null;
|
|
222
|
+
};
|
|
223
|
+
/** Update the session's wedge counter from a tool result and, once the
|
|
224
|
+
* session is wedged, splice `sessionWedged` + a recovery hint onto it.
|
|
225
|
+
* An anti-wedge timeout increments the streak; any responsive result
|
|
226
|
+
* (success, or a fast non-timeout error) clears it.
|
|
227
|
+
*
|
|
228
|
+
* Before stamping `sessionWedged: true`, the threshold-trip path probes
|
|
229
|
+
* the page with a 1s `evaluate(() => 1)` — if the page answers, the
|
|
230
|
+
* session is alive (the timeouts were action-shaped, not page-shaped:
|
|
231
|
+
* perpetually-busy SPAs hold WS keepalives / rAF loops that prevent
|
|
232
|
+
* Playwright actionability from settling, but the page itself responds
|
|
233
|
+
* fine to evaluate). A successful probe clears the streak instead of
|
|
234
|
+
* falsely tipping the caller into a session-discard. */
|
|
235
|
+
const noteWedgeOutcome = async (args, res) => {
|
|
236
|
+
const sessionId = args?.session ?? DEFAULT_SESSION_ID;
|
|
237
|
+
const entry = registry.peek(sessionId);
|
|
238
|
+
if (!entry)
|
|
239
|
+
return res;
|
|
240
|
+
const parsed = firstJsonResult(res);
|
|
241
|
+
const timedOut = !!parsed &&
|
|
242
|
+
parsed.obj.ok === false &&
|
|
243
|
+
typeof parsed.obj.error === "string" &&
|
|
244
|
+
/anti-wedge timeout/i.test(parsed.obj.error);
|
|
245
|
+
if (!timedOut || !parsed) {
|
|
246
|
+
entry.wedge.recordResponsive();
|
|
247
|
+
return res;
|
|
248
|
+
}
|
|
249
|
+
entry.wedge.recordTimeout();
|
|
250
|
+
if (!entry.wedge.wedged())
|
|
251
|
+
return res;
|
|
252
|
+
// Threshold tripped — confirm before stamping. Cheap liveness probe:
|
|
253
|
+
// if the page answers evaluate() within 1s, the session is alive and
|
|
254
|
+
// the timeouts were action-shaped (e.g. busy SPA blocks click
|
|
255
|
+
// actionability). Clear the streak rather than falsely wedge the
|
|
256
|
+
// caller. If the probe fails or times out, the session genuinely is
|
|
257
|
+
// wedged — stamp the response as before.
|
|
258
|
+
let aliveByProbe = false;
|
|
259
|
+
try {
|
|
260
|
+
const page = entry.session.page();
|
|
261
|
+
await withDeadline(page.evaluate(() => 1), 1_000, "wedge_probe");
|
|
262
|
+
aliveByProbe = true;
|
|
263
|
+
}
|
|
264
|
+
catch {
|
|
265
|
+
aliveByProbe = false;
|
|
266
|
+
}
|
|
267
|
+
if (aliveByProbe) {
|
|
268
|
+
entry.wedge.recordResponsive();
|
|
269
|
+
return res;
|
|
270
|
+
}
|
|
271
|
+
const obj = { ...parsed.obj, sessionWedged: true, sessionWedgedHint: entry.wedge.hint() };
|
|
272
|
+
return {
|
|
273
|
+
content: res.content.map((item, i) => i === parsed.idx ? { type: "text", text: JSON.stringify(obj, null, 2) } : item),
|
|
274
|
+
};
|
|
275
|
+
};
|
|
276
|
+
// Classify a dispatched tool result for the per-session metrics
|
|
277
|
+
// counter. We piggyback on `firstJsonResult` (already defined above) so we
|
|
278
|
+
// don't pay a second parse. A capability-denied result is the JSON shape the
|
|
279
|
+
// `gateCheck` helper emits (carries `requiredCapability`); any other
|
|
280
|
+
// `ok:false` result is an error; everything else is `ok`. The
|
|
281
|
+
// `tokensEstimate` field is read straight off the envelope when present —
|
|
282
|
+
// most tools surface it via the standard helper, but image-only / non-JSON
|
|
283
|
+
// results legitimately don't and that's fine (treated as 0).
|
|
284
|
+
const classifyOutcome = (res) => {
|
|
285
|
+
const parsed = firstJsonResult(res);
|
|
286
|
+
if (!parsed)
|
|
287
|
+
return { outcome: "ok" };
|
|
288
|
+
const obj = parsed.obj;
|
|
289
|
+
const tokens = typeof obj.tokensEstimate === "number" ? obj.tokensEstimate : undefined;
|
|
290
|
+
if (obj.ok === false) {
|
|
291
|
+
// Capability-denied shape (see `gateCheck`): carries `requiredCapability`.
|
|
292
|
+
// The denial path is a config-shape signal, not a tool-error signal —
|
|
293
|
+
// bucket it separately.
|
|
294
|
+
if (Object.prototype.hasOwnProperty.call(obj, "requiredCapability")) {
|
|
295
|
+
return { outcome: "denied", tokensEstimate: tokens };
|
|
296
|
+
}
|
|
297
|
+
return { outcome: "error", tokensEstimate: tokens };
|
|
298
|
+
}
|
|
299
|
+
return { outcome: "ok", tokensEstimate: tokens };
|
|
300
|
+
};
|
|
301
|
+
/** Record one dispatch on the session's metrics counter — peek-only on the
|
|
302
|
+
* registry. Calls against a not-yet-open session (e.g. a capability denial
|
|
303
|
+
* fired before the lazy session creation) are silently skipped: there's no
|
|
304
|
+
* SessionEntry to accumulate against, and the denial is still visible at the
|
|
305
|
+
* capability layer. Same posture as `noteWedgeOutcome` above. */
|
|
306
|
+
const noteMetrics = (toolName, args, res, startedAt) => {
|
|
307
|
+
const sessionId = args?.session ?? DEFAULT_SESSION_ID;
|
|
308
|
+
const entry = registry.peek(sessionId);
|
|
309
|
+
if (!entry)
|
|
310
|
+
return;
|
|
311
|
+
const { outcome, tokensEstimate } = classifyOutcome(res);
|
|
312
|
+
entry.metrics.record(toolName, outcome, Date.now() - startedAt, tokensEstimate);
|
|
313
|
+
};
|
|
314
|
+
/** Record one dispatched call into the diagnostics JSONL store. No-op when
|
|
315
|
+
* the diagnostics capability is OFF — the caller short-circuits on
|
|
316
|
+
* `diagnostics.enabled` BEFORE allocating anything. The recorder runs
|
|
317
|
+
* DOWNSTREAM of the URL sanitiser + secrets-masking chokepoint:
|
|
318
|
+
* by the time `res` lands here, every egress sink has already rewritten
|
|
319
|
+
* registered secret values back to `<NAME>` aliases. Args are additionally
|
|
320
|
+
* walked through `applyMaskDeep` so a secret echoed in the call args
|
|
321
|
+
* never reaches the JSONL raw. */
|
|
322
|
+
const noteDiagnostics = (toolName, args, res, startedAt) => {
|
|
323
|
+
if (!diagnostics.enabled)
|
|
324
|
+
return;
|
|
325
|
+
const sessionId = args?.session ?? DEFAULT_SESSION_ID;
|
|
326
|
+
const entry = registry.peek(sessionId);
|
|
327
|
+
// Apply the per-session secrets mask to args BEFORE structural redaction
|
|
328
|
+
// so a registered secret value echoed in the call args never lands raw
|
|
329
|
+
// in the JSONL store.
|
|
330
|
+
const maskedArgsIn = entry?.secrets ? entry.secrets.applyMaskDeep(args) : args;
|
|
331
|
+
const parsed = firstJsonResult(res);
|
|
332
|
+
const sizeBytes = res.content.reduce((n, item) => {
|
|
333
|
+
if (item.type === "text")
|
|
334
|
+
return n + Buffer.byteLength(item.text, "utf8");
|
|
335
|
+
if (item.type === "image")
|
|
336
|
+
return n + (typeof item.data === "string" ? item.data.length : 0);
|
|
337
|
+
return n;
|
|
338
|
+
}, 0);
|
|
339
|
+
const obj = parsed?.obj ?? null;
|
|
340
|
+
const ok = obj ? obj.ok !== false : true;
|
|
341
|
+
const warningsCount = obj && Array.isArray(obj.warnings) ? obj.warnings.length : 0;
|
|
342
|
+
let failureKind;
|
|
343
|
+
if (!ok && obj) {
|
|
344
|
+
if (Object.prototype.hasOwnProperty.call(obj, "requiredCapability")) {
|
|
345
|
+
failureKind = "capability-denied";
|
|
346
|
+
diagnostics.noteDenial();
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
const err = typeof obj.error === "string" ? obj.error : "";
|
|
350
|
+
if (/anti-wedge timeout/i.test(err))
|
|
351
|
+
failureKind = "timeout";
|
|
352
|
+
else if (/not found|no element matches|ref not found|locator did not resolve/i.test(err))
|
|
353
|
+
failureKind = "target-not-found";
|
|
354
|
+
else if (/must |invalid |unknown |expected /i.test(err))
|
|
355
|
+
failureKind = "bad-arg";
|
|
356
|
+
else
|
|
357
|
+
failureKind = "internal";
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
const record = {
|
|
361
|
+
kind: "call",
|
|
362
|
+
ts: new Date(startedAt).toISOString(),
|
|
363
|
+
tool: toolName,
|
|
364
|
+
sessionId,
|
|
365
|
+
argsRedacted: redactArgs(maskedArgsIn),
|
|
366
|
+
resultMeta: {
|
|
367
|
+
ok,
|
|
368
|
+
sizeBytes,
|
|
369
|
+
warningsCount,
|
|
370
|
+
...(failureKind ? { failureKind } : {}),
|
|
371
|
+
},
|
|
372
|
+
durationMs: Date.now() - startedAt,
|
|
373
|
+
capabilityDenials: diagnostics.denialsCount(),
|
|
374
|
+
};
|
|
375
|
+
const evalCap = buildEvalJsCapture(toolName, maskedArgsIn, obj);
|
|
376
|
+
if (evalCap)
|
|
377
|
+
record.evalJs = evalCap;
|
|
378
|
+
diagnostics.write(record);
|
|
379
|
+
};
|
|
380
|
+
// Wrapper that preserves the inner handler's parameter type for typechecking
|
|
381
|
+
// (destructuring inside each registration still works) but stores a
|
|
382
|
+
// type-erased copy for `batch` dispatch. Page-exercising tools additionally
|
|
383
|
+
// route their result through the wedge tracker; every tool is timed +
|
|
384
|
+
// counted on the session's per-session metrics rollup. When the
|
|
385
|
+
// `diagnostics` capability is on, each dispatch ALSO lands as a JSONL
|
|
386
|
+
// record under $BROWX_WORKSPACE/diagnostics/<sessionId>/<ISO>.jsonl;
|
|
387
|
+
// when off, the recorder is a zero-overhead gate check (no allocations,
|
|
388
|
+
// no file IO).
|
|
389
|
+
// Derived (RFC 0004 P2). Both are populated by `register` from the colocated
|
|
390
|
+
// `{ batchable }` / `{ capability, deep, inputSchema }` metadata each tool
|
|
391
|
+
// declares, so a tool's batchability, capability, deepness, and SDK type all
|
|
392
|
+
// trace back to its one registration call. `BATCH_ALLOWED_TOOLS` replaces the
|
|
393
|
+
// hand-maintained 71-entry literal; `await_human`, `batch`, the recording
|
|
394
|
+
// controls and the config mutators simply never declare `{ batchable: true }`,
|
|
395
|
+
// so they are excluded by construction rather than by an omission a human had
|
|
396
|
+
// to remember. The host exposes the batch set via `batchAllowedTools` and the
|
|
397
|
+
// full registration table via `registrations` (read by the SDK tool-types
|
|
398
|
+
// codegen, D7).
|
|
399
|
+
const BATCH_ALLOWED_TOOLS = new Set();
|
|
400
|
+
const registrations = new Map();
|
|
401
|
+
const register = (name, def, handler) => {
|
|
402
|
+
// L8/L2: a tool name registers EXACTLY once. The derived central maps
|
|
403
|
+
// (TOOL_CAPABILITY / BATCH_ALLOWED_TOOLS / DEEP_TOOLS) and `toolHandlers` all
|
|
404
|
+
// key on `name`, so a duplicate registration would silently shadow the
|
|
405
|
+
// handler AND desync the derived metadata from the live surface — the exact
|
|
406
|
+
// single-source-of-truth break L2 forbids. Every core family registers
|
|
407
|
+
// disjoint names (the registered-name freeze test pins the set), so this
|
|
408
|
+
// holds; the invariant turns "names are unique" from a convention into an
|
|
409
|
+
// asserted contract at the one seam every registration flows through.
|
|
410
|
+
invariant(!registrations.has(name), `tool "${name}" registered twice`);
|
|
411
|
+
// Colocated metadata → derived central maps (RFC 0004 P2 / D2). The
|
|
412
|
+
// capability/deep facts feed the lower-layer registries; `batchable` feeds the
|
|
413
|
+
// local batch allow-set; the whole record (incl. the zod schema) is kept for
|
|
414
|
+
// the SDK tool-types codegen (D7). The capability gate then reads `TOOL_CAPABILITY`
|
|
415
|
+
// (now derived from these declarations), so the assignment lives only here.
|
|
416
|
+
if (def.capability !== undefined)
|
|
417
|
+
declareToolCapability(name, def.capability);
|
|
418
|
+
if (def.deep)
|
|
419
|
+
declareDeepTool(name);
|
|
420
|
+
if (def.batchable)
|
|
421
|
+
BATCH_ALLOWED_TOOLS.add(name);
|
|
422
|
+
registrations.set(name, {
|
|
423
|
+
description: def.description,
|
|
424
|
+
inputSchema: def.inputSchema,
|
|
425
|
+
capability: def.capability,
|
|
426
|
+
batchable: def.batchable,
|
|
427
|
+
deep: def.deep,
|
|
428
|
+
});
|
|
429
|
+
const tracked = WEDGE_TRACKED_CAPABILITIES.has(def.capability ?? "");
|
|
430
|
+
const wrapped = async (rawArgs) => {
|
|
431
|
+
// MCP-wire boundary: the SDK parses + validates the inbound payload against
|
|
432
|
+
// this tool's `inputSchema` before dispatch, so the dispatched value IS the
|
|
433
|
+
// handler's declared arg shape. This is the one place that boundary narrows.
|
|
434
|
+
const args = rawArgs;
|
|
435
|
+
const startedAt = Date.now();
|
|
436
|
+
const inner = tracked
|
|
437
|
+
? await noteWedgeOutcome(args, await handler(args))
|
|
438
|
+
: await handler(args);
|
|
439
|
+
noteMetrics(name, args, inner, startedAt);
|
|
440
|
+
noteDiagnostics(name, args, inner, startedAt);
|
|
441
|
+
return inner;
|
|
442
|
+
};
|
|
443
|
+
toolHandlers[name] = wrapped;
|
|
444
|
+
// The SDK's `registerTool` generic cannot relate its conditional-typed
|
|
445
|
+
// callback to a still-generic `S`; widening the config's schema to a concrete
|
|
446
|
+
// `ZodRawShape` lets that conditional resolve, so `wrapped` (whose args are
|
|
447
|
+
// narrowed at the wire boundary above and whose result is a CallToolResult)
|
|
448
|
+
// matches with no assertion.
|
|
449
|
+
const sdkConfig = def;
|
|
450
|
+
server.registerTool(name, sdkConfig, wrapped);
|
|
451
|
+
};
|
|
452
|
+
// ---------- action tools ----------
|
|
453
|
+
const asActionResultText = async (p) => {
|
|
454
|
+
const r = await p;
|
|
455
|
+
return { content: [{ type: "text", text: JSON.stringify(r, null, 2) }] };
|
|
456
|
+
};
|
|
457
|
+
/** JSON envelope for the non-action families: stringify with `tokensEstimate`. */
|
|
458
|
+
const okText = (body) => {
|
|
459
|
+
const json = JSON.stringify(body);
|
|
460
|
+
const tokensEstimate = estimateTokens(json);
|
|
461
|
+
return {
|
|
462
|
+
content: [
|
|
463
|
+
{ type: "text", text: JSON.stringify({ ...body, tokensEstimate }, null, 2) },
|
|
464
|
+
],
|
|
465
|
+
};
|
|
466
|
+
};
|
|
467
|
+
/** Same shape for an `ok:false` rejection so callers see a uniform envelope. */
|
|
468
|
+
const errText = (tool, err) => okText({ ok: false, tool, error: err instanceof Error ? err.message : String(err) });
|
|
469
|
+
// The composition seam: bundle the shared state + helper closures into one
|
|
470
|
+
// host and hand it to each per-family tool module. createServer stays the
|
|
471
|
+
// registry composition root; the register() blocks live under src/tools/.
|
|
472
|
+
const host = {
|
|
473
|
+
register,
|
|
474
|
+
entryFor,
|
|
475
|
+
gateCheck,
|
|
476
|
+
engineGate,
|
|
477
|
+
confirmCtxFor,
|
|
478
|
+
ctxFor,
|
|
479
|
+
workspace,
|
|
480
|
+
denyContent,
|
|
481
|
+
asActionResultText,
|
|
482
|
+
okText,
|
|
483
|
+
errText,
|
|
484
|
+
asTarget,
|
|
485
|
+
hintFromTarget,
|
|
486
|
+
actionTimeout,
|
|
487
|
+
cfgActionTimeout,
|
|
488
|
+
actionsFor,
|
|
489
|
+
captureFor,
|
|
490
|
+
storageFor,
|
|
491
|
+
scriptFor,
|
|
492
|
+
emulationFor,
|
|
493
|
+
egressFor,
|
|
494
|
+
caps,
|
|
495
|
+
config,
|
|
496
|
+
configStore,
|
|
497
|
+
resolvedConfig,
|
|
498
|
+
startOptions,
|
|
499
|
+
z,
|
|
500
|
+
toolHandlers,
|
|
501
|
+
batchAllowedTools: BATCH_ALLOWED_TOOLS,
|
|
502
|
+
registrations,
|
|
503
|
+
registry,
|
|
504
|
+
diagnostics,
|
|
505
|
+
approvals,
|
|
506
|
+
credentialsResolved,
|
|
507
|
+
noteMetrics,
|
|
508
|
+
noteDiagnostics,
|
|
509
|
+
// `pluginRecords` is assigned after the host literal is built (plugin
|
|
510
|
+
// runtime starts later); expose it lazily so get_config sees the live set.
|
|
511
|
+
get pluginRecords() {
|
|
512
|
+
return pluginRecords();
|
|
513
|
+
},
|
|
514
|
+
};
|
|
515
|
+
return host;
|
|
516
|
+
}
|