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,402 @@
|
|
|
1
|
+
// Plugin runtime — the orchestrator the server invokes at start.
|
|
2
|
+
//
|
|
3
|
+
// Flow:
|
|
4
|
+
// 1. Read `<workspace>/plugins.json` for the declared set.
|
|
5
|
+
// 2. Resolve each declared plugin's manifest off disk.
|
|
6
|
+
// 3. Validate namespaces: globally unique + non-reserved.
|
|
7
|
+
// 4. Validate apiVersion: each plugin's apiVersion must be compatible
|
|
8
|
+
// with this runtime's RUNTIME_API_VERSION.
|
|
9
|
+
// 5. Validate dependsOn target exists + satisfies semver range.
|
|
10
|
+
// 6. Build dep graph; reject cycles loudly (server start fails).
|
|
11
|
+
// 7. Topo-sort load order.
|
|
12
|
+
// 8. For each plugin: check declared capabilities ⊆ enabled set;
|
|
13
|
+
// on mismatch, mark plugin disabled-by-capability-mismatch and
|
|
14
|
+
// skip without aborting server start.
|
|
15
|
+
// 9. Dynamic-import the entry module; call register(api).
|
|
16
|
+
// 10. Per-tool: gate behind the capability the plugin declared; route
|
|
17
|
+
// through the host's existing capability gate at dispatch.
|
|
18
|
+
//
|
|
19
|
+
// In-process JS modules only (v1). No out-of-process plugin processes.
|
|
20
|
+
// Resolved-once-at-server-start. No hot reload — restart is the contract.
|
|
21
|
+
import { pathToFileURL } from "node:url";
|
|
22
|
+
import { log } from "../util/logging.js";
|
|
23
|
+
import { PACKAGE_VERSION } from "../util/version.js";
|
|
24
|
+
import { isApiVersionCompatible, RUNTIME_API_VERSION, satisfiesRange } from "./manifest.js";
|
|
25
|
+
import { pluginPaths, readDeclaration, resolveDeclaredPlugin, } from "./resolver.js";
|
|
26
|
+
import { buildDepGraph, DepGraphCycleError } from "./depgraph.js";
|
|
27
|
+
/** Error code emitted when a plugin's `api.callTool` violates the call graph. */
|
|
28
|
+
export const PLUGIN_CALL_GRAPH_VIOLATION = "plugin-call-graph-violation";
|
|
29
|
+
/**
|
|
30
|
+
* Top-level entry point: read the declaration, resolve manifests,
|
|
31
|
+
* validate the graph, load each plugin in dep-order.
|
|
32
|
+
*
|
|
33
|
+
* Throws ONLY on cycle errors (server start aborts — the contract). All
|
|
34
|
+
* other failures (capability mismatch, missing dep, validation error,
|
|
35
|
+
* load-time exception) downgrade the affected plugin to a non-loaded
|
|
36
|
+
* status and continue.
|
|
37
|
+
*/
|
|
38
|
+
export async function startPluginRuntime(opts) {
|
|
39
|
+
const paths = pluginPaths(opts.workspaceRoot);
|
|
40
|
+
const fromFile = readDeclaration(paths).filter((d) => d.enabled);
|
|
41
|
+
// Union with any plugins declared via the config store. The config
|
|
42
|
+
// store entry is a simple `string[]` (npm names) — file entries (which
|
|
43
|
+
// can also carry a per-entry trust override) take precedence on name
|
|
44
|
+
// collision.
|
|
45
|
+
const known = new Set(fromFile.map((d) => d.name));
|
|
46
|
+
const merged = [...fromFile];
|
|
47
|
+
for (const name of opts.extraDeclared ?? []) {
|
|
48
|
+
if (!known.has(name)) {
|
|
49
|
+
merged.push({ name, enabled: true });
|
|
50
|
+
known.add(name);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const declared = merged;
|
|
54
|
+
if (declared.length === 0) {
|
|
55
|
+
log.info("plugin runtime: no plugins declared", { declarationFile: paths.declarationFile });
|
|
56
|
+
return { plugins: [], toolCount: 0 };
|
|
57
|
+
}
|
|
58
|
+
// Stage 1: resolve manifests.
|
|
59
|
+
const resolved = new Map();
|
|
60
|
+
for (const decl of declared) {
|
|
61
|
+
resolved.set(decl.name, resolveDeclaredPlugin(paths, decl));
|
|
62
|
+
}
|
|
63
|
+
// Stage 2: filter to fully-resolved + validate namespace uniqueness +
|
|
64
|
+
// apiVersion + dep targets. Anything that fails is downgraded to a
|
|
65
|
+
// load-error record we'll surface at the end.
|
|
66
|
+
const earlyDisabled = [];
|
|
67
|
+
const validResolved = new Map();
|
|
68
|
+
const declaredAt = new Date().toISOString();
|
|
69
|
+
for (const [name, res] of resolved) {
|
|
70
|
+
if (res.kind === "not-installed") {
|
|
71
|
+
earlyDisabled.push({
|
|
72
|
+
manifest: {
|
|
73
|
+
name,
|
|
74
|
+
version: "0.0.0",
|
|
75
|
+
path: "",
|
|
76
|
+
entryPath: "",
|
|
77
|
+
trust: "community",
|
|
78
|
+
browxai: {
|
|
79
|
+
apiVersion: "",
|
|
80
|
+
namespace: "",
|
|
81
|
+
register: "",
|
|
82
|
+
capabilities: [],
|
|
83
|
+
dependsOn: [],
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
status: "load-error",
|
|
87
|
+
tools: [],
|
|
88
|
+
transitiveDeps: [],
|
|
89
|
+
statusReason: `not installed under ${paths.nodeModulesDir}/${name}/. Run \`browxai plugin install ${name}\` (or \`browxai plugin sync\` if the declaration was hand-edited).`,
|
|
90
|
+
declaredCapabilities: [],
|
|
91
|
+
declaredAt,
|
|
92
|
+
});
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
if (res.kind === "invalid-manifest") {
|
|
96
|
+
earlyDisabled.push({
|
|
97
|
+
manifest: {
|
|
98
|
+
name,
|
|
99
|
+
version: "0.0.0",
|
|
100
|
+
path: "",
|
|
101
|
+
entryPath: "",
|
|
102
|
+
trust: "community",
|
|
103
|
+
browxai: {
|
|
104
|
+
apiVersion: "",
|
|
105
|
+
namespace: "",
|
|
106
|
+
register: "",
|
|
107
|
+
capabilities: [],
|
|
108
|
+
dependsOn: [],
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
status: "load-error",
|
|
112
|
+
tools: [],
|
|
113
|
+
transitiveDeps: [],
|
|
114
|
+
statusReason: `invalid plugin manifest: ${res.error}`,
|
|
115
|
+
declaredCapabilities: [],
|
|
116
|
+
declaredAt,
|
|
117
|
+
});
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
validResolved.set(name, res.manifest);
|
|
121
|
+
}
|
|
122
|
+
// browxaiVersion advisory. The manifest field is the host range the
|
|
123
|
+
// plugin was tested against — a mismatch NEVER rejects loading (a
|
|
124
|
+
// conservative range must not lock out a known-good host that already
|
|
125
|
+
// shipped), but it warns loudly so the operator knows the combination
|
|
126
|
+
// is untested.
|
|
127
|
+
for (const [name, m] of validResolved) {
|
|
128
|
+
const range = m.browxai.browxaiVersion;
|
|
129
|
+
if (range && !satisfiesRange(PACKAGE_VERSION, range)) {
|
|
130
|
+
log.warn(`plugin runtime: ${name} was tested against browxai "${range}" but this host is ${PACKAGE_VERSION} — ` +
|
|
131
|
+
`untested combination (advisory only; the plugin still loads). ` +
|
|
132
|
+
`Upgrade the plugin or widen its browxaiVersion range.`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// apiVersion check.
|
|
136
|
+
const apiVersionFail = [];
|
|
137
|
+
for (const [name, m] of validResolved) {
|
|
138
|
+
if (!isApiVersionCompatible(m.browxai.apiVersion, RUNTIME_API_VERSION)) {
|
|
139
|
+
apiVersionFail.push(name);
|
|
140
|
+
earlyDisabled.push({
|
|
141
|
+
manifest: m,
|
|
142
|
+
status: "load-error",
|
|
143
|
+
tools: [],
|
|
144
|
+
transitiveDeps: [],
|
|
145
|
+
statusReason: `plugin apiVersion "${m.browxai.apiVersion}" is incompatible with the host runtime apiVersion "${RUNTIME_API_VERSION}". ` +
|
|
146
|
+
`Upgrade the plugin (or pin a host browxai version compatible with the plugin's runtime contract).`,
|
|
147
|
+
declaredCapabilities: m.browxai.capabilities,
|
|
148
|
+
declaredAt,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
for (const n of apiVersionFail)
|
|
153
|
+
validResolved.delete(n);
|
|
154
|
+
// Namespace uniqueness.
|
|
155
|
+
const namespaceOwner = new Map();
|
|
156
|
+
const namespaceConflicts = [];
|
|
157
|
+
for (const [name, m] of validResolved) {
|
|
158
|
+
const ns = m.browxai.namespace;
|
|
159
|
+
const prior = namespaceOwner.get(ns);
|
|
160
|
+
if (prior) {
|
|
161
|
+
namespaceConflicts.push(name);
|
|
162
|
+
earlyDisabled.push({
|
|
163
|
+
manifest: m,
|
|
164
|
+
status: "disabled-by-namespace-conflict",
|
|
165
|
+
tools: [],
|
|
166
|
+
transitiveDeps: [],
|
|
167
|
+
statusReason: `namespace "${ns}" is already claimed by plugin "${prior}". Two plugins cannot share a namespace; rename one.`,
|
|
168
|
+
declaredCapabilities: m.browxai.capabilities,
|
|
169
|
+
declaredAt,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
namespaceOwner.set(ns, name);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
for (const n of namespaceConflicts)
|
|
177
|
+
validResolved.delete(n);
|
|
178
|
+
// dependsOn target + version-range check.
|
|
179
|
+
const depFail = new Map();
|
|
180
|
+
for (const [name, m] of validResolved) {
|
|
181
|
+
for (const dep of m.browxai.dependsOn) {
|
|
182
|
+
const target = validResolved.get(dep.plugin);
|
|
183
|
+
if (!target) {
|
|
184
|
+
depFail.set(name, `dependsOn["${dep.plugin}"] not loaded — install or enable it.`);
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
if (!satisfiesRange(target.version, dep.version)) {
|
|
188
|
+
depFail.set(name, `dependsOn["${dep.plugin}"] installed version ${target.version} does not satisfy range "${dep.version}".`);
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
for (const [name, reason] of depFail) {
|
|
194
|
+
const m = validResolved.get(name);
|
|
195
|
+
earlyDisabled.push({
|
|
196
|
+
manifest: m,
|
|
197
|
+
status: "disabled-by-dep-missing",
|
|
198
|
+
tools: [],
|
|
199
|
+
transitiveDeps: [],
|
|
200
|
+
statusReason: reason,
|
|
201
|
+
declaredCapabilities: m.browxai.capabilities,
|
|
202
|
+
declaredAt,
|
|
203
|
+
});
|
|
204
|
+
validResolved.delete(name);
|
|
205
|
+
}
|
|
206
|
+
// Stage 3: build dep graph. Cycles abort startup loudly.
|
|
207
|
+
const directDeps = new Map();
|
|
208
|
+
for (const [name, m] of validResolved) {
|
|
209
|
+
directDeps.set(name, m.browxai.dependsOn.map((d) => d.plugin));
|
|
210
|
+
}
|
|
211
|
+
let depResult;
|
|
212
|
+
try {
|
|
213
|
+
depResult = buildDepGraph({ directDeps });
|
|
214
|
+
}
|
|
215
|
+
catch (e) {
|
|
216
|
+
if (e instanceof DepGraphCycleError) {
|
|
217
|
+
// Surface every cycle plugin explicitly so the operator sees the
|
|
218
|
+
// shape of the cycle, then re-throw with the structured error.
|
|
219
|
+
for (const c of e.cycles) {
|
|
220
|
+
log.error(`plugin runtime: cycle ${c.join(" → ")} → ${c[0]}`);
|
|
221
|
+
}
|
|
222
|
+
throw e;
|
|
223
|
+
}
|
|
224
|
+
throw e;
|
|
225
|
+
}
|
|
226
|
+
// Stage 4: capability subset check. Mismatched plugins get a
|
|
227
|
+
// disabled-by-capability-mismatch record + skipped.
|
|
228
|
+
const capFail = new Map();
|
|
229
|
+
for (const [name, m] of validResolved) {
|
|
230
|
+
const missing = m.browxai.capabilities.filter((c) => !opts.enabledCapabilities.has(c));
|
|
231
|
+
if (missing.length > 0) {
|
|
232
|
+
capFail.set(name, `plugin declares capabilities [${missing.join(", ")}] not enabled on this server. ` +
|
|
233
|
+
`Add them to BROWX_CAPABILITIES (or set_config({capabilities:[...]})) and RESTART. ` +
|
|
234
|
+
`Capabilities are resolved ONCE at server start — set_config alone won't enable a plugin's gate.`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// Stage 5: load each plugin in dep-order.
|
|
238
|
+
// Note: skipped (capability-mismatched) plugins still consume their slot
|
|
239
|
+
// in the order — their dependents will fail later if they actually call
|
|
240
|
+
// a tool the skipped plugin owns, but the LOAD itself doesn't fail.
|
|
241
|
+
const records = [];
|
|
242
|
+
const liveTools = new Map();
|
|
243
|
+
let toolCount = 0;
|
|
244
|
+
const transitiveDeps = depResult.transitiveDeps;
|
|
245
|
+
const ownerOf = (toolName) => {
|
|
246
|
+
const t = liveTools.get(toolName);
|
|
247
|
+
if (t)
|
|
248
|
+
return t.ownerPlugin;
|
|
249
|
+
return opts.host.ownerOf(toolName);
|
|
250
|
+
};
|
|
251
|
+
for (const name of depResult.loadOrder) {
|
|
252
|
+
const m = validResolved.get(name);
|
|
253
|
+
const reason = capFail.get(name);
|
|
254
|
+
if (reason) {
|
|
255
|
+
records.push({
|
|
256
|
+
manifest: m,
|
|
257
|
+
status: "disabled-by-capability-mismatch",
|
|
258
|
+
tools: [],
|
|
259
|
+
transitiveDeps: [...(transitiveDeps.get(name) ?? new Set())],
|
|
260
|
+
statusReason: reason,
|
|
261
|
+
declaredCapabilities: m.browxai.capabilities,
|
|
262
|
+
declaredAt,
|
|
263
|
+
});
|
|
264
|
+
log.warn(`plugin runtime: ${name} disabled — ${reason}`);
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
const myToolNames = [];
|
|
268
|
+
const myDeps = transitiveDeps.get(name) ?? new Set();
|
|
269
|
+
const callTool = async (targetName, args) => {
|
|
270
|
+
// Core tools: always allowed (implicit-root).
|
|
271
|
+
if (opts.host.isCoreTool(targetName)) {
|
|
272
|
+
return opts.host.dispatch(targetName, args ?? {});
|
|
273
|
+
}
|
|
274
|
+
const targetOwner = ownerOf(targetName);
|
|
275
|
+
if (!targetOwner) {
|
|
276
|
+
return {
|
|
277
|
+
content: [
|
|
278
|
+
{
|
|
279
|
+
type: "text",
|
|
280
|
+
text: JSON.stringify({
|
|
281
|
+
ok: false,
|
|
282
|
+
error: `plugin "${name}" tried to call unknown tool "${targetName}"`,
|
|
283
|
+
code: PLUGIN_CALL_GRAPH_VIOLATION,
|
|
284
|
+
fromPlugin: name,
|
|
285
|
+
targetTool: targetName,
|
|
286
|
+
}, null, 2),
|
|
287
|
+
},
|
|
288
|
+
],
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
// Owner-call: a plugin may always call its own tools.
|
|
292
|
+
if (targetOwner === name) {
|
|
293
|
+
return opts.host.dispatch(targetName, args ?? {});
|
|
294
|
+
}
|
|
295
|
+
// Declared-graph check.
|
|
296
|
+
if (!myDeps.has(targetOwner)) {
|
|
297
|
+
return {
|
|
298
|
+
content: [
|
|
299
|
+
{
|
|
300
|
+
type: "text",
|
|
301
|
+
text: JSON.stringify({
|
|
302
|
+
ok: false,
|
|
303
|
+
error: `plugin call-graph violation: ${name} tried to call ${targetOwner}.${targetName.slice(targetName.indexOf(".") + 1)} but did not declare ${targetOwner} in dependsOn`,
|
|
304
|
+
code: PLUGIN_CALL_GRAPH_VIOLATION,
|
|
305
|
+
fromPlugin: name,
|
|
306
|
+
targetPlugin: targetOwner,
|
|
307
|
+
targetTool: targetName,
|
|
308
|
+
declaredDeps: [...myDeps].sort(),
|
|
309
|
+
hint: `Add { "plugin": "${targetOwner}", "version": "^${(validResolved.get(targetOwner) ?? { version: "0.0.0" }).version}" } to ` +
|
|
310
|
+
`the "dependsOn" array in this plugin's package.json#browxai field, reinstall (pnpm install in the plugin's repo), and restart the browxai server.`,
|
|
311
|
+
}, null, 2),
|
|
312
|
+
},
|
|
313
|
+
],
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
return opts.host.dispatch(targetName, args ?? {});
|
|
317
|
+
};
|
|
318
|
+
const api = {
|
|
319
|
+
namespace: m.browxai.namespace,
|
|
320
|
+
declaredCapabilities: m.browxai.capabilities,
|
|
321
|
+
registerTool: (toolName, def, handler) => {
|
|
322
|
+
if (!toolName.startsWith(`${m.browxai.namespace}.`)) {
|
|
323
|
+
throw new Error(`plugin "${name}": tool "${toolName}" must be prefixed with "${m.browxai.namespace}." — namespace prefix is mandatory. ` +
|
|
324
|
+
`Plugins cannot override or wrap core browxai tools.`);
|
|
325
|
+
}
|
|
326
|
+
if (toolName === `${m.browxai.namespace}.`) {
|
|
327
|
+
throw new Error(`plugin "${name}": tool name has empty suffix after the namespace — pass a real tool name like "${m.browxai.namespace}.do_thing".`);
|
|
328
|
+
}
|
|
329
|
+
if (liveTools.has(toolName) || opts.host.isCoreTool(toolName)) {
|
|
330
|
+
throw new Error(`plugin "${name}": tool "${toolName}" is already registered. Tool names are globally unique.`);
|
|
331
|
+
}
|
|
332
|
+
// The plugin's capability is the gate for ALL its tools. The
|
|
333
|
+
// simple v1 contract — fine-grained per-tool capabilities can
|
|
334
|
+
// be layered on top later without breaking this signature.
|
|
335
|
+
// If the plugin declared more than one capability, the gate is
|
|
336
|
+
// the FIRST one (semantic: "this tool needs at least these
|
|
337
|
+
// caps"; declaring multiple is an additive claim). We pass it
|
|
338
|
+
// through to the host's gate so an MCP call against the tool
|
|
339
|
+
// refuses cleanly when the capability isn't on.
|
|
340
|
+
const cap = m.browxai.capabilities[0];
|
|
341
|
+
const record = {
|
|
342
|
+
name: toolName,
|
|
343
|
+
ownerPlugin: name,
|
|
344
|
+
...(cap !== undefined ? { capability: cap } : {}),
|
|
345
|
+
description: def.description,
|
|
346
|
+
...(def.inputSchema !== undefined ? { inputSchema: def.inputSchema } : {}),
|
|
347
|
+
};
|
|
348
|
+
liveTools.set(toolName, record);
|
|
349
|
+
myToolNames.push(toolName);
|
|
350
|
+
opts.host.registerTool(toolName, def, handler, cap, name);
|
|
351
|
+
},
|
|
352
|
+
callTool,
|
|
353
|
+
log: {
|
|
354
|
+
info: (msg, meta) => log.info(`plugin[${m.browxai.namespace}]: ${msg}`, { plugin: name, ...(meta ?? {}) }),
|
|
355
|
+
warn: (msg, meta) => log.warn(`plugin[${m.browxai.namespace}]: ${msg}`, { plugin: name, ...(meta ?? {}) }),
|
|
356
|
+
error: (msg, meta) => log.error(`plugin[${m.browxai.namespace}]: ${msg}`, { plugin: name, ...(meta ?? {}) }),
|
|
357
|
+
},
|
|
358
|
+
};
|
|
359
|
+
let loaded = false;
|
|
360
|
+
let loadError;
|
|
361
|
+
try {
|
|
362
|
+
const mod = (await import(pathToFileURL(m.entryPath).href));
|
|
363
|
+
const fn = mod.register ?? mod.default;
|
|
364
|
+
if (typeof fn !== "function") {
|
|
365
|
+
throw new Error(`entry module ${m.entryPath} must export a \`register(api)\` function (named or default).`);
|
|
366
|
+
}
|
|
367
|
+
await fn(api);
|
|
368
|
+
loaded = true;
|
|
369
|
+
}
|
|
370
|
+
catch (e) {
|
|
371
|
+
loadError = e instanceof Error ? e.message : String(e);
|
|
372
|
+
log.warn(`plugin runtime: ${name} failed to load — ${loadError}`);
|
|
373
|
+
}
|
|
374
|
+
const status = loaded ? "loaded" : "load-error";
|
|
375
|
+
records.push({
|
|
376
|
+
manifest: m,
|
|
377
|
+
status,
|
|
378
|
+
tools: [...myToolNames],
|
|
379
|
+
transitiveDeps: [...myDeps].sort(),
|
|
380
|
+
...(status === "loaded" ? {} : { statusReason: loadError ?? "unknown load error" }),
|
|
381
|
+
declaredCapabilities: m.browxai.capabilities,
|
|
382
|
+
declaredAt,
|
|
383
|
+
...(loaded ? { enabledAt: new Date().toISOString() } : {}),
|
|
384
|
+
});
|
|
385
|
+
if (loaded)
|
|
386
|
+
toolCount += myToolNames.length;
|
|
387
|
+
}
|
|
388
|
+
return {
|
|
389
|
+
plugins: [...records, ...earlyDisabled].sort((a, b) => a.manifest.name.localeCompare(b.manifest.name)),
|
|
390
|
+
toolCount,
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Lookup table accessor exposed for the `plugins_info` MCP tool. The
|
|
395
|
+
* runtime holds an internal `liveTools` map; the result of
|
|
396
|
+
* {@link startPluginRuntime} is the structured surface — this helper is
|
|
397
|
+
* just for callers wanting the tool registry view on a plugin.
|
|
398
|
+
*/
|
|
399
|
+
export function toolsForPlugin(records, pluginName) {
|
|
400
|
+
const rec = records.find((r) => r.manifest.name === pluginName);
|
|
401
|
+
return rec?.tools ?? [];
|
|
402
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
import type { ResolvedManifest } from "./manifest.js";
|
|
3
|
+
/**
|
|
4
|
+
* MCP-style tool response. Same shape as the host's internal
|
|
5
|
+
* `ToolResponse` — plugin tools return this verbatim and the runtime
|
|
6
|
+
* forwards it through the MCP / SDK surface without rewriting.
|
|
7
|
+
*/
|
|
8
|
+
export interface PluginToolResponse {
|
|
9
|
+
readonly content: ReadonlyArray<{
|
|
10
|
+
type: "text";
|
|
11
|
+
text: string;
|
|
12
|
+
} | {
|
|
13
|
+
type: "image";
|
|
14
|
+
data: string;
|
|
15
|
+
mimeType: string;
|
|
16
|
+
}>;
|
|
17
|
+
}
|
|
18
|
+
/** Tool handler signature. Plugin authors implement this. */
|
|
19
|
+
export type PluginToolHandler = (args: unknown) => Promise<PluginToolResponse>;
|
|
20
|
+
/**
|
|
21
|
+
* The runtime API surface a plugin receives in its `register(api)` call.
|
|
22
|
+
* Stable across the runtime's API major version (`apiVersion` in the
|
|
23
|
+
* manifest).
|
|
24
|
+
*/
|
|
25
|
+
export interface PluginApi {
|
|
26
|
+
/** The plugin's own namespace, as declared in its manifest. */
|
|
27
|
+
readonly namespace: string;
|
|
28
|
+
/** The capabilities the plugin declared. (Already verified subset.) */
|
|
29
|
+
readonly declaredCapabilities: ReadonlyArray<string>;
|
|
30
|
+
/**
|
|
31
|
+
* Register a tool. The name MUST start with `<namespace>.` — passing
|
|
32
|
+
* anything else (or the bare namespace alone) throws synchronously.
|
|
33
|
+
*
|
|
34
|
+
* - `name` The full tool name (`figma.move_node`). Will appear
|
|
35
|
+
* on MCP `tools/list` exactly as given.
|
|
36
|
+
* - `def` Tool description + optional input schema. The
|
|
37
|
+
* schema is the same `inputSchema` shape host tools
|
|
38
|
+
* use — a `Record<string, z.ZodTypeAny>`. Pass an
|
|
39
|
+
* empty object (or omit) for argless tools.
|
|
40
|
+
* - `handler` Async function returning the MCP envelope. The
|
|
41
|
+
* runtime applies the per-tool capability gate +
|
|
42
|
+
* diagnostics + metrics wrapping the same as for
|
|
43
|
+
* core tools.
|
|
44
|
+
*/
|
|
45
|
+
registerTool(name: string, def: {
|
|
46
|
+
description: string;
|
|
47
|
+
inputSchema?: Record<string, z.ZodTypeAny> | undefined;
|
|
48
|
+
}, handler: PluginToolHandler): void;
|
|
49
|
+
/**
|
|
50
|
+
* Call another tool by name (a core browxai tool or a tool registered
|
|
51
|
+
* by a plugin in this plugin's transitively-declared `dependsOn`
|
|
52
|
+
* graph). Calls outside the declared graph fail with a structured
|
|
53
|
+
* error.
|
|
54
|
+
*
|
|
55
|
+
* Capability gates fire as if the call came in from MCP — a plugin
|
|
56
|
+
* cannot call a tool whose capability isn't enabled on the host.
|
|
57
|
+
*/
|
|
58
|
+
callTool(name: string, args?: Record<string, unknown>): Promise<PluginToolResponse>;
|
|
59
|
+
/**
|
|
60
|
+
* Plugin-scoped logger. Output is funnelled through the host's
|
|
61
|
+
* structured logger with `plugin=<namespace>` attached. Plugins should
|
|
62
|
+
* NOT write to stdout/stderr directly — stdout is the MCP wire.
|
|
63
|
+
*/
|
|
64
|
+
log: {
|
|
65
|
+
info(msg: string, meta?: Record<string, unknown>): void;
|
|
66
|
+
warn(msg: string, meta?: Record<string, unknown>): void;
|
|
67
|
+
error(msg: string, meta?: Record<string, unknown>): void;
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* The function shape a plugin's entry module must export — either as
|
|
72
|
+
* the default export or as a named `register`.
|
|
73
|
+
*/
|
|
74
|
+
export type PluginRegisterFn = (api: PluginApi) => void | Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* The post-load status of one plugin. Surfaced verbatim via
|
|
77
|
+
* `plugins_list` so an operator can see why anything didn't load.
|
|
78
|
+
*/
|
|
79
|
+
export type PluginStatus = "loaded" | "disabled-by-capability-mismatch" | "disabled-by-cycle" | "disabled-by-dep-missing" | "disabled-by-namespace-conflict" | "load-error";
|
|
80
|
+
export interface PluginRecord {
|
|
81
|
+
/** Resolved manifest (npm name, version, etc.). */
|
|
82
|
+
readonly manifest: ResolvedManifest;
|
|
83
|
+
/** Live status. */
|
|
84
|
+
readonly status: PluginStatus;
|
|
85
|
+
/** Tools registered by this plugin (`<namespace>.<tool>` names). */
|
|
86
|
+
readonly tools: ReadonlyArray<string>;
|
|
87
|
+
/** Transitive `dependsOn` closure (plugin names). */
|
|
88
|
+
readonly transitiveDeps: ReadonlyArray<string>;
|
|
89
|
+
/** Status-explainer (only populated for non-`loaded` statuses). */
|
|
90
|
+
readonly statusReason?: string;
|
|
91
|
+
/** Capabilities this plugin DECLARED. */
|
|
92
|
+
readonly declaredCapabilities: ReadonlyArray<string>;
|
|
93
|
+
/** ISO timestamp of when the manifest was read off disk. */
|
|
94
|
+
readonly declaredAt: string;
|
|
95
|
+
/** ISO timestamp of when this plugin loaded. Only set when status === "loaded". */
|
|
96
|
+
readonly enabledAt?: string;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Per-tool registration record — the runtime keeps one of these per
|
|
100
|
+
* plugin tool so it can route capability gating + call-graph
|
|
101
|
+
* enforcement against the right owner.
|
|
102
|
+
*/
|
|
103
|
+
export interface PluginToolRecord {
|
|
104
|
+
/** Full tool name (`<namespace>.<tool>`). */
|
|
105
|
+
readonly name: string;
|
|
106
|
+
/** Plugin (npm package name) that registered it. */
|
|
107
|
+
readonly ownerPlugin: string;
|
|
108
|
+
/** Capability gate for this tool (subset of the plugin's declaredCapabilities). */
|
|
109
|
+
readonly capability?: string | undefined;
|
|
110
|
+
/** Description + input schema (passed to MCP tools/list). */
|
|
111
|
+
readonly description: string;
|
|
112
|
+
readonly inputSchema?: Record<string, z.ZodTypeAny> | undefined;
|
|
113
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { type OriginPolicy } from "./origin.js";
|
|
2
|
+
import type { ConfirmHook } from "../util/capabilities.js";
|
|
3
|
+
import type { BrowxBridge } from "../helper/bridge.js";
|
|
4
|
+
export interface ConfirmContext {
|
|
5
|
+
hooks: ReadonlySet<ConfirmHook>;
|
|
6
|
+
policy: OriginPolicy;
|
|
7
|
+
bridge: BrowxBridge | null;
|
|
8
|
+
/** True iff the active session attached over CDP (BYOB). */
|
|
9
|
+
isByob: boolean;
|
|
10
|
+
/** session-scoped pre-approvals. When a scope is granted, confirm
|
|
11
|
+
* hooks for that scope auto-approve without the page-side `__browx.confirm`
|
|
12
|
+
* round-trip. Lets non-Claude MCP clients run unattended without a human
|
|
13
|
+
* at DevTools to issue confirms. */
|
|
14
|
+
approvals?: ApprovalStore;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* session-scoped pre-approvals. The non-Claude verification path
|
|
18
|
+
* surfaced that `__browx.confirm(true)` is operator-driven — a non-Claude MCP
|
|
19
|
+
* client can't drive it from inside a blocked action call. This store lets
|
|
20
|
+
* the client pre-approve confirm scopes for a TTL window. Each grant +
|
|
21
|
+
* consume is logged for audit.
|
|
22
|
+
*
|
|
23
|
+
* Pre-approval is *not* an override; the confirm hook still runs, finds the
|
|
24
|
+
* grant, and returns ok:true with `reason: "pre-approved"`. The page-side
|
|
25
|
+
* channel is the fallback when no pre-approval covers the scope.
|
|
26
|
+
*/
|
|
27
|
+
export declare class ApprovalStore {
|
|
28
|
+
private grants;
|
|
29
|
+
/** Grant a scope for `ttlSeconds`. Overwrites any prior grant for the same scope. */
|
|
30
|
+
grant(scope: ConfirmHook, ttlSeconds: number): void;
|
|
31
|
+
/** Revoke a previously-granted scope. Returns true if a live grant existed. */
|
|
32
|
+
revoke(scope: ConfirmHook): boolean;
|
|
33
|
+
/** Check (and consume) a grant. Returns true when an unexpired grant covers
|
|
34
|
+
* the scope — the call is counted toward audit. Returns false (and evicts
|
|
35
|
+
* the grant) when the grant has expired. */
|
|
36
|
+
consume(scope: ConfirmHook): boolean;
|
|
37
|
+
/** Snapshot of live grants for audit / `list_approvals` style tooling. */
|
|
38
|
+
list(): Array<{
|
|
39
|
+
scope: ConfirmHook;
|
|
40
|
+
grantedAt: number;
|
|
41
|
+
expiresAt: number;
|
|
42
|
+
uses: number;
|
|
43
|
+
remainingMs: number;
|
|
44
|
+
}>;
|
|
45
|
+
}
|
|
46
|
+
export interface ConfirmDecision {
|
|
47
|
+
/** Action proceeds if true. */
|
|
48
|
+
ok: boolean;
|
|
49
|
+
/** Short reason (logged). */
|
|
50
|
+
reason: string;
|
|
51
|
+
/** True iff a human confirmation was sought. */
|
|
52
|
+
asked: boolean;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Decide whether navigate() may proceed. If the URL is on-allowlist (or there's no
|
|
56
|
+
* allowlist), proceeds without asking. If off-allowlist:
|
|
57
|
+
* - if `navigate_off_allowlist` is in `hooks`, asks for human confirm via the bridge;
|
|
58
|
+
* - otherwise proceeds with a stderr warning.
|
|
59
|
+
*
|
|
60
|
+
* Returns `{ ok: false }` only when the human declined; never auto-denies (this is
|
|
61
|
+
* defense-in-depth, not a boundary).
|
|
62
|
+
*/
|
|
63
|
+
export declare function confirmNavigation(url: string, ctx: ConfirmContext): Promise<ConfirmDecision>;
|
|
64
|
+
/**
|
|
65
|
+
* Decide whether a generic action may proceed in BYOB mode. Returns ok:true when not
|
|
66
|
+
* in BYOB, or when the hook isn't set. Otherwise blocks on human confirm.
|
|
67
|
+
*
|
|
68
|
+
* Note: this is a *coarse* gate — every action in BYOB hits it. In practice most
|
|
69
|
+
* adopters either set the hook (and confirm once per session) or omit it (and trust
|
|
70
|
+
* the BYOB attach decision they already opted into).
|
|
71
|
+
*/
|
|
72
|
+
export declare function confirmByobAction(toolName: string, ctx: ConfirmContext): Promise<ConfirmDecision>;
|
|
73
|
+
/** Count of requests in an action window whose origin escaped the allowlist. */
|
|
74
|
+
export declare function countEgressOffAllowlist(requests: Array<{
|
|
75
|
+
url: string;
|
|
76
|
+
}>, policy: OriginPolicy): number;
|