@xopcai/xopc 0.0.251 → 0.0.252
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/README.md +8 -5
- package/README.zh-CN.md +8 -5
- package/dist/browser-ext/dist/background.js +358 -768
- package/dist/browser-ext/manifest.json +1 -2
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{activity-store-DfBjTSo9.js → activity-store-w3eq3YpP.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-Bo_dmLv8.js → agent-avatar-dicebear-k039rbUz.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-defaults-settings-panel-kILWelNb.js → agent-defaults-settings-panel-D4J4oq8p.js} +1 -1
- package/dist/gateway/static/root/assets/{agents-yuUn8n-f.js → agents-Bmth_bSQ.js} +1 -1
- package/dist/gateway/static/root/assets/{api-zxpcJfgj.js → api-2joIfbrH.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-Cz56nrVF.js → app-management-settings-panel-ByJ4kiD0.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-DxSws5U4.js → appearance-settings-BK2Jga-B.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-B3ky7cWU.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-7k15-hqo.js → archive-plugin-DMDKtYpi.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-B-SFpjd9.js → attachment-load-B764Ql3Z.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-Qy36j19q.js → automations-page-D-sO8CZe.js} +1 -1
- package/dist/gateway/static/root/assets/automations-workspace-Ds5-_-9z.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-CPOZQt8F.js → binary-plugins-fxtzYRpv.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-DhvVlIp9.js → block-editor-Bcjtvckh.js} +3 -3
- package/dist/gateway/static/root/assets/browser-automation-inputs-BSmnusjD.js +1 -0
- package/dist/gateway/static/root/assets/browser-automations-page-DC_OQIBk.js +3 -0
- package/dist/gateway/static/root/assets/browser-settings-page-C1FojyG6.js +3 -0
- package/dist/gateway/static/root/assets/capabilities-settings-panel-Bs59UCut.js +7 -0
- package/dist/gateway/static/root/assets/channels-settings-CM9vNmoo.js +1 -0
- package/dist/gateway/static/root/assets/{channels-status-swr-CX-yWwLD.js → channels-status-swr-BuWjIG_a.js} +1 -1
- package/dist/gateway/static/root/assets/{chat-terminal-dock-1PJoxRuV.js → chat-terminal-dock-5SevEo_I.js} +2 -2
- package/dist/gateway/static/root/assets/connectors-page-BPZ44D-V.js +2 -0
- package/dist/gateway/static/root/assets/{cron-expression-CBCc6zFA.js → cron-expression-DtsfalBM.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-u8K5Kt_N.js → date-picker-tDEQV5TP.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-y_i_cnpz.js → dependency-picker-HhNwg0Y2.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-DyL0JxLm.js → desktop-pet-acU4Li-C.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-d2d_IsyP.js → desktop-pet-settings-R84AR0Pe.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-DqIBKJwl.js → extension-debug-page-CrLlRkSN.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-DUW1xxj2.js → extension-page-BH5lmZXE.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-BHY9qaNw.js → extension-settings-page-BscjNAd1.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-CMNbl0FZ.js → gateway-config-swr-9HidFZUd.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-settings-BxLcW6ij.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-startup-retry-CR7Xg8As.js → gateway-startup-retry-DRCPXONr.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-7CD9iPR7.js → heartbeat-settings-K5Zhl2rx.js} +1 -1
- package/dist/gateway/static/root/assets/home-page-CZAg9RBv.js +1 -0
- package/dist/gateway/static/root/assets/{image-generation-api-C5mn73ca.js → image-generation-api-CR6Kle8H.js} +1 -1
- package/dist/gateway/static/root/assets/index-D4Ykja-U.js +72 -0
- package/dist/gateway/static/root/assets/index-zIJ3AXgR.css +2 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BtlqMleF.js → keyboard-shortcuts-settings-B1QR49-7.js} +1 -1
- package/dist/gateway/static/root/assets/{local-app-workbench-page-BjxfkjxE.js → local-app-workbench-page-wicoV-ti.js} +2 -2
- package/dist/gateway/static/root/assets/{local-apps-page-B7xqQe2s.js → local-apps-page-C74It-T8.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-CF4erhjB.js → locale-store-BfZGZKSs.js} +1 -1
- package/dist/gateway/static/root/assets/{logs-page-kACaPZKL.js → logs-page-xX-7S49A.js} +2 -2
- package/dist/gateway/static/root/assets/{management-settings-A432siER.js → management-settings-1kNnYL97.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-view-CQvzsE24.js → markdown-view-DjiwT28p.js} +2 -2
- package/dist/gateway/static/root/assets/{media-plugins-CpvYiauZ.js → media-plugins-B5c0AoS1.js} +1 -1
- package/dist/gateway/static/root/assets/messages-DaIwVWar.js +3 -0
- package/dist/gateway/static/root/assets/{mobile-pairing-wizard-DyjVGngO.js → mobile-pairing-wizard-CsIZqK51.js} +1 -1
- package/dist/gateway/static/root/assets/note-detail-panel-CfWxopl4.js +5 -0
- package/dist/gateway/static/root/assets/notes-page-CYN-LCHJ.js +8 -0
- package/dist/gateway/static/root/assets/{page-tabs-B3FKzjR6.js → page-tabs-CqJN6Ljz.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-DnjrwAHD.js → preview-open-alternatives-DqRIGxf4.js} +1 -1
- package/dist/gateway/static/root/assets/{product-open-page-COcr_NUJ.js → product-open-page-DE2nPE_K.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-B5G3LzDq.js +1 -0
- package/dist/gateway/static/root/assets/{projects-page-BzH8pjEz.js → projects-page-CuVK2mKu.js} +1 -1
- package/dist/gateway/static/root/assets/{registry-api-BsRBlji7.js → registry-api-Bpy8XX-5.js} +1 -1
- package/dist/gateway/static/root/assets/remote-access-hub-Dnd73xWt.js +1 -0
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-LO4wZ_dO.js → runtime-tools-settings-panel-Bb4b74-P.js} +2 -2
- package/dist/gateway/static/root/assets/{schema-form-crcj4-Pm.js → schema-form-DoPU5j3J.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-XL4LyKZe.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-0ForzDSS.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-Bl4MvTmq.js → settings-form-section-Ci-9WajJ.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-DplrjZ6x.js → settings-page-CL_2F95D.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-DVws6XZc.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-CJP1kURj.js → share-preview-page-XUA3oKQX.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-BwDvcacF.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-BJjrATqE.js +1 -0
- package/dist/gateway/static/root/assets/{skills-page-DsjcKg9Q.js → skills-page-sXXAZDc9.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page.utils-D6gWBbvy.js → skills-page.utils-DD79Bl1I.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-_eCXfqCo.js → system-settings-panel-BEH64qBV.js} +1 -1
- package/dist/gateway/static/root/assets/task-detail-page-0jxMi75O.js +1 -0
- package/dist/gateway/static/root/assets/{theme-store-BOgkc_9D.js → theme-store-CISSxU1c.js} +1 -1
- package/dist/gateway/static/root/assets/{tunnel-api-W5mktxl1.js → tunnel-api-DrKDhnJm.js} +1 -1
- package/dist/gateway/static/root/assets/{use-autosave-Na2DYzT3.js → use-autosave-CPYePL-Q.js} +1 -1
- package/dist/gateway/static/root/assets/user-model-page-B6zLDfDl.js +2 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-OXweUxS_.js → voice-api-key-field-DKqzrCXx.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-config-api-C-ryeIxj.js → voice-config-api-e9xWjwBX.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-BqOsO47I.js → work-discovery-overlay-kTQug6bq.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-B9S_lfT1.js → workflow-run-setup-panel-m9SKj_GT.js} +2 -2
- package/dist/gateway/static/root/assets/workflows-page-Bcd1XqP7.js +5 -0
- package/dist/gateway/static/root/index.html +10 -10
- package/dist/package.js +1 -1
- package/dist/packages/gateway-contract/src/new-session.js +9 -0
- package/dist/src/agent/agent-manager.d.ts +2 -1
- package/dist/src/agent/agent-manager.js +6 -5
- package/dist/src/agent/background-review/run-background-review.js +1 -1
- package/dist/src/agent/coding/repository-instructions.js +2 -2
- package/dist/src/agent/coding/workspace-revision.js +2 -2
- package/dist/src/agent/commands/command-isolation.js +2 -2
- package/dist/src/agent/embedded/model-runtime.js +1 -1
- package/dist/src/agent/embedded/run-for-session.js +1 -1
- package/dist/src/agent/external-tools/composio-provider.d.ts +1 -0
- package/dist/src/agent/external-tools/composio-provider.js +64 -34
- package/dist/src/agent/external-tools/search-error.js +5 -3
- package/dist/src/agent/image/tool-model-config.js +1 -1
- package/dist/src/agent/mcp/oauth/mcp-oauth-store.js +1 -1
- package/dist/src/agent/service.js +4 -3
- package/dist/src/agent/service.types.d.ts +2 -1
- package/dist/src/agent/session/session-inspector.js +1 -1
- package/dist/src/agent/skills/hub-lock.js +1 -1
- package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js +4 -0
- package/dist/src/agent/tasks/task-judge-service.js +3 -3
- package/dist/src/agent/tool-manuals/browser.d.ts +1 -1
- package/dist/src/agent/tool-manuals/browser.js +15 -226
- package/dist/src/agent/tools/browser/tool/browser-use-tool.d.ts +4 -21
- package/dist/src/agent/tools/browser/tool/browser-use-tool.js +48 -165
- package/dist/src/agent/tools/browser/tool/schemas.d.ts +203 -16
- package/dist/src/agent/tools/browser/tool/schemas.js +146 -16
- package/dist/src/agent/tools/browser-automation-tool.d.ts +121 -0
- package/dist/src/agent/tools/browser-automation-tool.js +197 -0
- package/dist/src/agent/tools/factory.d.ts +6 -9
- package/dist/src/agent/tools/factory.js +28 -55
- package/dist/src/agent/tools/index.d.ts +2 -2
- package/dist/src/agent/tools/index.js +3 -3
- package/dist/src/agent/tools/review-workspace.js +2 -2
- package/dist/src/ai-assist/text-assist.js +1 -1
- package/dist/src/auth/credentials.js +2 -2
- package/dist/src/auth/oauth/xopc-cloud.js +3 -1
- package/dist/src/auth/profiles/store.js +1 -1
- package/dist/src/auth/sync-provider-auth.js +2 -2
- package/dist/src/automations/domain/defaults.js +1 -1
- package/dist/src/automations/domain/types.d.ts +5 -5
- package/dist/src/automations/domain/validation.d.ts +12 -12
- package/dist/src/automations/domain/validation.js +3 -3
- package/dist/src/automations/draft/automation-draft-validator.d.ts +3 -3
- package/dist/src/automations/draft/automation-draft-validator.js +1 -1
- package/dist/src/automations/service/action-executor.d.ts +1 -1
- package/dist/src/automations/service/action-executor.js +7 -7
- package/dist/src/browser/{recipes → automations}/index.d.ts +1 -0
- package/dist/src/browser/automations/index.js +4 -0
- package/dist/src/browser/automations/repository.d.ts +13 -0
- package/dist/src/browser/automations/repository.js +60 -0
- package/dist/src/browser/automations/runner.d.ts +17 -0
- package/dist/src/browser/automations/runner.js +173 -0
- package/dist/src/browser/automations/runtime-service.d.ts +6 -0
- package/dist/src/browser/automations/runtime-service.js +37 -0
- package/dist/src/browser/automations/schema.d.ts +144 -0
- package/dist/src/browser/automations/schema.js +135 -0
- package/dist/src/browser/automations/service.d.ts +146 -0
- package/dist/src/browser/automations/service.js +168 -0
- package/dist/src/browser/automations/types.d.ts +90 -0
- package/dist/src/browser/cache-dir-policy.d.ts +1 -1
- package/dist/src/browser/cache-dir-policy.js +1 -4
- package/dist/src/browser/drivers/browser-driver.d.ts +17 -0
- package/dist/src/browser/drivers/create-driver.d.ts +3 -0
- package/dist/src/browser/drivers/create-driver.js +84 -0
- package/dist/src/browser/drivers/extension-driver.d.ts +20 -0
- package/dist/src/browser/drivers/extension-driver.js +47 -0
- package/dist/src/browser/drivers/playwright-driver.d.ts +38 -0
- package/dist/src/browser/drivers/playwright-driver.js +406 -0
- package/dist/src/browser/index.d.ts +10 -15
- package/dist/src/browser/index.js +10 -15
- package/dist/src/browser/install-lock.d.ts +1 -2
- package/dist/src/browser/install-lock.js +3 -9
- package/dist/src/browser/install-progress.d.ts +1 -1
- package/dist/src/browser/observation/format.d.ts +2 -0
- package/dist/src/browser/observation/format.js +26 -0
- package/dist/src/browser/policy/approval-store.d.ts +17 -0
- package/dist/src/browser/policy/approval-store.js +62 -0
- package/dist/src/browser/policy/browser-policy.d.ts +3 -0
- package/dist/src/browser/policy/browser-policy.js +27 -0
- package/dist/src/browser/providers/browser-ext-install.d.ts +1 -1
- package/dist/src/browser/providers/browser-ext-install.js +4 -6
- package/dist/src/browser/providers/browser-use.js +1 -1
- package/dist/src/browser/providers/browserbase.js +1 -1
- package/dist/src/browser/providers/extension-ws-acquire.d.ts +1 -4
- package/dist/src/browser/providers/extension-ws-acquire.js +1 -13
- package/dist/src/browser/providers/extension.d.ts +3 -22
- package/dist/src/browser/providers/extension.js +7 -15
- package/dist/src/browser/providers/index.d.ts +2 -2
- package/dist/src/browser/providers/index.js +3 -3
- package/dist/src/browser/providers/types.d.ts +0 -94
- package/dist/src/browser/readiness.d.ts +4 -22
- package/dist/src/browser/readiness.js +55 -118
- package/dist/src/browser/runtime/browser-runtime.d.ts +30 -0
- package/dist/src/browser/runtime/browser-runtime.js +362 -0
- package/dist/src/browser/url-policy.d.ts +3 -3
- package/dist/src/browser/url-policy.js +7 -6
- package/dist/src/browser/verification/expectation.d.ts +2 -0
- package/dist/src/browser/verification/expectation.js +17 -0
- package/dist/src/cli/command-loaders.js +1 -0
- package/dist/src/cli/command-manifest.js +5 -1
- package/dist/src/cli/commands/browser-cli-helpers.d.ts +0 -6
- package/dist/src/cli/commands/browser-cli-helpers.js +11 -144
- package/dist/src/cli/commands/browser.d.ts +0 -5
- package/dist/src/cli/commands/browser.js +11 -152
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/doctor/checks/node-version.js +25 -9
- package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
- package/dist/src/cli/commands/models.js +1 -1
- package/dist/src/cli/commands/platform.d.ts +1 -0
- package/dist/src/cli/commands/platform.js +111 -0
- package/dist/src/config/index.js +4 -4
- package/dist/src/config/loader.js +10 -4
- package/dist/src/config/models-json.js +1 -1
- package/dist/src/config/schema.d.ts +131 -84
- package/dist/src/config/schema.js +112 -59
- package/dist/src/connectors/composio-sessions.js +1 -3
- package/dist/src/extensions/lockfile.js +1 -1
- package/dist/src/extensions/marketplace.js +4 -0
- package/dist/src/gateway/agents-admin.js +1 -1
- package/dist/src/gateway/file-path-classifier.js +1 -1
- package/dist/src/gateway/heartbeat/service.js +1 -1
- package/dist/src/gateway/hono/lib/config-payload.d.ts +12 -26
- package/dist/src/gateway/hono/lib/config-payload.js +11 -40
- package/dist/src/gateway/hono/routes/browser-automations.d.ts +3 -0
- package/dist/src/gateway/hono/routes/browser-automations.js +77 -0
- package/dist/src/gateway/hono/routes/browser-install.js +0 -32
- package/dist/src/gateway/hono/routes/browser.d.ts +0 -17
- package/dist/src/gateway/hono/routes/browser.js +46 -568
- package/dist/src/gateway/hono/routes/config-patch/misc.js +8 -1
- package/dist/src/gateway/hono/routes/config.js +0 -11
- package/dist/src/gateway/hono/routes/lazy-bundles.js +5 -5
- package/dist/src/gateway/hono/routes/models.js +1 -1
- package/dist/src/gateway/service/config-coordinator.js +1 -1
- package/dist/src/gateway/service.d.ts +4 -6
- package/dist/src/gateway/service.js +24 -27
- package/dist/src/heartbeat/index.js +1 -1
- package/dist/src/platform/client.d.ts +121 -0
- package/dist/src/platform/client.js +108 -0
- package/dist/src/platform/contracts.d.ts +194 -0
- package/dist/src/platform/contracts.js +150 -0
- package/dist/src/platform/index.d.ts +4 -0
- package/dist/src/platform/index.js +9 -0
- package/dist/src/platform/resolution.d.ts +4 -0
- package/dist/src/platform/resolution.js +16 -0
- package/dist/src/platform/worker.d.ts +6 -0
- package/dist/src/platform/worker.js +75 -0
- package/dist/src/providers/auth-runtime/resolve-auth.js +1 -1
- package/dist/src/providers/index.js +2 -2
- package/dist/src/providers/model-registry.js +1 -1
- package/dist/src/providers/register-runtime-providers.js +1 -1
- package/dist/src/providers/xopc-cloud-config.js +3 -1
- package/dist/src/session/session-context-for-llm.js +41 -1
- package/dist/src/share/hosted-session-share.js +3 -1
- package/dist/src/share/share-thumbnail.js +1 -1
- package/dist/src/storage/sqlite/migrations/153_browser_control_v2.sql +45 -0
- package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
- package/dist/src/storage/sqlite/migrations/runner.js +3 -3
- package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/storage/sqlite/schema.sql +16 -20
- package/dist/src/tasks/home-query-service.js +1 -1
- package/dist/src/tui/tui-startup-resources.js +1 -1
- package/dist/src/tui/tui.js +1 -1
- package/dist/src/tunnel/env.js +3 -1
- package/dist/src/work-discovery/service.js +1 -1
- package/dist/src/workflows/service/workflow-run-service.js +1 -1
- package/package.json +6 -6
- package/dist/gateway/static/root/assets/apps-page-BnizTdgs.js +0 -1
- package/dist/gateway/static/root/assets/automations-workspace-CZRKqSqY.js +0 -6
- package/dist/gateway/static/root/assets/browser-settings-page-pN5LbChY.js +0 -8
- package/dist/gateway/static/root/assets/browser-workflow-inputs-BX1-uM9L.js +0 -1
- package/dist/gateway/static/root/assets/browser-workflows-page-C65MI57t.js +0 -3
- package/dist/gateway/static/root/assets/capabilities-settings-panel-CJw2e16J.js +0 -7
- package/dist/gateway/static/root/assets/channels-settings-CRgjb4Ck.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-Dcpdy06y.js +0 -2
- package/dist/gateway/static/root/assets/gateway-config-api-e3BRcgDx.js +0 -1
- package/dist/gateway/static/root/assets/gateway-settings-Cheo0Rkc.js +0 -1
- package/dist/gateway/static/root/assets/home-page-DVrTRqNc.js +0 -1
- package/dist/gateway/static/root/assets/index-B7CX4Qob.css +0 -2
- package/dist/gateway/static/root/assets/index-BHrpyJ4t.js +0 -72
- package/dist/gateway/static/root/assets/messages-Cf5hpZE6.js +0 -3
- package/dist/gateway/static/root/assets/note-detail-panel-CUd8O4K7.js +0 -5
- package/dist/gateway/static/root/assets/notes-page-BLQwd39W.js +0 -8
- package/dist/gateway/static/root/assets/project-detail-page-NttW338u.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-BxpjSDnL.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-BLMaibOb.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-BRvvKhoH.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-DTOsxQC1.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-CemgzEi4.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-BWYanBlQ.js +0 -1
- package/dist/gateway/static/root/assets/task-detail-page-D0Z_K5JT.js +0 -1
- package/dist/gateway/static/root/assets/user-model-page-B_-SNat-.js +0 -2
- package/dist/gateway/static/root/assets/workflows-page-CNOT2Coo.js +0 -5
- package/dist/src/agent/tools/browser-recipe-tool.d.ts +0 -12
- package/dist/src/agent/tools/browser-recipe-tool.js +0 -113
- package/dist/src/browser/actions/extension-registry-bridge.d.ts +0 -5
- package/dist/src/browser/actions/extension-registry-bridge.js +0 -312
- package/dist/src/browser/actions/registry.d.ts +0 -5
- package/dist/src/browser/actions/registry.js +0 -741
- package/dist/src/browser/actions/types.d.ts +0 -65
- package/dist/src/browser/backend-from-config.d.ts +0 -22
- package/dist/src/browser/backend-from-config.js +0 -99
- package/dist/src/browser/browser-command-timeout.d.ts +0 -2
- package/dist/src/browser/browser-command-timeout.js +0 -11
- package/dist/src/browser/cdp-local-launcher.d.ts +0 -35
- package/dist/src/browser/cdp-local-launcher.js +0 -154
- package/dist/src/browser/cdp-supervisor.d.ts +0 -58
- package/dist/src/browser/cdp-supervisor.js +0 -133
- package/dist/src/browser/humanize.d.ts +0 -80
- package/dist/src/browser/humanize.js +0 -363
- package/dist/src/browser/manager.d.ts +0 -50
- package/dist/src/browser/manager.js +0 -251
- package/dist/src/browser/pipeline/output.d.ts +0 -35
- package/dist/src/browser/pipeline/output.js +0 -74
- package/dist/src/browser/pipeline/runner.d.ts +0 -27
- package/dist/src/browser/pipeline/runner.js +0 -453
- package/dist/src/browser/pipeline/schema.d.ts +0 -42
- package/dist/src/browser/pipeline/schema.js +0 -116
- package/dist/src/browser/pipeline/template.d.ts +0 -30
- package/dist/src/browser/pipeline/template.js +0 -112
- package/dist/src/browser/providers/cloakbrowser.d.ts +0 -83
- package/dist/src/browser/providers/cloakbrowser.js +0 -612
- package/dist/src/browser/recipes/index.js +0 -3
- package/dist/src/browser/recipes/repository.d.ts +0 -13
- package/dist/src/browser/recipes/repository.js +0 -81
- package/dist/src/browser/recipes/runtime-service.d.ts +0 -6
- package/dist/src/browser/recipes/runtime-service.js +0 -30
- package/dist/src/browser/recipes/service.d.ts +0 -36
- package/dist/src/browser/recipes/service.js +0 -186
- package/dist/src/browser/recipes/types.d.ts +0 -36
- package/dist/src/browser/schemas.d.ts +0 -53
- package/dist/src/browser/schemas.js +0 -68
- package/dist/src/browser/session-lifecycle.d.ts +0 -40
- package/dist/src/browser/session-lifecycle.js +0 -136
- package/dist/src/browser/snapshot-helpers.d.ts +0 -24
- package/dist/src/browser/snapshot-helpers.js +0 -70
- package/dist/src/browser/stealth.d.ts +0 -46
- package/dist/src/browser/stealth.js +0 -163
- package/dist/src/gateway/hono/routes/browser-workflows.d.ts +0 -3
- package/dist/src/gateway/hono/routes/browser-workflows.js +0 -78
- /package/dist/src/browser/{actions → automations}/types.js +0 -0
- /package/dist/src/browser/{recipes/types.js → drivers/browser-driver.js} +0 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
+
//#region src/browser/policy/approval-store.ts
|
|
3
|
+
const TTL_MS = 600 * 1e3;
|
|
4
|
+
const approvals = /* @__PURE__ */ new Map();
|
|
5
|
+
function createBrowserApproval(sessionKey, input, risk, summary) {
|
|
6
|
+
expireApprovals();
|
|
7
|
+
const argumentsHash = browserArgumentsHash(input);
|
|
8
|
+
const existing = [...approvals.values()].find((approval) => approval.sessionKey === sessionKey && approval.argumentsHash === argumentsHash && approval.status === "pending");
|
|
9
|
+
if (existing) return existing;
|
|
10
|
+
const now = Date.now();
|
|
11
|
+
const approval = {
|
|
12
|
+
id: randomUUID(),
|
|
13
|
+
sessionKey,
|
|
14
|
+
risk,
|
|
15
|
+
action: input.action,
|
|
16
|
+
summary,
|
|
17
|
+
argumentsHash,
|
|
18
|
+
status: "pending",
|
|
19
|
+
createdAt: new Date(now).toISOString(),
|
|
20
|
+
expiresAt: new Date(now + TTL_MS).toISOString()
|
|
21
|
+
};
|
|
22
|
+
approvals.set(approval.id, approval);
|
|
23
|
+
return approval;
|
|
24
|
+
}
|
|
25
|
+
function listBrowserApprovals(sessionKey) {
|
|
26
|
+
expireApprovals();
|
|
27
|
+
return [...approvals.values()].filter((approval) => !sessionKey || approval.sessionKey === sessionKey).sort((left, right) => right.createdAt.localeCompare(left.createdAt));
|
|
28
|
+
}
|
|
29
|
+
function decideBrowserApproval(id, decision) {
|
|
30
|
+
expireApprovals();
|
|
31
|
+
const approval = approvals.get(id);
|
|
32
|
+
if (!approval || approval.status !== "pending") return approval;
|
|
33
|
+
approval.status = decision;
|
|
34
|
+
return approval;
|
|
35
|
+
}
|
|
36
|
+
function consumeBrowserApproval(id, sessionKey, input) {
|
|
37
|
+
expireApprovals();
|
|
38
|
+
const argumentsHash = browserArgumentsHash(input);
|
|
39
|
+
const approval = id ? approvals.get(id) : [...approvals.values()].find((candidate) => candidate.sessionKey === sessionKey && candidate.argumentsHash === argumentsHash && candidate.status === "approved");
|
|
40
|
+
if (!approval || approval.status !== "approved") return false;
|
|
41
|
+
if (approval.sessionKey !== sessionKey || approval.argumentsHash !== argumentsHash) return false;
|
|
42
|
+
approval.status = "consumed";
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
function browserArgumentsHash(input) {
|
|
46
|
+
const canonical = {
|
|
47
|
+
...input,
|
|
48
|
+
approvalId: void 0
|
|
49
|
+
};
|
|
50
|
+
return createHash("sha256").update(JSON.stringify(sortRecursively(canonical))).digest("hex");
|
|
51
|
+
}
|
|
52
|
+
function sortRecursively(value) {
|
|
53
|
+
if (Array.isArray(value)) return value.map(sortRecursively);
|
|
54
|
+
if (!value || typeof value !== "object") return value;
|
|
55
|
+
return Object.fromEntries(Object.entries(value).filter(([, child]) => child !== void 0).sort(([left], [right]) => left.localeCompare(right)).map(([key, child]) => [key, sortRecursively(child)]));
|
|
56
|
+
}
|
|
57
|
+
function expireApprovals() {
|
|
58
|
+
const now = Date.now();
|
|
59
|
+
for (const approval of approvals.values()) if ((approval.status === "pending" || approval.status === "approved") && Date.parse(approval.expiresAt) <= now) approval.status = "expired";
|
|
60
|
+
}
|
|
61
|
+
//#endregion
|
|
62
|
+
export { consumeBrowserApproval, createBrowserApproval, decideBrowserApproval, listBrowserApprovals };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { BrowserActionInput, BrowserNode, BrowserRiskLevel } from '@xopcai/browser-control-contract';
|
|
2
|
+
export declare function classifyBrowserRisk(input: BrowserActionInput, target?: BrowserNode): BrowserRiskLevel;
|
|
3
|
+
export declare function browserRiskNeedsApproval(risk: BrowserRiskLevel): boolean;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//#region src/browser/policy/browser-policy.ts
|
|
2
|
+
const DESTRUCTIVE_PATTERN = /\b(delete|remove|erase|destroy|cancel subscription|关闭账户|删除|移除|注销)\b/i;
|
|
3
|
+
const EXTERNAL_EFFECT_PATTERN = /\b(send|submit|publish|post|pay|buy|purchase|confirm|发送|提交|发布|支付|购买|确认)\b/i;
|
|
4
|
+
function classifyBrowserRisk(input, target) {
|
|
5
|
+
if (input.action === "upload") return "sensitive";
|
|
6
|
+
if (input.action === "fill") {
|
|
7
|
+
if (target?.states.includes("sensitive")) return "sensitive";
|
|
8
|
+
if (input.submit) return "external_effect";
|
|
9
|
+
return "draft";
|
|
10
|
+
}
|
|
11
|
+
if (input.action === "press") {
|
|
12
|
+
if (input.key === "Enter" && target?.states.includes("submit")) return "external_effect";
|
|
13
|
+
return "draft";
|
|
14
|
+
}
|
|
15
|
+
if (input.action === "select" || input.action === "scroll") return "draft";
|
|
16
|
+
if (input.action !== "click") return "read";
|
|
17
|
+
const label = `${target?.role ?? ""} ${target?.name ?? ""} ${target?.description ?? ""}`;
|
|
18
|
+
if (DESTRUCTIVE_PATTERN.test(label)) return "destructive";
|
|
19
|
+
if (target?.states.includes("submit")) return "external_effect";
|
|
20
|
+
if (EXTERNAL_EFFECT_PATTERN.test(label)) return "external_effect";
|
|
21
|
+
return "draft";
|
|
22
|
+
}
|
|
23
|
+
function browserRiskNeedsApproval(risk) {
|
|
24
|
+
return risk === "external_effect" || risk === "destructive" || risk === "sensitive";
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { browserRiskNeedsApproval, classifyBrowserRisk };
|
|
@@ -56,7 +56,7 @@ export declare function ensureBrowserExtensionArtifacts(opts?: {
|
|
|
56
56
|
force?: boolean;
|
|
57
57
|
cacheDir?: string;
|
|
58
58
|
}): Promise<EnsureBrowserExtResult>;
|
|
59
|
-
/** Gateway startup hook: ensure artifacts only while the extension
|
|
59
|
+
/** Gateway startup hook: ensure artifacts only while the extension driver is active. */
|
|
60
60
|
export declare function ensureBrowserExtensionOnStartup(config: Config | undefined): Promise<void>;
|
|
61
61
|
export declare function readInstalledExtensionDir(cacheDir?: string): Promise<string | null>;
|
|
62
62
|
export type BrowserExtensionOpenAction = 'chrome' | 'folder' | 'both';
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { PACKAGE_VERSION, init_package_version } from "../../package-version.js";
|
|
2
2
|
import { createLogger } from "../../utils/logger/index.js";
|
|
3
3
|
import { init_logger } from "../../utils/logger.js";
|
|
4
|
-
import { assertCacheDir, init_cache_dir_policy } from "../cache-dir-policy.js";
|
|
5
|
-
import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.js";
|
|
6
4
|
import { init_paths, resolveBinDir } from "../../config/paths.js";
|
|
7
|
-
import {
|
|
5
|
+
import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.js";
|
|
6
|
+
import { assertCacheDir } from "../cache-dir-policy.js";
|
|
8
7
|
import { resolvePackageRoot } from "../../infra/update-check.js";
|
|
9
8
|
import { dirname, join } from "node:path";
|
|
10
9
|
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
@@ -20,7 +19,6 @@ init_package_version();
|
|
|
20
19
|
init_paths();
|
|
21
20
|
init_write_file_atomic();
|
|
22
21
|
init_logger();
|
|
23
|
-
init_cache_dir_policy();
|
|
24
22
|
const log = createLogger("BrowserExtInstall");
|
|
25
23
|
const META_FILENAME = ".meta.json";
|
|
26
24
|
const STAGING_MAX_AGE_MS = 3600 * 1e3;
|
|
@@ -270,9 +268,9 @@ async function ensureBrowserExtensionArtifacts(opts) {
|
|
|
270
268
|
copied: true
|
|
271
269
|
};
|
|
272
270
|
}
|
|
273
|
-
/** Gateway startup hook: ensure artifacts only while the extension
|
|
271
|
+
/** Gateway startup hook: ensure artifacts only while the extension driver is active. */
|
|
274
272
|
async function ensureBrowserExtensionOnStartup(config) {
|
|
275
|
-
if (
|
|
273
|
+
if (config?.browser.enabled === false || config?.browser.driver.kind !== "extension") return;
|
|
276
274
|
await ensureBrowserExtensionArtifacts();
|
|
277
275
|
}
|
|
278
276
|
async function readInstalledExtensionDir(cacheDir) {
|
|
@@ -23,7 +23,7 @@ var BrowserUseProvider = class {
|
|
|
23
23
|
}
|
|
24
24
|
async connect() {
|
|
25
25
|
const apiKey = this.config.apiKey || process.env.BROWSER_USE_API_KEY;
|
|
26
|
-
if (!apiKey) throw new Error("Browser Use API key not configured (set BROWSER_USE_API_KEY or browser.
|
|
26
|
+
if (!apiKey) throw new Error("Browser Use API key not configured (set BROWSER_USE_API_KEY or browser.driver.apiKey)");
|
|
27
27
|
const response = await fetch("https://api.browser-use.com/api/v1/sessions", {
|
|
28
28
|
method: "POST",
|
|
29
29
|
headers: {
|
|
@@ -23,7 +23,7 @@ var BrowserbaseProvider = class {
|
|
|
23
23
|
}
|
|
24
24
|
async connect() {
|
|
25
25
|
const apiKey = this.config.apiKey || process.env.BROWSERBASE_API_KEY;
|
|
26
|
-
if (!apiKey) throw new Error("Browserbase API key not configured (set BROWSERBASE_API_KEY or browser.
|
|
26
|
+
if (!apiKey) throw new Error("Browserbase API key not configured (set BROWSERBASE_API_KEY or browser.driver.apiKey)");
|
|
27
27
|
const projectId = this.config.projectId || process.env.BROWSERBASE_PROJECT_ID;
|
|
28
28
|
const createUrl = "https://www.browserbase.com/v1/sessions";
|
|
29
29
|
const body = {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Single shared HTTP + WebSocket listener for the Chrome extension bridge.
|
|
3
|
-
* Gateway and
|
|
3
|
+
* Gateway and Browser Control sessions share one listener because only one process may bind the port.
|
|
4
4
|
*/
|
|
5
5
|
import type { ExtensionBrowserProvider, ExtensionProviderConfig } from './extension.js';
|
|
6
6
|
export type ExtensionBrowserServerSnapshot = {
|
|
@@ -9,9 +9,6 @@ export type ExtensionBrowserServerSnapshot = {
|
|
|
9
9
|
key: string | null;
|
|
10
10
|
};
|
|
11
11
|
export declare function getExtensionBrowserServerSnapshot(): ExtensionBrowserServerSnapshot;
|
|
12
|
-
export declare function getExtensionBrowserProvider(): ExtensionBrowserProvider | null;
|
|
13
|
-
/** Shut down the shared listener regardless of remaining ref counts (settings UI stop). */
|
|
14
|
-
export declare function forceShutdownExtensionBrowserServer(): Promise<boolean>;
|
|
15
12
|
/**
|
|
16
13
|
* Increment ref count and return the shared provider plus a one-shot release.
|
|
17
14
|
* First acquire starts the listener; further acquires reuse it (same host:port).
|
|
@@ -25,18 +25,6 @@ function getExtensionBrowserServerSnapshot() {
|
|
|
25
25
|
key: state.key
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
|
-
function getExtensionBrowserProvider() {
|
|
29
|
-
return state?.provider ?? null;
|
|
30
|
-
}
|
|
31
|
-
/** Shut down the shared listener regardless of remaining ref counts (settings UI stop). */
|
|
32
|
-
async function forceShutdownExtensionBrowserServer() {
|
|
33
|
-
return withExclusive(async () => {
|
|
34
|
-
if (!state) return false;
|
|
35
|
-
await state.provider.shutdown();
|
|
36
|
-
state = null;
|
|
37
|
-
return true;
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
28
|
function normalizeConfig(config) {
|
|
41
29
|
return {
|
|
42
30
|
port: config?.port ?? DEFAULT_PORT,
|
|
@@ -87,4 +75,4 @@ function acquireExtensionBrowserServer(config) {
|
|
|
87
75
|
});
|
|
88
76
|
}
|
|
89
77
|
//#endregion
|
|
90
|
-
export { acquireExtensionBrowserServer,
|
|
78
|
+
export { acquireExtensionBrowserServer, getExtensionBrowserServerSnapshot };
|
|
@@ -4,21 +4,7 @@
|
|
|
4
4
|
* The xopc process starts a WebSocket server; the Chrome Extension connects as a client.
|
|
5
5
|
* Commands are sent over the WS connection and results are returned asynchronously.
|
|
6
6
|
*/
|
|
7
|
-
|
|
8
|
-
export interface ExtensionCommand {
|
|
9
|
-
id: string;
|
|
10
|
-
action: ExtensionAction;
|
|
11
|
-
tabId?: number;
|
|
12
|
-
args?: Record<string, unknown>;
|
|
13
|
-
timeout?: number;
|
|
14
|
-
}
|
|
15
|
-
export interface ExtensionResult {
|
|
16
|
-
id: string;
|
|
17
|
-
ok: boolean;
|
|
18
|
-
data?: unknown;
|
|
19
|
-
error?: string;
|
|
20
|
-
durationMs?: number;
|
|
21
|
-
}
|
|
7
|
+
import type { BrowserActionInput, BrowserWireResult } from '@xopcai/browser-control-contract';
|
|
22
8
|
export interface ExtensionProviderConfig {
|
|
23
9
|
/** WebSocket server port. Default: 19820. */
|
|
24
10
|
port?: number;
|
|
@@ -48,15 +34,10 @@ export declare class ExtensionBrowserProvider {
|
|
|
48
34
|
start(): Promise<void>;
|
|
49
35
|
/** Wait for the Chrome Extension to connect. */
|
|
50
36
|
waitForConnection(timeoutMs?: number): Promise<void>;
|
|
51
|
-
/** Send
|
|
52
|
-
|
|
53
|
-
tabId?: number;
|
|
54
|
-
timeout?: number;
|
|
55
|
-
}): Promise<ExtensionResult>;
|
|
37
|
+
/** Send one Browser Control v2 action to the extension. */
|
|
38
|
+
send(input: BrowserActionInput, timeoutMs?: number, visualFallback?: boolean): Promise<BrowserWireResult>;
|
|
56
39
|
/** Whether the extension is currently connected. */
|
|
57
40
|
isConnected(): boolean;
|
|
58
|
-
/** Close the Chrome Extension client without stopping the WebSocket server. */
|
|
59
|
-
disconnectClient(): void;
|
|
60
41
|
/** Shutdown the WebSocket server. */
|
|
61
42
|
shutdown(): Promise<void>;
|
|
62
43
|
private _handleMessage;
|
|
@@ -139,22 +139,21 @@ var ExtensionBrowserProvider = class {
|
|
|
139
139
|
});
|
|
140
140
|
});
|
|
141
141
|
}
|
|
142
|
-
/** Send
|
|
143
|
-
async
|
|
142
|
+
/** Send one Browser Control v2 action to the extension. */
|
|
143
|
+
async send(input, timeoutMs, visualFallback = true) {
|
|
144
144
|
if (!this.connected || !this.clientWs) throw new Error("Extension not connected. Ensure the Chrome Extension is installed and connected.");
|
|
145
145
|
const id = `cmd_${++this.commandCounter}_${Date.now()}`;
|
|
146
146
|
const cmd = {
|
|
147
147
|
id,
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
timeout: options?.timeout ?? this.config.commandTimeout
|
|
148
|
+
input,
|
|
149
|
+
timeoutMs: timeoutMs ?? this.config.commandTimeout,
|
|
150
|
+
visualFallback
|
|
152
151
|
};
|
|
153
152
|
return new Promise((resolve, reject) => {
|
|
154
153
|
const timer = setTimeout(() => {
|
|
155
154
|
this.pending.delete(id);
|
|
156
|
-
reject(/* @__PURE__ */ new Error(`
|
|
157
|
-
}, cmd.
|
|
155
|
+
reject(/* @__PURE__ */ new Error(`Browser action timed out: ${input.action} (${cmd.timeoutMs}ms)`));
|
|
156
|
+
}, cmd.timeoutMs);
|
|
158
157
|
this.pending.set(id, {
|
|
159
158
|
resolve,
|
|
160
159
|
reject,
|
|
@@ -173,13 +172,6 @@ var ExtensionBrowserProvider = class {
|
|
|
173
172
|
isConnected() {
|
|
174
173
|
return this.connected;
|
|
175
174
|
}
|
|
176
|
-
/** Close the Chrome Extension client without stopping the WebSocket server. */
|
|
177
|
-
disconnectClient() {
|
|
178
|
-
if (!this.clientWs) return;
|
|
179
|
-
try {
|
|
180
|
-
this.clientWs.close();
|
|
181
|
-
} catch {}
|
|
182
|
-
}
|
|
183
175
|
/** Shutdown the WebSocket server. */
|
|
184
176
|
async shutdown() {
|
|
185
177
|
for (const waiter of this.connectionWaiters) waiter.reject(/* @__PURE__ */ new Error("Provider shutting down"));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type {
|
|
1
|
+
export type { CloudBrowserProvider, CloudBrowserProviderConfig } from './types.js';
|
|
2
2
|
export { BrowserbaseProvider } from './browserbase.js';
|
|
3
3
|
export { BrowserUseProvider } from './browser-use.js';
|
|
4
|
-
export {
|
|
4
|
+
export { ExtensionBrowserProvider } from './extension.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BrowserUseProvider } from "./browser-use.js";
|
|
2
1
|
import { BrowserbaseProvider } from "./browserbase.js";
|
|
3
|
-
import {
|
|
4
|
-
|
|
2
|
+
import { BrowserUseProvider } from "./browser-use.js";
|
|
3
|
+
import { ExtensionBrowserProvider } from "./extension.js";
|
|
4
|
+
export { BrowserUseProvider, BrowserbaseProvider, ExtensionBrowserProvider };
|
|
@@ -1,110 +1,16 @@
|
|
|
1
1
|
import type { Browser, BrowserContext } from 'playwright-core';
|
|
2
|
-
/**
|
|
3
|
-
* Cloud browser provider abstraction — aligned with hermes-agent's multi-backend architecture.
|
|
4
|
-
*
|
|
5
|
-
* Each provider is responsible for creating a Playwright-compatible Browser/Context
|
|
6
|
-
* that the BrowserManager can use interchangeably with local Chromium.
|
|
7
|
-
*/
|
|
8
2
|
export interface CloudBrowserProvider {
|
|
9
|
-
/** Human-readable provider name for logging. */
|
|
10
3
|
readonly name: string;
|
|
11
|
-
/**
|
|
12
|
-
* Connect to the cloud browser and return a Playwright BrowserContext.
|
|
13
|
-
* The provider owns the underlying Browser instance lifecycle.
|
|
14
|
-
*/
|
|
15
4
|
connect(): Promise<{
|
|
16
5
|
browser: Browser;
|
|
17
6
|
context: BrowserContext;
|
|
18
7
|
}>;
|
|
19
|
-
/**
|
|
20
|
-
* Gracefully disconnect from the cloud browser.
|
|
21
|
-
* Called during shutdown or session cleanup.
|
|
22
|
-
*/
|
|
23
8
|
disconnect(): Promise<void>;
|
|
24
|
-
/** Whether the provider is currently connected. */
|
|
25
9
|
isConnected(): boolean;
|
|
26
10
|
}
|
|
27
|
-
/** Configuration needed to instantiate a cloud browser provider. */
|
|
28
11
|
export interface CloudBrowserProviderConfig {
|
|
29
|
-
/** Provider type identifier. */
|
|
30
12
|
type: 'browserbase' | 'browser-use';
|
|
31
|
-
/** API key for the cloud provider. Falls back to provider-specific environment variables. */
|
|
32
13
|
apiKey?: string;
|
|
33
|
-
/** Optional project/session identifier. */
|
|
34
14
|
projectId?: string;
|
|
35
|
-
/** Optional region preference. */
|
|
36
15
|
region?: string;
|
|
37
16
|
}
|
|
38
|
-
/** Configuration for direct CDP WebSocket connection (bypasses cloud provider). */
|
|
39
|
-
export interface CdpConnectionConfig {
|
|
40
|
-
/** WebSocket endpoint URL (e.g. ws://localhost:9222/devtools/browser/...). */
|
|
41
|
-
wsEndpoint: string;
|
|
42
|
-
}
|
|
43
|
-
/** Configuration for the xopc Chrome Extension bridge backend. */
|
|
44
|
-
export interface ExtensionConnectionConfig {
|
|
45
|
-
/** WebSocket server port. Default: 19820. */
|
|
46
|
-
port?: number;
|
|
47
|
-
/** Host to bind. Default: 127.0.0.1. */
|
|
48
|
-
host?: string;
|
|
49
|
-
/** Timeout waiting for extension to connect (ms). Default: 30000. */
|
|
50
|
-
connectionTimeout?: number;
|
|
51
|
-
/** Default command timeout (ms). Default: 30000. */
|
|
52
|
-
commandTimeout?: number;
|
|
53
|
-
}
|
|
54
|
-
import type { BrowserInstallProgress } from '../install-progress.js';
|
|
55
|
-
/** Configuration for CloakBrowser — anti-fingerprint Chromium with stealth capabilities. */
|
|
56
|
-
export interface CloakBrowserConfig {
|
|
57
|
-
/** Directory for cached CloakBrowser binaries. Default: ~/.xopc/bin/cloakbrowser. */
|
|
58
|
-
cacheDir?: string;
|
|
59
|
-
/** Override the CloakBrowser binary path (skip auto-download). */
|
|
60
|
-
binaryPath?: string;
|
|
61
|
-
/** Run headless. Default: false. */
|
|
62
|
-
headless?: boolean;
|
|
63
|
-
/** Fixed CDP debugging port. Default: auto-pick free port, or 9222 if keepOpen. */
|
|
64
|
-
cdpPort?: number;
|
|
65
|
-
/** Keep browser process alive between tasks. Default: true. */
|
|
66
|
-
keepOpen?: boolean;
|
|
67
|
-
/** Reuse an already-running CloakBrowser instance on the same port. Default: false. */
|
|
68
|
-
reuseExisting?: boolean;
|
|
69
|
-
/** Create a temporary profile directory, cleaned up on close. Default: false. */
|
|
70
|
-
temporaryProfile?: boolean;
|
|
71
|
-
/** Persistent user data directory (overrides temporaryProfile). */
|
|
72
|
-
userDataDir?: string;
|
|
73
|
-
/** Extra Chromium launch args (override defaults with same --key= prefix). */
|
|
74
|
-
extraArgs?: string[];
|
|
75
|
-
/** Timezone to emulate (e.g. "America/New_York"). */
|
|
76
|
-
timezone?: string;
|
|
77
|
-
/** Locale to emulate (e.g. "en-US"). */
|
|
78
|
-
locale?: string;
|
|
79
|
-
/** Public IP for WebRTC leak prevention. */
|
|
80
|
-
webrtcIp?: string;
|
|
81
|
-
/** Platform to emulate in fingerprint (e.g. "windows", "macos"). */
|
|
82
|
-
fingerprintPlatform?: string;
|
|
83
|
-
/** Enable humanized input (mouse/keyboard/scroll). Default: true. */
|
|
84
|
-
humanize?: boolean;
|
|
85
|
-
/** Humanize behavior preset. Default: 'careful'. */
|
|
86
|
-
humanPreset?: 'default' | 'careful';
|
|
87
|
-
/** Optional install/download progress callback (gateway SSE, CLI). */
|
|
88
|
-
onProgress?: (progress: BrowserInstallProgress) => void | Promise<void>;
|
|
89
|
-
/** Abort long-running install/download (client disconnect). */
|
|
90
|
-
signal?: AbortSignal;
|
|
91
|
-
/** When true, wait for CDP then return without connecting Playwright (settings "open browser"). */
|
|
92
|
-
skipPlaywrightConnect?: boolean;
|
|
93
|
-
}
|
|
94
|
-
/** Union of all backend connection modes. */
|
|
95
|
-
export type BrowserBackend = {
|
|
96
|
-
mode: 'local';
|
|
97
|
-
headless: boolean;
|
|
98
|
-
} | {
|
|
99
|
-
mode: 'cdp';
|
|
100
|
-
config: CdpConnectionConfig;
|
|
101
|
-
} | {
|
|
102
|
-
mode: 'cloud';
|
|
103
|
-
config: CloudBrowserProviderConfig;
|
|
104
|
-
} | {
|
|
105
|
-
mode: 'extension';
|
|
106
|
-
config?: ExtensionConnectionConfig;
|
|
107
|
-
} | {
|
|
108
|
-
mode: 'cloakbrowser';
|
|
109
|
-
config?: CloakBrowserConfig;
|
|
110
|
-
};
|
|
@@ -1,33 +1,15 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Backend readiness preflight for the `browser_use` tool.
|
|
3
|
-
*
|
|
4
|
-
* Reuses the same doctor functions that power the Settings → Browser page so
|
|
5
|
-
* the agent never tries to launch a backend that the UI already knows is
|
|
6
|
-
* broken. Produces a structured signal the chat surface can render as a
|
|
7
|
-
* "Setup browser" card instead of a bare error string.
|
|
8
|
-
*/
|
|
9
1
|
import type { Config } from '../config/schema.js';
|
|
10
|
-
export type
|
|
11
|
-
export type BrowserNotReadyReason = 'extension_not_installed' | '
|
|
2
|
+
export type BrowserDriverKind = Config['browser']['driver']['kind'];
|
|
3
|
+
export type BrowserNotReadyReason = 'extension_not_installed' | 'extension_not_connected' | 'chromium_missing' | 'cdp_unreachable' | 'remote_api_key_missing';
|
|
12
4
|
export interface BrowserSetupHint {
|
|
13
|
-
|
|
5
|
+
driver: BrowserDriverKind;
|
|
14
6
|
reason: BrowserNotReadyReason;
|
|
15
|
-
/** Raw probe diagnostic; surfaced behind a disclosure for debugging. */
|
|
16
7
|
detail?: string;
|
|
17
|
-
/** Deep link into Settings → Browser focused on the right backend tab. */
|
|
18
8
|
deepLink: string;
|
|
19
9
|
}
|
|
20
10
|
export declare class BrowserNotReadyError extends Error {
|
|
21
11
|
readonly hint: BrowserSetupHint;
|
|
22
12
|
constructor(hint: BrowserSetupHint);
|
|
23
13
|
}
|
|
24
|
-
|
|
25
|
-
export declare function buildBrowserSetupDeepLink(backend: BrowserBackendKind): string;
|
|
26
|
-
/**
|
|
27
|
-
* Probe the currently-configured browser backend. Returns `null` when ready.
|
|
28
|
-
*
|
|
29
|
-
* Probe budget is small (filesystem stats + loopback fetches with a 2s timeout)
|
|
30
|
-
* so it's safe to call before every `browser_use` invocation — but callers
|
|
31
|
-
* typically cache the result for a few seconds to handle bursts.
|
|
32
|
-
*/
|
|
14
|
+
export declare function buildBrowserSetupDeepLink(driver: BrowserDriverKind): string;
|
|
33
15
|
export declare function checkBrowserReadiness(cfg: Config | undefined): Promise<BrowserNotReadyError | null>;
|
|
@@ -1,136 +1,73 @@
|
|
|
1
1
|
import { createLogger } from "../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../utils/logger.js";
|
|
3
|
-
import {
|
|
3
|
+
import { access } from "node:fs/promises";
|
|
4
4
|
//#region src/browser/readiness.ts
|
|
5
5
|
init_logger();
|
|
6
|
-
const log = createLogger("
|
|
6
|
+
const log = createLogger("BrowserReadiness");
|
|
7
7
|
var BrowserNotReadyError = class extends Error {
|
|
8
8
|
constructor(hint) {
|
|
9
|
-
super(`Browser
|
|
9
|
+
super(`Browser driver "${hint.driver}" is not ready: ${hint.reason}`);
|
|
10
10
|
this.hint = hint;
|
|
11
11
|
this.name = "BrowserNotReadyError";
|
|
12
12
|
}
|
|
13
13
|
};
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
return `/settings/agent-browser?tab=${backend}`;
|
|
14
|
+
function buildBrowserSetupDeepLink(driver) {
|
|
15
|
+
return `/settings/agent-browser?driver=${driver}`;
|
|
17
16
|
}
|
|
18
|
-
function hint(backend, reason, detail) {
|
|
19
|
-
return {
|
|
20
|
-
backend,
|
|
21
|
-
reason,
|
|
22
|
-
detail,
|
|
23
|
-
deepLink: buildBrowserSetupDeepLink(backend)
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
async function checkExtension(config) {
|
|
27
|
-
try {
|
|
28
|
-
const { browserExtDoctor } = await import("./providers/browser-ext-install.js");
|
|
29
|
-
if (!(await browserExtDoctor()).installed) return hint("extension", "extension_not_installed", "extension artifacts not on disk");
|
|
30
|
-
} catch (e) {
|
|
31
|
-
return hint("extension", "extension_not_installed", e instanceof Error ? e.message : String(e));
|
|
32
|
-
}
|
|
33
|
-
const host = config?.host?.trim() || "127.0.0.1";
|
|
34
|
-
const port = typeof config?.port === "number" && config.port >= 1024 && config.port <= 65535 ? Math.floor(config.port) : 19820;
|
|
35
|
-
try {
|
|
36
|
-
const { getExtensionBrowserServerSnapshot } = await import("./providers/extension-ws-acquire.js");
|
|
37
|
-
if (getExtensionBrowserServerSnapshot().active) try {
|
|
38
|
-
if ((await (await fetch(`http://${host}:${port}/`, { signal: AbortSignal.timeout(2e3) })).json().catch(() => null))?.connected) return null;
|
|
39
|
-
return hint("extension", "extension_not_connected", "WS bridge is listening but no Chrome Extension client connected yet");
|
|
40
|
-
} catch {
|
|
41
|
-
return hint("extension", "extension_bridge_offline", `health probe failed on ${host}:${port}`);
|
|
42
|
-
}
|
|
43
|
-
return hint("extension", "extension_bridge_offline", `bridge not started on ${host}:${port}`);
|
|
44
|
-
} catch (e) {
|
|
45
|
-
return hint("extension", "extension_bridge_offline", e instanceof Error ? e.message : String(e));
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
async function checkLocal() {
|
|
49
|
-
try {
|
|
50
|
-
const { playwrightChromiumDoctor } = await import("./providers/playwright-doctor.js");
|
|
51
|
-
const doctor = await playwrightChromiumDoctor();
|
|
52
|
-
if (!doctor.installed) return hint("local", "local_chromium_missing", doctor.reason ?? "Chromium binary not found on disk");
|
|
53
|
-
return null;
|
|
54
|
-
} catch (e) {
|
|
55
|
-
return hint("local", "local_chromium_missing", e instanceof Error ? e.message : String(e));
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
async function checkCloak(config) {
|
|
59
|
-
try {
|
|
60
|
-
const { cloakBrowserDoctor } = await import("./providers/cloakbrowser.js");
|
|
61
|
-
const doctor = await cloakBrowserDoctor({
|
|
62
|
-
...config?.cacheDir ? { cacheDir: config.cacheDir } : {},
|
|
63
|
-
...config?.binaryPath ? { binaryPath: config.binaryPath } : {}
|
|
64
|
-
});
|
|
65
|
-
if (!doctor.installed) return hint("cloakbrowser", "cloakbrowser_not_installed", `CloakBrowser binary not found (cacheDir=${doctor.cacheDir})`);
|
|
66
|
-
return null;
|
|
67
|
-
} catch (e) {
|
|
68
|
-
return hint("cloakbrowser", "cloakbrowser_not_installed", e instanceof Error ? e.message : String(e));
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
async function checkCdp(cdpUrl) {
|
|
72
|
-
let httpBase;
|
|
73
|
-
try {
|
|
74
|
-
httpBase = new URL(cdpUrl);
|
|
75
|
-
httpBase.protocol = httpBase.protocol === "wss:" ? "https:" : "http:";
|
|
76
|
-
httpBase.pathname = "/json/version";
|
|
77
|
-
httpBase.search = "";
|
|
78
|
-
httpBase.hash = "";
|
|
79
|
-
} catch (e) {
|
|
80
|
-
return hint("cdp", "cdp_unreachable", `invalid cdpUrl: ${e instanceof Error ? e.message : String(e)}`);
|
|
81
|
-
}
|
|
82
|
-
try {
|
|
83
|
-
const res = await fetch(httpBase.toString(), { signal: AbortSignal.timeout(2e3) });
|
|
84
|
-
if (!res.ok) return hint("cdp", "cdp_unreachable", `HTTP ${res.status} from ${httpBase.toString()}`);
|
|
85
|
-
return null;
|
|
86
|
-
} catch (e) {
|
|
87
|
-
return hint("cdp", "cdp_unreachable", e instanceof Error ? e.message : String(e));
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
function checkCloud(params) {
|
|
91
|
-
if (params.apiKey?.trim()) return null;
|
|
92
|
-
if (params.providerType === "browserbase" ? process.env.BROWSERBASE_API_KEY?.trim() : process.env.BROWSER_USE_API_KEY?.trim()) return null;
|
|
93
|
-
return hint("cloud", "cloud_api_key_missing", `no API key configured for ${params.providerType}`);
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Probe the currently-configured browser backend. Returns `null` when ready.
|
|
97
|
-
*
|
|
98
|
-
* Probe budget is small (filesystem stats + loopback fetches with a 2s timeout)
|
|
99
|
-
* so it's safe to call before every `browser_use` invocation — but callers
|
|
100
|
-
* typically cache the result for a few seconds to handle bursts.
|
|
101
|
-
*/
|
|
102
17
|
async function checkBrowserReadiness(cfg) {
|
|
103
|
-
|
|
104
|
-
|
|
18
|
+
if (!cfg?.browser.enabled) return null;
|
|
19
|
+
const driver = cfg.browser.driver;
|
|
20
|
+
let detail = null;
|
|
21
|
+
let reason = null;
|
|
105
22
|
try {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
probe = checkCloud({
|
|
121
|
-
providerType: backend.config.type,
|
|
122
|
-
apiKey: backend.config.apiKey
|
|
123
|
-
});
|
|
124
|
-
break;
|
|
23
|
+
if (driver.kind === "extension") {
|
|
24
|
+
const { browserExtDoctor } = await import("./providers/browser-ext-install.js");
|
|
25
|
+
if (!(await browserExtDoctor()).installed) {
|
|
26
|
+
reason = "extension_not_installed";
|
|
27
|
+
detail = "Chrome extension artifacts are not installed.";
|
|
28
|
+
}
|
|
29
|
+
} else if (driver.kind === "playwright") if (driver.executablePath) await access(driver.executablePath);
|
|
30
|
+
else {
|
|
31
|
+
const { playwrightChromiumDoctor } = await import("./providers/playwright-doctor.js");
|
|
32
|
+
const doctor = await playwrightChromiumDoctor();
|
|
33
|
+
if (!doctor.installed) {
|
|
34
|
+
reason = "chromium_missing";
|
|
35
|
+
detail = doctor.reason ?? "Chromium binary was not found.";
|
|
36
|
+
}
|
|
125
37
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
38
|
+
else if (driver.kind === "cdp") {
|
|
39
|
+
const probe = new URL(driver.endpoint);
|
|
40
|
+
probe.protocol = probe.protocol === "wss:" ? "https:" : "http:";
|
|
41
|
+
probe.pathname = "/json/version";
|
|
42
|
+
probe.search = "";
|
|
43
|
+
probe.hash = "";
|
|
44
|
+
const response = await fetch(probe, { signal: AbortSignal.timeout(2e3) });
|
|
45
|
+
if (!response.ok) {
|
|
46
|
+
reason = "cdp_unreachable";
|
|
47
|
+
detail = `CDP endpoint returned HTTP ${response.status}.`;
|
|
48
|
+
}
|
|
49
|
+
} else {
|
|
50
|
+
const envKey = driver.provider === "browserbase" ? process.env.BROWSERBASE_API_KEY : process.env.BROWSER_USE_API_KEY;
|
|
51
|
+
if (!driver.apiKey?.trim() && !envKey?.trim()) {
|
|
52
|
+
reason = "remote_api_key_missing";
|
|
53
|
+
detail = `No API key is configured for ${driver.provider}.`;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
} catch (error) {
|
|
57
|
+
log.debug({
|
|
58
|
+
err: error,
|
|
59
|
+
driver: driver.kind
|
|
60
|
+
}, "Browser readiness probe failed");
|
|
61
|
+
reason = driver.kind === "cdp" ? "cdp_unreachable" : driver.kind === "extension" ? "extension_not_connected" : "chromium_missing";
|
|
62
|
+
detail = error instanceof Error ? error.message : String(error);
|
|
132
63
|
}
|
|
133
|
-
|
|
64
|
+
if (!reason) return null;
|
|
65
|
+
return new BrowserNotReadyError({
|
|
66
|
+
driver: driver.kind,
|
|
67
|
+
reason,
|
|
68
|
+
detail: detail ?? void 0,
|
|
69
|
+
deepLink: buildBrowserSetupDeepLink(driver.kind)
|
|
70
|
+
});
|
|
134
71
|
}
|
|
135
72
|
//#endregion
|
|
136
73
|
export { BrowserNotReadyError, buildBrowserSetupDeepLink, checkBrowserReadiness };
|