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,208 @@
|
|
|
1
|
+
// RFC 0004 P3 / D3 (SRP) — the persistent-session extension context rebuild,
|
|
2
|
+
// extracted verbatim out of `extensions-batch-tools.ts` so each tool module stays
|
|
3
|
+
// under the size budget. Chromium cannot add/remove extensions on a live context,
|
|
4
|
+
// so install/reload/uninstall close the BrowserSession, relaunch with the updated
|
|
5
|
+
// `--load-extension` flags, and splice the new inner pieces onto the existing
|
|
6
|
+
// SessionEntry. The per-server boundary deps (caps / configStore / workspace /
|
|
7
|
+
// launch options) are threaded in EXPLICITLY — never a module-global — preserving
|
|
8
|
+
// the composition root's per-server isolation. Behaviour is byte-identical to the
|
|
9
|
+
// prior in-closure helper; only the dependency wiring is made explicit.
|
|
10
|
+
import { DEFAULT_SESSION_ID } from "../session/registry.js";
|
|
11
|
+
import { openManagedSession } from "../session/managed.js";
|
|
12
|
+
import { resolveDevice } from "../session/device.js";
|
|
13
|
+
import { reapplyAll as reapplyEmulation } from "../session/emulation.js";
|
|
14
|
+
import { attachDialogPolicy } from "../session/dialog.js";
|
|
15
|
+
import { attachPermissionPolicy, applyCdpBaseline as applyPermissionCdpBaseline, } from "../session/permission.js";
|
|
16
|
+
import { attachNotificationPolicy } from "../session/notification.js";
|
|
17
|
+
import { attachFsPickerPolicy } from "../session/fs-picker.js";
|
|
18
|
+
import { attachDeviceEmulation } from "../session/device-emu.js";
|
|
19
|
+
import { RefRegistry } from "../page/refs.js";
|
|
20
|
+
import { snapshotSubstrateFor } from "../page/snapshot-substrate-select.js";
|
|
21
|
+
import { networkSubstrateFor } from "../page/network-substrate-select.js";
|
|
22
|
+
import { WsInteractiveRegistry } from "../page/ws-interactive.js";
|
|
23
|
+
import { WorkersRegistry } from "../page/workers.js";
|
|
24
|
+
import { ConsoleBuffer } from "../page/console.js";
|
|
25
|
+
import { BrowxBridge } from "../helper/bridge.js";
|
|
26
|
+
import { applyOverlayHide } from "../helper/overlay-hide.js";
|
|
27
|
+
import { applyStealth } from "../helper/stealth.js";
|
|
28
|
+
import { requireCdp } from "../engine/index.js";
|
|
29
|
+
import { log } from "../util/logging.js";
|
|
30
|
+
/** Rebuild the persistent session's browser context with the entry's current
|
|
31
|
+
* extension list reflected as launch flags. Closes the existing BrowserSession +
|
|
32
|
+
* bridge, relaunches via `openManagedSession`, and replaces the entry's inner
|
|
33
|
+
* pieces in-place so the registry mapping (sessionId → entry) stays valid. Caller
|
|
34
|
+
* MUST have verified the entry is `persistent` and not headless (via the
|
|
35
|
+
* extension-refusal check). */
|
|
36
|
+
export async function rebuildPersistentForExtensions(e, deps) {
|
|
37
|
+
const { caps, configStore, workspace, opts, resolvedConfig } = deps;
|
|
38
|
+
const headless = opts.headless ?? resolvedConfig.headless;
|
|
39
|
+
const disableWebSecurity = configStore.resolve().disableWebSecurity === true;
|
|
40
|
+
const profileName = e.launchProfile ?? e.id;
|
|
41
|
+
const profileDir = e.id === DEFAULT_SESSION_ID && !e.launchProfile
|
|
42
|
+
? workspace.sub("profile")
|
|
43
|
+
: workspace.sub(`profiles/${profileName}`);
|
|
44
|
+
const extensionPaths = e.extensions.loaded.filter((x) => x.enabled).map((x) => x.path);
|
|
45
|
+
// Preserve the engine across the rebuild (extensions are Chromium-only, so
|
|
46
|
+
// this is chromium today; reading it before close keeps the rebuild engine-
|
|
47
|
+
// faithful for when a second engine lands).
|
|
48
|
+
const rebuildEngine = e.session.engine;
|
|
49
|
+
// Tear down the current session BEFORE relaunching — Chromium will not
|
|
50
|
+
// open a second persistent context on the same profile dir.
|
|
51
|
+
await e.bridge.detach().catch(() => undefined);
|
|
52
|
+
await e.session.close().catch(() => undefined);
|
|
53
|
+
// Resolve device fresh from the current resolved config (no spec stored
|
|
54
|
+
// post-creation; the device-emulation state on `e.deviceEmulation` is
|
|
55
|
+
// re-applied below).
|
|
56
|
+
const device = resolveDevice({
|
|
57
|
+
device: resolvedConfig.defaultDevice,
|
|
58
|
+
viewport: resolvedConfig.defaultViewport,
|
|
59
|
+
});
|
|
60
|
+
const sess = await openManagedSession({
|
|
61
|
+
headless,
|
|
62
|
+
profileDir,
|
|
63
|
+
device,
|
|
64
|
+
disableWebSecurity,
|
|
65
|
+
browserType: rebuildEngine,
|
|
66
|
+
...(extensionPaths.length ? { extensionPaths } : {}),
|
|
67
|
+
});
|
|
68
|
+
// Rebuild the per-session inner pieces. The secrets / dialog policy /
|
|
69
|
+
// device-emulation state survive on the entry (intentional — they are
|
|
70
|
+
// operator-supplied across rebuilds); buffers and refs are replaced
|
|
71
|
+
// since they referenced the now-closed CDP session.
|
|
72
|
+
const consoleBuf = new ConsoleBuffer();
|
|
73
|
+
consoleBuf.attach(sess.page());
|
|
74
|
+
// Re-select the network substrate on the rebuilt context (extensions are
|
|
75
|
+
// chromium-only, so this stays the CDP substrate — but routing through the
|
|
76
|
+
// selector keeps the rebuild engine-agnostic and the entry's substrate live).
|
|
77
|
+
const networkSub = networkSubstrateFor(sess);
|
|
78
|
+
await networkSub.attach();
|
|
79
|
+
const networkBuf = networkSub.http;
|
|
80
|
+
const wsBuf = networkSub.ws;
|
|
81
|
+
consoleBuf.setSecrets(e.secrets);
|
|
82
|
+
networkSub.setSecrets(e.secrets);
|
|
83
|
+
const br = new BrowxBridge();
|
|
84
|
+
await br.attach(sess.page().context());
|
|
85
|
+
attachDialogPolicy(sess.page().context(), e.dialog);
|
|
86
|
+
// Re-attach permission policy on the rebuilt context. The state's
|
|
87
|
+
// wired-contexts WeakSet ensures the new context is treated as fresh
|
|
88
|
+
// (the old one was torn down), so the binding + init-script install
|
|
89
|
+
// afresh and the CDP baseline is re-applied.
|
|
90
|
+
await attachPermissionPolicy(sess.page().context(), e.permission, async (permission, origin) => {
|
|
91
|
+
log.info(`permission ask-human: ${permission}${origin ? ` (${origin})` : ""} → call __browx.confirm(true|false) in DevTools to respond`);
|
|
92
|
+
try {
|
|
93
|
+
const sig = await br.awaitSignal("respond", 300_000);
|
|
94
|
+
const data = sig.data;
|
|
95
|
+
if (data && data.kind === "confirm" && data.value === true)
|
|
96
|
+
return "allow";
|
|
97
|
+
return "deny";
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return "deny";
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
await applyPermissionCdpBaseline(sess.page().context(), e.permission).catch(() => undefined);
|
|
104
|
+
// Re-attach notification-constructor policy on the rebuilt context. The
|
|
105
|
+
// state's wired-contexts WeakSet ensures the new context is treated as
|
|
106
|
+
// fresh (the old one was torn down), so the binding + init-script install
|
|
107
|
+
// afresh and the sync-decision hint is re-seeded.
|
|
108
|
+
await attachNotificationPolicy(sess.page().context(), e.notification, async (n) => {
|
|
109
|
+
log.info(`notification ask-human: ${JSON.stringify({ title: n.title, origin: n.origin })} → call __browx.confirm(true|false) in DevTools to respond`);
|
|
110
|
+
try {
|
|
111
|
+
const sig = await br.awaitSignal("respond", 300_000);
|
|
112
|
+
const data = sig.data;
|
|
113
|
+
if (data && data.kind === "confirm" && data.value === true)
|
|
114
|
+
return "allow";
|
|
115
|
+
return "deny";
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
return "deny";
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
// Re-attach fs-picker policy on the rebuilt context. WeakSet inside the
|
|
122
|
+
// state treats the new context as fresh — binding + init script are
|
|
123
|
+
// re-installed, write-target handles for the previous context are
|
|
124
|
+
// garbage-collected with it.
|
|
125
|
+
await attachFsPickerPolicy(sess.page().context(), e.fsPicker, workspace.root, async (api, suggestedName) => {
|
|
126
|
+
log.info(`fs-picker ask-human: ${api}${suggestedName ? ` (${suggestedName})` : ""} → call __browx.respond({files:[…]}) in DevTools (or fs_picker_respond) to answer`);
|
|
127
|
+
try {
|
|
128
|
+
const sig = await br.awaitSignal("respond", 300_000);
|
|
129
|
+
const data = sig.data;
|
|
130
|
+
if (data &&
|
|
131
|
+
data.kind === "fs_picker_respond" &&
|
|
132
|
+
Array.isArray(data.value?.files)) {
|
|
133
|
+
return data.value.files;
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
}).catch(() => undefined);
|
|
141
|
+
await applyOverlayHide(sess.page().context(), configStore.resolve().hideOverlaySelectors);
|
|
142
|
+
// Re-apply per-context stealth init-script (capability `stealth`) on the
|
|
143
|
+
// rebuilt context. Stealth must engage on every navigation post-rebuild,
|
|
144
|
+
// not just on the original launch.
|
|
145
|
+
if (caps.enabled.has("stealth")) {
|
|
146
|
+
await applyStealth(sess.page().context()).catch((err) => {
|
|
147
|
+
log.warn(`stealth: rebuild failed to apply init script — ${err instanceof Error ? err.message : String(err)}`);
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
// Re-apply per-primitive device emulation state to the fresh context's
|
|
151
|
+
// pages (locale/timezone/UA via CDP, geolocation/colour-scheme/reduced-
|
|
152
|
+
// motion/permissions via Playwright). Best-effort — failures don't
|
|
153
|
+
// abort the rebuild.
|
|
154
|
+
try {
|
|
155
|
+
await reapplyEmulation(sess.page().context(), sess.page(), requireCdp(sess), e.deviceEmulation);
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
/* best-effort */
|
|
159
|
+
}
|
|
160
|
+
// Re-attach Web Bluetooth / WebUSB / WebHID device-emulation wrappers on
|
|
161
|
+
// the rebuilt context. The state's wired-contexts WeakSet treats the new
|
|
162
|
+
// context as fresh — binding + init script reinstall, current catalog is
|
|
163
|
+
// re-served verbatim on the next page-side requestDevice.
|
|
164
|
+
await attachDeviceEmulation(sess.page().context(), e.webDeviceEmulation).catch(() => undefined);
|
|
165
|
+
sess
|
|
166
|
+
.page()
|
|
167
|
+
.context()
|
|
168
|
+
.on("page", (newPage) => {
|
|
169
|
+
(async () => {
|
|
170
|
+
try {
|
|
171
|
+
const newCdp = await sess.page().context().newCDPSession(newPage);
|
|
172
|
+
await reapplyEmulation(sess.page().context(), newPage, newCdp, e.deviceEmulation);
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
/* best-effort */
|
|
176
|
+
}
|
|
177
|
+
})().catch(() => undefined);
|
|
178
|
+
});
|
|
179
|
+
// Splice the new pieces onto the existing entry — sessionId still maps
|
|
180
|
+
// here so every caller holding `entry` keeps working.
|
|
181
|
+
e.session = sess;
|
|
182
|
+
e.console = consoleBuf;
|
|
183
|
+
e.networkSubstrate = networkSub;
|
|
184
|
+
e.network = networkBuf;
|
|
185
|
+
e.ws = wsBuf;
|
|
186
|
+
e.bridge = br;
|
|
187
|
+
e.refs = new RefRegistry();
|
|
188
|
+
// The rebuild minted a fresh CDP session on the new context; re-derive the
|
|
189
|
+
// snapshot substrate so it captures the live handle (extensions are
|
|
190
|
+
// chromium-only, so this stays the CDP substrate).
|
|
191
|
+
e.snapshotSubstrate = snapshotSubstrateFor(sess);
|
|
192
|
+
// Interactive-WS state is page-side; the rebuild destroyed the wrapper
|
|
193
|
+
// and any active interceptors with it. Discard the server-side mirror
|
|
194
|
+
// so it doesn't claim live interceptors that no longer exist, then
|
|
195
|
+
// re-install the wrapper before any nav so the new context's first
|
|
196
|
+
// page sees the wrapped WebSocket constructor.
|
|
197
|
+
e.wsInteractive = new WsInteractiveRegistry();
|
|
198
|
+
if (caps.enabled.has("action")) {
|
|
199
|
+
await e.wsInteractive.install(sess.page()).catch(() => undefined);
|
|
200
|
+
}
|
|
201
|
+
// workers visibility. Rebuild destroyed the page-side wrapper
|
|
202
|
+
// and any SW attachments; discard the server-side mirror and re-install.
|
|
203
|
+
e.workers.dispose();
|
|
204
|
+
e.workers = new WorkersRegistry();
|
|
205
|
+
if (caps.enabled.has("read")) {
|
|
206
|
+
await e.workers.installPageWrapper(sess.page()).catch(() => undefined);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
import { resolveExtensionPath, readManifest, refuseIfUnsupported as refuseExtensionsIfUnsupported, applyInstall as applyExtensionInstall, applyUninstall as applyExtensionUninstall, applyReload as applyExtensionReload, } from "../session/extensions.js";
|
|
2
|
+
import { estimateTokens } from "../util/tokens.js";
|
|
3
|
+
import { rebuildPersistentForExtensions } from "./extensions-rebuild.js";
|
|
4
|
+
import { SESSION_ARG } from "./schemas.js";
|
|
5
|
+
/**
|
|
6
|
+
* Chrome-extension management tools: extensions_install / extensions_list /
|
|
7
|
+
* extensions_reload / extensions_trigger / extensions_uninstall. Off-by-default
|
|
8
|
+
* `extensions` capability; headed-persistent only. install/reload/uninstall
|
|
9
|
+
* rebuild the underlying browser context (Chromium can't mutate extensions on a
|
|
10
|
+
* live context) via the extracted `rebuildPersistentForExtensions`. Split out of
|
|
11
|
+
* `extensions-batch-tools` by cohesive family (RFC 0004 P3 / D3 SRP); registered
|
|
12
|
+
* through the shared `ToolHost` seam in the same source order.
|
|
13
|
+
*/
|
|
14
|
+
/** Discover the loaded extensions' Chrome-runtime ids by inspecting the
|
|
15
|
+
* context's service-worker (MV3) + background-page (MV2) URLs — both start with
|
|
16
|
+
* `chrome-extension://<runtime-id>/`. Best-effort: older Playwright builds may
|
|
17
|
+
* not surface every channel; returns the deduped set. */
|
|
18
|
+
function discoverExtensionRuntimeIds(ctx) {
|
|
19
|
+
const idsFrom = (urls) => urls
|
|
20
|
+
.map((w) => w.url())
|
|
21
|
+
.filter((u) => u.startsWith("chrome-extension://"))
|
|
22
|
+
.map((u) => u.slice("chrome-extension://".length).split("/")[0]);
|
|
23
|
+
const c = ctx;
|
|
24
|
+
const swIds = idsFrom(c.serviceWorkers?.() ?? []);
|
|
25
|
+
const bgIds = idsFrom(c.backgroundPages?.() ?? []);
|
|
26
|
+
return Array.from(new Set([...swIds, ...bgIds]));
|
|
27
|
+
}
|
|
28
|
+
export function registerExtensionsTools(host) {
|
|
29
|
+
const { z, register, gateCheck, engineGate, entryFor, caps, workspace, configStore, startOptions: opts, resolvedConfig, } = host;
|
|
30
|
+
// The per-server boundary deps the context rebuild threads in (was the closure
|
|
31
|
+
// the in-module helper held). Passed explicitly to the extracted rebuild fn.
|
|
32
|
+
const rebuildDeps = {
|
|
33
|
+
caps,
|
|
34
|
+
configStore,
|
|
35
|
+
workspace,
|
|
36
|
+
opts,
|
|
37
|
+
resolvedConfig,
|
|
38
|
+
};
|
|
39
|
+
/** Pure refusal check for the extension tools. Returns a typed early-exit
|
|
40
|
+
* envelope when the session is incognito / attached / headless; null when
|
|
41
|
+
* the session can host extensions. */
|
|
42
|
+
const extensionRefusal = (e, tool) => {
|
|
43
|
+
if (e.mode === "persistent" || e.mode === "incognito" || e.mode === "attached") {
|
|
44
|
+
const headless = !!(opts.headless ?? resolvedConfig.headless);
|
|
45
|
+
const r = refuseExtensionsIfUnsupported({ mode: e.mode, headless, tool });
|
|
46
|
+
if (r) {
|
|
47
|
+
const body = { ok: false, error: r.error, hint: r.hint };
|
|
48
|
+
return {
|
|
49
|
+
content: [
|
|
50
|
+
{
|
|
51
|
+
type: "text",
|
|
52
|
+
text: JSON.stringify({ ...body, tokensEstimate: estimateTokens(JSON.stringify(body)) }, null, 2),
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
};
|
|
60
|
+
/** Envelope helper for the extension tools. */
|
|
61
|
+
const extensionEnvelope = (e, extra) => {
|
|
62
|
+
const body = {
|
|
63
|
+
ok: true,
|
|
64
|
+
session: e.id,
|
|
65
|
+
loaded: e.extensions.loaded.map((x) => ({ ...x })),
|
|
66
|
+
...extra,
|
|
67
|
+
};
|
|
68
|
+
body.tokensEstimate = estimateTokens(JSON.stringify(body));
|
|
69
|
+
return { content: [{ type: "text", text: JSON.stringify(body, null, 2) }] };
|
|
70
|
+
};
|
|
71
|
+
const extensionErrorEnvelope = (tool, err) => {
|
|
72
|
+
const body = {
|
|
73
|
+
ok: false,
|
|
74
|
+
action: { type: tool },
|
|
75
|
+
error: err instanceof Error ? err.message : String(err),
|
|
76
|
+
};
|
|
77
|
+
return {
|
|
78
|
+
content: [
|
|
79
|
+
{
|
|
80
|
+
type: "text",
|
|
81
|
+
text: JSON.stringify({ ...body, tokensEstimate: estimateTokens(JSON.stringify(body)) }, null, 2),
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
register("extensions_install", {
|
|
87
|
+
capability: "extensions",
|
|
88
|
+
deep: true,
|
|
89
|
+
description: "Load an unpacked Chromium extension (MV3 or MV2 directory containing `manifest.json`) into the session's managed-profile launch. **Gated behind the off-by-default `extensions` capability** — same posture class as `eval` / `network-body` / `secrets`. Loaded extensions can READ every page the session visits and make ARBITRARY network requests; the extension code itself becomes trust-equivalent to the agent. " +
|
|
90
|
+
"`path` is workspace-rooted (under $BROWX_WORKSPACE) — traversal / absolute-outside is rejected. Pass the UNPACKED extension directory; `.crx` packed archives must be unpacked first (the directory must contain `manifest.json`). " +
|
|
91
|
+
"Headed + persistent only — incognito / attached / headless sessions REFUSE with a structured error and hint. **install REBUILDS the underlying browser context** (Chromium doesn't support adding extensions to a live context): the current page navigates to about:blank, refs invalidate, console/network/ws buffers reset. Profile state on disk (cookies, localStorage, IndexedDB) survives. Treat install as a session-restart. " +
|
|
92
|
+
"Returns `{ok, session, installed:{id,name,version,path}, loaded:[…], note?, tokensEstimate}`. The `id` is a stable hash of the resolved path — pass it back to `extensions_reload` / `extensions_trigger` / `extensions_uninstall`.",
|
|
93
|
+
inputSchema: {
|
|
94
|
+
path: z
|
|
95
|
+
.string()
|
|
96
|
+
.describe("Workspace-rooted directory of the unpacked extension (must contain `manifest.json`)."),
|
|
97
|
+
...SESSION_ARG,
|
|
98
|
+
},
|
|
99
|
+
}, async ({ path, session }) => {
|
|
100
|
+
const g = gateCheck("extensions_install");
|
|
101
|
+
if (g)
|
|
102
|
+
return g;
|
|
103
|
+
const e = await entryFor(session);
|
|
104
|
+
const eg = engineGate("extensions_install", e);
|
|
105
|
+
if (eg)
|
|
106
|
+
return eg;
|
|
107
|
+
const refused = extensionRefusal(e, "extensions_install");
|
|
108
|
+
if (refused)
|
|
109
|
+
return refused;
|
|
110
|
+
let resolved;
|
|
111
|
+
let manifest;
|
|
112
|
+
try {
|
|
113
|
+
resolved = resolveExtensionPath(workspace.root, path, "extensions_install");
|
|
114
|
+
manifest = readManifest(resolved, "extensions_install");
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
return extensionErrorEnvelope("extensions_install", err);
|
|
118
|
+
}
|
|
119
|
+
let installed;
|
|
120
|
+
try {
|
|
121
|
+
const r = applyExtensionInstall(e.extensions, { path: resolved, name: manifest.name, version: manifest.version }, "extensions_install");
|
|
122
|
+
e.extensions.loaded = r.loaded;
|
|
123
|
+
installed = e.extensions.loaded.find((x) => x.id === r.id);
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
return extensionErrorEnvelope("extensions_install", err);
|
|
127
|
+
}
|
|
128
|
+
try {
|
|
129
|
+
await rebuildPersistentForExtensions(e, rebuildDeps);
|
|
130
|
+
}
|
|
131
|
+
catch (err) {
|
|
132
|
+
// rebuild failed — roll back the registry so the next call doesn't
|
|
133
|
+
// try to re-apply a now-doomed extension list.
|
|
134
|
+
e.extensions.loaded = e.extensions.loaded.filter((x) => x.id !== installed.id);
|
|
135
|
+
return extensionErrorEnvelope("extensions_install", err);
|
|
136
|
+
}
|
|
137
|
+
return extensionEnvelope(e, {
|
|
138
|
+
installed: {
|
|
139
|
+
id: installed.id,
|
|
140
|
+
name: installed.name,
|
|
141
|
+
version: installed.version,
|
|
142
|
+
path: installed.path,
|
|
143
|
+
},
|
|
144
|
+
note: "browser context rebuilt — refs / console / network / ws buffers reset; on-disk profile state preserved",
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
register("extensions_list", {
|
|
148
|
+
capability: "extensions",
|
|
149
|
+
deep: true,
|
|
150
|
+
description: "List extensions currently loaded for this session. Returns `[{id, name, version, path, enabled}]`. Empty list when no extension is loaded (the default). Gated behind the off-by-default `extensions` capability — disabled sessions return a structured error before reaching this list. Headed + persistent sessions only.",
|
|
151
|
+
inputSchema: { ...SESSION_ARG },
|
|
152
|
+
}, async ({ session }) => {
|
|
153
|
+
const g = gateCheck("extensions_list");
|
|
154
|
+
if (g)
|
|
155
|
+
return g;
|
|
156
|
+
const e = await entryFor(session);
|
|
157
|
+
const eg = engineGate("extensions_list", e);
|
|
158
|
+
if (eg)
|
|
159
|
+
return eg;
|
|
160
|
+
const refused = extensionRefusal(e, "extensions_list");
|
|
161
|
+
if (refused)
|
|
162
|
+
return refused;
|
|
163
|
+
return extensionEnvelope(e, {});
|
|
164
|
+
});
|
|
165
|
+
register("extensions_reload", {
|
|
166
|
+
capability: "extensions",
|
|
167
|
+
deep: true,
|
|
168
|
+
description: "Reload an installed extension: re-parse its `manifest.json`, then rebuild the underlying browser context so Chromium re-injects content scripts and restarts the MV3 service worker. Identify the extension by its `id` (from `extensions_install` / `extensions_list`). Same rebuild caveat as install — refs / buffers reset, on-disk profile state survives. Headed + persistent sessions only.",
|
|
169
|
+
inputSchema: {
|
|
170
|
+
id: z.string().describe("Extension id returned by extensions_install / extensions_list."),
|
|
171
|
+
...SESSION_ARG,
|
|
172
|
+
},
|
|
173
|
+
}, async ({ id, session }) => {
|
|
174
|
+
const g = gateCheck("extensions_reload");
|
|
175
|
+
if (g)
|
|
176
|
+
return g;
|
|
177
|
+
const e = await entryFor(session);
|
|
178
|
+
const eg = engineGate("extensions_reload", e);
|
|
179
|
+
if (eg)
|
|
180
|
+
return eg;
|
|
181
|
+
const refused = extensionRefusal(e, "extensions_reload");
|
|
182
|
+
if (refused)
|
|
183
|
+
return refused;
|
|
184
|
+
const target = e.extensions.loaded.find((x) => x.id === id);
|
|
185
|
+
if (!target) {
|
|
186
|
+
return extensionErrorEnvelope("extensions_reload", new Error(`no extension with id "${id}" is loaded in this session (call extensions_list to see ids)`));
|
|
187
|
+
}
|
|
188
|
+
let parsed;
|
|
189
|
+
try {
|
|
190
|
+
parsed = readManifest(target.path, "extensions_reload");
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
return extensionErrorEnvelope("extensions_reload", err);
|
|
194
|
+
}
|
|
195
|
+
try {
|
|
196
|
+
const r = applyExtensionReload(e.extensions, id, parsed, "extensions_reload");
|
|
197
|
+
e.extensions.loaded = r.loaded;
|
|
198
|
+
}
|
|
199
|
+
catch (err) {
|
|
200
|
+
return extensionErrorEnvelope("extensions_reload", err);
|
|
201
|
+
}
|
|
202
|
+
try {
|
|
203
|
+
await rebuildPersistentForExtensions(e, rebuildDeps);
|
|
204
|
+
}
|
|
205
|
+
catch (err) {
|
|
206
|
+
return extensionErrorEnvelope("extensions_reload", err);
|
|
207
|
+
}
|
|
208
|
+
const after = e.extensions.loaded.find((x) => x.id === id);
|
|
209
|
+
return extensionEnvelope(e, {
|
|
210
|
+
reloaded: after
|
|
211
|
+
? { id: after.id, name: after.name, version: after.version, path: after.path }
|
|
212
|
+
: null,
|
|
213
|
+
note: "browser context rebuilt — content scripts re-injected; refs / buffers reset",
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
register("extensions_trigger", {
|
|
217
|
+
capability: "extensions",
|
|
218
|
+
deep: true,
|
|
219
|
+
description: "Best-effort invoke of an installed extension's surface. With `command`, attempts to fire the keyboard-command binding declared in the extension's manifest (`commands` key). Without `command`, navigates the session's active page to the extension's `chrome-extension://<id>/<default_popup>` URL so the popup renders in-tab and is driveable like any other page. Many extensions lack both surfaces; this tool returns `ok:false` with a clear reason in those cases. Read-only side-effects on the extension itself — it does not mutate the loaded list. Headed + persistent sessions only.\n\n" +
|
|
220
|
+
"**Note on `id`.** browxai's id (a hash of the path) does NOT necessarily equal the Chrome-runtime id of the loaded extension — Chrome derives its id from the extension's signing key when one is present. For popup-style triggers we attempt to read the active page's `chrome-extension://` runtime id from the context's service workers / background pages; on a mismatch the tool returns a hint pointing at extensions_list and the page's own discovery.",
|
|
221
|
+
inputSchema: {
|
|
222
|
+
id: z.string().describe("Extension id returned by extensions_install / extensions_list."),
|
|
223
|
+
command: z
|
|
224
|
+
.string()
|
|
225
|
+
.optional()
|
|
226
|
+
.describe('Optional manifest `commands` binding name to fire (e.g. "_execute_action"). Omit to open the extension\'s default_popup in the active page.'),
|
|
227
|
+
...SESSION_ARG,
|
|
228
|
+
},
|
|
229
|
+
}, async ({ id, command, session }) => {
|
|
230
|
+
const g = gateCheck("extensions_trigger");
|
|
231
|
+
if (g)
|
|
232
|
+
return g;
|
|
233
|
+
const e = await entryFor(session);
|
|
234
|
+
const eg = engineGate("extensions_trigger", e);
|
|
235
|
+
if (eg)
|
|
236
|
+
return eg;
|
|
237
|
+
const refused = extensionRefusal(e, "extensions_trigger");
|
|
238
|
+
if (refused)
|
|
239
|
+
return refused;
|
|
240
|
+
const target = e.extensions.loaded.find((x) => x.id === id);
|
|
241
|
+
if (!target) {
|
|
242
|
+
return extensionErrorEnvelope("extensions_trigger", new Error(`no extension with id "${id}" is loaded in this session (call extensions_list to see ids)`));
|
|
243
|
+
}
|
|
244
|
+
try {
|
|
245
|
+
// Resolve the Chrome-runtime id by inspecting the context's
|
|
246
|
+
// service-worker / background-page URLs. Best-effort — surfaces the
|
|
247
|
+
// discovered ids so the caller can decide.
|
|
248
|
+
const runtimeIds = discoverExtensionRuntimeIds(e.session.page().context());
|
|
249
|
+
// We can't reliably map our path-hash id to the runtime id without
|
|
250
|
+
// parsing the manifest's `key` field — when there's exactly one loaded
|
|
251
|
+
// extension AND one runtime id we assume the mapping.
|
|
252
|
+
const runtimeId = runtimeIds.length === 1 && e.extensions.loaded.length === 1 ? runtimeIds[0] : undefined;
|
|
253
|
+
if (command) {
|
|
254
|
+
// Chrome keyboard-command bindings are user-keyboard-only; CDP has
|
|
255
|
+
// no public surface to dispatch them programmatically. Return a
|
|
256
|
+
// structured "not supported" rather than silently no-op.
|
|
257
|
+
return extensionErrorEnvelope("extensions_trigger", new Error(`extensions_trigger: keyboard command "${command}" — Chromium does not expose extension keyboard-command dispatch via CDP / Playwright. ` +
|
|
258
|
+
`Workaround: invoke the extension's underlying behaviour via its content-script API or open its popup (call extensions_trigger without \`command\`).`));
|
|
259
|
+
}
|
|
260
|
+
if (!runtimeId) {
|
|
261
|
+
return extensionErrorEnvelope("extensions_trigger", new Error(`extensions_trigger: cannot determine Chrome-runtime extension id for path-hash id "${id}". ` +
|
|
262
|
+
`Browxai's id is a hash of the unpacked path and does NOT necessarily equal Chrome's runtime id (Chrome derives that from the manifest \`key\` when present). ` +
|
|
263
|
+
`runtimeIdsDetected: ${JSON.stringify(runtimeIds)}; loaded: ${e.extensions.loaded.length}. ` +
|
|
264
|
+
`Workaround: navigate the page directly to the extension popup URL once you know the runtime id.`));
|
|
265
|
+
}
|
|
266
|
+
// Open the extension's popup (or its background page) in the active
|
|
267
|
+
// page. The extension serves `chrome-extension://<id>/` from its
|
|
268
|
+
// manifest's `action.default_popup` / `browser_action.default_popup`.
|
|
269
|
+
const url = `chrome-extension://${runtimeId}/`;
|
|
270
|
+
await e.session
|
|
271
|
+
.page()
|
|
272
|
+
.goto(url, { waitUntil: "domcontentloaded" })
|
|
273
|
+
.catch(() => undefined);
|
|
274
|
+
return extensionEnvelope(e, {
|
|
275
|
+
triggered: { id, runtimeId, url, command: command ?? null },
|
|
276
|
+
note: "best-effort: navigated active page to extension root; default_popup discovery depends on the extension's manifest",
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
catch (err) {
|
|
280
|
+
return extensionErrorEnvelope("extensions_trigger", err);
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
register("extensions_uninstall", {
|
|
284
|
+
capability: "extensions",
|
|
285
|
+
deep: true,
|
|
286
|
+
description: "Remove an installed extension from the session and rebuild the underlying browser context without it. Same rebuild caveat as install — refs / buffers reset, on-disk profile state survives. Headed + persistent sessions only.",
|
|
287
|
+
inputSchema: {
|
|
288
|
+
id: z.string().describe("Extension id returned by extensions_install / extensions_list."),
|
|
289
|
+
...SESSION_ARG,
|
|
290
|
+
},
|
|
291
|
+
}, async ({ id, session }) => {
|
|
292
|
+
const g = gateCheck("extensions_uninstall");
|
|
293
|
+
if (g)
|
|
294
|
+
return g;
|
|
295
|
+
const e = await entryFor(session);
|
|
296
|
+
const eg = engineGate("extensions_uninstall", e);
|
|
297
|
+
if (eg)
|
|
298
|
+
return eg;
|
|
299
|
+
const refused = extensionRefusal(e, "extensions_uninstall");
|
|
300
|
+
if (refused)
|
|
301
|
+
return refused;
|
|
302
|
+
let removed;
|
|
303
|
+
try {
|
|
304
|
+
const r = applyExtensionUninstall(e.extensions, id, "extensions_uninstall");
|
|
305
|
+
e.extensions.loaded = r.loaded;
|
|
306
|
+
removed = r.removed;
|
|
307
|
+
}
|
|
308
|
+
catch (err) {
|
|
309
|
+
return extensionErrorEnvelope("extensions_uninstall", err);
|
|
310
|
+
}
|
|
311
|
+
try {
|
|
312
|
+
await rebuildPersistentForExtensions(e, rebuildDeps);
|
|
313
|
+
}
|
|
314
|
+
catch (err) {
|
|
315
|
+
// rebuild failed after registry mutation — restore the entry so the
|
|
316
|
+
// agent can retry the operation. The original BrowserSession is
|
|
317
|
+
// already torn down (we cannot recover it), so the session itself
|
|
318
|
+
// is in a degraded state; surface that explicitly.
|
|
319
|
+
return extensionErrorEnvelope("extensions_uninstall", new Error(`(post-rebuild) ${err instanceof Error ? err.message : String(err)} — session "${e.id}" is now in a degraded state; close it and open a fresh one.`));
|
|
320
|
+
}
|
|
321
|
+
return extensionEnvelope(e, {
|
|
322
|
+
uninstalled: {
|
|
323
|
+
id: removed.id,
|
|
324
|
+
name: removed.name,
|
|
325
|
+
version: removed.version,
|
|
326
|
+
path: removed.path,
|
|
327
|
+
},
|
|
328
|
+
note: "browser context rebuilt without this extension — refs / buffers reset",
|
|
329
|
+
});
|
|
330
|
+
});
|
|
331
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RegisterHost, GateHost, SessionHost, ActionHost, EnvelopeHost, ServerServicesHost } from "./host.js";
|
|
2
|
+
/**
|
|
3
|
+
* Multi-field form-fill tool: `fill_form`. Compose N field fills (plus an optional
|
|
4
|
+
* final submit click) into one action window, with atomic pre-resolution. Split
|
|
5
|
+
* out of `forms-recording-tools` (RFC 0004 P3 / D3 SRP); registered through the
|
|
6
|
+
* shared `ToolHost` seam in the same source order.
|
|
7
|
+
*/
|
|
8
|
+
export declare function registerFormsFillTools(host: RegisterHost & GateHost & SessionHost & ActionHost & EnvelopeHost & ServerServicesHost): void;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { confirmByobAction } from "../policy/confirm.js";
|
|
2
|
+
import { fillForm } from "../page/fill-form.js";
|
|
3
|
+
import { ACTION_OPTS } from "./schemas.js";
|
|
4
|
+
/**
|
|
5
|
+
* Multi-field form-fill tool: `fill_form`. Compose N field fills (plus an optional
|
|
6
|
+
* final submit click) into one action window, with atomic pre-resolution. Split
|
|
7
|
+
* out of `forms-recording-tools` (RFC 0004 P3 / D3 SRP); registered through the
|
|
8
|
+
* shared `ToolHost` seam in the same source order.
|
|
9
|
+
*/
|
|
10
|
+
export function registerFormsFillTools(host) {
|
|
11
|
+
const { z, register, gateCheck, entryFor, confirmCtxFor, denyContent, actionTimeout, asActionResultText, ctxFor, } = host;
|
|
12
|
+
// ---------- multi-field form fill (compose fill into one action window) ----------
|
|
13
|
+
// Per-field target shape — same surface as the single-field tools, minus
|
|
14
|
+
// `coords` (fill needs a real input element, not a viewport point).
|
|
15
|
+
const FILL_FORM_FIELD = z.object({
|
|
16
|
+
ref: z.string().optional().describe("Stable [eN] ref from snapshot()/find()"),
|
|
17
|
+
selector: z.string().optional().describe("CSS / selectorHint fallback"),
|
|
18
|
+
named: z.string().optional().describe("Mnemonic name previously bound with name_ref"),
|
|
19
|
+
contextRef: z.string().optional().describe("Resolve `selector` within the subtree of this ref"),
|
|
20
|
+
value: z
|
|
21
|
+
.string()
|
|
22
|
+
.describe("Value to fill (substring `<NAME>` triggers secrets materialisation when the secrets capability is on)"),
|
|
23
|
+
});
|
|
24
|
+
// The optional submit slot accepts the same target shapes (also no coords —
|
|
25
|
+
// a coord-only submit is fine via a follow-up click, and keeping submit
|
|
26
|
+
// ref/selector-only matches the recorder's replay model).
|
|
27
|
+
const FILL_FORM_SUBMIT = z.object({
|
|
28
|
+
ref: z.string().optional(),
|
|
29
|
+
selector: z.string().optional(),
|
|
30
|
+
named: z.string().optional(),
|
|
31
|
+
contextRef: z.string().optional(),
|
|
32
|
+
});
|
|
33
|
+
/** Project a per-field user arg into an `ActionTarget` (the shape
|
|
34
|
+
* `fillForm` expects). Mirrors `asTarget` for one field at a time but
|
|
35
|
+
* scoped to "no coords" — coords on a form field is rejected upstream. */
|
|
36
|
+
const fieldArgToTarget = (raw, label, refs) => {
|
|
37
|
+
const provided = [raw.ref, raw.selector, raw.named].filter(Boolean).length;
|
|
38
|
+
if (provided === 0)
|
|
39
|
+
throw new Error(`fill_form: ${label} requires one of \`ref\` / \`selector\` / \`named\``);
|
|
40
|
+
if (provided > 1)
|
|
41
|
+
throw new Error(`fill_form: ${label} — pass exactly one of \`ref\` / \`selector\` / \`named\``);
|
|
42
|
+
if (raw.ref)
|
|
43
|
+
return { ref: raw.ref };
|
|
44
|
+
if (raw.named) {
|
|
45
|
+
const resolved = refs.refByNameLookup(raw.named);
|
|
46
|
+
if (!resolved)
|
|
47
|
+
throw new Error(`fill_form: ${label} — name "${raw.named}" not bound. Call name_ref({name, ref}) first.`);
|
|
48
|
+
return { ref: resolved };
|
|
49
|
+
}
|
|
50
|
+
return raw.contextRef
|
|
51
|
+
? { selector: raw.selector, contextRef: raw.contextRef }
|
|
52
|
+
: { selector: raw.selector };
|
|
53
|
+
};
|
|
54
|
+
register("fill_form", {
|
|
55
|
+
capability: "action",
|
|
56
|
+
batchable: true,
|
|
57
|
+
description: "Fill N form fields atomically in one action window, with an optional final `submit` click. Replaces the fill/fill/fill/click round-trip pattern with one dispatch — same action-window envelope (navigation/structure/console/network/snapshotDelta) as a single fill, plus an `elements: ElementProbe[]` slot carrying per-field probes in dispatch order. **Atomic pre-resolution**: every field's target (ref/selector/named) is resolved before any DOM write; if any target misses, the call returns `ok:false` with a structured `fieldResolution` block and NO partial fills land. Same posture for the optional `submit` — a missing submit aborts the whole call. **Secrets-masking composes**: a field value like `<SECRET_NAME>` triggers the standard registry substitution at dispatch (capability `secrets`); the recorded descriptor + per-field probe carry the alias, not the real value. Field targets accept `ref`/`selector`/`named` (no `coords` — fill needs a real input element).",
|
|
58
|
+
inputSchema: {
|
|
59
|
+
fields: z
|
|
60
|
+
.array(FILL_FORM_FIELD)
|
|
61
|
+
.min(1)
|
|
62
|
+
.describe("Ordered list of {target, value} pairs. Filled sequentially after atomic pre-resolution."),
|
|
63
|
+
submit: FILL_FORM_SUBMIT.optional().describe("Optional click target dispatched after every field fills. Aborts atomically if its target misses."),
|
|
64
|
+
...ACTION_OPTS,
|
|
65
|
+
},
|
|
66
|
+
}, async (args) => {
|
|
67
|
+
const g = gateCheck("fill_form");
|
|
68
|
+
if (g)
|
|
69
|
+
return g;
|
|
70
|
+
const e = await entryFor(args.session);
|
|
71
|
+
const c = await confirmByobAction("fill_form", confirmCtxFor(e));
|
|
72
|
+
if (!c.ok)
|
|
73
|
+
return denyContent("fill_form", c);
|
|
74
|
+
// Project the schema-validated args into the lower-half's shape. Any
|
|
75
|
+
// target-shape error here surfaces as a structured "invalid args"
|
|
76
|
+
// result rather than a thrown handler — agents debugging a malformed
|
|
77
|
+
// call shouldn't see a stack trace.
|
|
78
|
+
let mappedFields;
|
|
79
|
+
let mappedSubmit;
|
|
80
|
+
try {
|
|
81
|
+
mappedFields = args.fields.map((f, i) => ({
|
|
82
|
+
target: fieldArgToTarget(f, `fields[${i}]`, e.refs),
|
|
83
|
+
value: f.value,
|
|
84
|
+
}));
|
|
85
|
+
if (args.submit) {
|
|
86
|
+
mappedSubmit = fieldArgToTarget(args.submit, "submit", e.refs);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
return {
|
|
91
|
+
content: [
|
|
92
|
+
{
|
|
93
|
+
type: "text",
|
|
94
|
+
text: JSON.stringify({ ok: false, error: err instanceof Error ? err.message : String(err) }, null, 2),
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
const td = actionTimeout(args);
|
|
100
|
+
return asActionResultText(fillForm(ctxFor(e), {
|
|
101
|
+
fields: mappedFields,
|
|
102
|
+
submit: mappedSubmit,
|
|
103
|
+
mode: args.mode,
|
|
104
|
+
maxResultTokens: args.maxResultTokens,
|
|
105
|
+
deadlineMs: td.ms,
|
|
106
|
+
deadlineWarning: td.warning,
|
|
107
|
+
}));
|
|
108
|
+
});
|
|
109
|
+
}
|