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,622 @@
|
|
|
1
|
+
// Pluggable credentials / TOTP hook (capability `credentials`, off by default).
|
|
2
|
+
//
|
|
3
|
+
// Why it exists: agents driving real auth flows routinely block on 2FA or
|
|
4
|
+
// stored-credential vault lookups. Without a hook here, the only escapes are
|
|
5
|
+
// (a) bake the seed/password into the prompt — which leaks into transcripts
|
|
6
|
+
// and eval datasets, defeating the SecretRegistry masking — or (b) hand-fly
|
|
7
|
+
// the step every time. Substrate-tier solution: a thin provider abstraction
|
|
8
|
+
// that reads from a configured vault, with no provider bundled by default.
|
|
9
|
+
//
|
|
10
|
+
// Posture: same as `eval` / `network-body` / `secrets`. Off by default, loud
|
|
11
|
+
// one-time warning at boot. Provider selection is per-deployment — NEVER
|
|
12
|
+
// bundled, NEVER auto-purchased (see no-auto-purchases rule).
|
|
13
|
+
//
|
|
14
|
+
// Provider matrix (selected via `BROWX_CREDENTIALS_PROVIDER`):
|
|
15
|
+
// - `oathtool` default backend; shells out to the system `oathtool`
|
|
16
|
+
// binary against seeds supplied by the operator (env or
|
|
17
|
+
// config file). No paid dependency. If the binary is
|
|
18
|
+
// missing, every call returns a structured failure with an
|
|
19
|
+
// install hint (Homebrew / apt) — never auto-installed.
|
|
20
|
+
// - `1password` shells out to the `op` CLI. The operator must run
|
|
21
|
+
// `op signin` out-of-band; this module never prompts.
|
|
22
|
+
// - `bitwarden` shells out to the `bw` CLI. Same out-of-band auth model;
|
|
23
|
+
// expects `BW_SESSION` in the server env.
|
|
24
|
+
// - `lastpass` shells out to the `lpass` CLI. Same out-of-band auth.
|
|
25
|
+
// - `none` explicit no-op provider; both tools return a structured
|
|
26
|
+
// refusal. Useful when the capability is on for testing the
|
|
27
|
+
// surface without wiring a real vault.
|
|
28
|
+
//
|
|
29
|
+
// All shell invocations: fixed argv, no shell interpolation, account name
|
|
30
|
+
// is passed as a discrete argv element (no injection surface). stdout is
|
|
31
|
+
// captured to a string, stderr is captured to a string for failure
|
|
32
|
+
// diagnostics, no exec-via-shell paths.
|
|
33
|
+
//
|
|
34
|
+
// Integration with SecretRegistry masking: `get_credential` does NOT echo
|
|
35
|
+
// the password back in cleartext. It auto-registers the password into the
|
|
36
|
+
// per-session SecretRegistry under an alias derived from the account name
|
|
37
|
+
// (`<PASSWORD_<account>>`), and the returned object carries the alias —
|
|
38
|
+
// the agent then uses `fill({value:"<PASSWORD_acct>"})` and Playwright
|
|
39
|
+
// receives the real value at dispatch via the registry's materialise path.
|
|
40
|
+
// The egress-masking layer also catches the value in every other sink.
|
|
41
|
+
// `get_totp` returns the 6-digit code directly (TOTPs are single-use and short-lived
|
|
42
|
+
// — the value is "spent" the moment it's typed, so masking buys little
|
|
43
|
+
// and complicates the agent's verify-step flow).
|
|
44
|
+
import { spawn } from "node:child_process";
|
|
45
|
+
export const ALL_PROVIDERS = [
|
|
46
|
+
"oathtool",
|
|
47
|
+
"1password",
|
|
48
|
+
"bitwarden",
|
|
49
|
+
"lastpass",
|
|
50
|
+
"none",
|
|
51
|
+
];
|
|
52
|
+
/** Spawn a process with fixed argv (no shell). Returns combined result.
|
|
53
|
+
* Bounded by a 5s wall-clock — a hung CLI shouldn't block tool dispatch. */
|
|
54
|
+
export async function runArgv(argv, opts = {}) {
|
|
55
|
+
const timeoutMs = opts.timeoutMs ?? 5000;
|
|
56
|
+
return new Promise((resolve) => {
|
|
57
|
+
let settled = false;
|
|
58
|
+
const finish = (r) => {
|
|
59
|
+
if (settled)
|
|
60
|
+
return;
|
|
61
|
+
settled = true;
|
|
62
|
+
resolve(r);
|
|
63
|
+
};
|
|
64
|
+
try {
|
|
65
|
+
const cp = spawn(argv[0], argv.slice(1), {
|
|
66
|
+
env: opts.env ?? process.env,
|
|
67
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
68
|
+
});
|
|
69
|
+
let stdout = "";
|
|
70
|
+
let stderr = "";
|
|
71
|
+
const timer = setTimeout(() => {
|
|
72
|
+
try {
|
|
73
|
+
cp.kill("SIGKILL");
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
/* best-effort */
|
|
77
|
+
}
|
|
78
|
+
finish({
|
|
79
|
+
ok: false,
|
|
80
|
+
stdout,
|
|
81
|
+
stderr,
|
|
82
|
+
code: null,
|
|
83
|
+
spawnError: `timed out after ${timeoutMs}ms`,
|
|
84
|
+
});
|
|
85
|
+
}, timeoutMs);
|
|
86
|
+
cp.stdout.on("data", (d) => {
|
|
87
|
+
stdout += d.toString("utf8");
|
|
88
|
+
});
|
|
89
|
+
cp.stderr.on("data", (d) => {
|
|
90
|
+
stderr += d.toString("utf8");
|
|
91
|
+
});
|
|
92
|
+
cp.on("error", (e) => {
|
|
93
|
+
clearTimeout(timer);
|
|
94
|
+
finish({ ok: false, stdout, stderr, code: null, spawnError: e.message });
|
|
95
|
+
});
|
|
96
|
+
cp.on("close", (code) => {
|
|
97
|
+
clearTimeout(timer);
|
|
98
|
+
finish({ ok: code === 0, stdout, stderr, code });
|
|
99
|
+
});
|
|
100
|
+
if (opts.stdin !== undefined)
|
|
101
|
+
cp.stdin.end(opts.stdin);
|
|
102
|
+
else
|
|
103
|
+
cp.stdin.end();
|
|
104
|
+
}
|
|
105
|
+
catch (e) {
|
|
106
|
+
finish({
|
|
107
|
+
ok: false,
|
|
108
|
+
stdout: "",
|
|
109
|
+
stderr: "",
|
|
110
|
+
code: null,
|
|
111
|
+
spawnError: e instanceof Error ? e.message : String(e),
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
// Alias derivation
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
119
|
+
/** Turn an agent-facing account name into a SecretRegistry alias identifier.
|
|
120
|
+
* Result always matches `/^[A-Z][A-Z0-9_]*$/`. */
|
|
121
|
+
export function aliasFromAccount(account, prefix = "PASSWORD") {
|
|
122
|
+
const sanitised = account
|
|
123
|
+
.toUpperCase()
|
|
124
|
+
.replace(/[^A-Z0-9_]+/g, "_")
|
|
125
|
+
.replace(/^_+|_+$/g, "")
|
|
126
|
+
.replace(/_+/g, "_");
|
|
127
|
+
if (!sanitised)
|
|
128
|
+
return prefix;
|
|
129
|
+
// Guarantee leading letter (regex needs `[A-Z]` first).
|
|
130
|
+
const head = /^[A-Z]/.test(sanitised) ? sanitised : `X_${sanitised}`;
|
|
131
|
+
return `${prefix}_${head}`;
|
|
132
|
+
}
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
// `none` provider — explicit no-op
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
136
|
+
class NoneProvider {
|
|
137
|
+
name = "none";
|
|
138
|
+
getTotp(_account) {
|
|
139
|
+
return Promise.resolve({
|
|
140
|
+
ok: false,
|
|
141
|
+
provider: "none",
|
|
142
|
+
error: "credentials provider is `none` — no vault backend is configured",
|
|
143
|
+
hint: "set BROWX_CREDENTIALS_PROVIDER to one of: oathtool, 1password, bitwarden, lastpass",
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
getCredential(_account) {
|
|
147
|
+
return Promise.resolve({
|
|
148
|
+
ok: false,
|
|
149
|
+
provider: "none",
|
|
150
|
+
error: "credentials provider is `none` — no vault backend is configured",
|
|
151
|
+
hint: "set BROWX_CREDENTIALS_PROVIDER to one of: oathtool, 1password, bitwarden, lastpass",
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
class OathtoolProvider {
|
|
156
|
+
cfg;
|
|
157
|
+
name = "oathtool";
|
|
158
|
+
constructor(cfg) {
|
|
159
|
+
this.cfg = cfg;
|
|
160
|
+
}
|
|
161
|
+
async getTotp(account) {
|
|
162
|
+
const seed = this.cfg.seeds[account];
|
|
163
|
+
if (!seed) {
|
|
164
|
+
return {
|
|
165
|
+
ok: false,
|
|
166
|
+
provider: "oathtool",
|
|
167
|
+
error: `oathtool: no seed registered for account "${account}"`,
|
|
168
|
+
hint: 'register the seed via BROWX_OATHTOOL_SEEDS="<account>=<BASE32SECRET>,…" or ' +
|
|
169
|
+
"BROWX_OATHTOOL_SEEDS_FILE=<path-to-json>, then restart the server",
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
const binary = this.cfg.binary ?? "oathtool";
|
|
173
|
+
// oathtool -b --totp <seed> — base32 input, default 6-digit, default 30s step
|
|
174
|
+
const r = await runArgv([binary, "-b", "--totp", seed], { timeoutMs: 3000 });
|
|
175
|
+
if (r.spawnError && /ENOENT/.test(r.spawnError)) {
|
|
176
|
+
return {
|
|
177
|
+
ok: false,
|
|
178
|
+
provider: "oathtool",
|
|
179
|
+
error: `oathtool binary "${binary}" not found on PATH`,
|
|
180
|
+
hint: "install oathtool (macOS: `brew install oath-toolkit`; Debian/Ubuntu: `apt install oathtool`)",
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
if (!r.ok) {
|
|
184
|
+
return {
|
|
185
|
+
ok: false,
|
|
186
|
+
provider: "oathtool",
|
|
187
|
+
error: `oathtool failed (exit ${r.code ?? "?"})`,
|
|
188
|
+
hint: r.stderr.trim() || r.spawnError || "check the seed value is valid BASE32",
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
const code = r.stdout.trim();
|
|
192
|
+
if (!/^\d{6,8}$/.test(code)) {
|
|
193
|
+
return {
|
|
194
|
+
ok: false,
|
|
195
|
+
provider: "oathtool",
|
|
196
|
+
error: `oathtool returned unexpected output (not a 6-8 digit code)`,
|
|
197
|
+
hint: "verify the seed is BASE32 and oathtool's default options haven't been overridden",
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
return { ok: true, code, provider: "oathtool" };
|
|
201
|
+
}
|
|
202
|
+
getCredential(_account) {
|
|
203
|
+
return Promise.resolve({
|
|
204
|
+
ok: false,
|
|
205
|
+
provider: "oathtool",
|
|
206
|
+
error: "oathtool is a TOTP-only backend; it does not store username/password",
|
|
207
|
+
hint: "pair with another provider for credential lookup (1password, bitwarden, lastpass)",
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
/** Parse `acct1=SEED1,acct2=SEED2` into a record. Tolerates whitespace,
|
|
212
|
+
* rejects malformed entries silently (returns what parses). Internal — the
|
|
213
|
+
* full resolution flow surfaces a clean warning when nothing parses. */
|
|
214
|
+
export function parseSeedsEnv(raw) {
|
|
215
|
+
if (!raw)
|
|
216
|
+
return {};
|
|
217
|
+
const out = {};
|
|
218
|
+
for (const part of raw.split(",")) {
|
|
219
|
+
const trimmed = part.trim();
|
|
220
|
+
if (!trimmed)
|
|
221
|
+
continue;
|
|
222
|
+
const eq = trimmed.indexOf("=");
|
|
223
|
+
if (eq <= 0)
|
|
224
|
+
continue;
|
|
225
|
+
const k = trimmed.slice(0, eq).trim();
|
|
226
|
+
const v = trimmed.slice(eq + 1).trim();
|
|
227
|
+
if (k && v)
|
|
228
|
+
out[k] = v;
|
|
229
|
+
}
|
|
230
|
+
return out;
|
|
231
|
+
}
|
|
232
|
+
// ---------------------------------------------------------------------------
|
|
233
|
+
// `1password` provider — shells out to `op`
|
|
234
|
+
// ---------------------------------------------------------------------------
|
|
235
|
+
class OnePasswordProvider {
|
|
236
|
+
binary;
|
|
237
|
+
name = "1password";
|
|
238
|
+
constructor(binary = "op") {
|
|
239
|
+
this.binary = binary;
|
|
240
|
+
}
|
|
241
|
+
async getTotp(account) {
|
|
242
|
+
const r = await runArgv([this.binary, "item", "get", account, "--otp"], { timeoutMs: 5000 });
|
|
243
|
+
if (r.spawnError && /ENOENT/.test(r.spawnError)) {
|
|
244
|
+
return {
|
|
245
|
+
ok: false,
|
|
246
|
+
provider: "1password",
|
|
247
|
+
error: `1password CLI "${this.binary}" not found on PATH`,
|
|
248
|
+
hint: "install the 1Password CLI from https://developer.1password.com/docs/cli/get-started/",
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
if (!r.ok) {
|
|
252
|
+
return {
|
|
253
|
+
ok: false,
|
|
254
|
+
provider: "1password",
|
|
255
|
+
error: `op item get --otp failed (exit ${r.code ?? "?"})`,
|
|
256
|
+
hint: r.stderr.trim() || "ensure you've run `op signin` and the item name is correct",
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
const code = r.stdout.trim();
|
|
260
|
+
if (!/^\d{6,8}$/.test(code)) {
|
|
261
|
+
return {
|
|
262
|
+
ok: false,
|
|
263
|
+
provider: "1password",
|
|
264
|
+
error: "1password returned unexpected output (not a 6-8 digit code)",
|
|
265
|
+
hint: "verify the item has a one-time-password field configured",
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
return { ok: true, code, provider: "1password" };
|
|
269
|
+
}
|
|
270
|
+
async getCredential(account) {
|
|
271
|
+
// `op item get <name> --fields label=username,label=password --format json`
|
|
272
|
+
const r = await runArgv([
|
|
273
|
+
this.binary,
|
|
274
|
+
"item",
|
|
275
|
+
"get",
|
|
276
|
+
account,
|
|
277
|
+
"--fields",
|
|
278
|
+
"label=username,label=password",
|
|
279
|
+
"--format",
|
|
280
|
+
"json",
|
|
281
|
+
], { timeoutMs: 5000 });
|
|
282
|
+
if (r.spawnError && /ENOENT/.test(r.spawnError)) {
|
|
283
|
+
return {
|
|
284
|
+
ok: false,
|
|
285
|
+
provider: "1password",
|
|
286
|
+
error: `1password CLI "${this.binary}" not found on PATH`,
|
|
287
|
+
hint: "install the 1Password CLI from https://developer.1password.com/docs/cli/get-started/",
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
if (!r.ok) {
|
|
291
|
+
return {
|
|
292
|
+
ok: false,
|
|
293
|
+
provider: "1password",
|
|
294
|
+
error: `op item get failed (exit ${r.code ?? "?"})`,
|
|
295
|
+
hint: r.stderr.trim() || "ensure you've run `op signin` and the item name is correct",
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
const parsed = parseFieldsJson(r.stdout);
|
|
299
|
+
if (!parsed.username || !parsed.password) {
|
|
300
|
+
return {
|
|
301
|
+
ok: false,
|
|
302
|
+
provider: "1password",
|
|
303
|
+
error: "1password item missing username or password field",
|
|
304
|
+
hint: "verify the item has both a `username` and `password` field labelled accordingly",
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
return {
|
|
308
|
+
ok: true,
|
|
309
|
+
provider: "1password",
|
|
310
|
+
username: parsed.username,
|
|
311
|
+
_password: parsed.password,
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
// ---------------------------------------------------------------------------
|
|
316
|
+
// `bitwarden` provider — shells out to `bw`
|
|
317
|
+
// ---------------------------------------------------------------------------
|
|
318
|
+
class BitwardenProvider {
|
|
319
|
+
binary;
|
|
320
|
+
name = "bitwarden";
|
|
321
|
+
constructor(binary = "bw") {
|
|
322
|
+
this.binary = binary;
|
|
323
|
+
}
|
|
324
|
+
async getTotp(account) {
|
|
325
|
+
const r = await runArgv([this.binary, "get", "totp", account], { timeoutMs: 5000 });
|
|
326
|
+
if (r.spawnError && /ENOENT/.test(r.spawnError)) {
|
|
327
|
+
return {
|
|
328
|
+
ok: false,
|
|
329
|
+
provider: "bitwarden",
|
|
330
|
+
error: `bitwarden CLI "${this.binary}" not found on PATH`,
|
|
331
|
+
hint: "install the Bitwarden CLI: https://bitwarden.com/help/cli/",
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
if (!r.ok) {
|
|
335
|
+
return {
|
|
336
|
+
ok: false,
|
|
337
|
+
provider: "bitwarden",
|
|
338
|
+
error: `bw get totp failed (exit ${r.code ?? "?"})`,
|
|
339
|
+
hint: r.stderr.trim() || "ensure $BW_SESSION is set (`bw unlock`) and the item exists",
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
const code = r.stdout.trim();
|
|
343
|
+
if (!/^\d{6,8}$/.test(code)) {
|
|
344
|
+
return {
|
|
345
|
+
ok: false,
|
|
346
|
+
provider: "bitwarden",
|
|
347
|
+
error: "bitwarden returned unexpected output (not a 6-8 digit code)",
|
|
348
|
+
hint: "verify the item has a TOTP field configured",
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
return { ok: true, code, provider: "bitwarden" };
|
|
352
|
+
}
|
|
353
|
+
async getCredential(account) {
|
|
354
|
+
const r = await runArgv([this.binary, "get", "item", account], { timeoutMs: 5000 });
|
|
355
|
+
if (r.spawnError && /ENOENT/.test(r.spawnError)) {
|
|
356
|
+
return {
|
|
357
|
+
ok: false,
|
|
358
|
+
provider: "bitwarden",
|
|
359
|
+
error: `bitwarden CLI "${this.binary}" not found on PATH`,
|
|
360
|
+
hint: "install the Bitwarden CLI: https://bitwarden.com/help/cli/",
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
if (!r.ok) {
|
|
364
|
+
return {
|
|
365
|
+
ok: false,
|
|
366
|
+
provider: "bitwarden",
|
|
367
|
+
error: `bw get item failed (exit ${r.code ?? "?"})`,
|
|
368
|
+
hint: r.stderr.trim() || "ensure $BW_SESSION is set (`bw unlock`) and the item exists",
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
try {
|
|
372
|
+
const item = JSON.parse(r.stdout);
|
|
373
|
+
const username = item.login?.username;
|
|
374
|
+
const password = item.login?.password;
|
|
375
|
+
if (!username || !password) {
|
|
376
|
+
return {
|
|
377
|
+
ok: false,
|
|
378
|
+
provider: "bitwarden",
|
|
379
|
+
error: "bitwarden item missing username or password",
|
|
380
|
+
hint: "verify the item has both fields populated",
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
return {
|
|
384
|
+
ok: true,
|
|
385
|
+
provider: "bitwarden",
|
|
386
|
+
username,
|
|
387
|
+
_password: password,
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
catch (e) {
|
|
391
|
+
return {
|
|
392
|
+
ok: false,
|
|
393
|
+
provider: "bitwarden",
|
|
394
|
+
error: "could not parse bw output as JSON",
|
|
395
|
+
hint: e instanceof Error ? e.message : String(e),
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
// ---------------------------------------------------------------------------
|
|
401
|
+
// `lastpass` provider — shells out to `lpass`
|
|
402
|
+
// ---------------------------------------------------------------------------
|
|
403
|
+
class LastpassProvider {
|
|
404
|
+
binary;
|
|
405
|
+
name = "lastpass";
|
|
406
|
+
constructor(binary = "lpass") {
|
|
407
|
+
this.binary = binary;
|
|
408
|
+
}
|
|
409
|
+
async getTotp(account) {
|
|
410
|
+
const r = await runArgv([this.binary, "show", "--field=otp", account], { timeoutMs: 5000 });
|
|
411
|
+
if (r.spawnError && /ENOENT/.test(r.spawnError)) {
|
|
412
|
+
return {
|
|
413
|
+
ok: false,
|
|
414
|
+
provider: "lastpass",
|
|
415
|
+
error: `lastpass CLI "${this.binary}" not found on PATH`,
|
|
416
|
+
hint: "install lpass (macOS: `brew install lastpass-cli`)",
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
if (!r.ok) {
|
|
420
|
+
return {
|
|
421
|
+
ok: false,
|
|
422
|
+
provider: "lastpass",
|
|
423
|
+
error: `lpass show --field=otp failed (exit ${r.code ?? "?"})`,
|
|
424
|
+
hint: r.stderr.trim() || "ensure you've run `lpass login` and the item has an otp field",
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
const code = r.stdout.trim();
|
|
428
|
+
if (!/^\d{6,8}$/.test(code)) {
|
|
429
|
+
return {
|
|
430
|
+
ok: false,
|
|
431
|
+
provider: "lastpass",
|
|
432
|
+
error: "lastpass returned unexpected output (not a 6-8 digit code)",
|
|
433
|
+
hint: "verify the item has a TOTP field configured",
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
return { ok: true, code, provider: "lastpass" };
|
|
437
|
+
}
|
|
438
|
+
async getCredential(account) {
|
|
439
|
+
const r = await runArgv([this.binary, "show", "--username", "--password", account], {
|
|
440
|
+
timeoutMs: 5000,
|
|
441
|
+
});
|
|
442
|
+
if (r.spawnError && /ENOENT/.test(r.spawnError)) {
|
|
443
|
+
return {
|
|
444
|
+
ok: false,
|
|
445
|
+
provider: "lastpass",
|
|
446
|
+
error: `lastpass CLI "${this.binary}" not found on PATH`,
|
|
447
|
+
hint: "install lpass (macOS: `brew install lastpass-cli`)",
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
if (!r.ok) {
|
|
451
|
+
return {
|
|
452
|
+
ok: false,
|
|
453
|
+
provider: "lastpass",
|
|
454
|
+
error: `lpass show failed (exit ${r.code ?? "?"})`,
|
|
455
|
+
hint: r.stderr.trim() || "ensure you've run `lpass login` and the item exists",
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
// lpass emits the requested fields one per line in the order requested.
|
|
459
|
+
const lines = r.stdout
|
|
460
|
+
.split("\n")
|
|
461
|
+
.map((l) => l.trim())
|
|
462
|
+
.filter(Boolean);
|
|
463
|
+
const [username, password] = lines;
|
|
464
|
+
if (!username || !password) {
|
|
465
|
+
return {
|
|
466
|
+
ok: false,
|
|
467
|
+
provider: "lastpass",
|
|
468
|
+
error: "lastpass returned no username/password",
|
|
469
|
+
hint: "verify the item has both fields populated",
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
return {
|
|
473
|
+
ok: true,
|
|
474
|
+
provider: "lastpass",
|
|
475
|
+
username,
|
|
476
|
+
_password: password,
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
// ---------------------------------------------------------------------------
|
|
481
|
+
// JSON helpers
|
|
482
|
+
// ---------------------------------------------------------------------------
|
|
483
|
+
function parseFieldsJson(raw) {
|
|
484
|
+
try {
|
|
485
|
+
const parsed = JSON.parse(raw);
|
|
486
|
+
// `op item get --fields label=username,label=password --format json` emits
|
|
487
|
+
// an array of `{label, value, …}` entries.
|
|
488
|
+
if (Array.isArray(parsed)) {
|
|
489
|
+
const out = {};
|
|
490
|
+
for (const entry of parsed) {
|
|
491
|
+
const e = entry;
|
|
492
|
+
if (e.label === "username" && typeof e.value === "string")
|
|
493
|
+
out.username = e.value;
|
|
494
|
+
if (e.label === "password" && typeof e.value === "string")
|
|
495
|
+
out.password = e.value;
|
|
496
|
+
}
|
|
497
|
+
return out;
|
|
498
|
+
}
|
|
499
|
+
return {};
|
|
500
|
+
}
|
|
501
|
+
catch {
|
|
502
|
+
return {};
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Resolve the configured provider from env. Returns the provider singleton
|
|
507
|
+
* + any non-fatal startup warnings (the caller logs these via `log.warn`).
|
|
508
|
+
*
|
|
509
|
+
* Env contract:
|
|
510
|
+
* BROWX_CREDENTIALS_PROVIDER=oathtool|1password|bitwarden|lastpass|none
|
|
511
|
+
* BROWX_OATHTOOL_BIN=/custom/path/to/oathtool
|
|
512
|
+
* BROWX_OATHTOOL_SEEDS="acct1=BASE32,acct2=BASE32"
|
|
513
|
+
* BROWX_1PASSWORD_BIN=/custom/path/to/op
|
|
514
|
+
* BROWX_BITWARDEN_BIN=/custom/path/to/bw
|
|
515
|
+
* BROWX_LASTPASS_BIN=/custom/path/to/lpass
|
|
516
|
+
*
|
|
517
|
+
* Default is `oathtool` (the self-managed, no-paid-dependency path). The
|
|
518
|
+
* provider object is constructed eagerly; if its CLI is missing, that
|
|
519
|
+
* surfaces per-call, never at startup (so the server still boots).
|
|
520
|
+
*/
|
|
521
|
+
export function resolveCredentialsProvider(env = process.env) {
|
|
522
|
+
const raw = env.BROWX_CREDENTIALS_PROVIDER?.trim().toLowerCase();
|
|
523
|
+
const warnings = [];
|
|
524
|
+
const name = (() => {
|
|
525
|
+
if (!raw)
|
|
526
|
+
return "oathtool";
|
|
527
|
+
if (ALL_PROVIDERS.includes(raw))
|
|
528
|
+
return raw;
|
|
529
|
+
warnings.push(`BROWX_CREDENTIALS_PROVIDER: unknown provider "${raw}" — falling back to "oathtool". ` +
|
|
530
|
+
`Valid: ${ALL_PROVIDERS.join(", ")}.`);
|
|
531
|
+
return "oathtool";
|
|
532
|
+
})();
|
|
533
|
+
let provider;
|
|
534
|
+
switch (name) {
|
|
535
|
+
case "oathtool": {
|
|
536
|
+
const seeds = parseSeedsEnv(env.BROWX_OATHTOOL_SEEDS);
|
|
537
|
+
provider = new OathtoolProvider({
|
|
538
|
+
binary: env.BROWX_OATHTOOL_BIN?.trim() || undefined,
|
|
539
|
+
seeds,
|
|
540
|
+
});
|
|
541
|
+
break;
|
|
542
|
+
}
|
|
543
|
+
case "1password":
|
|
544
|
+
provider = new OnePasswordProvider(env.BROWX_1PASSWORD_BIN?.trim() || undefined);
|
|
545
|
+
break;
|
|
546
|
+
case "bitwarden":
|
|
547
|
+
provider = new BitwardenProvider(env.BROWX_BITWARDEN_BIN?.trim() || undefined);
|
|
548
|
+
break;
|
|
549
|
+
case "lastpass":
|
|
550
|
+
provider = new LastpassProvider(env.BROWX_LASTPASS_BIN?.trim() || undefined);
|
|
551
|
+
break;
|
|
552
|
+
case "none":
|
|
553
|
+
provider = new NoneProvider();
|
|
554
|
+
break;
|
|
555
|
+
}
|
|
556
|
+
return { provider, config: { provider: name, warnings } };
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Test seam: build a provider instance directly from a callable pair.
|
|
560
|
+
* Used by the test suite to mock both endpoints without spawning a real
|
|
561
|
+
* binary. Not exported for runtime use.
|
|
562
|
+
*/
|
|
563
|
+
export function makeFakeProvider(impl, name = "oathtool") {
|
|
564
|
+
return { name, getTotp: impl.getTotp, getCredential: impl.getCredential };
|
|
565
|
+
}
|
|
566
|
+
/**
|
|
567
|
+
* Apply a credential lookup to the per-session secrets registry:
|
|
568
|
+
* registers the password under an account-derived alias, then returns the
|
|
569
|
+
* public credential shape (username + aliasName only, NEVER the password).
|
|
570
|
+
*
|
|
571
|
+
* Callers pass `registry` only when the `secrets` capability is enabled.
|
|
572
|
+
* When it's not, the function returns a structured refusal — registering
|
|
573
|
+
* a password without the egress-masking layer engaged would leak the
|
|
574
|
+
* password into transcripts the first time the agent referenced it.
|
|
575
|
+
*/
|
|
576
|
+
export function applyCredentialToRegistry(result, registry, account, pageUrl) {
|
|
577
|
+
if (!result.ok) {
|
|
578
|
+
// Surface refusal verbatim; never carries a password.
|
|
579
|
+
return stripInternal(result);
|
|
580
|
+
}
|
|
581
|
+
if (!result._password || !result.username) {
|
|
582
|
+
return {
|
|
583
|
+
ok: false,
|
|
584
|
+
provider: result.provider,
|
|
585
|
+
error: "provider returned incomplete credential (missing username or password)",
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
if (!registry) {
|
|
589
|
+
return {
|
|
590
|
+
ok: false,
|
|
591
|
+
provider: result.provider,
|
|
592
|
+
error: "credentials lookup refused: the `secrets` capability is not enabled. " +
|
|
593
|
+
"Returning a password without secrets-masking would leak it into transcripts. " +
|
|
594
|
+
"Add `secrets` to BROWX_CAPABILITIES alongside `credentials`, then restart.",
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
const aliasName = aliasFromAccount(account);
|
|
598
|
+
try {
|
|
599
|
+
registry.register({
|
|
600
|
+
name: aliasName,
|
|
601
|
+
value: result._password,
|
|
602
|
+
...(pageUrl ? {} : {}),
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
catch (e) {
|
|
606
|
+
return {
|
|
607
|
+
ok: false,
|
|
608
|
+
provider: result.provider,
|
|
609
|
+
error: `could not register password into secrets registry: ${e instanceof Error ? e.message : String(e)}`,
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
return {
|
|
613
|
+
ok: true,
|
|
614
|
+
provider: result.provider,
|
|
615
|
+
username: result.username,
|
|
616
|
+
aliasName,
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
function stripInternal(r) {
|
|
620
|
+
const { _password, ...rest } = r;
|
|
621
|
+
return rest;
|
|
622
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const DEFAULT_ACTION_TIMEOUT_MS = 5000;
|
|
2
|
+
export declare const MIN_ACTION_TIMEOUT_MS = 1;
|
|
3
|
+
export declare const MAX_ACTION_TIMEOUT_MS = 3600000;
|
|
4
|
+
export declare class DeadlineError extends Error {
|
|
5
|
+
readonly label: string;
|
|
6
|
+
readonly ms: number;
|
|
7
|
+
constructor(label: string, ms: number);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Clamp a requested timeout into [MIN, MAX]. Returns the effective value plus
|
|
11
|
+
* an optional warning when the request was out of range (so the tool can
|
|
12
|
+
* surface "you asked for an insane timeout; clamped").
|
|
13
|
+
*/
|
|
14
|
+
export declare function clampTimeout(requested: number | undefined, fallback: number): {
|
|
15
|
+
ms: number;
|
|
16
|
+
warning?: string;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Race `p` against `ms`. Rejects with `DeadlineError` on expiry. The timer is
|
|
20
|
+
* always cleared (no leaked handles) whichever side wins.
|
|
21
|
+
*/
|
|
22
|
+
export declare function withDeadline<T>(p: Promise<T>, ms: number, label: string): Promise<T>;
|