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,287 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { basename as pathBasename } from "node:path";
|
|
3
|
+
import { estimateTokens } from "../util/tokens.js";
|
|
4
|
+
import { applyCdpBaseline as applyPermissionCdpBaseline, SUPPORTED_PERMISSIONS, BYOB_PERMISSION_WARNING, } from "../session/permission.js";
|
|
5
|
+
import { resolveWorkspaceFsPath, SUPPORTED_FS_PICKER_APIS, } from "../session/fs-picker.js";
|
|
6
|
+
import { SESSION_ARG } from "./schemas.js";
|
|
7
|
+
/**
|
|
8
|
+
* Dialog / permission / file-system-picker policy tools: set_dialog_policy /
|
|
9
|
+
* set_permission_policy / set_fs_picker_policy / fs_picker_respond. Split out of
|
|
10
|
+
* `session-policy-tools` by cohesive family (RFC 0004 P3 / D3 SRP); registered
|
|
11
|
+
* through the shared `ToolHost` seam in the same source order. The host owns the
|
|
12
|
+
* closures (register / gate / entry / workspace).
|
|
13
|
+
*/
|
|
14
|
+
export function registerSessionDialogPermissionTools(host) {
|
|
15
|
+
const { z, register, gateCheck, entryFor, workspace } = host;
|
|
16
|
+
register("set_dialog_policy", {
|
|
17
|
+
capability: "action",
|
|
18
|
+
description: "Mutate the session's dialog policy at runtime. Governs how `alert` / `confirm` / `prompt` / `beforeunload` dialogs are handled when fired by the page — without a policy installed, a dialog blocks every subsequent browser event and the session deadlocks. Modes:\n" +
|
|
19
|
+
' - "accept" — accept every dialog (confirm/prompt → OK; prompt answers with the empty string).\n' +
|
|
20
|
+
' - "dismiss" — dismiss every dialog (confirm/prompt → Cancel).\n' +
|
|
21
|
+
' - "accept-prompt-with" — accept; prompts answer with `text` (required). Alert/confirm just accept.\n' +
|
|
22
|
+
' - "raise" — DEFAULT. Dialog is dismissed server-side so the page never deadlocks, but the next action returns ok:false with `failure:{source:"app", hint:"unhandled dialog — set dialogPolicy"}` so a dialog can\'t silently change app state under a caller that didn\'t opt in.\n' +
|
|
23
|
+
"Persists across navigation: the handler is re-installed on every new page within the session. The initial policy is set at `open_session({dialogPolicy})`; this tool replaces it. Returns the resolved policy. Fired dialogs surface on `ActionResult.dialogs[]`.",
|
|
24
|
+
inputSchema: {
|
|
25
|
+
mode: z
|
|
26
|
+
.enum(["accept", "dismiss", "raise", "accept-prompt-with"])
|
|
27
|
+
.describe("Policy mode — see tool description."),
|
|
28
|
+
text: z
|
|
29
|
+
.string()
|
|
30
|
+
.optional()
|
|
31
|
+
.describe('Required when mode="accept-prompt-with" — the answer text to send for prompts. Ignored for other modes.'),
|
|
32
|
+
...SESSION_ARG,
|
|
33
|
+
},
|
|
34
|
+
}, async (args) => {
|
|
35
|
+
const g = gateCheck("set_dialog_policy");
|
|
36
|
+
if (g)
|
|
37
|
+
return g;
|
|
38
|
+
const e = await entryFor(args.session);
|
|
39
|
+
try {
|
|
40
|
+
const next = args.mode === "accept-prompt-with"
|
|
41
|
+
? { mode: "accept-prompt-with", text: args.text ?? "" }
|
|
42
|
+
: { mode: args.mode };
|
|
43
|
+
if (next.mode === "accept-prompt-with" && args.text === undefined) {
|
|
44
|
+
throw new Error('set_dialog_policy: mode "accept-prompt-with" requires `text`');
|
|
45
|
+
}
|
|
46
|
+
const resolved = e.dialog.set(next);
|
|
47
|
+
const tokensEstimate = estimateTokens(JSON.stringify(resolved));
|
|
48
|
+
return {
|
|
49
|
+
content: [
|
|
50
|
+
{
|
|
51
|
+
type: "text",
|
|
52
|
+
text: JSON.stringify({ ok: true, session: e.id, policy: resolved, tokensEstimate }, null, 2),
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
return {
|
|
59
|
+
content: [
|
|
60
|
+
{
|
|
61
|
+
type: "text",
|
|
62
|
+
text: JSON.stringify({ ok: false, error: err instanceof Error ? err.message : String(err) }, null, 2),
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
register("set_permission_policy", {
|
|
69
|
+
capability: "action",
|
|
70
|
+
description: "Mutate the session's permission policy at runtime. Governs how page-side permission requests — `getUserMedia` (camera/microphone), `getCurrentPosition`/`watchPosition` (geolocation), `Notification.requestPermission`, `clipboard.read`/`write`, and the sensor permissions — are handled. Without a policy installed, requests either fire silently (Chromium auto-denies in headless) or — if a prior `grant_permissions` pre-granted — change app behavior under an unaware caller. Modes:\n" +
|
|
71
|
+
' - "allow" — pre-grant via CDP `Browser.setPermission`; in-page wrappers call through. The app sees a granted permission.\n' +
|
|
72
|
+
' - "deny" — pre-deny via CDP; in-page wrappers reject with `NotAllowedError`. The app sees a denied permission.\n' +
|
|
73
|
+
' - "raise" — DEFAULT. Pre-deny + in-page wrappers reject AND RECORD; the next ActionResult flips `ok:false` with `failure:{source:"app", hint:"unhandled permission request — set permissionPolicy"}`. The page never deadlocks (the request is rejected), but a permission request can\'t silently change app state under a caller that didn\'t opt in.\n' +
|
|
74
|
+
' - "ask-human" — server blocks on `__browx.confirm(true|false)` (the `await_human({kind:"confirm"})` mechanism), then resolves to allow/deny per the human\'s answer.\n' +
|
|
75
|
+
'Per-permission overrides (`perPermission: { camera: "allow", notifications: "deny", … }`) win over the top-level `mode`. Persists across navigation: the init-script is re-injected on every new document within the session. The initial policy is set at `open_session({permissionPolicy})`; this tool replaces it. Returns the resolved policy. Fired requests surface on `ActionResult.permissionRequests[]`. Supported permission names (v1): ' +
|
|
76
|
+
SUPPORTED_PERMISSIONS.join(", ") +
|
|
77
|
+
". USB / Bluetooth / HID are out of scope for v1.\n" +
|
|
78
|
+
'Sibling to `grant_permissions` — that tool remains as the bulk-grant shortcut for the `mode:"allow"` case; this tool is the full policy surface.',
|
|
79
|
+
inputSchema: {
|
|
80
|
+
mode: z
|
|
81
|
+
.enum(["allow", "deny", "raise", "ask-human"])
|
|
82
|
+
.describe("Top-level policy mode — see tool description."),
|
|
83
|
+
perPermission: z
|
|
84
|
+
.record(z.enum(["allow", "deny", "raise", "ask-human"]))
|
|
85
|
+
.optional()
|
|
86
|
+
.describe("Per-permission overrides. Keys: one of the supported permission names (see tool description). Each value overrides the top-level `mode` for that permission. Unknown names are rejected."),
|
|
87
|
+
...SESSION_ARG,
|
|
88
|
+
},
|
|
89
|
+
}, async (args) => {
|
|
90
|
+
const g = gateCheck("set_permission_policy");
|
|
91
|
+
if (g)
|
|
92
|
+
return g;
|
|
93
|
+
const e = await entryFor(args.session);
|
|
94
|
+
try {
|
|
95
|
+
const next = {
|
|
96
|
+
mode: args.mode,
|
|
97
|
+
...(args.perPermission
|
|
98
|
+
? {
|
|
99
|
+
perPermission: args.perPermission,
|
|
100
|
+
}
|
|
101
|
+
: {}),
|
|
102
|
+
};
|
|
103
|
+
const resolved = e.permission.set(next);
|
|
104
|
+
// Re-apply the CDP baseline so the new mapping is in effect for the
|
|
105
|
+
// very next page-side check (the wrapper script reads policy live; CDP
|
|
106
|
+
// baseline must also be refreshed so `navigator.permissions.query`
|
|
107
|
+
// / native code paths see the new state).
|
|
108
|
+
await applyPermissionCdpBaseline(e.session.page().context(), e.permission).catch(() => undefined);
|
|
109
|
+
const warnings = [];
|
|
110
|
+
if (e.mode === "attached")
|
|
111
|
+
warnings.push(BYOB_PERMISSION_WARNING);
|
|
112
|
+
const tokensEstimate = estimateTokens(JSON.stringify(resolved));
|
|
113
|
+
const body = {
|
|
114
|
+
ok: true,
|
|
115
|
+
session: e.id,
|
|
116
|
+
policy: resolved,
|
|
117
|
+
tokensEstimate,
|
|
118
|
+
};
|
|
119
|
+
if (warnings.length)
|
|
120
|
+
body.warnings = warnings;
|
|
121
|
+
return { content: [{ type: "text", text: JSON.stringify(body, null, 2) }] };
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
return {
|
|
125
|
+
content: [
|
|
126
|
+
{
|
|
127
|
+
type: "text",
|
|
128
|
+
text: JSON.stringify({ ok: false, error: err instanceof Error ? err.message : String(err) }, null, 2),
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
register("set_fs_picker_policy", {
|
|
135
|
+
capability: "action",
|
|
136
|
+
description: "Mutate the session's File System Access picker policy at runtime. Governs how `showOpenFilePicker` / `showSaveFilePicker` / `showDirectoryPicker` calls are handled. Without a policy installed, modern web editors deadlock on the picker dialog the headless session can't drive. Modes:\n" +
|
|
137
|
+
' - "allow" — page-side stubs return synthetic FileSystem*Handle objects built from agent-supplied files (call `fs_picker_respond` BEFORE the action that triggers the picker, OR in parallel — the queue is drained per-API on the next matching call). For `showSaveFilePicker`, the agent supplies a workspace-rooted `path` and `createWritable()` writes from the page persist there. For `showOpenFilePicker`, the agent supplies inline `contents` (base64) or a workspace-rooted `path` (server inlines the bytes); the page reads via `getFile()`.\n' +
|
|
138
|
+
' - "deny" — stubs throw `NotAllowedError`. The page sees the user-dismissed-picker branch.\n' +
|
|
139
|
+
' - "raise" — DEFAULT. Stubs throw `NotAllowedError` AND RECORD; the next ActionResult flips `ok:false` with `failure:{source:"app", hint:"unhandled File System Access picker — set fsPickerPolicy"}`. The page never deadlocks (the picker rejects immediately), but a picker call can\'t silently change app state under a caller that didn\'t opt in.\n' +
|
|
140
|
+
' - "ask-human" — server blocks on `__browx.respond({kind:"fs_picker_respond", value:{files:[…]}})` (the `await_human` mechanism), then resolves with the human-approved file list or denies.\n' +
|
|
141
|
+
'Per-API overrides (`perAPI: { showSaveFilePicker: "allow", showOpenFilePicker: "deny", … }`) win over the top-level `mode`. Persists across navigation: the init-script is re-injected on every new document within the session. The initial policy is set at `open_session({fsPickerPolicy})`; this tool replaces it. Returns the resolved policy. Fired pickers surface on `ActionResult.fsPickerRequests[]`. Supported APIs (v1): ' +
|
|
142
|
+
SUPPORTED_FS_PICKER_APIS.join(", ") +
|
|
143
|
+
". Directory picker returns a minimal handle (`.name` set; iteration empty) — most editors will fall back to per-file pickers when iteration yields nothing.",
|
|
144
|
+
inputSchema: {
|
|
145
|
+
mode: z
|
|
146
|
+
.enum(["allow", "deny", "raise", "ask-human"])
|
|
147
|
+
.describe("Top-level policy mode — see tool description."),
|
|
148
|
+
perAPI: z
|
|
149
|
+
.record(z.enum(["allow", "deny", "raise", "ask-human"]))
|
|
150
|
+
.optional()
|
|
151
|
+
.describe("Per-API overrides. Keys: one of " +
|
|
152
|
+
SUPPORTED_FS_PICKER_APIS.join(", ") +
|
|
153
|
+
". Each value overrides the top-level `mode` for that picker. Unknown keys are rejected."),
|
|
154
|
+
...SESSION_ARG,
|
|
155
|
+
},
|
|
156
|
+
}, async (args) => {
|
|
157
|
+
const g = gateCheck("set_fs_picker_policy");
|
|
158
|
+
if (g)
|
|
159
|
+
return g;
|
|
160
|
+
const e = await entryFor(args.session);
|
|
161
|
+
try {
|
|
162
|
+
const next = {
|
|
163
|
+
mode: args.mode,
|
|
164
|
+
...(args.perAPI
|
|
165
|
+
? {
|
|
166
|
+
perAPI: args.perAPI,
|
|
167
|
+
}
|
|
168
|
+
: {}),
|
|
169
|
+
};
|
|
170
|
+
const resolved = e.fsPicker.set(next);
|
|
171
|
+
const tokensEstimate = estimateTokens(JSON.stringify(resolved));
|
|
172
|
+
return {
|
|
173
|
+
content: [
|
|
174
|
+
{
|
|
175
|
+
type: "text",
|
|
176
|
+
text: JSON.stringify({ ok: true, session: e.id, policy: resolved, tokensEstimate }, null, 2),
|
|
177
|
+
},
|
|
178
|
+
],
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
catch (err) {
|
|
182
|
+
return {
|
|
183
|
+
content: [
|
|
184
|
+
{
|
|
185
|
+
type: "text",
|
|
186
|
+
text: JSON.stringify({ ok: false, error: err instanceof Error ? err.message : String(err) }, null, 2),
|
|
187
|
+
},
|
|
188
|
+
],
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
register("fs_picker_respond", {
|
|
193
|
+
capability: "file-io",
|
|
194
|
+
description: 'Stage agent-supplied files for the next File System Access picker call on this session — paired with `set_fs_picker_policy({mode:"allow"})` (or a `perAPI` override). The queue is per-API: a response staged for `showSaveFilePicker` won\'t satisfy a `showOpenFilePicker` call. Each file is either inline `{contents, name?, mimeType?}` (base64 — no filesystem read) or workspace-rooted `{path}` (resolved inside `$BROWX_WORKSPACE` only; path escape rejected). For `showSaveFilePicker`, the supplied `path` becomes the destination for `createWritable()`-driven writes from the page — `write()` / `truncate()` / `close()` from the page-side stream are persisted there. For `showOpenFilePicker`, the server reads `path` once at respond-time and inlines the bytes (the page reads via `getFile()`). Capability `file-io` — same posture as `upload_file`. Returns `{ok, session, queued:{api, fileCount}, tokensEstimate}`.',
|
|
195
|
+
inputSchema: {
|
|
196
|
+
api: z
|
|
197
|
+
.enum(SUPPORTED_FS_PICKER_APIS)
|
|
198
|
+
.describe("The picker API this response is for. Must match the call the page will make next."),
|
|
199
|
+
files: z
|
|
200
|
+
.array(z.object({
|
|
201
|
+
path: z
|
|
202
|
+
.string()
|
|
203
|
+
.optional()
|
|
204
|
+
.describe("Workspace-rooted file path. Mutually exclusive with `contents`. For save-pickers: write destination. For open-pickers: source file bytes are inlined at respond-time. For directory-picker: basename becomes the handle's `.name`."),
|
|
205
|
+
contents: z
|
|
206
|
+
.string()
|
|
207
|
+
.optional()
|
|
208
|
+
.describe("base64 file content. Mutually exclusive with `path`. Open-picker only — for save-pickers the writable stream needs a destination path, not source bytes."),
|
|
209
|
+
name: z
|
|
210
|
+
.string()
|
|
211
|
+
.optional()
|
|
212
|
+
.describe('Filename presented to the page when `contents` is used. Default `"browxai-virtual"`. Ignored when `path` is used (basename of `path` is taken).'),
|
|
213
|
+
mimeType: z
|
|
214
|
+
.string()
|
|
215
|
+
.optional()
|
|
216
|
+
.describe('MIME type for the synthetic `File` exposed to the page. Default `"application/octet-stream"`.'),
|
|
217
|
+
}))
|
|
218
|
+
.describe("Files to hand back to the page. `showSaveFilePicker` consumes only the first entry; `showOpenFilePicker` consumes all (the page sees an Array<FileSystemFileHandle>); `showDirectoryPicker` consumes only the first entry and reads its basename as the directory `.name`."),
|
|
219
|
+
...SESSION_ARG,
|
|
220
|
+
},
|
|
221
|
+
}, async (args) => {
|
|
222
|
+
const g = gateCheck("fs_picker_respond");
|
|
223
|
+
if (g)
|
|
224
|
+
return g;
|
|
225
|
+
const e = await entryFor(args.session);
|
|
226
|
+
try {
|
|
227
|
+
for (const f of args.files) {
|
|
228
|
+
if (f.path !== undefined && f.contents !== undefined) {
|
|
229
|
+
throw new Error("fs_picker_respond: each file must pass exactly one of `path` or `contents`");
|
|
230
|
+
}
|
|
231
|
+
if (f.path === undefined && f.contents === undefined) {
|
|
232
|
+
throw new Error("fs_picker_respond: each file must pass `path` or `contents`");
|
|
233
|
+
}
|
|
234
|
+
if (f.path !== undefined) {
|
|
235
|
+
// Validate workspace-rooted; throws on escape. The actual file
|
|
236
|
+
// I/O for save-picker writes happens later when the page calls
|
|
237
|
+
// `createWritable()`; for open-picker the read happens at the
|
|
238
|
+
// binding layer when the page calls `getFile()` (we inline at
|
|
239
|
+
// respond-time below).
|
|
240
|
+
resolveWorkspaceFsPath(workspace.root, f.path);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
// For open-pickers + showDirectoryPicker: when the agent supplied
|
|
244
|
+
// `{path}` (no inline contents), read the file once now and inline
|
|
245
|
+
// its bytes so the page-side `getFile()` resolves without another
|
|
246
|
+
// server round-trip. Save-pickers keep `path` as the WRITE target
|
|
247
|
+
// (no read).
|
|
248
|
+
const api = args.api;
|
|
249
|
+
const prepared = args.files.map((f) => {
|
|
250
|
+
if (api === "showSaveFilePicker")
|
|
251
|
+
return f;
|
|
252
|
+
if (f.path === undefined || f.contents !== undefined)
|
|
253
|
+
return f;
|
|
254
|
+
try {
|
|
255
|
+
const resolved = resolveWorkspaceFsPath(workspace.root, f.path);
|
|
256
|
+
const bytes = readFileSync(resolved);
|
|
257
|
+
return {
|
|
258
|
+
...f,
|
|
259
|
+
contents: bytes.toString("base64"),
|
|
260
|
+
name: f.name ?? pathBasename(resolved),
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
catch (err) {
|
|
264
|
+
throw new Error(`fs_picker_respond: failed to read \`path\` ${JSON.stringify(f.path)} — ${err instanceof Error ? err.message : String(err)}`);
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
e.fsPicker.pushResponse(api, prepared);
|
|
268
|
+
const body = {
|
|
269
|
+
ok: true,
|
|
270
|
+
session: e.id,
|
|
271
|
+
queued: { api, fileCount: prepared.length },
|
|
272
|
+
tokensEstimate: estimateTokens(JSON.stringify({ api, fileCount: prepared.length })),
|
|
273
|
+
};
|
|
274
|
+
return { content: [{ type: "text", text: JSON.stringify(body, null, 2) }] };
|
|
275
|
+
}
|
|
276
|
+
catch (err) {
|
|
277
|
+
return {
|
|
278
|
+
content: [
|
|
279
|
+
{
|
|
280
|
+
type: "text",
|
|
281
|
+
text: JSON.stringify({ ok: false, error: err instanceof Error ? err.message : String(err) }, null, 2),
|
|
282
|
+
},
|
|
283
|
+
],
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RegisterHost, SessionHost, ServerServicesHost } from "./host.js";
|
|
2
|
+
/**
|
|
3
|
+
* Session lifecycle tools: open_session / close_session / close_sessions /
|
|
4
|
+
* list_sessions. Split out of `session-policy-tools` by cohesive family (RFC 0004
|
|
5
|
+
* P3 / D3 SRP); registered through the shared `ToolHost` seam in the same source
|
|
6
|
+
* order. The host owns the closures (register / registry).
|
|
7
|
+
*/
|
|
8
|
+
export declare function registerSessionLifecycleTools(host: RegisterHost & SessionHost & ServerServicesHost): void;
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import { parseDialogPolicyArg } from "../session/dialog.js";
|
|
2
|
+
import { parsePermissionPolicyArg } from "../session/permission.js";
|
|
3
|
+
import { parseNotificationPolicyArg } from "../session/notification.js";
|
|
4
|
+
import { parseFsPickerPolicyArg } from "../session/fs-picker.js";
|
|
5
|
+
/** Wrap a JSON-serialisable body as a tool text response — the shared shape the
|
|
6
|
+
* session-lifecycle handlers return. */
|
|
7
|
+
function lifecycleJson(body) {
|
|
8
|
+
return { content: [{ type: "text", text: JSON.stringify(body, null, 2) }] };
|
|
9
|
+
}
|
|
10
|
+
/** The standard `ok:false` lifecycle envelope for an unknown throw — the message
|
|
11
|
+
* lifted from an Error or stringified. */
|
|
12
|
+
function lifecycleError(err) {
|
|
13
|
+
return lifecycleJson({ ok: false, error: err instanceof Error ? err.message : String(err) });
|
|
14
|
+
}
|
|
15
|
+
/** Parse the four optional policy args (throws on a malformed policy string — the
|
|
16
|
+
* handler's try/catch surfaces it as a structured `ok:false`). Byte-identical to
|
|
17
|
+
* the prior inline ternaries. */
|
|
18
|
+
function parseOpenSessionPolicies(args) {
|
|
19
|
+
return {
|
|
20
|
+
dialogPolicy: args.dialogPolicy ? parseDialogPolicyArg(args.dialogPolicy) : undefined,
|
|
21
|
+
permissionPolicy: args.permissionPolicy
|
|
22
|
+
? parsePermissionPolicyArg(args.permissionPolicy)
|
|
23
|
+
: undefined,
|
|
24
|
+
notificationPolicy: args.notificationPolicy
|
|
25
|
+
? parseNotificationPolicyArg(args.notificationPolicy)
|
|
26
|
+
: undefined,
|
|
27
|
+
fsPickerPolicy: args.fsPickerPolicy ? parseFsPickerPolicyArg(args.fsPickerPolicy) : undefined,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/** Build the optional `har` / `harsReplay` / `video` fields of the open_session
|
|
31
|
+
* result envelope from the opened entry. Pure; byte-identical to the prior inline
|
|
32
|
+
* ternaries. */
|
|
33
|
+
function buildOpenSessionResultFields(e, hars) {
|
|
34
|
+
const harField = e.har.path
|
|
35
|
+
? {
|
|
36
|
+
har: {
|
|
37
|
+
path: e.har.path,
|
|
38
|
+
mode: e.har.mode,
|
|
39
|
+
content: e.har.content,
|
|
40
|
+
nativeRecord: !!e.har.nativeRecord,
|
|
41
|
+
finalizesOn: "close_session",
|
|
42
|
+
},
|
|
43
|
+
}
|
|
44
|
+
: {};
|
|
45
|
+
const replayField = hars && hars.length ? { harsReplay: hars.length } : {};
|
|
46
|
+
const videoField = e.video.active && e.video.targetPath
|
|
47
|
+
? {
|
|
48
|
+
video: {
|
|
49
|
+
path: e.video.targetPath,
|
|
50
|
+
size: e.video.size,
|
|
51
|
+
finalizesOn: "close_session",
|
|
52
|
+
},
|
|
53
|
+
}
|
|
54
|
+
: {};
|
|
55
|
+
return { ...harField, ...replayField, ...videoField };
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Session lifecycle tools: open_session / close_session / close_sessions /
|
|
59
|
+
* list_sessions. Split out of `session-policy-tools` by cohesive family (RFC 0004
|
|
60
|
+
* P3 / D3 SRP); registered through the shared `ToolHost` seam in the same source
|
|
61
|
+
* order. The host owns the closures (register / registry).
|
|
62
|
+
*/
|
|
63
|
+
export function registerSessionLifecycleTools(host) {
|
|
64
|
+
const { z, register, registry } = host;
|
|
65
|
+
register("open_session", {
|
|
66
|
+
description: "Eagerly create an isolated session (own browser context / cookie jar / refs). Optional — any tool with a `session` arg lazily creates the id on first use (inheriting the server's launch mode); call this to launch up-front, fail fast, or pick a `mode`. Re-opening a live id is an error (close it first). Different ids = full isolation, so two sessions logged in as different users on the same app don't bleed. This is also the second half of wedged-session recovery: after `close_session` discards a dead session, open a fresh one here (a fresh id, or the same id reused) and restart the wedged work in it.\n\n`mode`:\n - `persistent` (default off-attach) — own profile dir under the workspace; cookies survive across runs. `profile` names the dir (default = the session id).\n - `incognito` — ephemeral; nothing persisted, all state discarded on close.\n - `attached` — BYOB; requires the server started with BROWX_ATTACH_CDP.\n\nOptionally seed the new context with a storage state at creation. `storageState` accepts either an inline blob (as returned by `dump_storage_state`) or a workspace-rooted JSON path. `authState` references a named slot from `auth_save`. Mutually exclusive. Native primitive on `incognito`; on `persistent` it post-seeds AND clears the profile's existing cookies/localStorage first (loud-warned). Ignored on `attached`.",
|
|
67
|
+
inputSchema: {
|
|
68
|
+
session: z.string().describe('Session id to create (e.g. "agent-a", "user-2").'),
|
|
69
|
+
mode: z
|
|
70
|
+
.enum(["persistent", "incognito", "attached"])
|
|
71
|
+
.optional()
|
|
72
|
+
.describe("Session mode. Default: the server's launch mode (attached if BROWX_ATTACH_CDP is set, else persistent)."),
|
|
73
|
+
profile: z
|
|
74
|
+
.string()
|
|
75
|
+
.optional()
|
|
76
|
+
.describe("persistent mode only: named profile dir under <workspace>/profiles/. Default = the session id. Lets two ids share a profile, or one id pin a stable profile name."),
|
|
77
|
+
device: z
|
|
78
|
+
.string()
|
|
79
|
+
.optional()
|
|
80
|
+
.describe('Playwright device-preset name (e.g. "iPhone 14", "Pixel 7", "Desktop Chrome") → viewport + DPR + isMobile + hasTouch + UA. Falls back to config `defaultDevice`. Best-effort on `attached`.'),
|
|
81
|
+
viewport: z
|
|
82
|
+
.object({ width: z.number().int().positive(), height: z.number().int().positive() })
|
|
83
|
+
.optional()
|
|
84
|
+
.describe("explicit viewport; overrides a preset's viewport. Falls back to config `defaultViewport`."),
|
|
85
|
+
dialogPolicy: z
|
|
86
|
+
.string()
|
|
87
|
+
.optional()
|
|
88
|
+
.describe('How the session handles `alert`/`confirm`/`prompt` dialogs. One of: "accept" (auto-OK), "dismiss" (auto-cancel), "accept-prompt-with:<text>" (prompts answered with `<text>`; alert/confirm accepted), "raise" (DEFAULT — dialog dismissed server-side so the page never deadlocks, but the next action returns ok:false with a structured failure so a dialog never silently changes app state under an unaware caller). Mutate at runtime with `set_dialog_policy`.'),
|
|
89
|
+
permissionPolicy: z
|
|
90
|
+
.union([
|
|
91
|
+
z.string(),
|
|
92
|
+
z.object({
|
|
93
|
+
mode: z.enum(["allow", "deny", "raise", "ask-human"]),
|
|
94
|
+
perPermission: z.record(z.enum(["allow", "deny", "raise", "ask-human"])).optional(),
|
|
95
|
+
}),
|
|
96
|
+
])
|
|
97
|
+
.optional()
|
|
98
|
+
.describe('How the session handles page-side permission requests (camera, microphone, geolocation, notifications, clipboard, sensors). String form sets the top-level mode ("allow"|"deny"|"raise"|"ask-human"); object form takes `{mode, perPermission?:{<name>:<mode>}}` for per-permission overrides. DEFAULT "raise" — request rejected page-side so the page never deadlocks, but the next action returns ok:false with a structured failure so a permission request never silently changes app state under an unaware caller. Mutate at runtime with `set_permission_policy`. NOTE: governs the *permission check* (`Notification.requestPermission`) only — the `new Notification(...)` constructor surface is governed separately by `notificationPolicy`.'),
|
|
99
|
+
notificationPolicy: z
|
|
100
|
+
.union([z.string(), z.object({ mode: z.enum(["allow", "deny", "raise", "ask-human"]) })])
|
|
101
|
+
.optional()
|
|
102
|
+
.describe('How the session handles `new Notification(title, opts)` constructor calls. String form sets the mode; object form is `{mode}`. Modes mirror permissionPolicy. DEFAULT "allow" (browser default — constructor proceeds, OS displays per its settings) — but every call is still captured on `ActionResult.notifications[]` for observability. Distinct from `permissionPolicy.notifications` (which gates the W3C permission check); the two policies compose. Mutate at runtime with `set_notification_policy`.'),
|
|
103
|
+
fsPickerPolicy: z
|
|
104
|
+
.union([
|
|
105
|
+
z.string(),
|
|
106
|
+
z.object({
|
|
107
|
+
mode: z.enum(["allow", "deny", "raise", "ask-human"]),
|
|
108
|
+
perAPI: z.record(z.enum(["allow", "deny", "raise", "ask-human"])).optional(),
|
|
109
|
+
}),
|
|
110
|
+
])
|
|
111
|
+
.optional()
|
|
112
|
+
.describe('How the session handles page-side File System Access picker calls (showOpenFilePicker, showSaveFilePicker, showDirectoryPicker). String form sets the top-level mode ("allow"|"deny"|"raise"|"ask-human"); object form takes `{mode, perAPI?:{<api>:<mode>}}` for per-API overrides. DEFAULT "raise" — picker rejected page-side so the page never deadlocks, but the next action returns ok:false with a structured failure so a picker call never silently changes app state under an unaware caller. Pair `allow` with `fs_picker_respond` to stage agent-supplied files. Mutate at runtime with `set_fs_picker_policy`.'),
|
|
113
|
+
storageState: z
|
|
114
|
+
.union([
|
|
115
|
+
z.string(),
|
|
116
|
+
z
|
|
117
|
+
.object({
|
|
118
|
+
cookies: z.array(z.any()),
|
|
119
|
+
origins: z.array(z.any()),
|
|
120
|
+
})
|
|
121
|
+
.passthrough(),
|
|
122
|
+
])
|
|
123
|
+
.optional()
|
|
124
|
+
.describe("Bulk-seed: inline state blob (`{cookies, origins}` from dump_storage_state) OR a workspace-rooted JSON path. Mutually exclusive with `authState`. Native on incognito; on persistent it post-seeds AND clears the profile (loud-warned); ignored on attached."),
|
|
125
|
+
authState: z
|
|
126
|
+
.string()
|
|
127
|
+
.optional()
|
|
128
|
+
.describe("Named-state seed: load a slot from `$BROWX_WORKSPACE/.auth-states/<name>.json` (written by `auth_save`). Mutually exclusive with `storageState`."),
|
|
129
|
+
har: z
|
|
130
|
+
.object({
|
|
131
|
+
path: z
|
|
132
|
+
.string()
|
|
133
|
+
.optional()
|
|
134
|
+
.describe("Workspace-rooted HAR file path. Default: `<workspace>/har/<session-id>-<ISO>.har`. Path traversal outside `$BROWX_WORKSPACE` is rejected."),
|
|
135
|
+
mode: z
|
|
136
|
+
.enum(["full", "minimal"])
|
|
137
|
+
.optional()
|
|
138
|
+
.describe("`full` (default — full HAR with sizes/timing/cookies) or `minimal` (just enough to replay via `routeFromHAR`)."),
|
|
139
|
+
content: z
|
|
140
|
+
.enum(["embed", "attach", "omit"])
|
|
141
|
+
.optional()
|
|
142
|
+
.describe("Body persistence: `embed` (default for `.har`) inlines bodies, `attach` writes sidecar files (default for `.zip`), `omit` drops bodies."),
|
|
143
|
+
urlFilter: z
|
|
144
|
+
.string()
|
|
145
|
+
.optional()
|
|
146
|
+
.describe("Optional glob/regex URL filter — only matching requests are stored."),
|
|
147
|
+
})
|
|
148
|
+
.optional()
|
|
149
|
+
.describe("Record HAR for the lifetime of this session via Playwright's native `recordHar` context option. The file is finalized when the session closes (Playwright constraint — there is no mid-session flush on the native path). For runtime start/stop granularity use the `start_har`/`stop_har` tools instead. Honoured on `persistent` + `incognito` (we own the context); ignored on `attached` (consumer's Chrome is not-owned)."),
|
|
150
|
+
hars: z
|
|
151
|
+
.array(z.string())
|
|
152
|
+
.optional()
|
|
153
|
+
.describe('REPLAY HAR file(s) — workspace-rooted paths. Each is wired via `context.routeFromHAR(file, {notFound:"fallback"})` immediately after context creation: requests in the archive are served from it, anything missing falls through to the live network. Path traversal rejected; a missing file errors (no silent fallback on a typo). Compose multiple HARs to layer fixtures.'),
|
|
154
|
+
recordVideo: z
|
|
155
|
+
.object({
|
|
156
|
+
path: z
|
|
157
|
+
.string()
|
|
158
|
+
.optional()
|
|
159
|
+
.describe("Workspace-rooted .webm file path. Default: `<workspace>/videos/<session-id>-<ISO>.webm`. Path traversal outside `$BROWX_WORKSPACE` is rejected."),
|
|
160
|
+
size: z
|
|
161
|
+
.object({ width: z.number().int().positive(), height: z.number().int().positive() })
|
|
162
|
+
.optional()
|
|
163
|
+
.describe("Recorded video frame size. Defaults to the viewport scaled to fit 800x800 (Playwright default)."),
|
|
164
|
+
})
|
|
165
|
+
.optional()
|
|
166
|
+
.describe("Record session video for the lifetime of this session via Playwright's native `recordVideo` context option. The .webm is finalized when the session closes (Playwright constraint — there is no mid-context flush). `stop_video` signals intent + reserves the target path; `get_video` reads the file after `close_session`. Honoured on `persistent` + `incognito` (we own the context); refused on `attached` (consumer's Chrome is not-owned). Capability `file-io` on the stop/get tools."),
|
|
167
|
+
},
|
|
168
|
+
}, async ({ session, mode, profile, device, viewport, dialogPolicy, permissionPolicy, notificationPolicy, fsPickerPolicy, storageState, authState, har, hars, recordVideo, }) => {
|
|
169
|
+
if (registry.has(session)) {
|
|
170
|
+
return lifecycleJson({
|
|
171
|
+
ok: false,
|
|
172
|
+
error: `session "${session}" already open; close_session first`,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
let policies;
|
|
176
|
+
try {
|
|
177
|
+
policies = parseOpenSessionPolicies({
|
|
178
|
+
dialogPolicy,
|
|
179
|
+
permissionPolicy,
|
|
180
|
+
notificationPolicy,
|
|
181
|
+
fsPickerPolicy,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
catch (err) {
|
|
185
|
+
return lifecycleError(err);
|
|
186
|
+
}
|
|
187
|
+
try {
|
|
188
|
+
const e = await registry.get(session, {
|
|
189
|
+
mode,
|
|
190
|
+
profile,
|
|
191
|
+
device,
|
|
192
|
+
viewport,
|
|
193
|
+
dialogPolicy: policies.dialogPolicy,
|
|
194
|
+
permissionPolicy: policies.permissionPolicy,
|
|
195
|
+
notificationPolicy: policies.notificationPolicy,
|
|
196
|
+
fsPickerPolicy: policies.fsPickerPolicy,
|
|
197
|
+
storageState,
|
|
198
|
+
authState,
|
|
199
|
+
har: har,
|
|
200
|
+
hars,
|
|
201
|
+
recordVideo: recordVideo,
|
|
202
|
+
});
|
|
203
|
+
// safari has no Playwright Page — read the opened URL from its WebDriver
|
|
204
|
+
// Classic client instead.
|
|
205
|
+
const safariOpened = e.session.safari?.();
|
|
206
|
+
const openedUrl = safariOpened
|
|
207
|
+
? await safariOpened.webDriver.currentUrl(safariOpened.sessionId).catch(() => "")
|
|
208
|
+
: e.session.page().url();
|
|
209
|
+
return lifecycleJson({
|
|
210
|
+
ok: true,
|
|
211
|
+
session: e.id,
|
|
212
|
+
mode: e.mode,
|
|
213
|
+
url: openedUrl,
|
|
214
|
+
openedAt: new Date(e.openedAt).toISOString(),
|
|
215
|
+
...buildOpenSessionResultFields(e, hars),
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
catch (err) {
|
|
219
|
+
return lifecycleError(err);
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
register("close_session", {
|
|
223
|
+
description: "Tear down a session: detaches the bridge and closes the browser context (a BYOB/attached session detaches only — never closes the user's Chrome). The \"default\" session may be closed too; it'll be lazily re-created on the next call. No-op-safe. This is also the RECOVERY path for a wedged session: when calls time out repeatedly (a `sessionWedged` result, or snapshot/navigate/screenshot all timing out), close the session and `open_session` a fresh one — a wedged session is NOT recoverable in place by re-navigating or retrying.",
|
|
224
|
+
inputSchema: { session: z.string().describe("Session id to close.") },
|
|
225
|
+
}, async ({ session }) => {
|
|
226
|
+
const closed = await registry.close(session);
|
|
227
|
+
// Diagnostics JSONL is intentionally KEPT across close_session — the
|
|
228
|
+
// recovery path for a (real OR falsely-flagged) wedge IS close_session,
|
|
229
|
+
// and the notes / calls filed right before the close are the most
|
|
230
|
+
// valuable feedback the curator gets. Retention sweep (default 30d)
|
|
231
|
+
// handles long-term cleanup; per-session removal is the wrong scope.
|
|
232
|
+
return {
|
|
233
|
+
content: [
|
|
234
|
+
{
|
|
235
|
+
type: "text",
|
|
236
|
+
text: JSON.stringify({ ok: true, session, wasOpen: closed }, null, 2),
|
|
237
|
+
},
|
|
238
|
+
],
|
|
239
|
+
};
|
|
240
|
+
});
|
|
241
|
+
register("close_sessions", {
|
|
242
|
+
description: "Bulk session teardown for multi-agent cleanup. Select by `prefix` (id starts-with — e.g. one agent's `agentA-*`), `all`, and/or `idleMs` (no use in the last N ms). Filters AND together; at least one selector is required (`all:true` to close everything). Returns the closed ids. Use to reclaim memory + state when a sub-agent wedged or was killed and stranded its sessions.",
|
|
243
|
+
inputSchema: {
|
|
244
|
+
prefix: z.string().optional().describe("Close sessions whose id starts with this."),
|
|
245
|
+
all: z
|
|
246
|
+
.boolean()
|
|
247
|
+
.optional()
|
|
248
|
+
.describe("Close every live session. Required if neither prefix nor idleMs is given."),
|
|
249
|
+
idleMs: z
|
|
250
|
+
.number()
|
|
251
|
+
.int()
|
|
252
|
+
.positive()
|
|
253
|
+
.optional()
|
|
254
|
+
.describe("Close sessions with no activity in the last N ms (idle-age reap)."),
|
|
255
|
+
},
|
|
256
|
+
}, async ({ prefix, all, idleMs }) => {
|
|
257
|
+
if (prefix === undefined && idleMs === undefined && all !== true) {
|
|
258
|
+
return {
|
|
259
|
+
content: [
|
|
260
|
+
{
|
|
261
|
+
type: "text",
|
|
262
|
+
text: JSON.stringify({
|
|
263
|
+
ok: false,
|
|
264
|
+
error: "close_sessions: pass `prefix`, `idleMs`, and/or `all:true` — refusing to close nothing/everything implicitly",
|
|
265
|
+
}, null, 2),
|
|
266
|
+
},
|
|
267
|
+
],
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
const closed = await registry.closeMatching({ prefix, all, idleMs });
|
|
271
|
+
// Diagnostics JSONL is intentionally KEPT across session teardown —
|
|
272
|
+
// notes filed pre-close are exactly the valuable feedback. Retention
|
|
273
|
+
// sweep (default 30d) handles long-term cleanup.
|
|
274
|
+
return {
|
|
275
|
+
content: [
|
|
276
|
+
{
|
|
277
|
+
type: "text",
|
|
278
|
+
text: JSON.stringify({ ok: true, closed, count: closed.length }, null, 2),
|
|
279
|
+
},
|
|
280
|
+
],
|
|
281
|
+
};
|
|
282
|
+
});
|
|
283
|
+
register("list_sessions", {
|
|
284
|
+
batchable: true,
|
|
285
|
+
description: "List live sessions: id, mode, engine, current url, page count, openedAt. Audit / coordination helper for multi-session work.",
|
|
286
|
+
inputSchema: {},
|
|
287
|
+
}, async () => {
|
|
288
|
+
const rows = registry.list().map((e) => ({
|
|
289
|
+
id: e.id,
|
|
290
|
+
mode: e.mode,
|
|
291
|
+
engine: e.session.engine,
|
|
292
|
+
url: (() => {
|
|
293
|
+
try {
|
|
294
|
+
return e.session.page().url();
|
|
295
|
+
}
|
|
296
|
+
catch {
|
|
297
|
+
return null;
|
|
298
|
+
}
|
|
299
|
+
})(),
|
|
300
|
+
pages: (() => {
|
|
301
|
+
try {
|
|
302
|
+
return e.session.page().context().pages().length;
|
|
303
|
+
}
|
|
304
|
+
catch {
|
|
305
|
+
return null;
|
|
306
|
+
}
|
|
307
|
+
})(),
|
|
308
|
+
openedAt: new Date(e.openedAt).toISOString(),
|
|
309
|
+
}));
|
|
310
|
+
return {
|
|
311
|
+
content: [{ type: "text", text: JSON.stringify({ sessions: rows }, null, 2) }],
|
|
312
|
+
};
|
|
313
|
+
});
|
|
314
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { RegisterHost, GateHost, SessionHost, ServerServicesHost } from "./host.js";
|
|
2
|
+
/**
|
|
3
|
+
* Permission-state read + notification policy + device-request read tools:
|
|
4
|
+
* permission_state / set_notification_policy / device_requests. Split out of
|
|
5
|
+
* `session-policy-tools` by cohesive family (RFC 0004 P3 / D3 SRP); registered
|
|
6
|
+
* through the shared `ToolHost` seam in the same source order. The host owns the
|
|
7
|
+
* closures (register / gate / entry).
|
|
8
|
+
*/
|
|
9
|
+
export declare function registerSessionNotificationDeviceTools(host: RegisterHost & GateHost & SessionHost & ServerServicesHost): void;
|