kaijibot 2026.8.21 → 2026.8.23
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.en.md +1 -1
- package/README.md +1 -1
- package/dist/.buildstamp +1 -1
- package/dist/abort-Bg5O8Yiz.js +202 -0
- package/dist/abort-cutoff.runtime-CvjKPRCc.js +20 -0
- package/dist/abort-cutoff.runtime.js +1 -1
- package/dist/abort.runtime-UZvtDM6M.js +2 -0
- package/dist/abort.runtime.js +1 -1
- package/dist/acp-cli-BHDaxHbu.js +2171 -0
- package/dist/acp-spawn-BJJ8QbXE.js +1024 -0
- package/dist/acp-stateful-target-driver-DyZ1dneY.js +88 -0
- package/dist/action-agents-Bx5S-ZYL.js +67 -0
- package/dist/action-focus-DGURwLDo.js +124 -0
- package/dist/action-help-7ey3e-V9.js +7 -0
- package/dist/action-info-BxQpOqFZ.js +58 -0
- package/dist/action-kill-C7kGSXgP.js +33 -0
- package/dist/action-list-cwGVroWS.js +21 -0
- package/dist/action-log-DT-bRM9X.js +30 -0
- package/dist/action-send-BNv-Wz-l.js +39 -0
- package/dist/action-spawn-DkEYjxPF.js +46 -0
- package/dist/action-unfocus-CU1WRop0.js +28 -0
- package/dist/agent-BOaVCAE9.js +2 -0
- package/dist/agent-command-0Ie27CS4.js +1479 -0
- package/dist/agent-runner-utils-fBrjJUeq.js +202 -0
- package/dist/agent-runner.runtime-DEArTfVM.js +2825 -0
- package/dist/agent-runner.runtime.js +1 -1
- package/dist/agents/auth-profiles.runtime.js +1 -1
- package/dist/agents/model-catalog.runtime.js +1 -1
- package/dist/agents/models-config.runtime.js +1 -1
- package/dist/agents/pi-model-discovery-runtime.js +1 -1
- package/dist/agents-CH6NQBfT.js +5 -0
- package/dist/agents-DuBi4yGs.js +887 -0
- package/dist/anthropic-vertex-stream-C-dr7gew.js +5666 -0
- package/dist/api-C-d6hJ6R.js +3 -0
- package/dist/api-CWzMTsre.js +35 -0
- package/dist/api-CspIEuoI.js +4 -0
- package/dist/api-DWfH8UCU.js +19 -0
- package/dist/api-DnP8S2bH.js +5 -0
- package/dist/api-Y8trG2YC.js +2 -0
- package/dist/api-fZ1Mwhb9.js +2 -0
- package/dist/api-inKLxoen.js +45 -0
- package/dist/api-plrtNPKq.js +2 -0
- package/dist/api-tiV4Lam3.js +2 -0
- package/dist/apply-DyMW1n_a.js +493 -0
- package/dist/apply.runtime-BOvle-IJ.js +166 -0
- package/dist/apply.runtime-C0ny2nmc.js +2 -0
- package/dist/apply.runtime.js +1 -1
- package/dist/approval-client-helpers-Ss4gUaso.js +82 -0
- package/dist/approval-gateway-resolver-D6xh0K2G.js +58 -0
- package/dist/approval-gateway-runtime-CffF6RIQ.js +2 -0
- package/dist/approval-handler-runtime-p9BmT1Xf.js +439 -0
- package/dist/approval-native-runtime-DN73OHKf.js +709 -0
- package/dist/approval-renderers-CITEnajR.js +64 -0
- package/dist/asr-Jt-OmxEb.js +196 -0
- package/dist/audit-BM_BshdA.js +885 -0
- package/dist/audit-extra.async-Cvm-ViC4.js +847 -0
- package/dist/audit.deep.runtime-Ccabqd1Y.js +2 -0
- package/dist/audit.deep.runtime.js +1 -1
- package/dist/audit.nondeep.runtime-BNrDSb24.js +859 -0
- package/dist/audit.nondeep.runtime.js +1 -1
- package/dist/audit.runtime-BKUEHsrE.js +7 -0
- package/dist/audit.runtime.js +1 -1
- package/dist/auth-Dt8gUUJi.js +181 -0
- package/dist/auth-choice-BC_BWYZD.js +3 -0
- package/dist/auth-choice-BtwWAcEq.js +71 -0
- package/dist/auth-choice-CO__21te.js +353 -0
- package/dist/auth-choice-options-BxgjFsFO.js +104 -0
- package/dist/auth-choice-prompt-B-P39mib.js +2 -0
- package/dist/auth-choice-prompt-Dp7Vptqj.js +36 -0
- package/dist/auth-choice.plugin-providers.runtime-BJqmauZz.js +11 -0
- package/dist/auth-choice.plugin-providers.runtime.js +1 -1
- package/dist/auth-health-CPclIUZ3.js +165 -0
- package/dist/auth-profiles-P49vCUs4.js +438 -0
- package/dist/auth-profiles.runtime-pIuc_0v-.js +7 -0
- package/dist/auth-profiles.runtime.js +1 -1
- package/dist/auto-recall-Dm-J3oEj.js +78 -0
- package/dist/backup-create-DcO0pYFy.js +391 -0
- package/dist/banner-CIw8Yepm.js +2 -0
- package/dist/banner-w4GNKrs6.js +281 -0
- package/dist/binding-routing-upMo3iCO.js +50 -0
- package/dist/binding-targets-C9WygzAM.js +99 -0
- package/dist/bridge-server-Cu0xkN0E.js +103 -0
- package/dist/browser-config-runtime-3QVJiqnP.js +6 -0
- package/dist/browser-control-auth-BkunTzw7.js +120 -0
- package/dist/browser-node-runtime-BusKdg2E.js +12 -0
- package/dist/browser-profiles-BocOxjqC.js +170 -0
- package/dist/browser-runtime-D3goJLF9.js +377 -0
- package/dist/browser-setup-tools-j-IDYASL.js +12 -0
- package/dist/build-info.json +3 -3
- package/dist/bundled/boot-md/handler.js +4 -4
- package/dist/bundled/session-memory/handler.js +2 -2
- package/dist/call-CMDK9Mqx.js +2 -0
- package/dist/call-Cisydyym.js +495 -0
- package/dist/call.runtime-CJUaD_Ck.js +2 -0
- package/dist/call.runtime.js +1 -1
- package/dist/capability-cli-e_bf338W.js +1357 -0
- package/dist/catalog-provider-D5mzbnCM.js +40 -0
- package/dist/cdp.helpers-BqVqEY02.js +372 -0
- package/dist/channel-core-cQ4DROoP.js +5 -0
- package/dist/channel-summary-BHojSrOd.js +139 -0
- package/dist/channel-summary-CzjCL-4-.js +2 -0
- package/dist/channel.runtime-D6e2VBFb.js +399 -0
- package/dist/channel.runtime.js +1 -1
- package/dist/channels-cli-Y-Wnalvd.js +248 -0
- package/dist/channels-uiGUmLk2.js +1147 -0
- package/dist/chat-CQc5lJAu.js +213 -0
- package/dist/chrome-BcU0ZvUn.js +1080 -0
- package/dist/chrome.executables-Dp0Lkjmz.js +550 -0
- package/dist/cli/daemon-cli.js +1 -1
- package/dist/cli-BGB7qdp3.js +191 -0
- package/dist/cli-BtTS8CKF.js +2 -0
- package/dist/cli-CQX3q4Fm.js +57 -0
- package/dist/cli-ZLAF588A.js +154 -0
- package/dist/cli-auth-seam-D-Qci5-b.js +14 -0
- package/dist/cli-backend-DxaeTZ8N.js +66 -0
- package/dist/cli-g4KJW_UT.js +2 -0
- package/dist/cli-migration-B2SFdY0j.js +127 -0
- package/dist/cli-runner-BVQt0v1D.js +1662 -0
- package/dist/cli-runner.runtime-BAMS4uW0.js +3 -0
- package/dist/cli-runner.runtime-H3alxbDK.js +2 -0
- package/dist/cli-runner.runtime.js +1 -1
- package/dist/cli-shared-BaJRfEqD.js +142 -0
- package/dist/cli-startup-metadata.json +2 -2
- package/dist/cli.runtime-CQ1qvGdJ.js +819 -0
- package/dist/cli.runtime.js +1 -1
- package/dist/client-bootstrap-BE7PiMJr.js +28 -0
- package/dist/codex-native-web-search-TdFXLTHZ.js +2 -0
- package/dist/codex-native-web-search-dKQT4ZPV.js +156 -0
- package/dist/collector-BXDPP4rJ.js +2 -0
- package/dist/collector-CT3qBEYi.js +424 -0
- package/dist/command-auth-FR5r0kKW.js +75 -0
- package/dist/command-config-resolution-BfTLOZxI.js +23 -0
- package/dist/command-config-resolution-GV0h_B0u.js +2 -0
- package/dist/command-execution-startup-oMdUg9Py.js +269 -0
- package/dist/command-format-CZ8oMoC9.js +2 -0
- package/dist/command-queue-BlORGS1M.js +260 -0
- package/dist/command-registry-DNKWkedC.js +3 -0
- package/dist/command-registry-DO6fBZ31.js +113 -0
- package/dist/command-secret-gateway-Cnjliq_k.js +528 -0
- package/dist/commands-acp-OeD4TGXU.js +1017 -0
- package/dist/commands-compact.runtime-ZE5b-Pvj.js +10 -0
- package/dist/commands-compact.runtime.js +1 -1
- package/dist/commands-core.runtime-Ca3exd9B.js +2 -0
- package/dist/commands-core.runtime.js +1 -1
- package/dist/commands-handlers.runtime-DKL8ULNw.js +3762 -0
- package/dist/commands-handlers.runtime.js +1 -1
- package/dist/commands-models-uaQEC1GX.js +306 -0
- package/dist/commands-reset-hooks-0RFpUGBC.js +129 -0
- package/dist/commands-status-4HTjDVIN.js +223 -0
- package/dist/commands-status.runtime-CyJiWLQs.js +2 -0
- package/dist/commands-status.runtime.js +1 -1
- package/dist/commands-subagents-control.runtime-B3DtD7Se.js +3 -0
- package/dist/commands-subagents-control.runtime-BLHWicyx.js +2 -0
- package/dist/commands-subagents-control.runtime.js +1 -1
- package/dist/commands.runtime-Bk9-pUEs.js +103 -0
- package/dist/commands.runtime.js +1 -1
- package/dist/comment-shared-BCggDOtV.js +40 -0
- package/dist/compact-CBJu2_ft.js +11324 -0
- package/dist/compact.runtime-Bj3PGRRh.js +7 -0
- package/dist/compact.runtime.js +1 -1
- package/dist/completion-cli-B27D7vni.js +468 -0
- package/dist/completion-cli-QdkbM0Vz.js +2 -0
- package/dist/config-BZb7_jO5.js +166 -0
- package/dist/config-C2M27bOw.js +8 -0
- package/dist/config-D_fICGrQ.js +53 -0
- package/dist/config-cli-B7j3KePQ.js +948 -0
- package/dist/config-defaults-XFEo6I7v.js +163 -0
- package/dist/config-guard-wGGj2x7b.js +94 -0
- package/dist/config-runtime-xwO8vvQP.js +14 -0
- package/dist/config-validation-tPbNhbrH.js +279 -0
- package/dist/configure-CXFWPXal.js +1162 -0
- package/dist/configure-lBR_2rAt.js +2 -0
- package/dist/connection-auth-ClCO21bT.js +30 -0
- package/dist/context-CJMC7SyI.js +249 -0
- package/dist/context-CWC_tVM8.js +2 -0
- package/dist/context-writer-DNkMBOu9.js +290 -0
- package/dist/control-auth-DUZs9D8n.js +122 -0
- package/dist/control-ui/assets/agents-HENIRhRj.js +767 -0
- package/dist/control-ui/assets/anthropic-DlOZcqqy.js +40 -0
- package/dist/control-ui/assets/azure-openai-responses-BmSDwKAQ.js +2 -0
- package/dist/control-ui/assets/cron-B2CJajqc.js +744 -0
- package/dist/control-ui/assets/dialogues-DmWmdbMF.js +83 -0
- package/dist/control-ui/assets/history-CP7LOJan.js +71 -0
- package/dist/control-ui/assets/index-BsGBtIKy.css +1 -0
- package/dist/control-ui/assets/index-BtNFbQhY.js +2686 -0
- package/dist/control-ui/assets/mistral-CYEJ-E7G.js +72 -0
- package/dist/control-ui/assets/openai-codex-responses-BnLjDxo3.js +8 -0
- package/dist/control-ui/assets/openai-completions-D46D4eD2.js +6 -0
- package/dist/control-ui/assets/openai-responses-CNVWXuC0.js +2 -0
- package/dist/control-ui/assets/openai-responses-shared-ByeOE-gc.js +13 -0
- package/dist/control-ui/index.html +2 -2
- package/dist/conversation-id-DlazDTmW.js +140 -0
- package/dist/conversation-runtime-BjljNAU1.js +31 -0
- package/dist/core-4Dt1_PpO.js +210 -0
- package/dist/cron-cli-CTGN3Kum.js +637 -0
- package/dist/curator-BM2jeaou.js +600 -0
- package/dist/curator-_QLWjb7r.js +2 -0
- package/dist/daemon-cli-BLe7aLfJ.js +476 -0
- package/dist/daemon-install-BneaHOcs.js +70 -0
- package/dist/delegate-CyUm6mk6.js +61 -0
- package/dist/deliver-BvUx9v-a.js +3 -0
- package/dist/deliver-DQbRPHSb.js +782 -0
- package/dist/deliver-runtime-ERlRZAW4.js +2 -0
- package/dist/delivery-outbound.runtime-Bi6Lu4JP.js +6 -0
- package/dist/delivery-outbound.runtime.js +1 -1
- package/dist/delivery-queue-B4kCxhnW.js +2 -0
- package/dist/delivery-queue-DDHwRyN-.js +372 -0
- package/dist/deps-DZQeVHSD.js +60 -0
- package/dist/devices-cli-CFSjN2KZ.js +336 -0
- package/dist/diagnostic-Bh12mVkv.js +311 -0
- package/dist/direct-dm-Bn07LLbq.js +139 -0
- package/dist/directive-handling.fast-lane-Cd6SSr-l.js +64 -0
- package/dist/directive-handling.fast-lane-ejwgECy7.js +2 -0
- package/dist/directive-handling.impl-Bpy5KQZr.js +659 -0
- package/dist/directive-handling.impl-ZEKrT-pi.js +2 -0
- package/dist/directive-handling.parse-COyCTXvI.js +376 -0
- package/dist/directive-handling.persist-CgxhTMmz.js +139 -0
- package/dist/directive-handling.persist.runtime-4pppF2CM.js +2 -0
- package/dist/directive-handling.persist.runtime.js +1 -1
- package/dist/directive-handling.shared-BuNzwbwp.js +159 -0
- package/dist/directory-cli-gWQfdmFR.js +240 -0
- package/dist/dispatch-Cg_O6HsU.js +1126 -0
- package/dist/dispatch-acp-C7kPkeqX.js +969 -0
- package/dist/dispatch-acp-manager.runtime-Bh3V5wGh.js +3 -0
- package/dist/dispatch-acp-manager.runtime.js +1 -1
- package/dist/dispatch-acp-media.runtime-pWY6A7VY.js +3 -0
- package/dist/dispatch-acp-media.runtime.js +1 -1
- package/dist/dispatch-acp-session.runtime-DdkuSkq8.js +2 -0
- package/dist/dispatch-acp-session.runtime.js +1 -1
- package/dist/dispatch-acp.runtime-fr_7acr8.js +19 -0
- package/dist/dispatch-acp.runtime.js +1 -1
- package/dist/dns-cli-C4uepTJE.js +193 -0
- package/dist/docs-cli-DWzfteG6.js +156 -0
- package/dist/doctor-completion-D2s3ieS6.js +90 -0
- package/dist/doctor-config-preflight-BIf8igIW.js +148 -0
- package/dist/doctor-config-preflight-BiJSPUPg.js +2 -0
- package/dist/doctor-state-migrations-BbfPLoLz.js +2 -0
- package/dist/doctor-state-migrations-DFQets45.js +3 -0
- package/dist/drive-CvbBPFcl.js +718 -0
- package/dist/embedding-provider-DUT_HxYD.js +26 -0
- package/dist/embedding-provider-DjVEIg-4.js +33 -0
- package/dist/embedding-provider-TKNNnQ3m.js +129 -0
- package/dist/engine-CT4xJJ-H.js +82 -0
- package/dist/engine-embeddings-BN4uJOv0.js +1489 -0
- package/dist/entry-capabilities-BhpTqh0w.js +89 -0
- package/dist/entry.js +2 -2
- package/dist/env-overrides-Dn5yy0l4.js +347 -0
- package/dist/env-overrides.runtime-DdD841Km.js +7 -0
- package/dist/env-overrides.runtime.js +1 -1
- package/dist/exec-approval-forwarder.runtime-CV81fvQh.js +3 -0
- package/dist/exec-approval-forwarder.runtime.js +1 -1
- package/dist/exec-approval-reply-C_NfihTE.js +292 -0
- package/dist/exec-approvals-cli-DKOFcUAn.js +485 -0
- package/dist/exec-defaults-Cs1FwIKH.js +1440 -0
- package/dist/extensionAPI.js +4 -4
- package/dist/extensions/alibaba/index.js +1 -1
- package/dist/extensions/alibaba/video-generation-provider.js +1 -1
- package/dist/extensions/anthropic/api.js +2 -2
- package/dist/extensions/anthropic/cli-auth-seam.js +1 -1
- package/dist/extensions/anthropic/cli-backend-api.js +2 -2
- package/dist/extensions/anthropic/cli-backend.js +1 -1
- package/dist/extensions/anthropic/cli-migration.js +1 -1
- package/dist/extensions/anthropic/cli-shared.js +1 -1
- package/dist/extensions/anthropic/config-defaults.js +1 -1
- package/dist/extensions/anthropic/contract-api.js +1 -1
- package/dist/extensions/anthropic/index.js +1 -1
- package/dist/extensions/anthropic/media-understanding-provider.js +1 -1
- package/dist/extensions/anthropic/provider-policy-api.js +1 -1
- package/dist/extensions/anthropic/register.runtime.js +1 -1
- package/dist/extensions/anthropic/setup-api.js +1 -1
- package/dist/extensions/anthropic/stream-wrappers.js +1 -1
- package/dist/extensions/anthropic/test-api.js +3 -3
- package/dist/extensions/anthropic-vertex/api.js +3 -3
- package/dist/extensions/anthropic-vertex/index.js +2 -2
- package/dist/extensions/anthropic-vertex/provider-catalog.js +1 -1
- package/dist/extensions/anthropic-vertex/region.js +1 -1
- package/dist/extensions/anthropic-vertex/setup-api.js +1 -1
- package/dist/extensions/arcee/index.js +2 -2
- package/dist/extensions/browser/browser-bridge.js +1 -1
- package/dist/extensions/browser/browser-cdp.js +1 -1
- package/dist/extensions/browser/browser-config.js +3 -3
- package/dist/extensions/browser/browser-control-auth.js +1 -1
- package/dist/extensions/browser/browser-doctor.js +4 -4
- package/dist/extensions/browser/browser-host-inspection.js +1 -1
- package/dist/extensions/browser/browser-maintenance.js +2 -2
- package/dist/extensions/browser/browser-profiles.js +1 -1
- package/dist/extensions/browser/browser-runtime-api.js +11 -11
- package/dist/extensions/browser/index.js +1 -1
- package/dist/extensions/browser/plugin-registration.js +1 -1
- package/dist/extensions/browser/register.runtime.js +3 -3
- package/dist/extensions/browser/runtime-api.js +12 -12
- package/dist/extensions/browser/setup-api.js +2 -2
- package/dist/extensions/browser/test-support.js +1 -1
- package/dist/extensions/byteplus/index.js +3 -3
- package/dist/extensions/byteplus/video-generation-provider.js +1 -1
- package/dist/extensions/cerebras/index.js +1 -1
- package/dist/extensions/chutes/api.js +3 -3
- package/dist/extensions/chutes/index.js +7 -7
- package/dist/extensions/chutes/models.js +1 -1
- package/dist/extensions/chutes/onboard.js +2 -2
- package/dist/extensions/chutes/provider-catalog.js +1 -1
- package/dist/extensions/cloudflare-ai-gateway/api.js +1 -1
- package/dist/extensions/cloudflare-ai-gateway/catalog-provider.js +1 -1
- package/dist/extensions/cloudflare-ai-gateway/index.js +6 -6
- package/dist/extensions/deepinfra/api.js +3 -3
- package/dist/extensions/deepinfra/embedding-provider.js +1 -1
- package/dist/extensions/deepinfra/index.js +4 -4
- package/dist/extensions/deepinfra/media-understanding-provider.js +1 -1
- package/dist/extensions/deepinfra/memory-embedding-adapter.js +1 -1
- package/dist/extensions/deepinfra/video-generation-provider.js +1 -1
- package/dist/extensions/deepseek/index.js +1 -1
- package/dist/extensions/device-pair/api.js +2 -2
- package/dist/extensions/device-pair/index.js +5 -5
- package/dist/extensions/device-pair/notify.js +1 -1
- package/dist/extensions/device-pair/pair-command-approve.js +1 -1
- package/dist/extensions/device-pair/qr-image.js +2 -2
- package/dist/extensions/diffs/.kaijibot-runtime-deps-stamp.json +1 -1
- package/dist/extensions/diffs/index.js +1 -1
- package/dist/extensions/diffs/node_modules/.package-lock.json +3 -3
- package/dist/extensions/diffs/node_modules/typebox/build/format/email.mjs +1 -1
- package/dist/extensions/diffs/node_modules/typebox/build/format/idna/idn-hostname.mjs +19 -1
- package/dist/extensions/diffs/node_modules/typebox/package.json +1 -1
- package/dist/extensions/exa/index.js +1 -1
- package/dist/extensions/feishu/.kaijibot-runtime-deps-stamp.json +1 -1
- package/dist/extensions/feishu/api.js +16 -16
- package/dist/extensions/feishu/contract-api.js +2 -2
- package/dist/extensions/feishu/node_modules/.package-lock.json +3 -3
- package/dist/extensions/feishu/node_modules/typebox/build/format/email.mjs +1 -1
- package/dist/extensions/feishu/node_modules/typebox/build/format/idna/idn-hostname.mjs +19 -1
- package/dist/extensions/feishu/node_modules/typebox/package.json +1 -1
- package/dist/extensions/feishu/runtime-api.js +2 -2
- package/dist/extensions/feishu/security-contract-api.js +1 -1
- package/dist/extensions/feishu/session-key-api.js +1 -1
- package/dist/extensions/feishu/setup-api.js +1 -1
- package/dist/extensions/fireworks/index.js +1 -1
- package/dist/extensions/github-copilot/api.js +1 -1
- package/dist/extensions/github-copilot/index.js +6 -6
- package/dist/extensions/github-copilot/login.js +1 -1
- package/dist/extensions/github-copilot/models-defaults.js +1 -1
- package/dist/extensions/github-copilot/models.js +1 -1
- package/dist/extensions/github-copilot/register.runtime.js +4 -4
- package/dist/extensions/github-copilot/replay-policy.js +1 -1
- package/dist/extensions/google/api.js +1 -1
- package/dist/extensions/google/gemini-cli-provider.js +1 -1
- package/dist/extensions/google/image-generation-provider.js +1 -1
- package/dist/extensions/google/index.js +5 -5
- package/dist/extensions/google/media-understanding-provider.js +1 -1
- package/dist/extensions/google/music-generation-provider.js +1 -1
- package/dist/extensions/google/oauth-token-shared.js +1 -1
- package/dist/extensions/google/oauth.credentials.js +1 -1
- package/dist/extensions/google/oauth.flow.js +1 -1
- package/dist/extensions/google/oauth.js +2 -2
- package/dist/extensions/google/oauth.runtime.js +1 -1
- package/dist/extensions/google/oauth.settings.js +1 -1
- package/dist/extensions/google/oauth.token.js +1 -1
- package/dist/extensions/google/provider-models.js +1 -1
- package/dist/extensions/google/provider-registration.js +1 -1
- package/dist/extensions/google/runtime-api.js +2 -2
- package/dist/extensions/google/test-api.js +2 -2
- package/dist/extensions/google/video-generation-provider.js +1 -1
- package/dist/extensions/google/web-search-provider.js +1 -1
- package/dist/extensions/groq/index.js +1 -1
- package/dist/extensions/groq/media-understanding-provider.js +1 -1
- package/dist/extensions/groq/test-api.js +1 -1
- package/dist/extensions/huggingface/api.js +3 -3
- package/dist/extensions/huggingface/index.js +3 -3
- package/dist/extensions/huggingface/models.js +1 -1
- package/dist/extensions/huggingface/onboard.js +1 -1
- package/dist/extensions/huggingface/provider-catalog.js +2 -2
- package/dist/extensions/image-generation-core/api.js +2 -2
- package/dist/extensions/image-generation-core/runtime-api.js +2 -2
- package/dist/extensions/kilocode/api.js +2 -2
- package/dist/extensions/kilocode/index.js +6 -6
- package/dist/extensions/kilocode/onboard.js +2 -2
- package/dist/extensions/kilocode/provider-catalog.js +1 -1
- package/dist/extensions/kilocode/provider-models.js +1 -1
- package/dist/extensions/kilocode/shared.js +1 -1
- package/dist/extensions/kimi-coding/index.js +3 -3
- package/dist/extensions/kindle-portal/.kaijibot-runtime-deps-stamp.json +1 -1
- package/dist/extensions/kindle-portal/node_modules/.package-lock.json +3 -3
- package/dist/extensions/kindle-portal/node_modules/typebox/build/format/email.mjs +1 -1
- package/dist/extensions/kindle-portal/node_modules/typebox/build/format/idna/idn-hostname.mjs +19 -1
- package/dist/extensions/kindle-portal/node_modules/typebox/package.json +1 -1
- package/dist/extensions/knowledge-wiki/index.js +2 -2
- package/dist/extensions/litellm/index.js +1 -1
- package/dist/extensions/llm-task/index.js +1 -1
- package/dist/extensions/lmstudio/api.js +6 -6
- package/dist/extensions/lmstudio/index.js +2 -2
- package/dist/extensions/lmstudio/runtime-api.js +1 -1
- package/dist/extensions/media-understanding-core/runtime-api.js +2 -2
- package/dist/extensions/memory-core/cli-metadata.js +2 -2
- package/dist/extensions/memory-core/index.js +12 -12
- package/dist/extensions/memory-core/manager-runtime.js +1 -1
- package/dist/extensions/memory-core/runtime-api.js +5 -5
- package/dist/extensions/memory-lancedb/cli-metadata.js +1 -1
- package/dist/extensions/memory-lancedb/index.js +1 -1
- package/dist/extensions/microsoft/index.js +1 -1
- package/dist/extensions/microsoft/speech-provider.js +1 -1
- package/dist/extensions/microsoft/test-api.js +1 -1
- package/dist/extensions/microsoft/tts.js +1 -1
- package/dist/extensions/microsoft-foundry/auth.js +1 -1
- package/dist/extensions/microsoft-foundry/cli.js +1 -1
- package/dist/extensions/microsoft-foundry/index.js +1 -1
- package/dist/extensions/microsoft-foundry/onboard.js +2 -2
- package/dist/extensions/microsoft-foundry/provider.js +1 -1
- package/dist/extensions/microsoft-foundry/runtime.js +1 -1
- package/dist/extensions/microsoft-foundry/shared-runtime.js +2 -2
- package/dist/extensions/microsoft-foundry/shared.js +1 -1
- package/dist/extensions/minimax/image-generation-provider.js +1 -1
- package/dist/extensions/minimax/index.js +7 -7
- package/dist/extensions/minimax/media-understanding-provider.js +1 -1
- package/dist/extensions/minimax/music-generation-provider.js +1 -1
- package/dist/extensions/minimax/oauth.js +1 -1
- package/dist/extensions/minimax/oauth.runtime.js +1 -1
- package/dist/extensions/minimax/provider-registration.js +1 -1
- package/dist/extensions/minimax/speech-provider.js +1 -1
- package/dist/extensions/minimax/test-api.js +2 -2
- package/dist/extensions/minimax/video-generation-provider.js +1 -1
- package/dist/extensions/minimax/web-search-provider.js +1 -1
- package/dist/extensions/mistral/embedding-provider.js +1 -1
- package/dist/extensions/mistral/index.js +2 -2
- package/dist/extensions/mistral/media-understanding-provider.js +1 -1
- package/dist/extensions/mistral/memory-embedding-adapter.js +3 -3
- package/dist/extensions/mistral/test-api.js +1 -1
- package/dist/extensions/moonshot/index.js +5 -5
- package/dist/extensions/moonshot/media-understanding-provider.js +1 -1
- package/dist/extensions/moonshot/test-api.js +2 -2
- package/dist/extensions/moonshot/web-search-provider.js +1 -1
- package/dist/extensions/nvidia/index.js +1 -1
- package/dist/extensions/ollama/api.js +3 -3
- package/dist/extensions/ollama/index.js +6 -6
- package/dist/extensions/ollama/runtime-api.js +2 -2
- package/dist/extensions/ollama/web-search-provider.js +1 -1
- package/dist/extensions/openai/api.js +3 -3
- package/dist/extensions/openai/image-generation-provider.js +1 -1
- package/dist/extensions/openai/index.js +9 -9
- package/dist/extensions/openai/media-understanding-provider.js +1 -1
- package/dist/extensions/openai/openai-codex-auth-identity.js +1 -1
- package/dist/extensions/openai/openai-codex-cli-auth.js +1 -1
- package/dist/extensions/openai/openai-codex-provider.js +1 -1
- package/dist/extensions/openai/openai-codex-shared.js +1 -1
- package/dist/extensions/openai/openai-provider.js +1 -1
- package/dist/extensions/openai/prompt-overlay.js +1 -1
- package/dist/extensions/openai/realtime-provider-shared.js +1 -1
- package/dist/extensions/openai/realtime-transcription-provider.js +1 -1
- package/dist/extensions/openai/realtime-voice-provider.js +1 -1
- package/dist/extensions/openai/register.runtime.js +8 -8
- package/dist/extensions/openai/shared.js +1 -1
- package/dist/extensions/openai/speech-provider.js +1 -1
- package/dist/extensions/openai/test-api.js +5 -5
- package/dist/extensions/openai/transport-policy.js +1 -1
- package/dist/extensions/openai/video-generation-provider.js +1 -1
- package/dist/extensions/opencode/index.js +3 -3
- package/dist/extensions/opencode-go/index.js +2 -2
- package/dist/extensions/openrouter/api.js +2 -2
- package/dist/extensions/openrouter/image-generation-provider.js +1 -1
- package/dist/extensions/openrouter/index.js +6 -6
- package/dist/extensions/openrouter/media-understanding-provider.js +1 -1
- package/dist/extensions/openrouter/music-generation-provider.js +1 -1
- package/dist/extensions/openrouter/test-api.js +3 -3
- package/dist/extensions/openrouter/video-generation-provider.js +1 -1
- package/dist/extensions/openshell/index.js +4 -4
- package/dist/extensions/qianfan/index.js +1 -1
- package/dist/extensions/qwen/index.js +3 -3
- package/dist/extensions/qwen/media-understanding-provider.js +1 -1
- package/dist/extensions/qwen/test-api.js +2 -2
- package/dist/extensions/qwen/video-generation-provider.js +1 -1
- package/dist/extensions/runway/index.js +1 -1
- package/dist/extensions/runway/video-generation-provider.js +1 -1
- package/dist/extensions/sglang/api.js +2 -2
- package/dist/extensions/sglang/index.js +2 -2
- package/dist/extensions/sglang/models.js +1 -1
- package/dist/extensions/sherpa-speech/asr.js +1 -1
- package/dist/extensions/sherpa-speech/engine.js +1 -1
- package/dist/extensions/sherpa-speech/index.js +1 -1
- package/dist/extensions/speech-core/api.js +2 -2
- package/dist/extensions/speech-core/runtime-api.js +4 -4
- package/dist/extensions/stepfun/index.js +2 -2
- package/dist/extensions/talk-voice/index.js +3 -3
- package/dist/extensions/tavily/index.js +1 -1
- package/dist/extensions/together/index.js +1 -1
- package/dist/extensions/together/video-generation-provider.js +1 -1
- package/dist/extensions/venice/api.js +3 -3
- package/dist/extensions/venice/index.js +5 -5
- package/dist/extensions/venice/models.js +1 -1
- package/dist/extensions/venice/onboard.js +2 -2
- package/dist/extensions/venice/provider-catalog.js +1 -1
- package/dist/extensions/vercel-ai-gateway/index.js +1 -1
- package/dist/extensions/vllm/api.js +2 -2
- package/dist/extensions/vllm/index.js +2 -2
- package/dist/extensions/vllm/models.js +1 -1
- package/dist/extensions/vllm/register.runtime.js +2 -2
- package/dist/extensions/volcengine/index.js +2 -2
- package/dist/extensions/vydra/image-generation-provider.js +1 -1
- package/dist/extensions/vydra/index.js +5 -5
- package/dist/extensions/vydra/shared.js +1 -1
- package/dist/extensions/vydra/speech-provider.js +1 -1
- package/dist/extensions/vydra/video-generation-provider.js +1 -1
- package/dist/extensions/webhooks/.kaijibot-runtime-deps-stamp.json +1 -1
- package/dist/extensions/webhooks/api.js +1 -1
- package/dist/extensions/webhooks/index.js +3 -3
- package/dist/extensions/webhooks/runtime-api.js +1 -1
- package/dist/extensions/wechat/api.js +3 -3
- package/dist/extensions/xai/api.js +5 -5
- package/dist/extensions/xai/code-execution.js +3 -3
- package/dist/extensions/xai/index.js +9 -9
- package/dist/extensions/xai/model-definitions.js +1 -1
- package/dist/extensions/xai/onboard.js +1 -1
- package/dist/extensions/xai/provider-catalog.js +1 -1
- package/dist/extensions/xai/provider-models.js +1 -1
- package/dist/extensions/xai/setup-api.js +1 -1
- package/dist/extensions/xai/video-generation-provider.js +1 -1
- package/dist/extensions/xai/web-search.js +1 -1
- package/dist/extensions/xai/x-search.js +3 -3
- package/dist/extensions/xiaomi/index.js +1 -1
- package/dist/extensions/zai/index.js +5 -5
- package/dist/extensions/zai/media-understanding-provider.js +1 -1
- package/dist/extensions/zai/test-api.js +1 -1
- package/dist/extra-params-CEZLNZPM.js +295 -0
- package/dist/format-P9xNDyfD.js +245 -0
- package/dist/fragment-collector-D6OalgG0.js +189 -0
- package/dist/gateway-cli-Zfvn259p.js +1532 -0
- package/dist/gateway-install-token-6z725yP4.js +284 -0
- package/dist/gateway-rpc-BIq75xob.js +14 -0
- package/dist/gateway-rpc.runtime-qaUC59kw.js +23 -0
- package/dist/gateway-rpc.runtime.js +1 -1
- package/dist/gemini-cli-provider-DapCuX8Q.js +106 -0
- package/dist/gemini-web-search-provider-qckYFHgT.js +167 -0
- package/dist/get-reply-from-config.runtime-DHsGpgGI.js +2 -0
- package/dist/get-reply-from-config.runtime.js +1 -1
- package/dist/gmail-setup-utils-Cc3pRzTO.js +422 -0
- package/dist/health-3b-YI19K.js +579 -0
- package/dist/health-MLtfjMov.js +2 -0
- package/dist/heartbeat-runner-BUj0aHm6.js +4 -0
- package/dist/heartbeat-runner-CsnBv3An.js +1365 -0
- package/dist/heartbeat-runner.runtime-DYHZ3Vol.js +2 -0
- package/dist/heartbeat-runner.runtime.js +1 -1
- package/dist/help-ktSd2tag.js +76 -0
- package/dist/hooks-cli-IZb2tmWn.js +364 -0
- package/dist/image-C3lHN8WH.js +152 -0
- package/dist/image-generation-core-Csa-tOLR.js +17 -0
- package/dist/image-generation-core.auth.runtime-DWfzUU3N.js +2 -0
- package/dist/image-generation-core.auth.runtime.js +1 -1
- package/dist/image-generation-provider-Bq81bEDF.js +94 -0
- package/dist/image-generation-provider-D9rV0jKg.js +280 -0
- package/dist/image-generation-provider-DLxx1bzz.js +130 -0
- package/dist/image-generation-provider-DtYtLZ5X.js +136 -0
- package/dist/image-generation-provider-DxkBVWXc.js +163 -0
- package/dist/image-generation-runtime-BSjvNi3e.js +2 -0
- package/dist/image-runtime-DiMm78ho.js +7 -0
- package/dist/inbound-reply-dispatch-vAjY1w2F.js +73 -0
- package/dist/inbound.runtime-CRF3jMe0.js +3 -0
- package/dist/inbound.runtime-DTPuWSKr.js +4 -0
- package/dist/inbound.runtime.js +1 -1
- package/dist/index.js +2 -2
- package/dist/infra-runtime-D3jjt6RI.js +25 -0
- package/dist/ingest-DZbARiPc.js +2 -0
- package/dist/ingest-gzQEKaUE.js +842 -0
- package/dist/io-NwOu0Lqq.js +7188 -0
- package/dist/io-p7f7Dzgz.js +5 -0
- package/dist/kaijibot-tools-DlPDuhB1.js +9434 -0
- package/dist/kaijibot-tools.runtime-Cme2o8P6.js +2 -0
- package/dist/kaijibot-tools.runtime.js +1 -1
- package/dist/kimi-web-search-provider-Ccz-6FOv.js +308 -0
- package/dist/library-CNY5LwdW.js +45 -0
- package/dist/lifecycle-DPisznBr.js +51 -0
- package/dist/lifecycle-core-DHpL48zF.js +422 -0
- package/dist/list.runtime-BGQLMIEV.js +9 -0
- package/dist/list.runtime-rNaKvGI6.js +12 -0
- package/dist/list.runtime.js +1 -1
- package/dist/llm-engine-CJ4a8si7.js +2 -0
- package/dist/llm-engine-JflSw21y.js +1792 -0
- package/dist/llm-extractor-f_T1e84b.js +445 -0
- package/dist/llm-slug-generator.js +2 -2
- package/dist/load-context-BgiRixkE.js +51 -0
- package/dist/logging-BmlPHvHz.js +13 -0
- package/dist/logging-i6p97HMj.js +2 -0
- package/dist/login-BCtkm5rk.js +108 -0
- package/dist/logs-cli-ObIjoAas.js +264 -0
- package/dist/logs-cli.runtime-BFjo2k4n.js +2 -0
- package/dist/logs-cli.runtime.js +1 -1
- package/dist/manager-CWqmCOrL.js +2049 -0
- package/dist/manager-YA9gsC3-.js +3314 -0
- package/dist/mcp/plugin-tools-serve.js +3 -3
- package/dist/mcp-cli-4snhlJll.js +733 -0
- package/dist/mcp-config-BorcRx6O.js +115 -0
- package/dist/media-runtime-we0ajcYl.js +312 -0
- package/dist/media-understanding-provider-3Ttl6hmp.js +18 -0
- package/dist/media-understanding-provider-BGTcMbZI.js +13 -0
- package/dist/media-understanding-provider-BWZtBNix.js +30 -0
- package/dist/media-understanding-provider-CLJBFDyf.js +123 -0
- package/dist/media-understanding-provider-CZ0oRDnO.js +69 -0
- package/dist/media-understanding-provider-CfBvdveE.js +112 -0
- package/dist/media-understanding-provider-D6Ei6zjV.js +18 -0
- package/dist/media-understanding-provider-DEbLZtur.js +37 -0
- package/dist/media-understanding-provider-DysTPulI.js +14 -0
- package/dist/media-understanding-provider-guIrycoj.js +21 -0
- package/dist/media-understanding-provider-sqqt3Zo1.js +67 -0
- package/dist/media-understanding-runtime-DIH8yX06.js +2 -0
- package/dist/media-understanding-zIdRKTHF.js +83 -0
- package/dist/memory-CEPz51C1.js +242 -0
- package/dist/memory-Dz9LyrwM.js +3 -0
- package/dist/memory-core-host-engine-embeddings-D_hioQXv.js +2 -0
- package/dist/memory-core-host-engine-foundation-1Abnrvzg.js +11 -0
- package/dist/memory-core-host-runtime-cli-CPpWR4jD.js +9 -0
- package/dist/memory-core-host-runtime-core-QOAE1eXJ.js +8 -0
- package/dist/memory-embedding-adapter-CJMHQ4fD.js +33 -0
- package/dist/memory-host-search.runtime-CCL0QyRa.js +2 -0
- package/dist/memory-host-search.runtime.js +1 -1
- package/dist/memory-index-BaKGqStn.js +2 -0
- package/dist/memory-index-Dq16t3Le.js +514 -0
- package/dist/memory-runtime-Cr2ycPVC.js +2 -0
- package/dist/memory-runtime-DuWAywa6.js +26 -0
- package/dist/message-B59-6tOr.js +223 -0
- package/dist/message-action-runner-CD2L-ZBQ.js +2 -0
- package/dist/message-action-runner-y-EYEp0n.js +1628 -0
- package/dist/message.config.runtime-NCa2v5Ci.js +3 -0
- package/dist/message.config.runtime.js +1 -1
- package/dist/message.gateway.runtime-Ba2cmeG0.js +2 -0
- package/dist/message.gateway.runtime.js +1 -1
- package/dist/metadata-registry-loader-BAAhCgIz.js +2 -0
- package/dist/metadata-registry-loader-D7YsnsL7.js +15 -0
- package/dist/minimax-vlm-CRQ1qjBy.js +183 -0
- package/dist/minimax-web-search-provider-CBq2_5UU.js +165 -0
- package/dist/mmr-CqmAMXIW.js +146 -0
- package/dist/model-NNxPja4R.js +630 -0
- package/dist/model-auth-BCNvl8s6.js +427 -0
- package/dist/model-auth-label-B0iZbvPM.js +45 -0
- package/dist/model-catalog-B_WMQ0w_.js +204 -0
- package/dist/model-definitions-YQ1lzfH1.js +258 -0
- package/dist/model-picker-ByUUyua6.js +3 -0
- package/dist/model-picker-D2NwBUVu.js +500 -0
- package/dist/model-picker.runtime-BLIC1v4k.js +15 -0
- package/dist/model-picker.runtime.js +1 -1
- package/dist/model-selection-BNkt6VsY.js +381 -0
- package/dist/model-suppression-BLpblK4C.js +28 -0
- package/dist/model-suppression.runtime-CzgXh3-Q.js +7 -0
- package/dist/model-suppression.runtime.js +1 -1
- package/dist/models-11Amlqm7.js +2584 -0
- package/dist/models-BAPi-xJJ.js +2 -0
- package/dist/models-BUxoFu33.js +47 -0
- package/dist/models-Ch34kBry.js +18 -0
- package/dist/models-CxT1_oJh.js +157 -0
- package/dist/models-DdsCg0Z3.js +18 -0
- package/dist/models-cli-DyOOLtYl.js +198 -0
- package/dist/models-config-C91hdcPk.js +900 -0
- package/dist/models-config.providers.secrets-CAQfFlJs.js +299 -0
- package/dist/models-jeG3zz29.js +555 -0
- package/dist/models-uX_1Gq3N.js +760 -0
- package/dist/models.fetch-CBAxXkYq.js +518 -0
- package/dist/monitor-DAF8Gyq4.js +4435 -0
- package/dist/monitor-DSKG-_yl.js +1023 -0
- package/dist/music-generation-provider-BnrTAmbY.js +142 -0
- package/dist/music-generation-provider-CEN-hiuw.js +238 -0
- package/dist/music-generation-provider-CltAphNV.js +169 -0
- package/dist/node-cli-DiZrvwCr.js +2374 -0
- package/dist/nodes-cli-CHIEN-F1.js +1046 -0
- package/dist/nodes-utils-DsRDUdkI.js +196 -0
- package/dist/notify-CLlD_xFa.js +305 -0
- package/dist/oauth-BH1NzJxX.js +57 -0
- package/dist/oauth-oo4i0YoK.js +152 -0
- package/dist/oauth-token-shared-DQSx2gNJ.js +28 -0
- package/dist/oauth.credentials-Bry_dis_.js +165 -0
- package/dist/oauth.flow-BHm8lbRc.js +122 -0
- package/dist/oauth.settings-BEQZQI_l.js +44 -0
- package/dist/oauth.token-CrxxQ__U.js +43 -0
- package/dist/onboard-7nVuWCbc.js +25 -0
- package/dist/onboard-BR4C6q_p.js +25 -0
- package/dist/onboard-CLJvlk15.js +621 -0
- package/dist/onboard-CdxRLmEw2.js +58 -0
- package/dist/onboard-ClstIj39.js +29 -0
- package/dist/onboard-DCvok686.js +25 -0
- package/dist/onboard-RcjANnyK.js +312 -0
- package/dist/onboard-custom-utbZx3tp.js +2 -0
- package/dist/onboard-custom-zmMvywOs.js +647 -0
- package/dist/onboard-helpers-DptwxvqO.js +223 -0
- package/dist/onboard-helpers-hUiLSHkd.js +5 -0
- package/dist/onboard-remote-BLFcjcH2.js +2 -0
- package/dist/onboard-remote-D21HhC2v.js +193 -0
- package/dist/onboard-search-D-BZAp6B.js +324 -0
- package/dist/onboard-skills-B90sl6kA.js +134 -0
- package/dist/onboard-skills-DBZJuUNt.js +2 -0
- package/dist/openai-codex-auth-identity-DJ-yiC5N.js +45 -0
- package/dist/openai-codex-cli-auth-BdZB_Fn0.js +57 -0
- package/dist/openai-codex-provider-D23flY_z.js +299 -0
- package/dist/openai-codex-shared-7LLW54Av.js +6 -0
- package/dist/openai-provider-xmL-RBDi.js +283 -0
- package/dist/openai-transport-stream-M1bujvhd.js +1632 -0
- package/dist/operator-approvals-client-DNHRZj38.js +68 -0
- package/dist/order-DFWeiLxK.js +794 -0
- package/dist/pair-command-approve-CSw5-2fz.js +34 -0
- package/dist/pairing-cli-WXk-duET.js +118 -0
- package/dist/persistent-bindings.lifecycle-CvUywK5_.js +94 -0
- package/dist/pi-bundle-mcp-tools-CX0SFgbF.js +709 -0
- package/dist/pi-embedded-BycqI-F6.js +2 -0
- package/dist/pi-embedded-CROyZQKw.js +6 -0
- package/dist/pi-embedded-runner-DvjFL5Sg.js +8350 -0
- package/dist/pi-embedded-subscribe.handlers.compaction.runtime-DAY2Idkx.js +23 -0
- package/dist/pi-embedded-subscribe.handlers.compaction.runtime.js +1 -1
- package/dist/pi-embedded.runtime-CnpLMfdZ.js +5 -0
- package/dist/pi-embedded.runtime.js +1 -1
- package/dist/pi-model-discovery-eCOzFFEF.js +232 -0
- package/dist/pi-tools.before-tool-call.runtime-DxhFk59d.js +354 -0
- package/dist/pi-tools.before-tool-call.runtime.js +1 -1
- package/dist/plugin-enabled-CHyNN_TN.js +71 -0
- package/dist/plugin-install-config-policy-AxFoCFZw.js +137 -0
- package/dist/plugin-registration-DNzK0hY5.js +23 -0
- package/dist/plugin-registry-CtFzpQUT.js +3 -0
- package/dist/plugin-registry-loader-2DtlC05M.js +22 -0
- package/dist/plugin-registry-rGAVZ04A.js +2 -0
- package/dist/plugin-sdk/.boundary-entry-shims.stamp +1 -1
- package/dist/plugin-sdk/acp-binding-runtime.js +1 -1
- package/dist/plugin-sdk/acp-runtime.js +3 -3
- package/dist/plugin-sdk/agent-harness-runtime.js +6 -6
- package/dist/plugin-sdk/agent-runtime.js +9 -9
- package/dist/plugin-sdk/approval-client-runtime.js +2 -2
- package/dist/plugin-sdk/approval-gateway-runtime.js +2 -2
- package/dist/plugin-sdk/approval-handler-runtime.js +3 -3
- package/dist/plugin-sdk/approval-reply-runtime.js +2 -2
- package/dist/plugin-sdk/approval-runtime.js +4 -4
- package/dist/plugin-sdk/browser-config-runtime.js +2 -2
- package/dist/plugin-sdk/browser-config.js +2 -2
- package/dist/plugin-sdk/browser-control-auth.js +1 -1
- package/dist/plugin-sdk/browser-node-runtime.js +3 -3
- package/dist/plugin-sdk/browser-profiles.js +1 -1
- package/dist/plugin-sdk/browser-setup-tools.js +2 -2
- package/dist/plugin-sdk/browser-support.js +7 -7
- package/dist/plugin-sdk/channel-core.js +2 -2
- package/dist/plugin-sdk/channel-inbound.js +3 -3
- package/dist/plugin-sdk/command-auth.js +4 -4
- package/dist/plugin-sdk/compat.js +2 -2
- package/dist/plugin-sdk/config-mutation.js +4 -4
- package/dist/plugin-sdk/config-runtime.js +6 -6
- package/dist/plugin-sdk/config-schema.js +1 -1
- package/dist/plugin-sdk/conversation-binding-runtime.js +1 -1
- package/dist/plugin-sdk/conversation-runtime.js +4 -4
- package/dist/plugin-sdk/core.js +3 -3
- package/dist/plugin-sdk/direct-dm.js +1 -1
- package/dist/plugin-sdk/gateway-method-runtime.js +1 -1
- package/dist/plugin-sdk/gateway-runtime.js +1 -1
- package/dist/plugin-sdk/generate-text.js +1 -1
- package/dist/plugin-sdk/image-generation-core.js +2 -2
- package/dist/plugin-sdk/image-generation-runtime.js +2 -2
- package/dist/plugin-sdk/inbound-reply-dispatch.js +1 -1
- package/dist/plugin-sdk/index.js +1 -1
- package/dist/plugin-sdk/infra-runtime.js +4 -4
- package/dist/plugin-sdk/media-generation-runtime-shared.js +1 -1
- package/dist/plugin-sdk/media-generation-runtime.js +1 -1
- package/dist/plugin-sdk/media-runtime.js +5 -5
- package/dist/plugin-sdk/media-understanding-runtime.js +2 -2
- package/dist/plugin-sdk/media-understanding.js +2 -2
- package/dist/plugin-sdk/memory-core-host-engine-embeddings.js +2 -2
- package/dist/plugin-sdk/memory-core-host-engine-foundation.js +2 -2
- package/dist/plugin-sdk/memory-core-host-runtime-cli.js +2 -2
- package/dist/plugin-sdk/memory-core-host-runtime-core.js +3 -3
- package/dist/plugin-sdk/memory-core.js +5 -5
- package/dist/plugin-sdk/memory-host-core.js +3 -3
- package/dist/plugin-sdk/memory-host-search.js +1 -1
- package/dist/plugin-sdk/models-provider-runtime.js +1 -1
- package/dist/plugin-sdk/plugin-test-runtime.js +3 -3
- package/dist/plugin-sdk/provider-auth-api-key.js +4 -4
- package/dist/plugin-sdk/provider-auth.js +7 -7
- package/dist/plugin-sdk/provider-entry.js +1 -1
- package/dist/plugin-sdk/provider-setup.js +2 -2
- package/dist/plugin-sdk/provider-stream-family.js +3 -3
- package/dist/plugin-sdk/provider-stream.js +2 -2
- package/dist/plugin-sdk/provider-test-contracts.js +2 -2
- package/dist/plugin-sdk/provider-transport-runtime.js +1 -1
- package/dist/plugin-sdk/reply-dispatch-runtime.js +1 -1
- package/dist/plugin-sdk/reply-runtime.js +7 -7
- package/dist/plugin-sdk/runtime-secret-resolution.js +1 -1
- package/dist/plugin-sdk/runtime.js +3 -3
- package/dist/plugin-sdk/sandbox.js +2 -2
- package/dist/plugin-sdk/self-hosted-provider-setup.js +1 -1
- package/dist/plugin-sdk/session-store-runtime.js +2 -2
- package/dist/plugin-sdk/simple-completion-runtime.js +1 -1
- package/dist/plugin-sdk/skill-commands-runtime.js +1 -1
- package/dist/plugin-sdk/speech-core.js +1 -1
- package/dist/plugin-sdk/src/cognitive/feedback/collector.d.ts +21 -0
- package/dist/plugin-sdk/src/cognitive/persona/lifecycle.d.ts +3 -6
- package/dist/plugin-sdk/src/cognitive/types.d.ts +14 -0
- package/dist/plugin-sdk/src/config/types.cognitive.d.ts +2 -0
- package/dist/plugin-sdk/src/config/zod-schema.cognitive.d.ts +2 -0
- package/dist/plugin-sdk/src/config/zod-schema.d.ts +1 -0
- package/dist/plugin-sdk/testing.js +5 -5
- package/dist/plugin-sdk/text-runtime.js +2 -2
- package/dist/plugin-sdk/video-generation-core.js +1 -1
- package/dist/plugin-sdk/video-generation-runtime.js +1 -1
- package/dist/plugin-service-ByhemcPW.js +2494 -0
- package/dist/plugins/provider-discovery.runtime.js +1 -1
- package/dist/plugins/provider-runtime.runtime.js +1 -1
- package/dist/plugins/runtime/index.js +1 -1
- package/dist/plugins-cli-Bsu-vzeD.js +576 -0
- package/dist/plugins-command-helpers-DHYkcqua.js +117 -0
- package/dist/plugins-install-persist-C8eGd_C5.js +121 -0
- package/dist/plugins-update-command-3xt3Uqf8.js +1009 -0
- package/dist/policy-D-ZKSMmN.js +172 -0
- package/dist/preemptive-compaction-DBfSd-op.js +430 -0
- package/dist/proactive-scheduler-CsHZHnLk.js +1535 -0
- package/dist/probe-CWzUPp-f.js +426 -0
- package/dist/probe-QRfkrTQp.js +54 -0
- package/dist/probe-auth-DG3q8vB9.js +69 -0
- package/dist/probe-auth-GBOKLPAd.js +3 -0
- package/dist/profiles-CBddrdQK.js +117 -0
- package/dist/program-g6p3Qeig.js +111 -0
- package/dist/prompt-overlay-CTwbv1jO.js +72 -0
- package/dist/prompt-select-styled-Cgy0KIgT.js +5305 -0
- package/dist/provider-B_TyrVqo.js +70 -0
- package/dist/provider-api-key-auth-DsEmjrKm.js +113 -0
- package/dist/provider-api-key-auth.runtime-DnU922Pm.js +14 -0
- package/dist/provider-api-key-auth.runtime.js +1 -1
- package/dist/provider-auth-B0NxCABI.js +36 -0
- package/dist/provider-auth-api-key-BRkYGkki.js +5 -0
- package/dist/provider-auth-choice-BU5MwS9n.js +134 -0
- package/dist/provider-auth-choice-preference-BjTvWslj.js +62 -0
- package/dist/provider-auth-choice.runtime-B8ZRr0Ji.js +2 -0
- package/dist/provider-auth-choice.runtime-DIN9GqRk.js +14 -0
- package/dist/provider-auth-choice.runtime.js +1 -1
- package/dist/provider-auth-guidance-BmbcHSR7.js +34 -0
- package/dist/provider-auth-helpers-BHAUl4Gr.js +168 -0
- package/dist/provider-catalog-BL8_CAyj.js +11 -0
- package/dist/provider-catalog-BRtoWqwn.js +11 -0
- package/dist/provider-catalog-BeddZRA_.js +12 -0
- package/dist/provider-catalog-Dl5yMnFQ.js +17 -0
- package/dist/provider-catalog-Doxz6-g3.js +56 -0
- package/dist/provider-catalog-nJImUuqB.js +26 -0
- package/dist/provider-dispatcher-D2GbNyfD.js +22 -0
- package/dist/provider-entry-B01Usrgw.js +97 -0
- package/dist/provider-flow-DgiCMoEf.js +66 -0
- package/dist/provider-models-CjNZS5bS.js +35 -0
- package/dist/provider-models-KjFLrk3V.js +119 -0
- package/dist/provider-models-vPWkBVJC.js +116 -0
- package/dist/provider-registration-BKyn4HAU.js +238 -0
- package/dist/provider-registration-Dtxvk5CC.js +57 -0
- package/dist/provider-runtime-DOtN11v9.js +2 -0
- package/dist/provider-runtime-DSAVX2DR.js +366 -0
- package/dist/provider-runtime.runtime-kKhVhqLz.js +26 -0
- package/dist/provider-runtime.runtime.js +1 -1
- package/dist/provider-self-hosted-setup-l_z2VcmU.js +249 -0
- package/dist/provider-setup-Bf_9tp4f.js +2 -0
- package/dist/provider-stream-BdikYSRa.js +285 -0
- package/dist/provider-stream-family-DSm3KbQw.js +2 -0
- package/dist/provider-usage-BGu0-R4j.js +289 -0
- package/dist/provider-usage-lgVGEKOt.js +3 -0
- package/dist/provider-wizard-BLwU3k7w.js +166 -0
- package/dist/providers.runtime-C0Xkoksw.js +125 -0
- package/dist/providers.runtime.js +1 -1
- package/dist/proxy-stream-wrappers-CIRRoMpa.js +480 -0
- package/dist/push-apns-BuLz1QrB.js +1061 -0
- package/dist/pw-ai-Ld88tf39.js +2268 -0
- package/dist/qmd-manager-kG_qjIil.js +1799 -0
- package/dist/qr-cli-CsNdevN-.js +359 -0
- package/dist/qr-image-CJ2mMFzI.js +2 -0
- package/dist/queue-fniCZ6ND.js +636 -0
- package/dist/realtime-provider-shared-B2y3nIjr.js +21 -0
- package/dist/realtime-transcription-provider-BYeb_Pdh.js +180 -0
- package/dist/realtime-voice-provider-Cs5kAI5o.js +342 -0
- package/dist/record-shared-vbhlkLLm.js +10 -0
- package/dist/refresh-DgMFD0Y0.js +115 -0
- package/dist/region-BOx9--Jp.js +74 -0
- package/dist/register.agent-i88emBrg.js +241 -0
- package/dist/register.backup-PaaKiScO.js +234 -0
- package/dist/register.configure-DOwB_pGJ.js +15 -0
- package/dist/register.maintenance-CYchYFw1.js +443 -0
- package/dist/register.message-DCzLrhHI.js +601 -0
- package/dist/register.onboard-La1ps81U.js +83 -0
- package/dist/register.runtime-Br9LK2gh.js +81 -0
- package/dist/register.runtime-CgbjcVmK.js +343 -0
- package/dist/register.runtime.js +1 -1
- package/dist/register.setup-BwGIBl0j.js +104 -0
- package/dist/register.status-health-sessions-Bg-JiJ0c.js +1211 -0
- package/dist/register.subclis-BvRTTvO6.js +3 -0
- package/dist/register.subclis-C72FAl_s.js +232 -0
- package/dist/repair-DUb-NpH_.js +112 -0
- package/dist/replay-policy-8aUdDKqI.js +8 -0
- package/dist/reply-SolAjGzg.js +3523 -0
- package/dist/reply.runtime-BzJw9WP7.js +2 -0
- package/dist/reply.runtime.js +1 -1
- package/dist/resolve-b0jc4sM3.js +280 -0
- package/dist/restart-CReI1iMn.js +454 -0
- package/dist/root-help-DOYfXVGX.js +44 -0
- package/dist/route-reply-Bsd_X1hM.js +141 -0
- package/dist/route-reply.runtime-0EDNxcfO.js +2 -0
- package/dist/route-reply.runtime.js +1 -1
- package/dist/rpc-C4VoC6lx.js +61 -0
- package/dist/rpc.runtime-CrjwpfEG.js +21 -0
- package/dist/rpc.runtime.js +1 -1
- package/dist/run-main-BqkJC57m.js +453 -0
- package/dist/run-wait-KirpkWGm.js +118 -0
- package/dist/runner-BVkPQnQI.js +1497 -0
- package/dist/runs-Djzm6zWd.js +495 -0
- package/dist/runtime-6nDEFb75.js +72 -0
- package/dist/runtime-BU-qtT4-.js +107 -0
- package/dist/runtime-BYFm5p1W.js +725 -0
- package/dist/runtime-Bw9f54EP.js +355 -0
- package/dist/runtime-D2tXO42J2.js +242 -0
- package/dist/runtime-DOWgnTkX.js +191 -0
- package/dist/runtime-DObmMc6X.js +253 -0
- package/dist/runtime-DoFRWRgY.js +9 -0
- package/dist/runtime-Dt-rXRTW.js +2 -0
- package/dist/runtime-api-BtobjiSx.js +12 -0
- package/dist/runtime-api-CjjNrjOu2.js +2 -0
- package/dist/runtime-api-D7fKSLcI.js +3 -0
- package/dist/runtime-embedded-pi.runtime-2nLOBaP4.js +3 -0
- package/dist/runtime-embedded-pi.runtime.js +1 -1
- package/dist/runtime-internal-BBIguEmO.js +2 -0
- package/dist/runtime-model-auth.runtime-Cgx5HiVv.js +39 -0
- package/dist/runtime-model-auth.runtime.js +1 -1
- package/dist/runtime-oxFh0OA-.js +2 -0
- package/dist/runtime-plugins-zeEZH6Ee.js +69 -0
- package/dist/runtime-prepare.runtime-C1hoi3Pj.js +80 -0
- package/dist/runtime-prepare.runtime.js +1 -1
- package/dist/runtime-provider-CXi4BTPW.js +21 -0
- package/dist/runtime-r3Ke_KuH.js +200 -0
- package/dist/runtime-registry-loader-471RbKgH.js +2 -0
- package/dist/runtime-registry-loader-Dov85dVR.js +58 -0
- package/dist/runtime-schema-DUetufoV.js +28395 -0
- package/dist/runtime-shared-BGttaPX3.js +249 -0
- package/dist/runtime-taskflow-CXpDzGWH.js +250 -0
- package/dist/runtime-web-channel-plugin-Dyt-ZWxm.js +215 -0
- package/dist/runtime-web-tools-CXeVnAOE.js +1467 -0
- package/dist/runtime-web-tools-fallback.runtime-B5P96RjD.js +9 -0
- package/dist/runtime-web-tools-fallback.runtime.js +1 -1
- package/dist/sandbox-B7Mdkad9.js +2586 -0
- package/dist/sandbox-Bkj7NfH_.js +4 -0
- package/dist/sandbox-cli-BMrDh7ip.js +447 -0
- package/dist/secrets-cli-CDO_S3rr.js +2114 -0
- package/dist/security-audit-D4tdLi7R.js +34 -0
- package/dist/security-cli-BtMEiNIM.js +486 -0
- package/dist/semantic-dedup-BGgf2SFR.js +95 -0
- package/dist/send-C5pIHqBv.js +993 -0
- package/dist/send-media-Dcmyu6Y-.js +2123 -0
- package/dist/server-D0ZKpih4.js +77 -0
- package/dist/server-context-BekzVd0R.js +4164 -0
- package/dist/server-iDg2UFb7.js +13 -0
- package/dist/server-methods-MPVSmE3_.js +11937 -0
- package/dist/server-middleware-FqXPNqqT.js +110 -0
- package/dist/server-node-events-C1iGhswC.js +451 -0
- package/dist/server.impl-CFp5ICor.js +19766 -0
- package/dist/session-C-0F1BlP.js +48 -0
- package/dist/session-conversation-Ckza03tl.js +27 -0
- package/dist/session-cost-usage-Dnbtqvv7.js +648 -0
- package/dist/session-cost-usage-iTVG22AO.js +2 -0
- package/dist/session-file-CiJXAZP4.js +44 -0
- package/dist/session-key-6G1LpIon.js +65 -0
- package/dist/session-meta-knhthO95.js +109 -0
- package/dist/session-override-CGqy8cfR.js +103 -0
- package/dist/session-reset-model.runtime-VxsiNT-r.js +120 -0
- package/dist/session-reset-model.runtime.js +1 -1
- package/dist/session-reset-service-6oOKZMC9.js +474 -0
- package/dist/session-subagent-reactivation.runtime-DzMHk0SH.js +2 -0
- package/dist/session-subagent-reactivation.runtime.js +1 -1
- package/dist/session-system-events-BifSkL6x.js +63 -0
- package/dist/session-tab-registry-DR0gRhet.js +553 -0
- package/dist/session-updates-CHOc_4vH.js +234 -0
- package/dist/session-updates.runtime-DsHKjhyM.js +2 -0
- package/dist/session-updates.runtime.js +1 -1
- package/dist/session-utils-GLg54NBi.js +930 -0
- package/dist/sessions-BxOkBx-e.js +45 -0
- package/dist/sessions-C6oolVsU.js +231 -0
- package/dist/sessions-D6_b32XT.js +2 -0
- package/dist/sessions.runtime-Dtv72AMI.js +2 -0
- package/dist/sessions.runtime.js +1 -1
- package/dist/setup-DOX0TZju.js +505 -0
- package/dist/setup-DwqTuGTp.js +329 -0
- package/dist/setup-surface-Ore2Ehcn.js +586 -0
- package/dist/setup.finalize-hAPbyOmw.js +436 -0
- package/dist/setup.gateway-config-DteoOy8F.js +246 -0
- package/dist/shared-CLjMam2L.js +36 -0
- package/dist/shared-DGIkRU6J.js +218 -0
- package/dist/shared-DUnO9yTD.js +175 -0
- package/dist/shared-DeBJWig-.js +137 -0
- package/dist/shared-igYZ1cFQ.js +224 -0
- package/dist/shared-runtime-cWVnVIl5.js +7 -0
- package/dist/short-term-promotion-BhxerFzv.js +1631 -0
- package/dist/simple-completion-runtime-Bv1VtWSA.js +131 -0
- package/dist/simple-completion-transport-CLqa5Iyl.js +32 -0
- package/dist/skill-commands-D02-U6zf.js +82 -0
- package/dist/skill-commands.runtime-J2XiyESs.js +2 -0
- package/dist/skill-commands.runtime.js +1 -1
- package/dist/skills-BI8fjdW_.js +4 -0
- package/dist/skills-C6n71k5r.js +1075 -0
- package/dist/skills-cli-zp3lOjti.js +382 -0
- package/dist/skills-install-DlqA6nec.js +822 -0
- package/dist/skills-status-B57B5p12.js +170 -0
- package/dist/skills-status-DSk7-Gbk.js +2 -0
- package/dist/soul-cli-D_VMWljI.js +110 -0
- package/dist/speech-core-5C9NDTWw.js +126 -0
- package/dist/speech-provider-5npDU3CX.js +103 -0
- package/dist/speech-provider-B-nDtAnq.js +182 -0
- package/dist/speech-provider-BgLqt9Ul.js +184 -0
- package/dist/speech-provider-DAxRZc2f.js +167 -0
- package/dist/stage-sandbox-media.runtime-CFdAVxo8.js +230 -0
- package/dist/stage-sandbox-media.runtime.js +1 -1
- package/dist/standalone-generate-BG6TQ0jK.js +217 -0
- package/dist/standalone-generate-CgZQCsuI.js +2 -0
- package/dist/startup-auth-CKh--SuD.js +151 -0
- package/dist/state-migrations-CN7oRMHd.js +823 -0
- package/dist/status-BAqccuUp.js +278 -0
- package/dist/status-BaSW-xxu.js +2 -0
- package/dist/status-CAODeWKS.js +3 -0
- package/dist/status-CJpxvQmZ.js +500 -0
- package/dist/status-KOZpSuVN.js +2 -0
- package/dist/status-TqK4AoMQ.js +473 -0
- package/dist/status-all-DNG9crv3.js +495 -0
- package/dist/status-evx_KM_Z.js +399 -0
- package/dist/status-json-CT6-w9e9.js +14 -0
- package/dist/status-json-command-sAasGH5G.js +92 -0
- package/dist/status-runtime-shared-DTGujn3T.js +271 -0
- package/dist/status.command.text-runtime-CugrZfYj.js +15 -0
- package/dist/status.gateway-connection.runtime-kuu5mcJa.js +2 -0
- package/dist/status.gateway-connection.runtime.js +1 -1
- package/dist/status.gateway-probe-DNRjTzrV.js +16 -0
- package/dist/status.scan-overview-BjX4TLdw.js +395 -0
- package/dist/status.scan-rcGDJYtU.js +62 -0
- package/dist/status.scan.deps.runtime-CvmH94mX.js +18 -0
- package/dist/status.scan.deps.runtime.js +1 -1
- package/dist/status.scan.fast-json-BJv_9gqh.js +128 -0
- package/dist/status.scan.fast-json-DKOmheDO.js +2 -0
- package/dist/status.scan.runtime-BRjuY3QE.js +417 -0
- package/dist/status.scan.runtime.js +1 -1
- package/dist/status.summary-Bxs_2k1b.js +2 -0
- package/dist/status.summary-Dag8_BJw.js +209 -0
- package/dist/store-BCDEVRXR.js +1112 -0
- package/dist/store-C6poa5Og.js +1075 -0
- package/dist/store-DxQRR8Va.js +424 -0
- package/dist/store.runtime-D6t_wvEo.js +2 -0
- package/dist/store.runtime.js +1 -1
- package/dist/stream-CxAFhAae.js +649 -0
- package/dist/stream-wrappers-BALQapyz.js +144 -0
- package/dist/subagent-announce.registry.runtime-C55O0bdZ.js +3 -0
- package/dist/subagent-announce.registry.runtime.js +1 -1
- package/dist/subagent-control-CoVHKnJF.js +485 -0
- package/dist/subagent-followup.runtime-9Gmh8O_s.js +68 -0
- package/dist/subagent-followup.runtime.js +1 -1
- package/dist/subagent-list-BPsxOWK_.js +168 -0
- package/dist/subagent-orphan-recovery-BCcEet7k.js +214 -0
- package/dist/subagent-registry-DfHx9pew.js +2889 -0
- package/dist/subagent-registry-runtime-B_Mc7UDa.js +2 -0
- package/dist/subagent-registry.runtime-gOuSIzDg.js +3 -0
- package/dist/subagent-registry.runtime.js +1 -1
- package/dist/subagent-spawn-BOLGVu7f.js +782 -0
- package/dist/subagents-format-DXuyOMu-.js +629 -0
- package/dist/system-cli-_jfrKryu.js +60 -0
- package/dist/targets-DKzJlbu6.js +595 -0
- package/dist/task-executor-DhjMRE2d.js +350 -0
- package/dist/task-owner-access-rwopIPhc.js +48 -0
- package/dist/task-registry-C6EQpySp.js +2346 -0
- package/dist/task-registry-control.runtime-t4jeMENC.js +3 -0
- package/dist/task-registry-control.runtime.js +1 -1
- package/dist/task-registry-delivery-runtime-BMfszrF8.js +2 -0
- package/dist/task-registry-delivery-runtime-D_Ocdg0_.js +3 -0
- package/dist/task-registry.maintenance-DNXaqTr4.js +2 -0
- package/dist/task-registry.maintenance-DqvsLuqb.js +425 -0
- package/dist/testing-CXEcd2QQ.js +441 -0
- package/dist/text-report-CUwo5L1k.js +587 -0
- package/dist/text-runtime-B3UrMt6T.js +313 -0
- package/dist/thread-bindings-BR0oLaqe.js +223 -0
- package/dist/tool-auth-shared-BwlRX_zo.js +53 -0
- package/dist/tool-config-shared-CThVi2Zv.js +19 -0
- package/dist/tool-schema-runtime-CiqxCMkH.js +1892 -0
- package/dist/tools-BUzk9uUn.js +110 -0
- package/dist/tools-effective-inventory-CMhZ6G55.js +152 -0
- package/dist/tools.runtime-D6GnPvuW.js +4 -0
- package/dist/tools.runtime.js +1 -1
- package/dist/transcript-kBzFcvfJ.js +233 -0
- package/dist/transcript.runtime-X5nUWG5J.js +2 -0
- package/dist/transcript.runtime.js +1 -1
- package/dist/transport-policy-qrbV7LdB.js +75 -0
- package/dist/tts-BW2-rTjx.js +31 -0
- package/dist/tui-Cnxy7MIi.js +4018 -0
- package/dist/tui-cli-COdAidhT.js +31 -0
- package/dist/update-cli-C62761SQ.js +1779 -0
- package/dist/update-runner-BY92EdE9.js +1492 -0
- package/dist/usage-format-CPx6tGPA.js +2 -0
- package/dist/usage-format-CpsXzXcG.js +507 -0
- package/dist/video-generation-provider-BKRHP8oO.js +171 -0
- package/dist/video-generation-provider-CCsVq0-G.js +263 -0
- package/dist/video-generation-provider-CPHXFGar.js +246 -0
- package/dist/video-generation-provider-DRMOwtTj.js +104 -0
- package/dist/video-generation-provider-DohNwNos.js +181 -0
- package/dist/video-generation-provider-DsIqJI0e.js +227 -0
- package/dist/video-generation-provider-Kg01Dy_G.js +233 -0
- package/dist/video-generation-provider-Z-xZjApd.js +240 -0
- package/dist/video-generation-provider-kfoZ8epM.js +64 -0
- package/dist/video-generation-provider-wgwFq2Wr.js +77 -0
- package/dist/web-fetch-providers.runtime-YHUYJGZL.js +33 -0
- package/dist/web-fetch-providers.runtime.js +1 -1
- package/dist/web-search-C0DUuJkz.js +221 -0
- package/dist/web-search-provider-BVISR8ti.js +155 -0
- package/dist/web-search-providers.runtime-BxK0HVx5.js +206 -0
- package/dist/web-search-providers.runtime.js +1 -1
- package/dist/webhooks-cli-CNvp2Osa.js +321 -0
- package/dist/x-search-shared-uvKOvvdl.js +109 -0
- package/dist/zod-schema-CgftpN_n.js +1401 -0
- package/docs/concepts/cognitive-overview.md +27 -12
- package/package.json +2 -1
- package/dist/abort-BA4i4CO6.js +0 -202
- package/dist/abort-cutoff.runtime-140Dy9Z_.js +0 -20
- package/dist/abort.runtime-D2xd_Jxq.js +0 -2
- package/dist/acp-cli-lUerPOt4.js +0 -2171
- package/dist/acp-spawn-CKu5HWZd.js +0 -1024
- package/dist/acp-stateful-target-driver-DNcDMame.js +0 -88
- package/dist/action-agents-bNO5zlxQ.js +0 -67
- package/dist/action-focus-BQH1yzA9.js +0 -124
- package/dist/action-help-Copk6G3d.js +0 -7
- package/dist/action-info-BUV_zoSU.js +0 -58
- package/dist/action-kill-BMDz9l_U.js +0 -33
- package/dist/action-list-CxkulhYF.js +0 -21
- package/dist/action-log-D0K9-YCV.js +0 -30
- package/dist/action-send-B8ggJVwC.js +0 -39
- package/dist/action-spawn-D9kSXA_K.js +0 -46
- package/dist/action-unfocus-bI4VBonB.js +0 -28
- package/dist/agent-CdxQT19_.js +0 -2
- package/dist/agent-command-Bu_cXSEL.js +0 -1479
- package/dist/agent-runner-utils--p6HAP6k.js +0 -202
- package/dist/agent-runner.runtime-BossnlL1.js +0 -2825
- package/dist/agents-DA2-qNUI.js +0 -887
- package/dist/agents-DaKVGj9F.js +0 -5
- package/dist/anthropic-vertex-stream-CrF-fPgb.js +0 -5666
- package/dist/api-BPByI3-X.js +0 -2
- package/dist/api-BRJq6Aya.js +0 -2
- package/dist/api-BpAm-eRQ.js +0 -2
- package/dist/api-BvFPt7b2.js +0 -19
- package/dist/api-CSOm-O9I.js +0 -5
- package/dist/api-ChQfiSmG.js +0 -4
- package/dist/api-CqBQhm6r.js +0 -2
- package/dist/api-D7qSjVDS.js +0 -3
- package/dist/api-DbRoXBTn.js +0 -45
- package/dist/api-_HshnS5J.js +0 -35
- package/dist/apply-G86rau7x.js +0 -493
- package/dist/apply.runtime-BoYc09wu.js +0 -166
- package/dist/apply.runtime-Dmh02lO-.js +0 -2
- package/dist/approval-client-helpers-cyaJyAMz.js +0 -82
- package/dist/approval-gateway-resolver-bdX78er-.js +0 -58
- package/dist/approval-gateway-runtime-CJm68vrp.js +0 -2
- package/dist/approval-handler-runtime-CT08B2_a.js +0 -439
- package/dist/approval-native-runtime-CN4meUkM.js +0 -709
- package/dist/approval-renderers-CnmO8wke.js +0 -64
- package/dist/asr-Cz-FH-3c.js +0 -196
- package/dist/audit-Cbfv4nmn.js +0 -885
- package/dist/audit-extra.async-DQv_s9K0.js +0 -847
- package/dist/audit.deep.runtime-CAPtrWg1.js +0 -2
- package/dist/audit.nondeep.runtime-HUJ6INiD.js +0 -859
- package/dist/audit.runtime-CAKbHyXK.js +0 -7
- package/dist/auth-CRAwpkC_.js +0 -181
- package/dist/auth-choice-Bhps2D29.js +0 -3
- package/dist/auth-choice-kMIs0xTd.js +0 -71
- package/dist/auth-choice-options-Bx_XsiW-.js +0 -104
- package/dist/auth-choice-prompt-B-koxVGL.js +0 -2
- package/dist/auth-choice-prompt-DytHsI5U.js +0 -36
- package/dist/auth-choice-vRXPONqL.js +0 -353
- package/dist/auth-choice.plugin-providers.runtime-BNfpK_sp.js +0 -11
- package/dist/auth-health-BAxUQXZE.js +0 -165
- package/dist/auth-profiles-YXfmeEhu.js +0 -438
- package/dist/auth-profiles.runtime-CNNciZQU.js +0 -7
- package/dist/auto-recall-CsrNcQNa.js +0 -78
- package/dist/backup-create-DuIPhK_s.js +0 -391
- package/dist/banner-Bb9u_-IS.js +0 -2
- package/dist/banner-BkHTsqFt.js +0 -281
- package/dist/binding-routing-C6_mrNEN.js +0 -50
- package/dist/binding-targets-Cq2e7wRT.js +0 -99
- package/dist/bridge-server-Co3awCAM.js +0 -103
- package/dist/browser-config-runtime-BtkKPBMj.js +0 -6
- package/dist/browser-control-auth-Bqu1lakr.js +0 -120
- package/dist/browser-node-runtime-D8xut4fJ.js +0 -12
- package/dist/browser-profiles-gPG14SPk.js +0 -170
- package/dist/browser-runtime-BBkGI01q.js +0 -377
- package/dist/browser-setup-tools-CD_s48fd.js +0 -12
- package/dist/call-CiUZqjsN.js +0 -2
- package/dist/call-k_nZXTJ3.js +0 -495
- package/dist/call.runtime-CZI7yxSF.js +0 -2
- package/dist/capability-cli-CIm_YhHH.js +0 -1357
- package/dist/catalog-provider-Ch4CMHLl.js +0 -40
- package/dist/cdp.helpers-BVl3YwYe.js +0 -372
- package/dist/channel-core-BB7pTANC.js +0 -5
- package/dist/channel-summary-TxoZjGPA.js +0 -139
- package/dist/channel-summary-dKkFDRbe.js +0 -2
- package/dist/channel.runtime-2WY9MkoH.js +0 -399
- package/dist/channels-D66hRVnR.js +0 -1147
- package/dist/channels-cli-0DjAVaKh.js +0 -248
- package/dist/chat-Fv3LkEfF.js +0 -213
- package/dist/chrome-CEE9kYYR.js +0 -1080
- package/dist/chrome.executables-Dp7W-RgV.js +0 -550
- package/dist/cli-BsNkLoFI.js +0 -57
- package/dist/cli-DQH9X5IE.js +0 -2
- package/dist/cli-DW_ou4hw.js +0 -2
- package/dist/cli-DuoVlLKx.js +0 -154
- package/dist/cli-QG03g_im.js +0 -191
- package/dist/cli-auth-seam-BrijKBRQ.js +0 -14
- package/dist/cli-backend-CIs4F7ip.js +0 -66
- package/dist/cli-migration-CVktTGRI.js +0 -127
- package/dist/cli-runner-12iECISR.js +0 -1662
- package/dist/cli-runner.runtime-C5noDuQ-.js +0 -3
- package/dist/cli-runner.runtime-YrAg_h19.js +0 -2
- package/dist/cli-shared-BUW2okV2.js +0 -142
- package/dist/cli.runtime-Bhxt80sB.js +0 -819
- package/dist/client-bootstrap-BWo-ZK_j.js +0 -28
- package/dist/codex-native-web-search-C6s55zGf.js +0 -2
- package/dist/codex-native-web-search-Cxf1u7R-.js +0 -156
- package/dist/collector-CRTTihSY.js +0 -349
- package/dist/collector-tJxrYXuY.js +0 -2
- package/dist/command-auth-Dlrd5CYD.js +0 -75
- package/dist/command-config-resolution-B8pxzh3W.js +0 -2
- package/dist/command-config-resolution-BXSCDJTh.js +0 -23
- package/dist/command-execution-startup-DYXpKpvc.js +0 -269
- package/dist/command-format-JYoGhCek.js +0 -2
- package/dist/command-queue-CmX7XAL1.js +0 -260
- package/dist/command-registry-BF51N12E.js +0 -3
- package/dist/command-registry-BqpfCBbW.js +0 -113
- package/dist/command-secret-gateway-DuuctECr.js +0 -528
- package/dist/commands-acp-DiLJUV45.js +0 -1017
- package/dist/commands-compact.runtime-BOM8PsWH.js +0 -10
- package/dist/commands-core.runtime-CH_aGeT-.js +0 -2
- package/dist/commands-handlers.runtime-Ca6xoeW5.js +0 -3762
- package/dist/commands-models-CRURuXR-.js +0 -306
- package/dist/commands-reset-hooks-D3RzsOIn.js +0 -129
- package/dist/commands-status-Cufj4x2j.js +0 -223
- package/dist/commands-status.runtime-C8Nz4Glk.js +0 -2
- package/dist/commands-subagents-control.runtime-DjhcmoRT.js +0 -3
- package/dist/commands-subagents-control.runtime-s_DYQWfW.js +0 -2
- package/dist/commands.runtime-ChfYOBeV.js +0 -103
- package/dist/comment-shared-DFEZzqhH.js +0 -40
- package/dist/compact-DEsHFhEL.js +0 -11324
- package/dist/compact.runtime-BzLFUSmk.js +0 -7
- package/dist/completion-cli-CiWtzUFQ.js +0 -2
- package/dist/completion-cli-h3zgpXGM.js +0 -468
- package/dist/config-B3cxNRyw.js +0 -8
- package/dist/config-Bd1PtH4x.js +0 -166
- package/dist/config-DuLfQQvE.js +0 -53
- package/dist/config-cli-BiEmyiRa.js +0 -948
- package/dist/config-defaults-Bw9wwyo1.js +0 -163
- package/dist/config-guard-BGGjXg_Y.js +0 -94
- package/dist/config-runtime-Bvdi0W59.js +0 -14
- package/dist/config-validation-BDeuMlc1.js +0 -279
- package/dist/configure-CUSDnrHs.js +0 -2
- package/dist/configure-FDqT3i_9.js +0 -1162
- package/dist/connection-auth-7izNv08V.js +0 -30
- package/dist/context-B2wCjR9D.js +0 -249
- package/dist/context-n8ANhlMJ.js +0 -2
- package/dist/context-writer-COhxMkVz.js +0 -290
- package/dist/control-auth-Csa4b5CR.js +0 -122
- package/dist/control-ui/assets/agents-CYCtph5J.js +0 -767
- package/dist/control-ui/assets/anthropic-B66S-tt5.js +0 -40
- package/dist/control-ui/assets/azure-openai-responses-CRJyPvrW.js +0 -2
- package/dist/control-ui/assets/cron-DPaLQLTR.js +0 -744
- package/dist/control-ui/assets/dialogues-DPJy1B4C.js +0 -83
- package/dist/control-ui/assets/history-CT3DjMa7.js +0 -71
- package/dist/control-ui/assets/index-Ci2oc-eJ.css +0 -1
- package/dist/control-ui/assets/index-Ua-cFlP6.js +0 -2686
- package/dist/control-ui/assets/mistral-DWkPN1WM.js +0 -72
- package/dist/control-ui/assets/openai-codex-responses-CSJ_tbUW.js +0 -8
- package/dist/control-ui/assets/openai-completions-QUhkmdlC.js +0 -6
- package/dist/control-ui/assets/openai-responses-CjthZA3L.js +0 -2
- package/dist/control-ui/assets/openai-responses-shared-tozh4HQx.js +0 -13
- package/dist/conversation-id-d7KXWjzV.js +0 -140
- package/dist/conversation-runtime-D-YmpVS2.js +0 -31
- package/dist/core-8TPCsNB-.js +0 -210
- package/dist/cron-cli-C5ok2iVK.js +0 -637
- package/dist/curator-9KwCnpXG.js +0 -598
- package/dist/curator-t_jLT3Ie.js +0 -2
- package/dist/daemon-cli-Cr_y38yv.js +0 -476
- package/dist/daemon-install-CrhzPiZ-.js +0 -70
- package/dist/delegate-r3VqUt34.js +0 -61
- package/dist/deliver-Cuu36rnv.js +0 -3
- package/dist/deliver-SAyi_F0e.js +0 -782
- package/dist/deliver-runtime-DKv9J6QE.js +0 -2
- package/dist/delivery-outbound.runtime-DDoInTnF.js +0 -6
- package/dist/delivery-queue-CWi3kUit.js +0 -372
- package/dist/delivery-queue-ecSu6ZNL.js +0 -2
- package/dist/deps-BIU2SScd.js +0 -60
- package/dist/devices-cli-BUAuMOOj.js +0 -336
- package/dist/diagnostic-BLwuJXPT.js +0 -311
- package/dist/direct-dm-D_7_vKGq.js +0 -139
- package/dist/directive-handling.fast-lane-C91i_iZm.js +0 -2
- package/dist/directive-handling.fast-lane-F7l0XNwG.js +0 -64
- package/dist/directive-handling.impl-8RAWZiZE.js +0 -659
- package/dist/directive-handling.impl-BxAIWFS-.js +0 -2
- package/dist/directive-handling.parse-B3O0CfXY.js +0 -376
- package/dist/directive-handling.persist-QXt7GHcD.js +0 -139
- package/dist/directive-handling.persist.runtime-CPPm2qYQ.js +0 -2
- package/dist/directive-handling.shared-C5ywsGJd.js +0 -159
- package/dist/directory-cli-D9v1dSPr.js +0 -240
- package/dist/dispatch-DoyBs65s.js +0 -1126
- package/dist/dispatch-acp-Dz8rU6t9.js +0 -969
- package/dist/dispatch-acp-manager.runtime-tPUGDjl3.js +0 -3
- package/dist/dispatch-acp-media.runtime-rwYN3ewY.js +0 -3
- package/dist/dispatch-acp-session.runtime-C9nyGih8.js +0 -2
- package/dist/dispatch-acp.runtime-Co-JFuKU.js +0 -19
- package/dist/dns-cli-BRVJtnve.js +0 -193
- package/dist/docs-cli-DvJd--iI.js +0 -156
- package/dist/doctor-completion-C46W5KI7.js +0 -90
- package/dist/doctor-config-preflight-B_UDrFsE.js +0 -148
- package/dist/doctor-config-preflight-DtvhOeuT.js +0 -2
- package/dist/doctor-state-migrations-Cd3yfnI1.js +0 -2
- package/dist/doctor-state-migrations-D3qorqjy.js +0 -3
- package/dist/drive-C2mxxJx5.js +0 -718
- package/dist/embedding-provider-C5S1sxvR.js +0 -129
- package/dist/embedding-provider-CNDA2uD3.js +0 -26
- package/dist/embedding-provider-CdVS1B85.js +0 -33
- package/dist/engine-CKgZ1obQ.js +0 -82
- package/dist/engine-embeddings-Bt1bTxtw.js +0 -1489
- package/dist/entry-capabilities-DrciJZn1.js +0 -89
- package/dist/env-overrides-DTd6EBBV.js +0 -347
- package/dist/env-overrides.runtime-Dxy8Shg7.js +0 -7
- package/dist/exec-approval-forwarder.runtime-Dpa8Gi_P.js +0 -3
- package/dist/exec-approval-reply-BaUWuhD6.js +0 -292
- package/dist/exec-approvals-cli-BuOJPaPp.js +0 -485
- package/dist/exec-defaults-B5egc-6t.js +0 -1440
- package/dist/extra-params-Bfdm7Piq.js +0 -295
- package/dist/format-KzNAm6y6.js +0 -245
- package/dist/fragment-collector-DEW1fwlc.js +0 -189
- package/dist/gateway-cli-CWHsIpm8.js +0 -1532
- package/dist/gateway-install-token-CcpoWcqs.js +0 -284
- package/dist/gateway-rpc-Do_3fQSm.js +0 -14
- package/dist/gateway-rpc.runtime-C4kzyrJj.js +0 -23
- package/dist/gemini-cli-provider-YULRMcs8.js +0 -106
- package/dist/gemini-web-search-provider-D_QJZMM3.js +0 -167
- package/dist/get-reply-from-config.runtime-BpdriKtr.js +0 -2
- package/dist/gmail-setup-utils-D_e1q-h_.js +0 -422
- package/dist/health-B5YmS_bW.js +0 -2
- package/dist/health-CQ4zXQ-2.js +0 -579
- package/dist/heartbeat-runner--rVDmB2Z.js +0 -1365
- package/dist/heartbeat-runner-CwtXIPI-.js +0 -4
- package/dist/heartbeat-runner.runtime-D_5UeAsX.js +0 -2
- package/dist/help-CAj5xloH.js +0 -76
- package/dist/hooks-cli-BGDBJqzt.js +0 -364
- package/dist/image-DiK7kcmJ.js +0 -152
- package/dist/image-generation-core-Cwutmg_V.js +0 -17
- package/dist/image-generation-core.auth.runtime-DA7XD5V2.js +0 -2
- package/dist/image-generation-provider-B-0SxnvJ.js +0 -280
- package/dist/image-generation-provider-B-UW3NU_.js +0 -94
- package/dist/image-generation-provider-BR1_oIU4.js +0 -130
- package/dist/image-generation-provider-CnGMLnE9.js +0 -163
- package/dist/image-generation-provider-DHvw6TSJ.js +0 -136
- package/dist/image-generation-runtime-DCWf9P6F.js +0 -2
- package/dist/image-runtime-DGNzvqkb.js +0 -7
- package/dist/inbound-reply-dispatch-DgEqNffL.js +0 -73
- package/dist/inbound.runtime-CloYEZJO.js +0 -4
- package/dist/inbound.runtime-DLbKJWOY.js +0 -3
- package/dist/infra-runtime-DE-Vi3Dn.js +0 -25
- package/dist/ingest-DbZJju1a.js +0 -842
- package/dist/ingest-Dyj9M3ZM.js +0 -2
- package/dist/io-Bz-M35LC.js +0 -7184
- package/dist/io-DacBLjh1.js +0 -5
- package/dist/kaijibot-tools-Df_9YJcO.js +0 -9434
- package/dist/kaijibot-tools.runtime-CZId-V1O.js +0 -2
- package/dist/kimi-web-search-provider-DunVVASJ.js +0 -308
- package/dist/library-BqMFzJMy.js +0 -45
- package/dist/lifecycle-core-DD_IXtH-.js +0 -422
- package/dist/lifecycle-lZ5BtT_X.js +0 -57
- package/dist/list.runtime-DU0ctAjd.js +0 -12
- package/dist/list.runtime-DXWlaAJq.js +0 -9
- package/dist/llm-engine-CMR9RxLA.js +0 -1792
- package/dist/llm-engine-VKRjaGY_.js +0 -2
- package/dist/llm-extractor-BCPvoWmb.js +0 -445
- package/dist/load-context-DV3B4twI.js +0 -51
- package/dist/logging-BMNGvpuz.js +0 -13
- package/dist/logging-CN3VAZ70.js +0 -2
- package/dist/login-Dex1JqnY.js +0 -108
- package/dist/logs-cli-BZFJyrsk.js +0 -264
- package/dist/logs-cli.runtime-bBS2Sbi6.js +0 -2
- package/dist/manager-BmS2ofc4.js +0 -2049
- package/dist/manager-CabVEPeE.js +0 -3314
- package/dist/mcp-cli-DGrmbpsu.js +0 -733
- package/dist/mcp-config-CY_3tJVi.js +0 -115
- package/dist/media-runtime-CAa8uHqv.js +0 -312
- package/dist/media-understanding-D_VRj6xY.js +0 -83
- package/dist/media-understanding-provider-B9Jfjq6L.js +0 -13
- package/dist/media-understanding-provider-BWksuEBw.js +0 -30
- package/dist/media-understanding-provider-Bhtq5Kpe.js +0 -14
- package/dist/media-understanding-provider-BzsmDAMk.js +0 -67
- package/dist/media-understanding-provider-C6_6yxvP.js +0 -123
- package/dist/media-understanding-provider-CdRlAb9s.js +0 -18
- package/dist/media-understanding-provider-D5m-2RW8.js +0 -21
- package/dist/media-understanding-provider-PmVmfI6p.js +0 -112
- package/dist/media-understanding-provider-cmLTPd8x.js +0 -18
- package/dist/media-understanding-provider-nPxfFv8l.js +0 -37
- package/dist/media-understanding-provider-yp9gxov6.js +0 -69
- package/dist/media-understanding-runtime-Bu7m-lVs.js +0 -2
- package/dist/memory-5jlpYBqx.js +0 -242
- package/dist/memory-BFKl6oSn.js +0 -3
- package/dist/memory-core-host-engine-embeddings-p06288xV.js +0 -2
- package/dist/memory-core-host-engine-foundation-DHbdNLgZ.js +0 -11
- package/dist/memory-core-host-runtime-cli-BnvAiNzO.js +0 -9
- package/dist/memory-core-host-runtime-core-CnVg69Uw.js +0 -8
- package/dist/memory-embedding-adapter-Cux48Bvk.js +0 -33
- package/dist/memory-host-search.runtime-D6ORyqHq.js +0 -2
- package/dist/memory-index-DSbV_yD0.js +0 -2
- package/dist/memory-index-EFkCRTeh.js +0 -514
- package/dist/memory-runtime-BKqNwQ9X.js +0 -2
- package/dist/memory-runtime-Cn41W0bC.js +0 -26
- package/dist/message-CMCdNyAT.js +0 -223
- package/dist/message-action-runner-CG2CcWaS.js +0 -1628
- package/dist/message-action-runner-DUZQ7nmt.js +0 -2
- package/dist/message.config.runtime-B3ztIjsr.js +0 -3
- package/dist/message.gateway.runtime-COLMRCv4.js +0 -2
- package/dist/metadata-registry-loader-BSyFpHop.js +0 -15
- package/dist/metadata-registry-loader-Ci3mcmNV.js +0 -2
- package/dist/minimax-vlm-D1DbVSjC.js +0 -183
- package/dist/minimax-web-search-provider-BzgvahXM.js +0 -165
- package/dist/mmr-Clamw4uq.js +0 -146
- package/dist/model-CJIbRRp9.js +0 -630
- package/dist/model-auth-BQpkMtoP.js +0 -427
- package/dist/model-auth-label-dLSkL9EI.js +0 -45
- package/dist/model-catalog-DgqowW_L.js +0 -204
- package/dist/model-definitions-BOTIDDWJ.js +0 -258
- package/dist/model-picker-B4SuA28P.js +0 -3
- package/dist/model-picker-buwrc8kM.js +0 -500
- package/dist/model-picker.runtime-DXgS2Rab.js +0 -15
- package/dist/model-selection-CBuo2hSg.js +0 -381
- package/dist/model-suppression-CthTVW_x.js +0 -28
- package/dist/model-suppression.runtime-R-qnGNBa.js +0 -7
- package/dist/models-B3UnmjRf.js +0 -18
- package/dist/models-BucP8NI1.js +0 -760
- package/dist/models-C3w7hz3K.js +0 -18
- package/dist/models-C4-eAnR7.js +0 -157
- package/dist/models-DMLYOe4h.js +0 -2
- package/dist/models-DNNfkS3j.js +0 -2584
- package/dist/models-DkiHZi9S.js +0 -47
- package/dist/models-OhM18fW_.js +0 -555
- package/dist/models-cli-CfvtZXPd.js +0 -198
- package/dist/models-config-BLMZzgfx.js +0 -900
- package/dist/models-config.providers.secrets-rjdH8T5l.js +0 -299
- package/dist/models.fetch-D1o7sMO8.js +0 -518
- package/dist/monitor-CJdL31iS.js +0 -4435
- package/dist/monitor-DB732mUY.js +0 -1023
- package/dist/music-generation-provider-BrUTQBmG.js +0 -169
- package/dist/music-generation-provider-D6aYWSSm.js +0 -238
- package/dist/music-generation-provider-dpX_Oiuw.js +0 -142
- package/dist/node-cli-BSrC37hh.js +0 -2374
- package/dist/nodes-cli-uwgDIsqv.js +0 -1046
- package/dist/nodes-utils-ChvZvxK1.js +0 -196
- package/dist/notify-C9-q0Rdu.js +0 -305
- package/dist/oauth-CVAbqwnx.js +0 -152
- package/dist/oauth-RbN-L8pg.js +0 -57
- package/dist/oauth-token-shared-CCzflFLG.js +0 -28
- package/dist/oauth.credentials-BeCOUsTe.js +0 -165
- package/dist/oauth.flow-C2PFyq_h.js +0 -122
- package/dist/oauth.settings-CBmYrmAk.js +0 -44
- package/dist/oauth.token-DSow_5Ie.js +0 -43
- package/dist/onboard-B-ZJptUZ.js +0 -25
- package/dist/onboard-Beu-mw_-.js +0 -29
- package/dist/onboard-BzUrcgZ5.js +0 -25
- package/dist/onboard-CPuf8esc.js +0 -25
- package/dist/onboard-CTfex1XR2.js +0 -58
- package/dist/onboard-D-ccZlbM.js +0 -312
- package/dist/onboard-DHXNhsF7.js +0 -621
- package/dist/onboard-custom-9KIp_ybR.js +0 -647
- package/dist/onboard-custom-CbXUFVN6.js +0 -2
- package/dist/onboard-helpers-BFknCN7m.js +0 -223
- package/dist/onboard-helpers-DSJ_xWpL.js +0 -5
- package/dist/onboard-remote-C28pAu4b.js +0 -193
- package/dist/onboard-remote-DQxyE18D.js +0 -2
- package/dist/onboard-search-CPHGVmos.js +0 -324
- package/dist/onboard-skills-B642NK1o.js +0 -2
- package/dist/onboard-skills-CI4B6Kx5.js +0 -134
- package/dist/openai-codex-auth-identity-PqpqYz4a.js +0 -45
- package/dist/openai-codex-cli-auth-cFTkwXjR.js +0 -57
- package/dist/openai-codex-provider-DjUpM_l9.js +0 -299
- package/dist/openai-codex-shared-o0pq7UkS.js +0 -6
- package/dist/openai-provider-ChZN4Q0c.js +0 -283
- package/dist/openai-transport-stream-DXBBlxJ9.js +0 -1632
- package/dist/operator-approvals-client-RJESCyw4.js +0 -68
- package/dist/order-D863tCt-.js +0 -794
- package/dist/pair-command-approve-5Jr6xo-1.js +0 -34
- package/dist/pairing-cli-BF3jieZo.js +0 -118
- package/dist/persistent-bindings.lifecycle-CjXEQUMz.js +0 -94
- package/dist/pi-bundle-mcp-tools-DPVGNVRw.js +0 -709
- package/dist/pi-embedded-Cp3OIZy9.js +0 -2
- package/dist/pi-embedded-DJN2vlNF.js +0 -6
- package/dist/pi-embedded-runner-DXHhhGRS.js +0 -8348
- package/dist/pi-embedded-subscribe.handlers.compaction.runtime-D1jUEg-R.js +0 -23
- package/dist/pi-embedded.runtime-DQPfEvkF.js +0 -5
- package/dist/pi-model-discovery-B9q9ykaA.js +0 -232
- package/dist/pi-tools.before-tool-call.runtime-vGvkJ6V9.js +0 -354
- package/dist/plugin-enabled-CMdiRqJS.js +0 -71
- package/dist/plugin-install-config-policy-32D2JJMl.js +0 -137
- package/dist/plugin-registration-BhPJI7wp.js +0 -23
- package/dist/plugin-registry-Bo4RF_Fn.js +0 -2
- package/dist/plugin-registry-C4M8QkVh.js +0 -3
- package/dist/plugin-registry-loader-ZzUapRh3.js +0 -22
- package/dist/plugin-service-31XQtuZr.js +0 -2494
- package/dist/plugins-cli-20A8dYUN.js +0 -576
- package/dist/plugins-command-helpers-C3Qls10N.js +0 -117
- package/dist/plugins-install-persist-DEr-zA4G.js +0 -121
- package/dist/plugins-update-command-D0Iv4BPb.js +0 -1009
- package/dist/policy-BEVsx7jw.js +0 -172
- package/dist/preemptive-compaction-DlRJt7Zq.js +0 -430
- package/dist/proactive-scheduler-B3w5rW0h.js +0 -1444
- package/dist/probe-CCTEVLB2.js +0 -54
- package/dist/probe-DcSW0ngD.js +0 -426
- package/dist/probe-auth-C7DjgU_m.js +0 -69
- package/dist/probe-auth-Cfwc8qaj.js +0 -3
- package/dist/profiles-BYudUysD.js +0 -117
- package/dist/program-E_Dt_QTp.js +0 -111
- package/dist/prompt-overlay-DsEnjhTn.js +0 -72
- package/dist/prompt-select-styled-Dtw90p2J.js +0 -5305
- package/dist/provider-api-key-auth-CerNsquw.js +0 -113
- package/dist/provider-api-key-auth.runtime-B0BpFkRm.js +0 -14
- package/dist/provider-auth-DwgUXcgu.js +0 -36
- package/dist/provider-auth-api-key-BQfXwqgU.js +0 -5
- package/dist/provider-auth-choice-BKxMQwxd.js +0 -134
- package/dist/provider-auth-choice-preference-DeDdHlsY.js +0 -62
- package/dist/provider-auth-choice.runtime-BJxc73Ex.js +0 -2
- package/dist/provider-auth-choice.runtime-DBcrr0Ab.js +0 -14
- package/dist/provider-auth-guidance-Cqo9An-I.js +0 -34
- package/dist/provider-auth-helpers-r9kVb6L3.js +0 -168
- package/dist/provider-catalog-CjNAbR9b.js +0 -12
- package/dist/provider-catalog-CpTP4D3p.js +0 -56
- package/dist/provider-catalog-D1iJW59q.js +0 -11
- package/dist/provider-catalog-Dc48HHhB.js +0 -11
- package/dist/provider-catalog-jKq2UIeG.js +0 -17
- package/dist/provider-catalog-pmlFBXYr.js +0 -26
- package/dist/provider-dispatcher-Dl07uV70.js +0 -22
- package/dist/provider-entry-DkwXZuZY.js +0 -97
- package/dist/provider-flow-CmI4jkWV.js +0 -66
- package/dist/provider-iVtrs6XY.js +0 -70
- package/dist/provider-models-BXMZj2p1.js +0 -119
- package/dist/provider-models-Bq_MZ0xR.js +0 -35
- package/dist/provider-models-CsUYkHTw.js +0 -116
- package/dist/provider-registration-DkqLtXSj.js +0 -57
- package/dist/provider-registration-vrLHkywc.js +0 -238
- package/dist/provider-runtime-C_ebc-4l.js +0 -2
- package/dist/provider-runtime-Czioyn5w.js +0 -366
- package/dist/provider-runtime.runtime-lPuF4lqy.js +0 -26
- package/dist/provider-self-hosted-setup-Bjk91HZ7.js +0 -249
- package/dist/provider-setup-hUbxRciz.js +0 -2
- package/dist/provider-stream-DTbeHqKf.js +0 -285
- package/dist/provider-stream-family-Cz7SHqeS.js +0 -2
- package/dist/provider-usage-4x0im5xP.js +0 -3
- package/dist/provider-usage-CdkW3Bkb.js +0 -289
- package/dist/provider-wizard-BPkIa2bk.js +0 -166
- package/dist/providers.runtime-CawuCJXc.js +0 -125
- package/dist/proxy-stream-wrappers-BcJuaE24.js +0 -480
- package/dist/push-apns-CO3sqbX3.js +0 -1061
- package/dist/pw-ai-DEf5tZLp.js +0 -2268
- package/dist/qmd-manager-CrqmeTuY.js +0 -1799
- package/dist/qr-cli-g_Pkqstu.js +0 -359
- package/dist/qr-image-DcG1bUox.js +0 -2
- package/dist/queue-BveCZpTb.js +0 -636
- package/dist/realtime-provider-shared-BIili3oc.js +0 -21
- package/dist/realtime-transcription-provider-DqEHy_Jr.js +0 -180
- package/dist/realtime-voice-provider-Dau1KlKK.js +0 -342
- package/dist/record-shared-CC55xbFE.js +0 -10
- package/dist/refresh-BXJ80ji4.js +0 -115
- package/dist/region-CPFmncMW.js +0 -74
- package/dist/register.agent-D5el253o.js +0 -241
- package/dist/register.backup-CBhoChp-.js +0 -234
- package/dist/register.configure-DeqUaelp.js +0 -15
- package/dist/register.maintenance-Dv5x9ZE6.js +0 -443
- package/dist/register.message-e2Pbh8A_.js +0 -601
- package/dist/register.onboard-COuTKpAw.js +0 -83
- package/dist/register.runtime-BjOIl4eF.js +0 -81
- package/dist/register.runtime-BzJ6RkQN.js +0 -343
- package/dist/register.setup-DQYY7K4K.js +0 -104
- package/dist/register.status-health-sessions-CXNGQh_O.js +0 -1211
- package/dist/register.subclis-B6uy_ogx.js +0 -232
- package/dist/register.subclis-Cmdrfiej.js +0 -3
- package/dist/repair-C8v1vNU-.js +0 -112
- package/dist/replay-policy-C6igC4nS.js +0 -8
- package/dist/reply-Bd8ShNWW.js +0 -3523
- package/dist/reply.runtime-ByKwE5dg.js +0 -2
- package/dist/resolve-CSTOvc_c.js +0 -280
- package/dist/restart-C0QhPXk1.js +0 -454
- package/dist/root-help-D2vz4lbV.js +0 -44
- package/dist/route-reply-CXZFXlfK.js +0 -141
- package/dist/route-reply.runtime-BK8V9NEg.js +0 -2
- package/dist/rpc-f0OkPaI1.js +0 -61
- package/dist/rpc.runtime-BQ78T_pB.js +0 -21
- package/dist/run-main-CkwrrhfI.js +0 -453
- package/dist/run-wait-B4pXPLkF.js +0 -118
- package/dist/runner-BSA9M_M9.js +0 -1497
- package/dist/runs-CEDW87Fd.js +0 -495
- package/dist/runtime-C18YgW822.js +0 -242
- package/dist/runtime-C3OJQ1Xd.js +0 -200
- package/dist/runtime-CDNVtwVk.js +0 -72
- package/dist/runtime-CMNHfJtF.js +0 -725
- package/dist/runtime-C_o_otMV.js +0 -355
- package/dist/runtime-CiJWy5Ce.js +0 -9
- package/dist/runtime-D8bLKXLh.js +0 -253
- package/dist/runtime-DM4z9RVx.js +0 -2
- package/dist/runtime-Di50Fr1z.js +0 -191
- package/dist/runtime-W3qG5LHM.js +0 -2
- package/dist/runtime-api-Bx7nlc4w.js +0 -12
- package/dist/runtime-api-DCNC_FTy2.js +0 -2
- package/dist/runtime-api-_Z8MjR0l.js +0 -3
- package/dist/runtime-embedded-pi.runtime-Cv0MW9ps.js +0 -3
- package/dist/runtime-internal-DclGtT-e.js +0 -2
- package/dist/runtime-model-auth.runtime-Bjl23_fr.js +0 -39
- package/dist/runtime-oEwr_zQb.js +0 -107
- package/dist/runtime-plugins-CwWhqXLJ.js +0 -69
- package/dist/runtime-prepare.runtime-Bi-YD5R-.js +0 -80
- package/dist/runtime-provider-CSEDbSxr.js +0 -21
- package/dist/runtime-registry-loader-CbbaZCXY.js +0 -58
- package/dist/runtime-registry-loader-kqiMFCUa.js +0 -2
- package/dist/runtime-schema-CDuvvU7B.js +0 -28383
- package/dist/runtime-shared-BxJFDFe6.js +0 -249
- package/dist/runtime-taskflow-RwpXng2l.js +0 -250
- package/dist/runtime-web-channel-plugin-Bw74Ar_q.js +0 -215
- package/dist/runtime-web-tools-CEaAGeYr.js +0 -1467
- package/dist/runtime-web-tools-fallback.runtime-DU8Hp_QZ.js +0 -9
- package/dist/sandbox-BC2XUWcW.js +0 -4
- package/dist/sandbox-cli-ain0MYTB.js +0 -447
- package/dist/sandbox-epLgxWBQ.js +0 -2586
- package/dist/secrets-cli-iLwRZbRt.js +0 -2114
- package/dist/security-audit-DfrokBuq.js +0 -34
- package/dist/security-cli-BqsMM550.js +0 -486
- package/dist/semantic-dedup-BBpIPaSV.js +0 -95
- package/dist/send-C5LHdZqP.js +0 -993
- package/dist/send-media-Df0E2Z_m.js +0 -2123
- package/dist/server-2CD2yd73.js +0 -13
- package/dist/server-B44RMlVT.js +0 -77
- package/dist/server-context-SulhWpXY.js +0 -4164
- package/dist/server-methods-BPzzX5VC.js +0 -11937
- package/dist/server-middleware-WQzQIrD4.js +0 -110
- package/dist/server-node-events-Ug_Atc7G.js +0 -451
- package/dist/server.impl-InfVdwPj.js +0 -19765
- package/dist/session-B5RmIL21.js +0 -48
- package/dist/session-conversation-CFty7VTc.js +0 -27
- package/dist/session-cost-usage-CckjvorH.js +0 -2
- package/dist/session-cost-usage-DMRjhi4B.js +0 -648
- package/dist/session-file-DGJqy_ea.js +0 -44
- package/dist/session-key-D-jBcxEp.js +0 -65
- package/dist/session-meta-BijZlLS3.js +0 -109
- package/dist/session-override-1YQHEAlz.js +0 -103
- package/dist/session-reset-model.runtime-CEWrfXLr.js +0 -120
- package/dist/session-reset-service-Dphtb16d.js +0 -474
- package/dist/session-subagent-reactivation.runtime-CF4aqSpn.js +0 -2
- package/dist/session-system-events-BSVIh760.js +0 -63
- package/dist/session-tab-registry-DG9SGi0I.js +0 -553
- package/dist/session-updates-BRFvmIoC.js +0 -234
- package/dist/session-updates.runtime-CiHARWGr.js +0 -2
- package/dist/session-utils-Cai4P9ih.js +0 -930
- package/dist/sessions-BTcXDmCA.js +0 -2
- package/dist/sessions-CyYVTseV.js +0 -45
- package/dist/sessions-Fb0ep3uj.js +0 -231
- package/dist/sessions.runtime-BGyynSR4.js +0 -2
- package/dist/setup-CjEjg8Ci.js +0 -505
- package/dist/setup-D-ypxGnK.js +0 -329
- package/dist/setup-surface-QaubzT60.js +0 -586
- package/dist/setup.finalize-B3MWkUF9.js +0 -436
- package/dist/setup.gateway-config-BdK0tA_r.js +0 -246
- package/dist/shared-0JcWj8-R.js +0 -224
- package/dist/shared-BOd3OCF0.js +0 -36
- package/dist/shared-DICWV0-6.js +0 -218
- package/dist/shared-DiGX-JK8.js +0 -137
- package/dist/shared-DktX3NHd.js +0 -175
- package/dist/shared-runtime-BltNIfGY.js +0 -7
- package/dist/short-term-promotion-CT1zdD1r.js +0 -1631
- package/dist/simple-completion-runtime-CZyp8rJ3.js +0 -131
- package/dist/simple-completion-transport-BWyoXghG.js +0 -32
- package/dist/skill-commands-BC_2IdwF.js +0 -82
- package/dist/skill-commands.runtime-BP6BnOeq.js +0 -2
- package/dist/skills-BQX1AsbM.js +0 -4
- package/dist/skills-D7XPR8N-.js +0 -1075
- package/dist/skills-cli-CxmgxC7X.js +0 -382
- package/dist/skills-install-CHUWYiLs.js +0 -822
- package/dist/skills-status-DRTnP8E3.js +0 -170
- package/dist/skills-status-v28wm8HD.js +0 -2
- package/dist/soul-cli-B1-3BHbA.js +0 -110
- package/dist/speech-core-aXx4I3sB.js +0 -126
- package/dist/speech-provider-BTBQ5VOv.js +0 -103
- package/dist/speech-provider-BciszvJf.js +0 -184
- package/dist/speech-provider-BoQDEC_Y.js +0 -167
- package/dist/speech-provider-C-wTEx8k.js +0 -182
- package/dist/stage-sandbox-media.runtime-DhlTQjXA.js +0 -230
- package/dist/standalone-generate-BRvNW_O7.js +0 -2
- package/dist/standalone-generate-CDfZss4x.js +0 -217
- package/dist/startup-auth-B5V0AaIU.js +0 -151
- package/dist/state-migrations-BNib6l8O.js +0 -823
- package/dist/status-8clcfnN0.js +0 -473
- package/dist/status-C9YBVOov.js +0 -278
- package/dist/status-CNcOKUs2.js +0 -500
- package/dist/status-D1l9Tu3s.js +0 -399
- package/dist/status-DKth_wbp.js +0 -2
- package/dist/status-P3bvFirO.js +0 -3
- package/dist/status-TmH9qSMG.js +0 -2
- package/dist/status-all-BeyVXDNT.js +0 -495
- package/dist/status-json-Cj42CVZZ.js +0 -14
- package/dist/status-json-command-DWk5RiyN.js +0 -92
- package/dist/status-runtime-shared-orzti3tZ.js +0 -271
- package/dist/status.command.text-runtime-B-tNLc3T.js +0 -15
- package/dist/status.gateway-connection.runtime-BrkaJ2f5.js +0 -2
- package/dist/status.gateway-probe-BwuiZk1h.js +0 -16
- package/dist/status.scan-DegSjLE2.js +0 -62
- package/dist/status.scan-overview-CrSELCru.js +0 -395
- package/dist/status.scan.deps.runtime-DrUvBz4e.js +0 -18
- package/dist/status.scan.fast-json-Bm5lN6IK.js +0 -2
- package/dist/status.scan.fast-json-Ch2Zw813.js +0 -128
- package/dist/status.scan.runtime-D-LvzBYN.js +0 -417
- package/dist/status.summary-OB-43Bvk.js +0 -2
- package/dist/status.summary-gJukahkb.js +0 -209
- package/dist/store-D5JODeba.js +0 -421
- package/dist/store-D_vXZ7m9.js +0 -1112
- package/dist/store-yc7MvXdd.js +0 -1075
- package/dist/store.runtime-6eaZtPq6.js +0 -2
- package/dist/stream-BgcqyefI.js +0 -649
- package/dist/stream-wrappers-B7-5gN0i.js +0 -144
- package/dist/subagent-announce.registry.runtime-R2bop0gW.js +0 -3
- package/dist/subagent-control-UyMtkJwo.js +0 -485
- package/dist/subagent-followup.runtime-bTK0TymS.js +0 -68
- package/dist/subagent-list-c0JKZR0g.js +0 -168
- package/dist/subagent-orphan-recovery-CSEzwva5.js +0 -214
- package/dist/subagent-registry-Be219RP1.js +0 -2889
- package/dist/subagent-registry-runtime-Dk57Y91p.js +0 -2
- package/dist/subagent-registry.runtime-D6h_BK2i.js +0 -3
- package/dist/subagent-spawn-BeyYZuFf.js +0 -782
- package/dist/subagents-format-ZcZBg1Vh.js +0 -629
- package/dist/system-cli-_3czEwa7.js +0 -60
- package/dist/targets-CXrDP8_l.js +0 -595
- package/dist/task-executor-DNUNtRg8.js +0 -350
- package/dist/task-owner-access--E5Vkg9U.js +0 -48
- package/dist/task-registry-COE-B6MO.js +0 -2346
- package/dist/task-registry-control.runtime-BzsTfRw1.js +0 -3
- package/dist/task-registry-delivery-runtime-Cv6xz8KP.js +0 -2
- package/dist/task-registry-delivery-runtime-DSfcd2LA.js +0 -3
- package/dist/task-registry.maintenance-Bhd9abl9.js +0 -2
- package/dist/task-registry.maintenance-W3lTkY0l.js +0 -425
- package/dist/testing-CQ_-oCQB.js +0 -441
- package/dist/text-report-BgqWDKJR.js +0 -587
- package/dist/text-runtime-asv4kIxS.js +0 -313
- package/dist/thread-bindings-BCRWofo_.js +0 -223
- package/dist/tool-auth-shared-BWZwTobX.js +0 -53
- package/dist/tool-config-shared-BleK697I.js +0 -19
- package/dist/tool-schema-runtime-DZsW_KR4.js +0 -1892
- package/dist/tools-C7lv9rSD.js +0 -110
- package/dist/tools-effective-inventory-SB9JwX-y.js +0 -152
- package/dist/tools.runtime-J5rhfXQp.js +0 -4
- package/dist/transcript-DxWx6dVc.js +0 -233
- package/dist/transcript.runtime-CmBnobSv.js +0 -2
- package/dist/transport-policy-BGfaKNz0.js +0 -75
- package/dist/tts-C1GyTLOi.js +0 -31
- package/dist/tui-Cqdp1x16.js +0 -4018
- package/dist/tui-cli-BC4O3H6r.js +0 -31
- package/dist/update-cli-BzaCTuax.js +0 -1779
- package/dist/update-runner-Cvxezvhf.js +0 -1492
- package/dist/usage-format-DQTT4pqY.js +0 -507
- package/dist/usage-format-sR4xu0xw.js +0 -2
- package/dist/video-generation-provider-7YR4_ldd.js +0 -171
- package/dist/video-generation-provider-AlAZkYIW.js +0 -181
- package/dist/video-generation-provider-BEqi4pUJ.js +0 -104
- package/dist/video-generation-provider-CraaZaR7.js +0 -77
- package/dist/video-generation-provider-CuvO2Hzh.js +0 -246
- package/dist/video-generation-provider-D-t16ACe.js +0 -240
- package/dist/video-generation-provider-DeowxvLt.js +0 -233
- package/dist/video-generation-provider-HbOZ3qzI.js +0 -227
- package/dist/video-generation-provider-_apx1yFE.js +0 -263
- package/dist/video-generation-provider-bvpb6cdV.js +0 -64
- package/dist/web-fetch-providers.runtime-m66rypbB.js +0 -33
- package/dist/web-search-DSDz1iyf.js +0 -221
- package/dist/web-search-provider-DnYRRBVM.js +0 -155
- package/dist/web-search-providers.runtime-Cv56XIGr.js +0 -206
- package/dist/webhooks-cli-DQ_JTSNA.js +0 -321
- package/dist/x-search-shared-DKPdPR5_.js +0 -109
- package/dist/zod-schema-B7jQiHXQ.js +0 -1400
|
@@ -0,0 +1,4164 @@
|
|
|
1
|
+
import { d as readStringValue, i as normalizeLowercaseStringOrEmpty, s as normalizeOptionalString } from "./string-coerce-xZwG7Dq8.js";
|
|
2
|
+
import { n as extractErrorCode, r as formatErrorMessage } from "./errors-Ez4cKI2Y.js";
|
|
3
|
+
import { m as resolveUserPath } from "./utils-C8dt4mi-.js";
|
|
4
|
+
import { i as runExec } from "./exec-CJA8CYRJ.js";
|
|
5
|
+
import { g as writeConfigFile, i as createConfigIO, o as loadConfig } from "./io-NwOu0Lqq.js";
|
|
6
|
+
import { n as asNullableRecord } from "./record-coerce-nraI4tOL.js";
|
|
7
|
+
import { r as getRuntimeConfigSnapshot } from "./runtime-snapshot-DaE9cWKG.js";
|
|
8
|
+
import { i as generateSecureToken } from "./secure-random-B1Z18GKR.js";
|
|
9
|
+
import { a as getImageMetadata, l as resizeToJpeg, r as buildImageResizeSideGrid, t as IMAGE_REDUCE_QUALITY_STEPS } from "./image-ops-D1gXlUdD.js";
|
|
10
|
+
import { t as SsrFBlockedError } from "./ssrf-DLGp20IL.js";
|
|
11
|
+
import { a as ensureMediaDir, l as saveMediaBuffer } from "./store-BqvhZgld.js";
|
|
12
|
+
import { t as parseBooleanValue } from "./boolean-7xU1p3Dc.js";
|
|
13
|
+
import { r as deriveDefaultBrowserCdpPortRange } from "./port-defaults-CAGftlqE.js";
|
|
14
|
+
import "./text-runtime-B3UrMt6T.js";
|
|
15
|
+
import "./browser-config-runtime-3QVJiqnP.js";
|
|
16
|
+
import "./browser-node-runtime-BusKdg2E.js";
|
|
17
|
+
import "./browser-security-runtime-CzhzXJ8D.js";
|
|
18
|
+
import "./browser-setup-tools-j-IDYASL.js";
|
|
19
|
+
import { S as resolveCdpReachabilityTimeouts, a as fetchOk, c as normalizeCdpHttpBaseForJsonEndpoints, i as fetchJson, m as CDP_JSON_NEW_TIMEOUT_MS, n as assertCdpEndpointAllowed, t as appendCdpPath, u as parseBrowserHttpUrl, v as CHROME_MCP_ATTACH_READY_WINDOW_MS } from "./cdp.helpers-BqVqEY02.js";
|
|
20
|
+
import { A as BrowserValidationError, C as BrowserConflictError, D as BrowserResourceExhaustedError, E as BrowserResetUnsupportedError, F as assertBrowserNavigationResultAllowed, I as requiresInspectableBrowserNavigationRedirects, L as withBrowserNavigationPolicy, M as InvalidBrowserNavigationUrlError, N as assertBrowserNavigationAllowed, O as BrowserTabNotFoundError, T as BrowserProfileUnavailableError, _ as normalizeCdpWsUrl, a as resolveKaijiBotUserDataDir, d as CONTENT_ROLES, f as INTERACTIVE_ROLES, h as createTargetViaCdp, i as launchKaijiBotChrome, j as toBrowserErrorResponse, k as BrowserTargetAmbiguousError, l as getRoleSnapshotStats, m as captureScreenshot, n as isChromeCdpReady, o as stopKaijiBotChrome, p as STRUCTURAL_ROLES, r as isChromeReachable, v as snapshotAria, w as BrowserProfileNotFoundError, x as normalizeBrowserFormField, y as matchBrowserUrlPattern } from "./chrome-BcU0ZvUn.js";
|
|
21
|
+
import { n as normalizeString } from "./record-shared-vbhlkLLm.js";
|
|
22
|
+
import { c as DEFAULT_DOWNLOAD_DIR, d as resolveExistingPathsWithinRoot, l as DEFAULT_TRACE_DIR, n as DEFAULT_AI_SNAPSHOT_MAX_CHARS, p as resolveWritablePathWithinRoot, t as DEFAULT_AI_SNAPSHOT_EFFICIENT_MAX_CHARS, u as DEFAULT_UPLOAD_DIR } from "./utils-CBnbWiRL.js";
|
|
23
|
+
import { r as resolveBrowserExecutableForPlatform } from "./chrome.executables-Dp0Lkjmz.js";
|
|
24
|
+
import "./control-auth-DUZs9D8n.js";
|
|
25
|
+
import { n as resolveProfile, t as resolveBrowserConfig } from "./config-BZb7_jO5.js";
|
|
26
|
+
import fs from "node:fs";
|
|
27
|
+
import os from "node:os";
|
|
28
|
+
import path from "node:path";
|
|
29
|
+
import fs$1 from "node:fs/promises";
|
|
30
|
+
import crypto, { randomUUID } from "node:crypto";
|
|
31
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
32
|
+
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
33
|
+
//#region extensions/browser/src/browser/bridge-auth-registry.ts
|
|
34
|
+
const authByPort = /* @__PURE__ */ new Map();
|
|
35
|
+
function setBridgeAuthForPort(port, auth) {
|
|
36
|
+
if (!Number.isFinite(port) || port <= 0) return;
|
|
37
|
+
const token = normalizeOptionalString(auth.token) ?? "";
|
|
38
|
+
const password = normalizeOptionalString(auth.password) ?? "";
|
|
39
|
+
authByPort.set(port, {
|
|
40
|
+
token: token || void 0,
|
|
41
|
+
password: password || void 0
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function getBridgeAuthForPort(port) {
|
|
45
|
+
if (!Number.isFinite(port) || port <= 0) return;
|
|
46
|
+
return authByPort.get(port);
|
|
47
|
+
}
|
|
48
|
+
function deleteBridgeAuthForPort(port) {
|
|
49
|
+
if (!Number.isFinite(port) || port <= 0) return;
|
|
50
|
+
authByPort.delete(port);
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
//#region extensions/browser/src/browser/chrome-mcp.ts
|
|
54
|
+
const DEFAULT_CHROME_MCP_COMMAND = "npx";
|
|
55
|
+
const DEFAULT_CHROME_MCP_ARGS = [
|
|
56
|
+
"-y",
|
|
57
|
+
"chrome-devtools-mcp@latest",
|
|
58
|
+
"--autoConnect",
|
|
59
|
+
"--experimentalStructuredContent",
|
|
60
|
+
"--experimental-page-id-routing"
|
|
61
|
+
];
|
|
62
|
+
const sessions = /* @__PURE__ */ new Map();
|
|
63
|
+
const pendingSessions = /* @__PURE__ */ new Map();
|
|
64
|
+
let sessionFactory = null;
|
|
65
|
+
function asPages(value) {
|
|
66
|
+
if (!Array.isArray(value)) return [];
|
|
67
|
+
const out = [];
|
|
68
|
+
for (const entry of value) {
|
|
69
|
+
const record = asNullableRecord(entry);
|
|
70
|
+
if (!record || typeof record.id !== "number") continue;
|
|
71
|
+
out.push({
|
|
72
|
+
id: record.id,
|
|
73
|
+
url: readStringValue(record.url),
|
|
74
|
+
selected: record.selected === true
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
79
|
+
function parsePageId(targetId) {
|
|
80
|
+
const parsed = Number.parseInt(targetId.trim(), 10);
|
|
81
|
+
if (!Number.isFinite(parsed)) throw new BrowserTabNotFoundError();
|
|
82
|
+
return parsed;
|
|
83
|
+
}
|
|
84
|
+
function toBrowserTabs(pages) {
|
|
85
|
+
return pages.map((page) => ({
|
|
86
|
+
targetId: String(page.id),
|
|
87
|
+
title: "",
|
|
88
|
+
url: page.url ?? "",
|
|
89
|
+
type: "page"
|
|
90
|
+
}));
|
|
91
|
+
}
|
|
92
|
+
function extractStructuredContent(result) {
|
|
93
|
+
return asNullableRecord(result.structuredContent) ?? {};
|
|
94
|
+
}
|
|
95
|
+
function extractTextContent(result) {
|
|
96
|
+
return (Array.isArray(result.content) ? result.content : []).map((entry) => {
|
|
97
|
+
const record = asNullableRecord(entry);
|
|
98
|
+
return record && typeof record.text === "string" ? record.text : "";
|
|
99
|
+
}).filter(Boolean);
|
|
100
|
+
}
|
|
101
|
+
function extractTextPages(result) {
|
|
102
|
+
const pages = [];
|
|
103
|
+
for (const block of extractTextContent(result)) for (const line of block.split(/\r?\n/)) {
|
|
104
|
+
const match = line.match(/^\s*(\d+):\s+(.+?)(?:\s+\[(selected)\])?\s*$/i);
|
|
105
|
+
if (!match) continue;
|
|
106
|
+
pages.push({
|
|
107
|
+
id: Number.parseInt(match[1] ?? "", 10),
|
|
108
|
+
url: normalizeOptionalString(match[2]),
|
|
109
|
+
selected: Boolean(match[3])
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
return pages;
|
|
113
|
+
}
|
|
114
|
+
function extractStructuredPages(result) {
|
|
115
|
+
const structured = asPages(extractStructuredContent(result).pages);
|
|
116
|
+
return structured.length > 0 ? structured : extractTextPages(result);
|
|
117
|
+
}
|
|
118
|
+
function extractSnapshot(result) {
|
|
119
|
+
const snapshot = asNullableRecord(extractStructuredContent(result).snapshot);
|
|
120
|
+
if (!snapshot) throw new Error("Chrome MCP snapshot response was missing structured snapshot data.");
|
|
121
|
+
return snapshot;
|
|
122
|
+
}
|
|
123
|
+
function extractJsonBlock(text) {
|
|
124
|
+
const raw = text.match(/```json\s*([\s\S]*?)\s*```/i)?.[1]?.trim() || text.trim();
|
|
125
|
+
return raw ? JSON.parse(raw) : null;
|
|
126
|
+
}
|
|
127
|
+
function extractMessageText(result) {
|
|
128
|
+
const message = extractStructuredContent(result).message;
|
|
129
|
+
if (typeof message === "string" && message.trim()) return message;
|
|
130
|
+
return extractTextContent(result).find((block) => block.trim()) ?? "";
|
|
131
|
+
}
|
|
132
|
+
function extractToolErrorMessage(result, name) {
|
|
133
|
+
return extractMessageText(result).trim() || `Chrome MCP tool "${name}" failed.`;
|
|
134
|
+
}
|
|
135
|
+
function extractJsonMessage(result) {
|
|
136
|
+
const candidates = [extractMessageText(result), ...extractTextContent(result)].filter((text) => text.trim());
|
|
137
|
+
let lastError;
|
|
138
|
+
for (const candidate of candidates) try {
|
|
139
|
+
return extractJsonBlock(candidate);
|
|
140
|
+
} catch (err) {
|
|
141
|
+
lastError = err;
|
|
142
|
+
}
|
|
143
|
+
if (lastError) throw lastError;
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
function normalizeChromeMcpUserDataDir(userDataDir) {
|
|
147
|
+
const trimmed = userDataDir?.trim();
|
|
148
|
+
return trimmed ? trimmed : void 0;
|
|
149
|
+
}
|
|
150
|
+
function buildChromeMcpSessionCacheKey(profileName, userDataDir) {
|
|
151
|
+
return JSON.stringify([profileName, normalizeChromeMcpUserDataDir(userDataDir) ?? ""]);
|
|
152
|
+
}
|
|
153
|
+
function cacheKeyMatchesProfileName(cacheKey, profileName) {
|
|
154
|
+
try {
|
|
155
|
+
const parsed = JSON.parse(cacheKey);
|
|
156
|
+
return Array.isArray(parsed) && parsed[0] === profileName;
|
|
157
|
+
} catch {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
async function closeChromeMcpSessionsForProfile(profileName, keepKey) {
|
|
162
|
+
let closed = false;
|
|
163
|
+
for (const key of Array.from(pendingSessions.keys())) if (key !== keepKey && cacheKeyMatchesProfileName(key, profileName)) {
|
|
164
|
+
pendingSessions.delete(key);
|
|
165
|
+
closed = true;
|
|
166
|
+
}
|
|
167
|
+
for (const [key, session] of Array.from(sessions.entries())) if (key !== keepKey && cacheKeyMatchesProfileName(key, profileName)) {
|
|
168
|
+
sessions.delete(key);
|
|
169
|
+
closed = true;
|
|
170
|
+
await session.client.close().catch(() => {});
|
|
171
|
+
}
|
|
172
|
+
return closed;
|
|
173
|
+
}
|
|
174
|
+
function buildChromeMcpArgs(userDataDir) {
|
|
175
|
+
const normalizedUserDataDir = normalizeChromeMcpUserDataDir(userDataDir);
|
|
176
|
+
return normalizedUserDataDir ? [
|
|
177
|
+
...DEFAULT_CHROME_MCP_ARGS,
|
|
178
|
+
"--userDataDir",
|
|
179
|
+
normalizedUserDataDir
|
|
180
|
+
] : [...DEFAULT_CHROME_MCP_ARGS];
|
|
181
|
+
}
|
|
182
|
+
async function createRealSession(profileName, userDataDir) {
|
|
183
|
+
const transport = new StdioClientTransport({
|
|
184
|
+
command: DEFAULT_CHROME_MCP_COMMAND,
|
|
185
|
+
args: buildChromeMcpArgs(userDataDir),
|
|
186
|
+
stderr: "pipe"
|
|
187
|
+
});
|
|
188
|
+
const client = new Client({
|
|
189
|
+
name: "kaijibot-browser",
|
|
190
|
+
version: "0.0.0"
|
|
191
|
+
}, {});
|
|
192
|
+
return {
|
|
193
|
+
client,
|
|
194
|
+
transport,
|
|
195
|
+
ready: (async () => {
|
|
196
|
+
try {
|
|
197
|
+
await client.connect(transport);
|
|
198
|
+
if (!(await client.listTools()).tools.some((tool) => tool.name === "list_pages")) throw new Error("Chrome MCP server did not expose the expected navigation tools.");
|
|
199
|
+
} catch (err) {
|
|
200
|
+
await client.close().catch(() => {});
|
|
201
|
+
throw new BrowserProfileUnavailableError(`Chrome MCP existing-session attach failed for profile "${profileName}". Make sure ${userDataDir ? `the configured Chromium user data dir (${userDataDir})` : "Google Chrome's default profile"} is running locally with remote debugging enabled. Details: ${String(err)}`);
|
|
202
|
+
}
|
|
203
|
+
})()
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
async function getSession(profileName, userDataDir) {
|
|
207
|
+
const cacheKey = buildChromeMcpSessionCacheKey(profileName, userDataDir);
|
|
208
|
+
await closeChromeMcpSessionsForProfile(profileName, cacheKey);
|
|
209
|
+
let session = sessions.get(cacheKey);
|
|
210
|
+
if (session && session.transport.pid === null) {
|
|
211
|
+
sessions.delete(cacheKey);
|
|
212
|
+
session = void 0;
|
|
213
|
+
}
|
|
214
|
+
if (!session) {
|
|
215
|
+
let pending = pendingSessions.get(cacheKey);
|
|
216
|
+
if (!pending) {
|
|
217
|
+
pending = (async () => {
|
|
218
|
+
const created = await (sessionFactory ?? createRealSession)(profileName, userDataDir);
|
|
219
|
+
if (pendingSessions.get(cacheKey) === pending) sessions.set(cacheKey, created);
|
|
220
|
+
else await created.client.close().catch(() => {});
|
|
221
|
+
return created;
|
|
222
|
+
})();
|
|
223
|
+
pendingSessions.set(cacheKey, pending);
|
|
224
|
+
}
|
|
225
|
+
try {
|
|
226
|
+
session = await pending;
|
|
227
|
+
} finally {
|
|
228
|
+
if (pendingSessions.get(cacheKey) === pending) pendingSessions.delete(cacheKey);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
try {
|
|
232
|
+
await session.ready;
|
|
233
|
+
return session;
|
|
234
|
+
} catch (err) {
|
|
235
|
+
if (sessions.get(cacheKey)?.transport === session.transport) sessions.delete(cacheKey);
|
|
236
|
+
throw err;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
async function callTool(profileName, userDataDir, name, args = {}) {
|
|
240
|
+
const cacheKey = buildChromeMcpSessionCacheKey(profileName, userDataDir);
|
|
241
|
+
const session = await getSession(profileName, userDataDir);
|
|
242
|
+
let result;
|
|
243
|
+
try {
|
|
244
|
+
result = await session.client.callTool({
|
|
245
|
+
name,
|
|
246
|
+
arguments: args
|
|
247
|
+
});
|
|
248
|
+
} catch (err) {
|
|
249
|
+
sessions.delete(cacheKey);
|
|
250
|
+
await session.client.close().catch(() => {});
|
|
251
|
+
throw err;
|
|
252
|
+
}
|
|
253
|
+
if (result.isError) throw new Error(extractToolErrorMessage(result, name));
|
|
254
|
+
return result;
|
|
255
|
+
}
|
|
256
|
+
async function withTempFile(fn) {
|
|
257
|
+
const dir = await fs$1.mkdtemp(path.join(os.tmpdir(), "kaijibot-chrome-mcp-"));
|
|
258
|
+
const filePath = path.join(dir, randomUUID());
|
|
259
|
+
try {
|
|
260
|
+
return await fn(filePath);
|
|
261
|
+
} finally {
|
|
262
|
+
await fs$1.rm(dir, {
|
|
263
|
+
recursive: true,
|
|
264
|
+
force: true
|
|
265
|
+
}).catch(() => {});
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
async function findPageById(profileName, pageId, userDataDir) {
|
|
269
|
+
const page = (await listChromeMcpPages(profileName, userDataDir)).find((entry) => entry.id === pageId);
|
|
270
|
+
if (!page) throw new BrowserTabNotFoundError();
|
|
271
|
+
return page;
|
|
272
|
+
}
|
|
273
|
+
async function ensureChromeMcpAvailable(profileName, userDataDir) {
|
|
274
|
+
await getSession(profileName, userDataDir);
|
|
275
|
+
}
|
|
276
|
+
function getChromeMcpPid(profileName) {
|
|
277
|
+
for (const [key, session] of sessions.entries()) if (cacheKeyMatchesProfileName(key, profileName)) return session.transport.pid ?? null;
|
|
278
|
+
return null;
|
|
279
|
+
}
|
|
280
|
+
async function closeChromeMcpSession(profileName) {
|
|
281
|
+
return await closeChromeMcpSessionsForProfile(profileName);
|
|
282
|
+
}
|
|
283
|
+
async function listChromeMcpPages(profileName, userDataDir) {
|
|
284
|
+
return extractStructuredPages(await callTool(profileName, userDataDir, "list_pages"));
|
|
285
|
+
}
|
|
286
|
+
async function listChromeMcpTabs(profileName, userDataDir) {
|
|
287
|
+
return toBrowserTabs(await listChromeMcpPages(profileName, userDataDir));
|
|
288
|
+
}
|
|
289
|
+
async function openChromeMcpTab(profileName, url, userDataDir) {
|
|
290
|
+
const pages = extractStructuredPages(await callTool(profileName, userDataDir, "new_page", { url }));
|
|
291
|
+
const chosen = pages.find((page) => page.selected) ?? pages.at(-1);
|
|
292
|
+
if (!chosen) throw new Error("Chrome MCP did not return the created page.");
|
|
293
|
+
return {
|
|
294
|
+
targetId: String(chosen.id),
|
|
295
|
+
title: "",
|
|
296
|
+
url: chosen.url ?? url,
|
|
297
|
+
type: "page"
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
async function focusChromeMcpTab(profileName, targetId, userDataDir) {
|
|
301
|
+
await callTool(profileName, userDataDir, "select_page", {
|
|
302
|
+
pageId: parsePageId(targetId),
|
|
303
|
+
bringToFront: true
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
async function closeChromeMcpTab(profileName, targetId, userDataDir) {
|
|
307
|
+
await callTool(profileName, userDataDir, "close_page", { pageId: parsePageId(targetId) });
|
|
308
|
+
}
|
|
309
|
+
async function navigateChromeMcpPage(params) {
|
|
310
|
+
await callTool(params.profileName, params.userDataDir, "navigate_page", {
|
|
311
|
+
pageId: parsePageId(params.targetId),
|
|
312
|
+
type: "url",
|
|
313
|
+
url: params.url,
|
|
314
|
+
...typeof params.timeoutMs === "number" ? { timeout: params.timeoutMs } : {}
|
|
315
|
+
});
|
|
316
|
+
return { url: (await findPageById(params.profileName, parsePageId(params.targetId), params.userDataDir)).url ?? params.url };
|
|
317
|
+
}
|
|
318
|
+
async function takeChromeMcpSnapshot(params) {
|
|
319
|
+
return extractSnapshot(await callTool(params.profileName, params.userDataDir, "take_snapshot", { pageId: parsePageId(params.targetId) }));
|
|
320
|
+
}
|
|
321
|
+
async function takeChromeMcpScreenshot(params) {
|
|
322
|
+
return await withTempFile(async (filePath) => {
|
|
323
|
+
await callTool(params.profileName, params.userDataDir, "take_screenshot", {
|
|
324
|
+
pageId: parsePageId(params.targetId),
|
|
325
|
+
filePath,
|
|
326
|
+
format: params.format ?? "png",
|
|
327
|
+
...params.uid ? { uid: params.uid } : {},
|
|
328
|
+
...params.fullPage ? { fullPage: true } : {}
|
|
329
|
+
});
|
|
330
|
+
return await fs$1.readFile(filePath);
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
async function clickChromeMcpElement(params) {
|
|
334
|
+
await callTool(params.profileName, params.userDataDir, "click", {
|
|
335
|
+
pageId: parsePageId(params.targetId),
|
|
336
|
+
uid: params.uid,
|
|
337
|
+
...params.doubleClick ? { dblClick: true } : {}
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
async function fillChromeMcpElement(params) {
|
|
341
|
+
await callTool(params.profileName, params.userDataDir, "fill", {
|
|
342
|
+
pageId: parsePageId(params.targetId),
|
|
343
|
+
uid: params.uid,
|
|
344
|
+
value: params.value
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
async function fillChromeMcpForm(params) {
|
|
348
|
+
await callTool(params.profileName, params.userDataDir, "fill_form", {
|
|
349
|
+
pageId: parsePageId(params.targetId),
|
|
350
|
+
elements: params.elements
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
async function hoverChromeMcpElement(params) {
|
|
354
|
+
await callTool(params.profileName, params.userDataDir, "hover", {
|
|
355
|
+
pageId: parsePageId(params.targetId),
|
|
356
|
+
uid: params.uid
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
async function dragChromeMcpElement(params) {
|
|
360
|
+
await callTool(params.profileName, params.userDataDir, "drag", {
|
|
361
|
+
pageId: parsePageId(params.targetId),
|
|
362
|
+
from_uid: params.fromUid,
|
|
363
|
+
to_uid: params.toUid
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
async function uploadChromeMcpFile(params) {
|
|
367
|
+
await callTool(params.profileName, params.userDataDir, "upload_file", {
|
|
368
|
+
pageId: parsePageId(params.targetId),
|
|
369
|
+
uid: params.uid,
|
|
370
|
+
filePath: params.filePath
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
async function pressChromeMcpKey(params) {
|
|
374
|
+
await callTool(params.profileName, params.userDataDir, "press_key", {
|
|
375
|
+
pageId: parsePageId(params.targetId),
|
|
376
|
+
key: params.key
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
async function resizeChromeMcpPage(params) {
|
|
380
|
+
await callTool(params.profileName, params.userDataDir, "resize_page", {
|
|
381
|
+
pageId: parsePageId(params.targetId),
|
|
382
|
+
width: params.width,
|
|
383
|
+
height: params.height
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
async function evaluateChromeMcpScript(params) {
|
|
387
|
+
return extractJsonMessage(await callTool(params.profileName, params.userDataDir, "evaluate_script", {
|
|
388
|
+
pageId: parsePageId(params.targetId),
|
|
389
|
+
function: params.fn,
|
|
390
|
+
...params.args?.length ? { args: params.args } : {}
|
|
391
|
+
}));
|
|
392
|
+
}
|
|
393
|
+
//#endregion
|
|
394
|
+
//#region extensions/browser/src/browser/profile-capabilities.ts
|
|
395
|
+
function getBrowserProfileCapabilities(profile) {
|
|
396
|
+
if (profile.driver === "existing-session") return {
|
|
397
|
+
mode: "local-existing-session",
|
|
398
|
+
isRemote: false,
|
|
399
|
+
usesChromeMcp: true,
|
|
400
|
+
usesPersistentPlaywright: false,
|
|
401
|
+
supportsPerTabWs: false,
|
|
402
|
+
supportsJsonTabEndpoints: false,
|
|
403
|
+
supportsReset: false,
|
|
404
|
+
supportsManagedTabLimit: false
|
|
405
|
+
};
|
|
406
|
+
if (!profile.cdpIsLoopback) return {
|
|
407
|
+
mode: "remote-cdp",
|
|
408
|
+
isRemote: true,
|
|
409
|
+
usesChromeMcp: false,
|
|
410
|
+
usesPersistentPlaywright: true,
|
|
411
|
+
supportsPerTabWs: false,
|
|
412
|
+
supportsJsonTabEndpoints: false,
|
|
413
|
+
supportsReset: false,
|
|
414
|
+
supportsManagedTabLimit: false
|
|
415
|
+
};
|
|
416
|
+
return {
|
|
417
|
+
mode: "local-managed",
|
|
418
|
+
isRemote: false,
|
|
419
|
+
usesChromeMcp: false,
|
|
420
|
+
usesPersistentPlaywright: false,
|
|
421
|
+
supportsPerTabWs: true,
|
|
422
|
+
supportsJsonTabEndpoints: true,
|
|
423
|
+
supportsReset: true,
|
|
424
|
+
supportsManagedTabLimit: true
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
function resolveDefaultSnapshotFormat(params) {
|
|
428
|
+
if (params.explicitFormat) return params.explicitFormat;
|
|
429
|
+
if (params.mode === "efficient") return "ai";
|
|
430
|
+
if (getBrowserProfileCapabilities(params.profile).mode === "local-existing-session") return "ai";
|
|
431
|
+
return params.hasPlaywright ? "ai" : "aria";
|
|
432
|
+
}
|
|
433
|
+
function shouldUsePlaywrightForScreenshot(params) {
|
|
434
|
+
return !params.wsUrl || Boolean(params.ref) || Boolean(params.element);
|
|
435
|
+
}
|
|
436
|
+
function shouldUsePlaywrightForAriaSnapshot(params) {
|
|
437
|
+
return !params.wsUrl;
|
|
438
|
+
}
|
|
439
|
+
//#endregion
|
|
440
|
+
//#region extensions/browser/src/browser/pw-ai-module.ts
|
|
441
|
+
let pwAiModuleSoft = null;
|
|
442
|
+
let pwAiModuleStrict = null;
|
|
443
|
+
function isModuleNotFoundError(err) {
|
|
444
|
+
if (extractErrorCode(err) === "ERR_MODULE_NOT_FOUND") return true;
|
|
445
|
+
const msg = formatErrorMessage(err);
|
|
446
|
+
return msg.includes("Cannot find module") || msg.includes("Cannot find package") || msg.includes("Failed to resolve import") || msg.includes("Failed to resolve entry for package") || msg.includes("Failed to load url");
|
|
447
|
+
}
|
|
448
|
+
async function loadPwAiModule(mode) {
|
|
449
|
+
try {
|
|
450
|
+
return await import("./pw-ai-Ld88tf39.js");
|
|
451
|
+
} catch (err) {
|
|
452
|
+
if (mode === "soft") return null;
|
|
453
|
+
if (isModuleNotFoundError(err)) return null;
|
|
454
|
+
throw err;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
async function getPwAiModule$1(opts) {
|
|
458
|
+
if ((opts?.mode ?? "soft") === "soft") {
|
|
459
|
+
if (!pwAiModuleSoft) pwAiModuleSoft = loadPwAiModule("soft");
|
|
460
|
+
return await pwAiModuleSoft;
|
|
461
|
+
}
|
|
462
|
+
if (!pwAiModuleStrict) pwAiModuleStrict = loadPwAiModule("strict");
|
|
463
|
+
return await pwAiModuleStrict;
|
|
464
|
+
}
|
|
465
|
+
//#endregion
|
|
466
|
+
//#region extensions/browser/src/browser/routes/utils.ts
|
|
467
|
+
/**
|
|
468
|
+
* Extract profile name from query string or body and get profile context.
|
|
469
|
+
* Query string takes precedence over body for consistency with GET routes.
|
|
470
|
+
*/
|
|
471
|
+
function getProfileContext(req, ctx) {
|
|
472
|
+
let profileName;
|
|
473
|
+
if (typeof req.query.profile === "string") profileName = normalizeOptionalString(req.query.profile);
|
|
474
|
+
if (!profileName && req.body && typeof req.body === "object") {
|
|
475
|
+
const body = req.body;
|
|
476
|
+
if (typeof body.profile === "string") profileName = normalizeOptionalString(body.profile);
|
|
477
|
+
}
|
|
478
|
+
try {
|
|
479
|
+
return ctx.forProfile(profileName);
|
|
480
|
+
} catch (err) {
|
|
481
|
+
return {
|
|
482
|
+
error: String(err),
|
|
483
|
+
status: 404
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
function jsonError(res, status, message) {
|
|
488
|
+
res.status(status).json({ error: message });
|
|
489
|
+
}
|
|
490
|
+
function toStringOrEmpty(value) {
|
|
491
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return normalizeOptionalString(String(value)) ?? "";
|
|
492
|
+
return "";
|
|
493
|
+
}
|
|
494
|
+
function toNumber(value) {
|
|
495
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
496
|
+
const normalized = typeof value === "string" ? normalizeOptionalString(value) : void 0;
|
|
497
|
+
if (normalized) {
|
|
498
|
+
const parsed = Number(normalized);
|
|
499
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
function toBoolean(value) {
|
|
503
|
+
return parseBooleanValue(value, {
|
|
504
|
+
truthy: [
|
|
505
|
+
"true",
|
|
506
|
+
"1",
|
|
507
|
+
"yes"
|
|
508
|
+
],
|
|
509
|
+
falsy: [
|
|
510
|
+
"false",
|
|
511
|
+
"0",
|
|
512
|
+
"no"
|
|
513
|
+
]
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
function toStringArray(value) {
|
|
517
|
+
if (!Array.isArray(value)) return;
|
|
518
|
+
const strings = value.map((v) => toStringOrEmpty(v)).filter(Boolean);
|
|
519
|
+
return strings.length ? strings : void 0;
|
|
520
|
+
}
|
|
521
|
+
//#endregion
|
|
522
|
+
//#region extensions/browser/src/browser/routes/agent.shared.ts
|
|
523
|
+
const SELECTOR_UNSUPPORTED_MESSAGE = [
|
|
524
|
+
"Error: 'selector' is not supported. Use 'ref' from snapshot instead.",
|
|
525
|
+
"",
|
|
526
|
+
"Example workflow:",
|
|
527
|
+
"1. snapshot action to get page state with refs",
|
|
528
|
+
"2. act with ref: \"e123\" to interact with element",
|
|
529
|
+
"",
|
|
530
|
+
"This is more reliable for modern SPAs."
|
|
531
|
+
].join("\n");
|
|
532
|
+
function readBody(req) {
|
|
533
|
+
const body = req.body;
|
|
534
|
+
if (!body || typeof body !== "object" || Array.isArray(body)) return {};
|
|
535
|
+
return body;
|
|
536
|
+
}
|
|
537
|
+
function resolveTargetIdFromBody(body) {
|
|
538
|
+
return (normalizeOptionalString(body.targetId) ?? "") || void 0;
|
|
539
|
+
}
|
|
540
|
+
function resolveTargetIdFromQuery(query) {
|
|
541
|
+
return (normalizeOptionalString(query.targetId) ?? "") || void 0;
|
|
542
|
+
}
|
|
543
|
+
function handleRouteError(ctx, res, err) {
|
|
544
|
+
const mapped = ctx.mapTabError(err);
|
|
545
|
+
if (mapped) return jsonError(res, mapped.status, mapped.message);
|
|
546
|
+
const browserMapped = toBrowserErrorResponse(err);
|
|
547
|
+
if (browserMapped) return jsonError(res, browserMapped.status, browserMapped.message);
|
|
548
|
+
jsonError(res, 500, String(err));
|
|
549
|
+
}
|
|
550
|
+
function resolveProfileContext(req, res, ctx) {
|
|
551
|
+
const profileCtx = getProfileContext(req, ctx);
|
|
552
|
+
if ("error" in profileCtx) {
|
|
553
|
+
jsonError(res, profileCtx.status, profileCtx.error);
|
|
554
|
+
return null;
|
|
555
|
+
}
|
|
556
|
+
return profileCtx;
|
|
557
|
+
}
|
|
558
|
+
async function getPwAiModule() {
|
|
559
|
+
return await getPwAiModule$1({ mode: "soft" });
|
|
560
|
+
}
|
|
561
|
+
async function requirePwAi(res, feature) {
|
|
562
|
+
const mod = await getPwAiModule();
|
|
563
|
+
if (mod) return mod;
|
|
564
|
+
jsonError(res, 501, [
|
|
565
|
+
`Playwright is not available in this gateway build; '${feature}' is unsupported.`,
|
|
566
|
+
"Install the full Playwright package (not playwright-core) and restart the gateway, or reinstall with browser support.",
|
|
567
|
+
"Docs: /tools/browser#playwright-requirement"
|
|
568
|
+
].join("\n"));
|
|
569
|
+
return null;
|
|
570
|
+
}
|
|
571
|
+
async function withRouteTabContext(params) {
|
|
572
|
+
const profileCtx = resolveProfileContext(params.req, params.res, params.ctx);
|
|
573
|
+
if (!profileCtx) return;
|
|
574
|
+
try {
|
|
575
|
+
const tab = await profileCtx.ensureTabAvailable(params.targetId);
|
|
576
|
+
return await params.run({
|
|
577
|
+
profileCtx,
|
|
578
|
+
tab,
|
|
579
|
+
cdpUrl: profileCtx.profile.cdpUrl
|
|
580
|
+
});
|
|
581
|
+
} catch (err) {
|
|
582
|
+
handleRouteError(params.ctx, params.res, err);
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
async function withPlaywrightRouteContext(params) {
|
|
587
|
+
return await withRouteTabContext({
|
|
588
|
+
req: params.req,
|
|
589
|
+
res: params.res,
|
|
590
|
+
ctx: params.ctx,
|
|
591
|
+
targetId: params.targetId,
|
|
592
|
+
run: async ({ profileCtx, tab, cdpUrl }) => {
|
|
593
|
+
const pw = await requirePwAi(params.res, params.feature);
|
|
594
|
+
if (!pw) return;
|
|
595
|
+
return await params.run({
|
|
596
|
+
profileCtx,
|
|
597
|
+
tab,
|
|
598
|
+
cdpUrl,
|
|
599
|
+
pw
|
|
600
|
+
});
|
|
601
|
+
}
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
//#endregion
|
|
605
|
+
//#region extensions/browser/src/browser/routes/output-paths.ts
|
|
606
|
+
async function ensureOutputRootDir(rootDir) {
|
|
607
|
+
await fs$1.mkdir(rootDir, { recursive: true });
|
|
608
|
+
}
|
|
609
|
+
async function resolveWritableOutputPathOrRespond(params) {
|
|
610
|
+
if (params.ensureRootDir) await ensureOutputRootDir(params.rootDir);
|
|
611
|
+
const pathResult = await resolveWritablePathWithinRoot({
|
|
612
|
+
rootDir: params.rootDir,
|
|
613
|
+
requestedPath: params.requestedPath,
|
|
614
|
+
scopeLabel: params.scopeLabel,
|
|
615
|
+
defaultFileName: params.defaultFileName
|
|
616
|
+
});
|
|
617
|
+
if (!pathResult.ok) {
|
|
618
|
+
params.res.status(400).json({ error: pathResult.error });
|
|
619
|
+
return null;
|
|
620
|
+
}
|
|
621
|
+
return pathResult.path;
|
|
622
|
+
}
|
|
623
|
+
//#endregion
|
|
624
|
+
//#region extensions/browser/src/browser/routes/agent.act.download.ts
|
|
625
|
+
function buildDownloadRequestBase(cdpUrl, targetId, timeoutMs) {
|
|
626
|
+
return {
|
|
627
|
+
cdpUrl,
|
|
628
|
+
targetId,
|
|
629
|
+
timeoutMs: timeoutMs ?? void 0
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
function registerBrowserAgentActDownloadRoutes(app, ctx) {
|
|
633
|
+
app.post("/wait/download", async (req, res) => {
|
|
634
|
+
const body = readBody(req);
|
|
635
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
636
|
+
const out = toStringOrEmpty(body.path) || "";
|
|
637
|
+
const timeoutMs = toNumber(body.timeoutMs);
|
|
638
|
+
await withRouteTabContext({
|
|
639
|
+
req,
|
|
640
|
+
res,
|
|
641
|
+
ctx,
|
|
642
|
+
targetId,
|
|
643
|
+
run: async ({ profileCtx, cdpUrl, tab }) => {
|
|
644
|
+
if (getBrowserProfileCapabilities(profileCtx.profile).usesChromeMcp) return jsonError(res, 501, "download waiting is not supported for existing-session profiles yet.");
|
|
645
|
+
const pw = await requirePwAi(res, "wait for download");
|
|
646
|
+
if (!pw) return;
|
|
647
|
+
await ensureOutputRootDir(DEFAULT_DOWNLOAD_DIR);
|
|
648
|
+
let downloadPath;
|
|
649
|
+
if (out.trim()) {
|
|
650
|
+
const resolvedDownloadPath = await resolveWritableOutputPathOrRespond({
|
|
651
|
+
res,
|
|
652
|
+
rootDir: DEFAULT_DOWNLOAD_DIR,
|
|
653
|
+
requestedPath: out,
|
|
654
|
+
scopeLabel: "downloads directory"
|
|
655
|
+
});
|
|
656
|
+
if (!resolvedDownloadPath) return;
|
|
657
|
+
downloadPath = resolvedDownloadPath;
|
|
658
|
+
}
|
|
659
|
+
const requestBase = buildDownloadRequestBase(cdpUrl, tab.targetId, timeoutMs);
|
|
660
|
+
const result = await pw.waitForDownloadViaPlaywright({
|
|
661
|
+
...requestBase,
|
|
662
|
+
path: downloadPath
|
|
663
|
+
});
|
|
664
|
+
res.json({
|
|
665
|
+
ok: true,
|
|
666
|
+
targetId: tab.targetId,
|
|
667
|
+
download: result
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
});
|
|
671
|
+
});
|
|
672
|
+
app.post("/download", async (req, res) => {
|
|
673
|
+
const body = readBody(req);
|
|
674
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
675
|
+
const ref = toStringOrEmpty(body.ref);
|
|
676
|
+
const out = toStringOrEmpty(body.path);
|
|
677
|
+
const timeoutMs = toNumber(body.timeoutMs);
|
|
678
|
+
if (!ref) return jsonError(res, 400, "ref is required");
|
|
679
|
+
if (!out) return jsonError(res, 400, "path is required");
|
|
680
|
+
await withRouteTabContext({
|
|
681
|
+
req,
|
|
682
|
+
res,
|
|
683
|
+
ctx,
|
|
684
|
+
targetId,
|
|
685
|
+
run: async ({ profileCtx, cdpUrl, tab }) => {
|
|
686
|
+
if (getBrowserProfileCapabilities(profileCtx.profile).usesChromeMcp) return jsonError(res, 501, "downloads are not supported for existing-session profiles yet.");
|
|
687
|
+
const pw = await requirePwAi(res, "download");
|
|
688
|
+
if (!pw) return;
|
|
689
|
+
await ensureOutputRootDir(DEFAULT_DOWNLOAD_DIR);
|
|
690
|
+
const downloadPath = await resolveWritableOutputPathOrRespond({
|
|
691
|
+
res,
|
|
692
|
+
rootDir: DEFAULT_DOWNLOAD_DIR,
|
|
693
|
+
requestedPath: out,
|
|
694
|
+
scopeLabel: "downloads directory"
|
|
695
|
+
});
|
|
696
|
+
if (!downloadPath) return;
|
|
697
|
+
const requestBase = buildDownloadRequestBase(cdpUrl, tab.targetId, timeoutMs);
|
|
698
|
+
const result = await pw.downloadViaPlaywright({
|
|
699
|
+
...requestBase,
|
|
700
|
+
ref,
|
|
701
|
+
path: downloadPath
|
|
702
|
+
});
|
|
703
|
+
res.json({
|
|
704
|
+
ok: true,
|
|
705
|
+
targetId: tab.targetId,
|
|
706
|
+
download: result
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
});
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
//#endregion
|
|
713
|
+
//#region extensions/browser/src/browser/routes/agent.act.hooks.ts
|
|
714
|
+
function registerBrowserAgentActHookRoutes(app, ctx) {
|
|
715
|
+
app.post("/hooks/file-chooser", async (req, res) => {
|
|
716
|
+
const body = readBody(req);
|
|
717
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
718
|
+
const ref = toStringOrEmpty(body.ref) || void 0;
|
|
719
|
+
const inputRef = toStringOrEmpty(body.inputRef) || void 0;
|
|
720
|
+
const element = toStringOrEmpty(body.element) || void 0;
|
|
721
|
+
const paths = toStringArray(body.paths) ?? [];
|
|
722
|
+
const timeoutMs = toNumber(body.timeoutMs);
|
|
723
|
+
if (!paths.length) return jsonError(res, 400, "paths are required");
|
|
724
|
+
await withRouteTabContext({
|
|
725
|
+
req,
|
|
726
|
+
res,
|
|
727
|
+
ctx,
|
|
728
|
+
targetId,
|
|
729
|
+
run: async ({ profileCtx, cdpUrl, tab }) => {
|
|
730
|
+
const uploadPathsResult = await resolveExistingPathsWithinRoot({
|
|
731
|
+
rootDir: DEFAULT_UPLOAD_DIR,
|
|
732
|
+
requestedPaths: paths,
|
|
733
|
+
scopeLabel: `uploads directory (${DEFAULT_UPLOAD_DIR})`
|
|
734
|
+
});
|
|
735
|
+
if (!uploadPathsResult.ok) {
|
|
736
|
+
res.status(400).json({ error: uploadPathsResult.error });
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
739
|
+
const resolvedPaths = uploadPathsResult.paths;
|
|
740
|
+
if (getBrowserProfileCapabilities(profileCtx.profile).usesChromeMcp) {
|
|
741
|
+
if (element) return jsonError(res, 501, "existing-session file uploads do not support element selectors; use ref/inputRef.");
|
|
742
|
+
if (resolvedPaths.length !== 1) return jsonError(res, 501, "existing-session file uploads currently support one file at a time.");
|
|
743
|
+
const uid = inputRef || ref;
|
|
744
|
+
if (!uid) return jsonError(res, 501, "existing-session file uploads require ref or inputRef.");
|
|
745
|
+
await uploadChromeMcpFile({
|
|
746
|
+
profileName: profileCtx.profile.name,
|
|
747
|
+
userDataDir: profileCtx.profile.userDataDir,
|
|
748
|
+
targetId: tab.targetId,
|
|
749
|
+
uid,
|
|
750
|
+
filePath: resolvedPaths[0] ?? ""
|
|
751
|
+
});
|
|
752
|
+
return res.json({ ok: true });
|
|
753
|
+
}
|
|
754
|
+
const pw = await requirePwAi(res, "file chooser hook");
|
|
755
|
+
if (!pw) return;
|
|
756
|
+
if (inputRef || element) {
|
|
757
|
+
if (ref) return jsonError(res, 400, "ref cannot be combined with inputRef/element");
|
|
758
|
+
await pw.setInputFilesViaPlaywright({
|
|
759
|
+
cdpUrl,
|
|
760
|
+
targetId: tab.targetId,
|
|
761
|
+
inputRef,
|
|
762
|
+
element,
|
|
763
|
+
paths: resolvedPaths
|
|
764
|
+
});
|
|
765
|
+
} else {
|
|
766
|
+
await pw.armFileUploadViaPlaywright({
|
|
767
|
+
cdpUrl,
|
|
768
|
+
targetId: tab.targetId,
|
|
769
|
+
paths: resolvedPaths,
|
|
770
|
+
timeoutMs: timeoutMs ?? void 0
|
|
771
|
+
});
|
|
772
|
+
if (ref) await pw.clickViaPlaywright({
|
|
773
|
+
cdpUrl,
|
|
774
|
+
targetId: tab.targetId,
|
|
775
|
+
ssrfPolicy: ctx.state().resolved.ssrfPolicy,
|
|
776
|
+
ref
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
res.json({ ok: true });
|
|
780
|
+
}
|
|
781
|
+
});
|
|
782
|
+
});
|
|
783
|
+
app.post("/hooks/dialog", async (req, res) => {
|
|
784
|
+
const body = readBody(req);
|
|
785
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
786
|
+
const accept = toBoolean(body.accept);
|
|
787
|
+
const promptText = toStringOrEmpty(body.promptText) || void 0;
|
|
788
|
+
const timeoutMs = toNumber(body.timeoutMs);
|
|
789
|
+
if (accept === void 0) return jsonError(res, 400, "accept is required");
|
|
790
|
+
await withRouteTabContext({
|
|
791
|
+
req,
|
|
792
|
+
res,
|
|
793
|
+
ctx,
|
|
794
|
+
targetId,
|
|
795
|
+
run: async ({ profileCtx, cdpUrl, tab }) => {
|
|
796
|
+
if (getBrowserProfileCapabilities(profileCtx.profile).usesChromeMcp) {
|
|
797
|
+
if (timeoutMs) return jsonError(res, 501, "existing-session dialog handling does not support timeoutMs.");
|
|
798
|
+
await evaluateChromeMcpScript({
|
|
799
|
+
profileName: profileCtx.profile.name,
|
|
800
|
+
userDataDir: profileCtx.profile.userDataDir,
|
|
801
|
+
targetId: tab.targetId,
|
|
802
|
+
fn: `() => {
|
|
803
|
+
const state = (window.__kaijibotDialogHook ??= {});
|
|
804
|
+
if (!state.originals) {
|
|
805
|
+
state.originals = {
|
|
806
|
+
alert: window.alert.bind(window),
|
|
807
|
+
confirm: window.confirm.bind(window),
|
|
808
|
+
prompt: window.prompt.bind(window),
|
|
809
|
+
};
|
|
810
|
+
}
|
|
811
|
+
const originals = state.originals;
|
|
812
|
+
const restore = () => {
|
|
813
|
+
window.alert = originals.alert;
|
|
814
|
+
window.confirm = originals.confirm;
|
|
815
|
+
window.prompt = originals.prompt;
|
|
816
|
+
delete window.__kaijibotDialogHook;
|
|
817
|
+
};
|
|
818
|
+
window.alert = (...args) => {
|
|
819
|
+
try {
|
|
820
|
+
return undefined;
|
|
821
|
+
} finally {
|
|
822
|
+
restore();
|
|
823
|
+
}
|
|
824
|
+
};
|
|
825
|
+
window.confirm = (...args) => {
|
|
826
|
+
try {
|
|
827
|
+
return ${accept ? "true" : "false"};
|
|
828
|
+
} finally {
|
|
829
|
+
restore();
|
|
830
|
+
}
|
|
831
|
+
};
|
|
832
|
+
window.prompt = (...args) => {
|
|
833
|
+
try {
|
|
834
|
+
return ${accept ? JSON.stringify(promptText ?? "") : "null"};
|
|
835
|
+
} finally {
|
|
836
|
+
restore();
|
|
837
|
+
}
|
|
838
|
+
};
|
|
839
|
+
return true;
|
|
840
|
+
}`
|
|
841
|
+
});
|
|
842
|
+
return res.json({ ok: true });
|
|
843
|
+
}
|
|
844
|
+
const pw = await requirePwAi(res, "dialog hook");
|
|
845
|
+
if (!pw) return;
|
|
846
|
+
await pw.armDialogViaPlaywright({
|
|
847
|
+
cdpUrl,
|
|
848
|
+
targetId: tab.targetId,
|
|
849
|
+
accept,
|
|
850
|
+
promptText,
|
|
851
|
+
timeoutMs: timeoutMs ?? void 0
|
|
852
|
+
});
|
|
853
|
+
res.json({ ok: true });
|
|
854
|
+
}
|
|
855
|
+
});
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
//#endregion
|
|
859
|
+
//#region extensions/browser/src/browser/routes/agent.act.shared.ts
|
|
860
|
+
const ACT_KINDS = [
|
|
861
|
+
"batch",
|
|
862
|
+
"click",
|
|
863
|
+
"close",
|
|
864
|
+
"drag",
|
|
865
|
+
"evaluate",
|
|
866
|
+
"fill",
|
|
867
|
+
"hover",
|
|
868
|
+
"scrollIntoView",
|
|
869
|
+
"press",
|
|
870
|
+
"resize",
|
|
871
|
+
"select",
|
|
872
|
+
"type",
|
|
873
|
+
"wait"
|
|
874
|
+
];
|
|
875
|
+
function isActKind(value) {
|
|
876
|
+
if (typeof value !== "string") return false;
|
|
877
|
+
return ACT_KINDS.includes(value);
|
|
878
|
+
}
|
|
879
|
+
const ALLOWED_CLICK_MODIFIERS = new Set([
|
|
880
|
+
"Alt",
|
|
881
|
+
"Control",
|
|
882
|
+
"ControlOrMeta",
|
|
883
|
+
"Meta",
|
|
884
|
+
"Shift"
|
|
885
|
+
]);
|
|
886
|
+
function parseClickButton(raw) {
|
|
887
|
+
if (raw === "left" || raw === "right" || raw === "middle") return raw;
|
|
888
|
+
}
|
|
889
|
+
function parseClickModifiers(raw) {
|
|
890
|
+
if (raw.filter((m) => !ALLOWED_CLICK_MODIFIERS.has(m)).length) return { error: "modifiers must be Alt|Control|ControlOrMeta|Meta|Shift" };
|
|
891
|
+
return { modifiers: raw.length ? raw : void 0 };
|
|
892
|
+
}
|
|
893
|
+
//#endregion
|
|
894
|
+
//#region extensions/browser/src/browser/routes/agent.act.ts
|
|
895
|
+
function sleep(ms) {
|
|
896
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
897
|
+
}
|
|
898
|
+
function browserEvaluateDisabledMessage(action) {
|
|
899
|
+
return [action === "wait" ? "wait --fn is disabled by config (browser.evaluateEnabled=false)." : "act:evaluate is disabled by config (browser.evaluateEnabled=false).", "Docs: /gateway/configuration#browser-kaijibot-managed-browser"].join("\n");
|
|
900
|
+
}
|
|
901
|
+
function buildExistingSessionWaitPredicate(params) {
|
|
902
|
+
const checks = [];
|
|
903
|
+
if (params.text) checks.push(`Boolean(document.body?.innerText?.includes(${JSON.stringify(params.text)}))`);
|
|
904
|
+
if (params.textGone) checks.push(`!document.body?.innerText?.includes(${JSON.stringify(params.textGone)})`);
|
|
905
|
+
if (params.selector) checks.push(`Boolean(document.querySelector(${JSON.stringify(params.selector)}))`);
|
|
906
|
+
if (params.loadState === "domcontentloaded") checks.push(`document.readyState === "interactive" || document.readyState === "complete"`);
|
|
907
|
+
else if (params.loadState === "load") checks.push(`document.readyState === "complete"`);
|
|
908
|
+
if (params.fn) checks.push(`Boolean(await (${params.fn})())`);
|
|
909
|
+
if (checks.length === 0) return null;
|
|
910
|
+
return checks.length === 1 ? checks[0] : checks.map((check) => `(${check})`).join(" && ");
|
|
911
|
+
}
|
|
912
|
+
async function waitForExistingSessionCondition(params) {
|
|
913
|
+
if (params.timeMs && params.timeMs > 0) await sleep(params.timeMs);
|
|
914
|
+
const predicate = buildExistingSessionWaitPredicate(params);
|
|
915
|
+
if (!predicate && !params.url) return;
|
|
916
|
+
const timeoutMs = Math.max(250, params.timeoutMs ?? 1e4);
|
|
917
|
+
const deadline = Date.now() + timeoutMs;
|
|
918
|
+
while (Date.now() < deadline) {
|
|
919
|
+
let ready = true;
|
|
920
|
+
if (predicate) ready = Boolean(await evaluateChromeMcpScript({
|
|
921
|
+
profileName: params.profileName,
|
|
922
|
+
userDataDir: params.userDataDir,
|
|
923
|
+
targetId: params.targetId,
|
|
924
|
+
fn: `async () => ${predicate}`
|
|
925
|
+
}));
|
|
926
|
+
if (ready && params.url) {
|
|
927
|
+
const currentUrl = await evaluateChromeMcpScript({
|
|
928
|
+
profileName: params.profileName,
|
|
929
|
+
userDataDir: params.userDataDir,
|
|
930
|
+
targetId: params.targetId,
|
|
931
|
+
fn: "() => window.location.href"
|
|
932
|
+
});
|
|
933
|
+
ready = typeof currentUrl === "string" && matchBrowserUrlPattern(params.url, currentUrl);
|
|
934
|
+
}
|
|
935
|
+
if (ready) return;
|
|
936
|
+
await sleep(250);
|
|
937
|
+
}
|
|
938
|
+
throw new Error("Timed out waiting for condition");
|
|
939
|
+
}
|
|
940
|
+
const SELECTOR_ALLOWED_KINDS = new Set([
|
|
941
|
+
"batch",
|
|
942
|
+
"click",
|
|
943
|
+
"drag",
|
|
944
|
+
"hover",
|
|
945
|
+
"scrollIntoView",
|
|
946
|
+
"select",
|
|
947
|
+
"type",
|
|
948
|
+
"wait"
|
|
949
|
+
]);
|
|
950
|
+
const MAX_BATCH_ACTIONS = 100;
|
|
951
|
+
const MAX_BATCH_CLICK_DELAY_MS = 5e3;
|
|
952
|
+
const MAX_BATCH_WAIT_TIME_MS = 3e4;
|
|
953
|
+
function normalizeBoundedNonNegativeMs(value, fieldName, maxMs) {
|
|
954
|
+
const ms = toNumber(value);
|
|
955
|
+
if (ms === void 0) return;
|
|
956
|
+
if (ms < 0) throw new Error(`${fieldName} must be >= 0`);
|
|
957
|
+
const normalized = Math.floor(ms);
|
|
958
|
+
if (normalized > maxMs) throw new Error(`${fieldName} exceeds maximum of ${maxMs}ms`);
|
|
959
|
+
return normalized;
|
|
960
|
+
}
|
|
961
|
+
function countBatchActions(actions) {
|
|
962
|
+
let count = 0;
|
|
963
|
+
for (const action of actions) {
|
|
964
|
+
count += 1;
|
|
965
|
+
if (action.kind === "batch") count += countBatchActions(action.actions);
|
|
966
|
+
}
|
|
967
|
+
return count;
|
|
968
|
+
}
|
|
969
|
+
function validateBatchTargetIds(actions, targetId) {
|
|
970
|
+
for (const action of actions) {
|
|
971
|
+
if (action.targetId && action.targetId !== targetId) return "batched action targetId must match request targetId";
|
|
972
|
+
if (action.kind === "batch") {
|
|
973
|
+
const nestedError = validateBatchTargetIds(action.actions, targetId);
|
|
974
|
+
if (nestedError) return nestedError;
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
return null;
|
|
978
|
+
}
|
|
979
|
+
function normalizeBatchAction(value) {
|
|
980
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("batch actions must be objects");
|
|
981
|
+
const raw = value;
|
|
982
|
+
const kind = toStringOrEmpty(raw.kind);
|
|
983
|
+
if (!isActKind(kind)) throw new Error("batch actions must use a supported kind");
|
|
984
|
+
switch (kind) {
|
|
985
|
+
case "click": {
|
|
986
|
+
const ref = toStringOrEmpty(raw.ref) || void 0;
|
|
987
|
+
const selector = toStringOrEmpty(raw.selector) || void 0;
|
|
988
|
+
if (!ref && !selector) throw new Error("click requires ref or selector");
|
|
989
|
+
const buttonRaw = toStringOrEmpty(raw.button);
|
|
990
|
+
const button = buttonRaw ? parseClickButton(buttonRaw) : void 0;
|
|
991
|
+
if (buttonRaw && !button) throw new Error("click button must be left|right|middle");
|
|
992
|
+
const parsedModifiers = parseClickModifiers(toStringArray(raw.modifiers) ?? []);
|
|
993
|
+
if (parsedModifiers.error) throw new Error(parsedModifiers.error);
|
|
994
|
+
const doubleClick = toBoolean(raw.doubleClick);
|
|
995
|
+
const delayMs = normalizeBoundedNonNegativeMs(raw.delayMs, "click delayMs", MAX_BATCH_CLICK_DELAY_MS);
|
|
996
|
+
const timeoutMs = toNumber(raw.timeoutMs);
|
|
997
|
+
const targetId = toStringOrEmpty(raw.targetId) || void 0;
|
|
998
|
+
return {
|
|
999
|
+
kind,
|
|
1000
|
+
...ref ? { ref } : {},
|
|
1001
|
+
...selector ? { selector } : {},
|
|
1002
|
+
...targetId ? { targetId } : {},
|
|
1003
|
+
...doubleClick !== void 0 ? { doubleClick } : {},
|
|
1004
|
+
...button ? { button } : {},
|
|
1005
|
+
...parsedModifiers.modifiers ? { modifiers: parsedModifiers.modifiers } : {},
|
|
1006
|
+
...delayMs !== void 0 ? { delayMs } : {},
|
|
1007
|
+
...timeoutMs !== void 0 ? { timeoutMs } : {}
|
|
1008
|
+
};
|
|
1009
|
+
}
|
|
1010
|
+
case "type": {
|
|
1011
|
+
const ref = toStringOrEmpty(raw.ref) || void 0;
|
|
1012
|
+
const selector = toStringOrEmpty(raw.selector) || void 0;
|
|
1013
|
+
const text = raw.text;
|
|
1014
|
+
if (!ref && !selector) throw new Error("type requires ref or selector");
|
|
1015
|
+
if (typeof text !== "string") throw new Error("type requires text");
|
|
1016
|
+
const targetId = toStringOrEmpty(raw.targetId) || void 0;
|
|
1017
|
+
const submit = toBoolean(raw.submit);
|
|
1018
|
+
const slowly = toBoolean(raw.slowly);
|
|
1019
|
+
const timeoutMs = toNumber(raw.timeoutMs);
|
|
1020
|
+
return {
|
|
1021
|
+
kind,
|
|
1022
|
+
...ref ? { ref } : {},
|
|
1023
|
+
...selector ? { selector } : {},
|
|
1024
|
+
text,
|
|
1025
|
+
...targetId ? { targetId } : {},
|
|
1026
|
+
...submit !== void 0 ? { submit } : {},
|
|
1027
|
+
...slowly !== void 0 ? { slowly } : {},
|
|
1028
|
+
...timeoutMs !== void 0 ? { timeoutMs } : {}
|
|
1029
|
+
};
|
|
1030
|
+
}
|
|
1031
|
+
case "press": {
|
|
1032
|
+
const key = toStringOrEmpty(raw.key);
|
|
1033
|
+
if (!key) throw new Error("press requires key");
|
|
1034
|
+
const targetId = toStringOrEmpty(raw.targetId) || void 0;
|
|
1035
|
+
const delayMs = toNumber(raw.delayMs);
|
|
1036
|
+
return {
|
|
1037
|
+
kind,
|
|
1038
|
+
key,
|
|
1039
|
+
...targetId ? { targetId } : {},
|
|
1040
|
+
...delayMs !== void 0 ? { delayMs } : {}
|
|
1041
|
+
};
|
|
1042
|
+
}
|
|
1043
|
+
case "hover":
|
|
1044
|
+
case "scrollIntoView": {
|
|
1045
|
+
const ref = toStringOrEmpty(raw.ref) || void 0;
|
|
1046
|
+
const selector = toStringOrEmpty(raw.selector) || void 0;
|
|
1047
|
+
if (!ref && !selector) throw new Error(`${kind} requires ref or selector`);
|
|
1048
|
+
const targetId = toStringOrEmpty(raw.targetId) || void 0;
|
|
1049
|
+
const timeoutMs = toNumber(raw.timeoutMs);
|
|
1050
|
+
return {
|
|
1051
|
+
kind,
|
|
1052
|
+
...ref ? { ref } : {},
|
|
1053
|
+
...selector ? { selector } : {},
|
|
1054
|
+
...targetId ? { targetId } : {},
|
|
1055
|
+
...timeoutMs !== void 0 ? { timeoutMs } : {}
|
|
1056
|
+
};
|
|
1057
|
+
}
|
|
1058
|
+
case "drag": {
|
|
1059
|
+
const startRef = toStringOrEmpty(raw.startRef) || void 0;
|
|
1060
|
+
const startSelector = toStringOrEmpty(raw.startSelector) || void 0;
|
|
1061
|
+
const endRef = toStringOrEmpty(raw.endRef) || void 0;
|
|
1062
|
+
const endSelector = toStringOrEmpty(raw.endSelector) || void 0;
|
|
1063
|
+
if (!startRef && !startSelector) throw new Error("drag requires startRef or startSelector");
|
|
1064
|
+
if (!endRef && !endSelector) throw new Error("drag requires endRef or endSelector");
|
|
1065
|
+
const targetId = toStringOrEmpty(raw.targetId) || void 0;
|
|
1066
|
+
const timeoutMs = toNumber(raw.timeoutMs);
|
|
1067
|
+
return {
|
|
1068
|
+
kind,
|
|
1069
|
+
...startRef ? { startRef } : {},
|
|
1070
|
+
...startSelector ? { startSelector } : {},
|
|
1071
|
+
...endRef ? { endRef } : {},
|
|
1072
|
+
...endSelector ? { endSelector } : {},
|
|
1073
|
+
...targetId ? { targetId } : {},
|
|
1074
|
+
...timeoutMs !== void 0 ? { timeoutMs } : {}
|
|
1075
|
+
};
|
|
1076
|
+
}
|
|
1077
|
+
case "select": {
|
|
1078
|
+
const ref = toStringOrEmpty(raw.ref) || void 0;
|
|
1079
|
+
const selector = toStringOrEmpty(raw.selector) || void 0;
|
|
1080
|
+
const values = toStringArray(raw.values);
|
|
1081
|
+
if (!ref && !selector || !values?.length) throw new Error("select requires ref/selector and values");
|
|
1082
|
+
const targetId = toStringOrEmpty(raw.targetId) || void 0;
|
|
1083
|
+
const timeoutMs = toNumber(raw.timeoutMs);
|
|
1084
|
+
return {
|
|
1085
|
+
kind,
|
|
1086
|
+
...ref ? { ref } : {},
|
|
1087
|
+
...selector ? { selector } : {},
|
|
1088
|
+
values,
|
|
1089
|
+
...targetId ? { targetId } : {},
|
|
1090
|
+
...timeoutMs !== void 0 ? { timeoutMs } : {}
|
|
1091
|
+
};
|
|
1092
|
+
}
|
|
1093
|
+
case "fill": {
|
|
1094
|
+
const fields = (Array.isArray(raw.fields) ? raw.fields : []).map((field) => {
|
|
1095
|
+
if (!field || typeof field !== "object") return null;
|
|
1096
|
+
return normalizeBrowserFormField(field);
|
|
1097
|
+
}).filter((field) => field !== null);
|
|
1098
|
+
if (!fields.length) throw new Error("fill requires fields");
|
|
1099
|
+
const targetId = toStringOrEmpty(raw.targetId) || void 0;
|
|
1100
|
+
const timeoutMs = toNumber(raw.timeoutMs);
|
|
1101
|
+
return {
|
|
1102
|
+
kind,
|
|
1103
|
+
fields,
|
|
1104
|
+
...targetId ? { targetId } : {},
|
|
1105
|
+
...timeoutMs !== void 0 ? { timeoutMs } : {}
|
|
1106
|
+
};
|
|
1107
|
+
}
|
|
1108
|
+
case "resize": {
|
|
1109
|
+
const width = toNumber(raw.width);
|
|
1110
|
+
const height = toNumber(raw.height);
|
|
1111
|
+
if (width === void 0 || height === void 0) throw new Error("resize requires width and height");
|
|
1112
|
+
const targetId = toStringOrEmpty(raw.targetId) || void 0;
|
|
1113
|
+
return {
|
|
1114
|
+
kind,
|
|
1115
|
+
width,
|
|
1116
|
+
height,
|
|
1117
|
+
...targetId ? { targetId } : {}
|
|
1118
|
+
};
|
|
1119
|
+
}
|
|
1120
|
+
case "wait": {
|
|
1121
|
+
const loadStateRaw = toStringOrEmpty(raw.loadState);
|
|
1122
|
+
const loadState = loadStateRaw === "load" || loadStateRaw === "domcontentloaded" || loadStateRaw === "networkidle" ? loadStateRaw : void 0;
|
|
1123
|
+
const timeMs = normalizeBoundedNonNegativeMs(raw.timeMs, "wait timeMs", MAX_BATCH_WAIT_TIME_MS);
|
|
1124
|
+
const text = toStringOrEmpty(raw.text) || void 0;
|
|
1125
|
+
const textGone = toStringOrEmpty(raw.textGone) || void 0;
|
|
1126
|
+
const selector = toStringOrEmpty(raw.selector) || void 0;
|
|
1127
|
+
const url = toStringOrEmpty(raw.url) || void 0;
|
|
1128
|
+
const fn = toStringOrEmpty(raw.fn) || void 0;
|
|
1129
|
+
if (timeMs === void 0 && !text && !textGone && !selector && !url && !loadState && !fn) throw new Error("wait requires at least one of: timeMs, text, textGone, selector, url, loadState, fn");
|
|
1130
|
+
const targetId = toStringOrEmpty(raw.targetId) || void 0;
|
|
1131
|
+
const timeoutMs = toNumber(raw.timeoutMs);
|
|
1132
|
+
return {
|
|
1133
|
+
kind,
|
|
1134
|
+
...timeMs !== void 0 ? { timeMs } : {},
|
|
1135
|
+
...text ? { text } : {},
|
|
1136
|
+
...textGone ? { textGone } : {},
|
|
1137
|
+
...selector ? { selector } : {},
|
|
1138
|
+
...url ? { url } : {},
|
|
1139
|
+
...loadState ? { loadState } : {},
|
|
1140
|
+
...fn ? { fn } : {},
|
|
1141
|
+
...targetId ? { targetId } : {},
|
|
1142
|
+
...timeoutMs !== void 0 ? { timeoutMs } : {}
|
|
1143
|
+
};
|
|
1144
|
+
}
|
|
1145
|
+
case "evaluate": {
|
|
1146
|
+
const fn = toStringOrEmpty(raw.fn);
|
|
1147
|
+
if (!fn) throw new Error("evaluate requires fn");
|
|
1148
|
+
const ref = toStringOrEmpty(raw.ref) || void 0;
|
|
1149
|
+
const targetId = toStringOrEmpty(raw.targetId) || void 0;
|
|
1150
|
+
const timeoutMs = toNumber(raw.timeoutMs);
|
|
1151
|
+
return {
|
|
1152
|
+
kind,
|
|
1153
|
+
fn,
|
|
1154
|
+
...ref ? { ref } : {},
|
|
1155
|
+
...targetId ? { targetId } : {},
|
|
1156
|
+
...timeoutMs !== void 0 ? { timeoutMs } : {}
|
|
1157
|
+
};
|
|
1158
|
+
}
|
|
1159
|
+
case "close": {
|
|
1160
|
+
const targetId = toStringOrEmpty(raw.targetId) || void 0;
|
|
1161
|
+
return {
|
|
1162
|
+
kind,
|
|
1163
|
+
...targetId ? { targetId } : {}
|
|
1164
|
+
};
|
|
1165
|
+
}
|
|
1166
|
+
case "batch": {
|
|
1167
|
+
const actions = Array.isArray(raw.actions) ? raw.actions.map(normalizeBatchAction) : [];
|
|
1168
|
+
if (!actions.length) throw new Error("batch requires actions");
|
|
1169
|
+
if (countBatchActions(actions) > MAX_BATCH_ACTIONS) throw new Error(`batch exceeds maximum of ${MAX_BATCH_ACTIONS} actions`);
|
|
1170
|
+
const targetId = toStringOrEmpty(raw.targetId) || void 0;
|
|
1171
|
+
const stopOnError = toBoolean(raw.stopOnError);
|
|
1172
|
+
return {
|
|
1173
|
+
kind,
|
|
1174
|
+
actions,
|
|
1175
|
+
...targetId ? { targetId } : {},
|
|
1176
|
+
...stopOnError !== void 0 ? { stopOnError } : {}
|
|
1177
|
+
};
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
function registerBrowserAgentActRoutes(app, ctx) {
|
|
1182
|
+
app.post("/act", async (req, res) => {
|
|
1183
|
+
const body = readBody(req);
|
|
1184
|
+
const kindRaw = toStringOrEmpty(body.kind);
|
|
1185
|
+
if (!isActKind(kindRaw)) return jsonError(res, 400, "kind is required");
|
|
1186
|
+
const kind = kindRaw;
|
|
1187
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
1188
|
+
if (Object.hasOwn(body, "selector") && !SELECTOR_ALLOWED_KINDS.has(kind)) return jsonError(res, 400, SELECTOR_UNSUPPORTED_MESSAGE);
|
|
1189
|
+
const earlyFn = kind === "wait" || kind === "evaluate" ? toStringOrEmpty(body.fn) : "";
|
|
1190
|
+
if ((kind === "evaluate" || kind === "wait" && earlyFn) && !ctx.state().resolved.evaluateEnabled) return jsonError(res, 403, browserEvaluateDisabledMessage(kind === "evaluate" ? "evaluate" : "wait"));
|
|
1191
|
+
await withRouteTabContext({
|
|
1192
|
+
req,
|
|
1193
|
+
res,
|
|
1194
|
+
ctx,
|
|
1195
|
+
targetId,
|
|
1196
|
+
run: async ({ profileCtx, cdpUrl, tab }) => {
|
|
1197
|
+
const evaluateEnabled = ctx.state().resolved.evaluateEnabled;
|
|
1198
|
+
const ssrfPolicy = ctx.state().resolved.ssrfPolicy;
|
|
1199
|
+
const isExistingSession = getBrowserProfileCapabilities(profileCtx.profile).usesChromeMcp;
|
|
1200
|
+
const profileName = profileCtx.profile.name;
|
|
1201
|
+
switch (kind) {
|
|
1202
|
+
case "click": {
|
|
1203
|
+
const ref = toStringOrEmpty(body.ref) || void 0;
|
|
1204
|
+
const selector = toStringOrEmpty(body.selector) || void 0;
|
|
1205
|
+
if (!ref && !selector) return jsonError(res, 400, "ref or selector is required");
|
|
1206
|
+
const doubleClick = toBoolean(body.doubleClick) ?? false;
|
|
1207
|
+
const timeoutMs = toNumber(body.timeoutMs);
|
|
1208
|
+
const delayMs = toNumber(body.delayMs);
|
|
1209
|
+
const buttonRaw = toStringOrEmpty(body.button) || "";
|
|
1210
|
+
const button = buttonRaw ? parseClickButton(buttonRaw) : void 0;
|
|
1211
|
+
if (buttonRaw && !button) return jsonError(res, 400, "button must be left|right|middle");
|
|
1212
|
+
const parsedModifiers = parseClickModifiers(toStringArray(body.modifiers) ?? []);
|
|
1213
|
+
if (parsedModifiers.error) return jsonError(res, 400, parsedModifiers.error);
|
|
1214
|
+
const modifiers = parsedModifiers.modifiers;
|
|
1215
|
+
if (isExistingSession) {
|
|
1216
|
+
if (selector) return jsonError(res, 501, "existing-session click does not support selector targeting yet; use ref.");
|
|
1217
|
+
if (button && button !== "left" || modifiers && modifiers.length > 0) return jsonError(res, 501, "existing-session click currently supports left-click only (no button overrides/modifiers).");
|
|
1218
|
+
await clickChromeMcpElement({
|
|
1219
|
+
profileName,
|
|
1220
|
+
userDataDir: profileCtx.profile.userDataDir,
|
|
1221
|
+
targetId: tab.targetId,
|
|
1222
|
+
uid: ref,
|
|
1223
|
+
doubleClick
|
|
1224
|
+
});
|
|
1225
|
+
return res.json({
|
|
1226
|
+
ok: true,
|
|
1227
|
+
targetId: tab.targetId,
|
|
1228
|
+
url: tab.url
|
|
1229
|
+
});
|
|
1230
|
+
}
|
|
1231
|
+
const pw = await requirePwAi(res, `act:${kind}`);
|
|
1232
|
+
if (!pw) return;
|
|
1233
|
+
const clickRequest = {
|
|
1234
|
+
cdpUrl,
|
|
1235
|
+
targetId: tab.targetId,
|
|
1236
|
+
ssrfPolicy: ctx.state().resolved.ssrfPolicy,
|
|
1237
|
+
doubleClick
|
|
1238
|
+
};
|
|
1239
|
+
if (ref) clickRequest.ref = ref;
|
|
1240
|
+
if (selector) clickRequest.selector = selector;
|
|
1241
|
+
if (button) clickRequest.button = button;
|
|
1242
|
+
if (modifiers) clickRequest.modifiers = modifiers;
|
|
1243
|
+
if (delayMs) clickRequest.delayMs = delayMs;
|
|
1244
|
+
if (timeoutMs) clickRequest.timeoutMs = timeoutMs;
|
|
1245
|
+
await pw.clickViaPlaywright(clickRequest);
|
|
1246
|
+
return res.json({
|
|
1247
|
+
ok: true,
|
|
1248
|
+
targetId: tab.targetId,
|
|
1249
|
+
url: tab.url
|
|
1250
|
+
});
|
|
1251
|
+
}
|
|
1252
|
+
case "type": {
|
|
1253
|
+
const ref = toStringOrEmpty(body.ref) || void 0;
|
|
1254
|
+
const selector = toStringOrEmpty(body.selector) || void 0;
|
|
1255
|
+
if (!ref && !selector) return jsonError(res, 400, "ref or selector is required");
|
|
1256
|
+
if (typeof body.text !== "string") return jsonError(res, 400, "text is required");
|
|
1257
|
+
const text = body.text;
|
|
1258
|
+
const submit = toBoolean(body.submit) ?? false;
|
|
1259
|
+
const slowly = toBoolean(body.slowly) ?? false;
|
|
1260
|
+
const timeoutMs = toNumber(body.timeoutMs);
|
|
1261
|
+
if (isExistingSession) {
|
|
1262
|
+
if (selector) return jsonError(res, 501, "existing-session type does not support selector targeting yet; use ref.");
|
|
1263
|
+
if (slowly) return jsonError(res, 501, "existing-session type does not support slowly=true; use fill/press instead.");
|
|
1264
|
+
await fillChromeMcpElement({
|
|
1265
|
+
profileName,
|
|
1266
|
+
userDataDir: profileCtx.profile.userDataDir,
|
|
1267
|
+
targetId: tab.targetId,
|
|
1268
|
+
uid: ref,
|
|
1269
|
+
value: text
|
|
1270
|
+
});
|
|
1271
|
+
if (submit) await pressChromeMcpKey({
|
|
1272
|
+
profileName,
|
|
1273
|
+
userDataDir: profileCtx.profile.userDataDir,
|
|
1274
|
+
targetId: tab.targetId,
|
|
1275
|
+
key: "Enter"
|
|
1276
|
+
});
|
|
1277
|
+
return res.json({
|
|
1278
|
+
ok: true,
|
|
1279
|
+
targetId: tab.targetId
|
|
1280
|
+
});
|
|
1281
|
+
}
|
|
1282
|
+
const pw = await requirePwAi(res, `act:${kind}`);
|
|
1283
|
+
if (!pw) return;
|
|
1284
|
+
const typeRequest = {
|
|
1285
|
+
cdpUrl,
|
|
1286
|
+
targetId: tab.targetId,
|
|
1287
|
+
text,
|
|
1288
|
+
submit,
|
|
1289
|
+
slowly,
|
|
1290
|
+
ssrfPolicy
|
|
1291
|
+
};
|
|
1292
|
+
if (ref) typeRequest.ref = ref;
|
|
1293
|
+
if (selector) typeRequest.selector = selector;
|
|
1294
|
+
if (timeoutMs) typeRequest.timeoutMs = timeoutMs;
|
|
1295
|
+
await pw.typeViaPlaywright(typeRequest);
|
|
1296
|
+
return res.json({
|
|
1297
|
+
ok: true,
|
|
1298
|
+
targetId: tab.targetId
|
|
1299
|
+
});
|
|
1300
|
+
}
|
|
1301
|
+
case "press": {
|
|
1302
|
+
const key = toStringOrEmpty(body.key);
|
|
1303
|
+
if (!key) return jsonError(res, 400, "key is required");
|
|
1304
|
+
const delayMs = toNumber(body.delayMs);
|
|
1305
|
+
if (isExistingSession) {
|
|
1306
|
+
if (delayMs) return jsonError(res, 501, "existing-session press does not support delayMs.");
|
|
1307
|
+
await pressChromeMcpKey({
|
|
1308
|
+
profileName,
|
|
1309
|
+
userDataDir: profileCtx.profile.userDataDir,
|
|
1310
|
+
targetId: tab.targetId,
|
|
1311
|
+
key
|
|
1312
|
+
});
|
|
1313
|
+
return res.json({
|
|
1314
|
+
ok: true,
|
|
1315
|
+
targetId: tab.targetId
|
|
1316
|
+
});
|
|
1317
|
+
}
|
|
1318
|
+
const pw = await requirePwAi(res, `act:${kind}`);
|
|
1319
|
+
if (!pw) return;
|
|
1320
|
+
await pw.pressKeyViaPlaywright({
|
|
1321
|
+
cdpUrl,
|
|
1322
|
+
targetId: tab.targetId,
|
|
1323
|
+
key,
|
|
1324
|
+
delayMs: delayMs ?? void 0,
|
|
1325
|
+
ssrfPolicy
|
|
1326
|
+
});
|
|
1327
|
+
return res.json({
|
|
1328
|
+
ok: true,
|
|
1329
|
+
targetId: tab.targetId
|
|
1330
|
+
});
|
|
1331
|
+
}
|
|
1332
|
+
case "hover": {
|
|
1333
|
+
const ref = toStringOrEmpty(body.ref) || void 0;
|
|
1334
|
+
const selector = toStringOrEmpty(body.selector) || void 0;
|
|
1335
|
+
if (!ref && !selector) return jsonError(res, 400, "ref or selector is required");
|
|
1336
|
+
const timeoutMs = toNumber(body.timeoutMs);
|
|
1337
|
+
if (isExistingSession) {
|
|
1338
|
+
if (selector) return jsonError(res, 501, "existing-session hover does not support selector targeting yet; use ref.");
|
|
1339
|
+
if (timeoutMs) return jsonError(res, 501, "existing-session hover does not support timeoutMs overrides.");
|
|
1340
|
+
await hoverChromeMcpElement({
|
|
1341
|
+
profileName,
|
|
1342
|
+
userDataDir: profileCtx.profile.userDataDir,
|
|
1343
|
+
targetId: tab.targetId,
|
|
1344
|
+
uid: ref
|
|
1345
|
+
});
|
|
1346
|
+
return res.json({
|
|
1347
|
+
ok: true,
|
|
1348
|
+
targetId: tab.targetId
|
|
1349
|
+
});
|
|
1350
|
+
}
|
|
1351
|
+
const pw = await requirePwAi(res, `act:${kind}`);
|
|
1352
|
+
if (!pw) return;
|
|
1353
|
+
await pw.hoverViaPlaywright({
|
|
1354
|
+
cdpUrl,
|
|
1355
|
+
targetId: tab.targetId,
|
|
1356
|
+
ref,
|
|
1357
|
+
selector,
|
|
1358
|
+
timeoutMs: timeoutMs ?? void 0
|
|
1359
|
+
});
|
|
1360
|
+
return res.json({
|
|
1361
|
+
ok: true,
|
|
1362
|
+
targetId: tab.targetId
|
|
1363
|
+
});
|
|
1364
|
+
}
|
|
1365
|
+
case "scrollIntoView": {
|
|
1366
|
+
const ref = toStringOrEmpty(body.ref) || void 0;
|
|
1367
|
+
const selector = toStringOrEmpty(body.selector) || void 0;
|
|
1368
|
+
if (!ref && !selector) return jsonError(res, 400, "ref or selector is required");
|
|
1369
|
+
const timeoutMs = toNumber(body.timeoutMs);
|
|
1370
|
+
if (isExistingSession) {
|
|
1371
|
+
if (selector) return jsonError(res, 501, "existing-session scrollIntoView does not support selector targeting yet; use ref.");
|
|
1372
|
+
if (timeoutMs) return jsonError(res, 501, "existing-session scrollIntoView does not support timeoutMs overrides.");
|
|
1373
|
+
await evaluateChromeMcpScript({
|
|
1374
|
+
profileName,
|
|
1375
|
+
userDataDir: profileCtx.profile.userDataDir,
|
|
1376
|
+
targetId: tab.targetId,
|
|
1377
|
+
fn: `(el) => { el.scrollIntoView({ block: "center", inline: "center" }); return true; }`,
|
|
1378
|
+
args: [ref]
|
|
1379
|
+
});
|
|
1380
|
+
return res.json({
|
|
1381
|
+
ok: true,
|
|
1382
|
+
targetId: tab.targetId
|
|
1383
|
+
});
|
|
1384
|
+
}
|
|
1385
|
+
const pw = await requirePwAi(res, `act:${kind}`);
|
|
1386
|
+
if (!pw) return;
|
|
1387
|
+
const scrollRequest = {
|
|
1388
|
+
cdpUrl,
|
|
1389
|
+
targetId: tab.targetId
|
|
1390
|
+
};
|
|
1391
|
+
if (ref) scrollRequest.ref = ref;
|
|
1392
|
+
if (selector) scrollRequest.selector = selector;
|
|
1393
|
+
if (timeoutMs) scrollRequest.timeoutMs = timeoutMs;
|
|
1394
|
+
await pw.scrollIntoViewViaPlaywright(scrollRequest);
|
|
1395
|
+
return res.json({
|
|
1396
|
+
ok: true,
|
|
1397
|
+
targetId: tab.targetId
|
|
1398
|
+
});
|
|
1399
|
+
}
|
|
1400
|
+
case "drag": {
|
|
1401
|
+
const startRef = toStringOrEmpty(body.startRef) || void 0;
|
|
1402
|
+
const startSelector = toStringOrEmpty(body.startSelector) || void 0;
|
|
1403
|
+
const endRef = toStringOrEmpty(body.endRef) || void 0;
|
|
1404
|
+
const endSelector = toStringOrEmpty(body.endSelector) || void 0;
|
|
1405
|
+
if (!startRef && !startSelector) return jsonError(res, 400, "startRef or startSelector is required");
|
|
1406
|
+
if (!endRef && !endSelector) return jsonError(res, 400, "endRef or endSelector is required");
|
|
1407
|
+
const timeoutMs = toNumber(body.timeoutMs);
|
|
1408
|
+
if (isExistingSession) {
|
|
1409
|
+
if (startSelector || endSelector) return jsonError(res, 501, "existing-session drag does not support selector targeting yet; use startRef/endRef.");
|
|
1410
|
+
if (timeoutMs) return jsonError(res, 501, "existing-session drag does not support timeoutMs overrides.");
|
|
1411
|
+
await dragChromeMcpElement({
|
|
1412
|
+
profileName,
|
|
1413
|
+
userDataDir: profileCtx.profile.userDataDir,
|
|
1414
|
+
targetId: tab.targetId,
|
|
1415
|
+
fromUid: startRef,
|
|
1416
|
+
toUid: endRef
|
|
1417
|
+
});
|
|
1418
|
+
return res.json({
|
|
1419
|
+
ok: true,
|
|
1420
|
+
targetId: tab.targetId
|
|
1421
|
+
});
|
|
1422
|
+
}
|
|
1423
|
+
const pw = await requirePwAi(res, `act:${kind}`);
|
|
1424
|
+
if (!pw) return;
|
|
1425
|
+
await pw.dragViaPlaywright({
|
|
1426
|
+
cdpUrl,
|
|
1427
|
+
targetId: tab.targetId,
|
|
1428
|
+
startRef,
|
|
1429
|
+
startSelector,
|
|
1430
|
+
endRef,
|
|
1431
|
+
endSelector,
|
|
1432
|
+
timeoutMs: timeoutMs ?? void 0
|
|
1433
|
+
});
|
|
1434
|
+
return res.json({
|
|
1435
|
+
ok: true,
|
|
1436
|
+
targetId: tab.targetId
|
|
1437
|
+
});
|
|
1438
|
+
}
|
|
1439
|
+
case "select": {
|
|
1440
|
+
const ref = toStringOrEmpty(body.ref) || void 0;
|
|
1441
|
+
const selector = toStringOrEmpty(body.selector) || void 0;
|
|
1442
|
+
const values = toStringArray(body.values);
|
|
1443
|
+
if (!ref && !selector || !values?.length) return jsonError(res, 400, "ref/selector and values are required");
|
|
1444
|
+
const timeoutMs = toNumber(body.timeoutMs);
|
|
1445
|
+
if (isExistingSession) {
|
|
1446
|
+
if (selector) return jsonError(res, 501, "existing-session select does not support selector targeting yet; use ref.");
|
|
1447
|
+
if (values.length !== 1) return jsonError(res, 501, "existing-session select currently supports a single value only.");
|
|
1448
|
+
if (timeoutMs) return jsonError(res, 501, "existing-session select does not support timeoutMs overrides.");
|
|
1449
|
+
await fillChromeMcpElement({
|
|
1450
|
+
profileName,
|
|
1451
|
+
userDataDir: profileCtx.profile.userDataDir,
|
|
1452
|
+
targetId: tab.targetId,
|
|
1453
|
+
uid: ref,
|
|
1454
|
+
value: values[0] ?? ""
|
|
1455
|
+
});
|
|
1456
|
+
return res.json({
|
|
1457
|
+
ok: true,
|
|
1458
|
+
targetId: tab.targetId
|
|
1459
|
+
});
|
|
1460
|
+
}
|
|
1461
|
+
const pw = await requirePwAi(res, `act:${kind}`);
|
|
1462
|
+
if (!pw) return;
|
|
1463
|
+
await pw.selectOptionViaPlaywright({
|
|
1464
|
+
cdpUrl,
|
|
1465
|
+
targetId: tab.targetId,
|
|
1466
|
+
ref,
|
|
1467
|
+
selector,
|
|
1468
|
+
values,
|
|
1469
|
+
timeoutMs: timeoutMs ?? void 0
|
|
1470
|
+
});
|
|
1471
|
+
return res.json({
|
|
1472
|
+
ok: true,
|
|
1473
|
+
targetId: tab.targetId
|
|
1474
|
+
});
|
|
1475
|
+
}
|
|
1476
|
+
case "fill": {
|
|
1477
|
+
const fields = (Array.isArray(body.fields) ? body.fields : []).map((field) => {
|
|
1478
|
+
if (!field || typeof field !== "object") return null;
|
|
1479
|
+
return normalizeBrowserFormField(field);
|
|
1480
|
+
}).filter((field) => field !== null);
|
|
1481
|
+
if (!fields.length) return jsonError(res, 400, "fields are required");
|
|
1482
|
+
const timeoutMs = toNumber(body.timeoutMs);
|
|
1483
|
+
if (isExistingSession) {
|
|
1484
|
+
if (timeoutMs) return jsonError(res, 501, "existing-session fill does not support timeoutMs overrides.");
|
|
1485
|
+
await fillChromeMcpForm({
|
|
1486
|
+
profileName,
|
|
1487
|
+
userDataDir: profileCtx.profile.userDataDir,
|
|
1488
|
+
targetId: tab.targetId,
|
|
1489
|
+
elements: fields.map((field) => ({
|
|
1490
|
+
uid: field.ref,
|
|
1491
|
+
value: String(field.value ?? "")
|
|
1492
|
+
}))
|
|
1493
|
+
});
|
|
1494
|
+
return res.json({
|
|
1495
|
+
ok: true,
|
|
1496
|
+
targetId: tab.targetId
|
|
1497
|
+
});
|
|
1498
|
+
}
|
|
1499
|
+
const pw = await requirePwAi(res, `act:${kind}`);
|
|
1500
|
+
if (!pw) return;
|
|
1501
|
+
await pw.fillFormViaPlaywright({
|
|
1502
|
+
cdpUrl,
|
|
1503
|
+
targetId: tab.targetId,
|
|
1504
|
+
fields,
|
|
1505
|
+
timeoutMs: timeoutMs ?? void 0
|
|
1506
|
+
});
|
|
1507
|
+
return res.json({
|
|
1508
|
+
ok: true,
|
|
1509
|
+
targetId: tab.targetId
|
|
1510
|
+
});
|
|
1511
|
+
}
|
|
1512
|
+
case "resize": {
|
|
1513
|
+
const width = toNumber(body.width);
|
|
1514
|
+
const height = toNumber(body.height);
|
|
1515
|
+
if (!width || !height) return jsonError(res, 400, "width and height are required");
|
|
1516
|
+
if (isExistingSession) {
|
|
1517
|
+
await resizeChromeMcpPage({
|
|
1518
|
+
profileName,
|
|
1519
|
+
userDataDir: profileCtx.profile.userDataDir,
|
|
1520
|
+
targetId: tab.targetId,
|
|
1521
|
+
width,
|
|
1522
|
+
height
|
|
1523
|
+
});
|
|
1524
|
+
return res.json({
|
|
1525
|
+
ok: true,
|
|
1526
|
+
targetId: tab.targetId,
|
|
1527
|
+
url: tab.url
|
|
1528
|
+
});
|
|
1529
|
+
}
|
|
1530
|
+
const pw = await requirePwAi(res, `act:${kind}`);
|
|
1531
|
+
if (!pw) return;
|
|
1532
|
+
await pw.resizeViewportViaPlaywright({
|
|
1533
|
+
cdpUrl,
|
|
1534
|
+
targetId: tab.targetId,
|
|
1535
|
+
width,
|
|
1536
|
+
height
|
|
1537
|
+
});
|
|
1538
|
+
return res.json({
|
|
1539
|
+
ok: true,
|
|
1540
|
+
targetId: tab.targetId,
|
|
1541
|
+
url: tab.url
|
|
1542
|
+
});
|
|
1543
|
+
}
|
|
1544
|
+
case "wait": {
|
|
1545
|
+
const timeMs = toNumber(body.timeMs);
|
|
1546
|
+
const text = toStringOrEmpty(body.text) || void 0;
|
|
1547
|
+
const textGone = toStringOrEmpty(body.textGone) || void 0;
|
|
1548
|
+
const selector = toStringOrEmpty(body.selector) || void 0;
|
|
1549
|
+
const url = toStringOrEmpty(body.url) || void 0;
|
|
1550
|
+
const loadStateRaw = toStringOrEmpty(body.loadState);
|
|
1551
|
+
const loadState = loadStateRaw === "load" || loadStateRaw === "domcontentloaded" || loadStateRaw === "networkidle" ? loadStateRaw : void 0;
|
|
1552
|
+
const fn = toStringOrEmpty(body.fn) || void 0;
|
|
1553
|
+
const timeoutMs = toNumber(body.timeoutMs) ?? void 0;
|
|
1554
|
+
if (fn && !evaluateEnabled) return jsonError(res, 403, browserEvaluateDisabledMessage("wait"));
|
|
1555
|
+
if (timeMs === void 0 && !text && !textGone && !selector && !url && !loadState && !fn) return jsonError(res, 400, "wait requires at least one of: timeMs, text, textGone, selector, url, loadState, fn");
|
|
1556
|
+
if (isExistingSession) {
|
|
1557
|
+
if (loadState === "networkidle") return jsonError(res, 501, "existing-session wait does not support loadState=networkidle yet.");
|
|
1558
|
+
await waitForExistingSessionCondition({
|
|
1559
|
+
profileName,
|
|
1560
|
+
userDataDir: profileCtx.profile.userDataDir,
|
|
1561
|
+
targetId: tab.targetId,
|
|
1562
|
+
timeMs,
|
|
1563
|
+
text,
|
|
1564
|
+
textGone,
|
|
1565
|
+
selector,
|
|
1566
|
+
url,
|
|
1567
|
+
loadState,
|
|
1568
|
+
fn,
|
|
1569
|
+
timeoutMs
|
|
1570
|
+
});
|
|
1571
|
+
return res.json({
|
|
1572
|
+
ok: true,
|
|
1573
|
+
targetId: tab.targetId
|
|
1574
|
+
});
|
|
1575
|
+
}
|
|
1576
|
+
const pw = await requirePwAi(res, `act:${kind}`);
|
|
1577
|
+
if (!pw) return;
|
|
1578
|
+
await pw.waitForViaPlaywright({
|
|
1579
|
+
cdpUrl,
|
|
1580
|
+
targetId: tab.targetId,
|
|
1581
|
+
timeMs,
|
|
1582
|
+
text,
|
|
1583
|
+
textGone,
|
|
1584
|
+
selector,
|
|
1585
|
+
url,
|
|
1586
|
+
loadState,
|
|
1587
|
+
fn,
|
|
1588
|
+
timeoutMs
|
|
1589
|
+
});
|
|
1590
|
+
return res.json({
|
|
1591
|
+
ok: true,
|
|
1592
|
+
targetId: tab.targetId
|
|
1593
|
+
});
|
|
1594
|
+
}
|
|
1595
|
+
case "evaluate": {
|
|
1596
|
+
if (!evaluateEnabled) return jsonError(res, 403, browserEvaluateDisabledMessage("evaluate"));
|
|
1597
|
+
const fn = toStringOrEmpty(body.fn);
|
|
1598
|
+
if (!fn) return jsonError(res, 400, "fn is required");
|
|
1599
|
+
const ref = toStringOrEmpty(body.ref) || void 0;
|
|
1600
|
+
const evalTimeoutMs = toNumber(body.timeoutMs);
|
|
1601
|
+
if (isExistingSession) {
|
|
1602
|
+
if (evalTimeoutMs !== void 0) return jsonError(res, 501, "existing-session evaluate does not support timeoutMs overrides.");
|
|
1603
|
+
const result = await evaluateChromeMcpScript({
|
|
1604
|
+
profileName,
|
|
1605
|
+
userDataDir: profileCtx.profile.userDataDir,
|
|
1606
|
+
targetId: tab.targetId,
|
|
1607
|
+
fn,
|
|
1608
|
+
args: ref ? [ref] : void 0
|
|
1609
|
+
});
|
|
1610
|
+
return res.json({
|
|
1611
|
+
ok: true,
|
|
1612
|
+
targetId: tab.targetId,
|
|
1613
|
+
url: tab.url,
|
|
1614
|
+
result
|
|
1615
|
+
});
|
|
1616
|
+
}
|
|
1617
|
+
const pw = await requirePwAi(res, `act:${kind}`);
|
|
1618
|
+
if (!pw) return;
|
|
1619
|
+
const evalRequest = {
|
|
1620
|
+
cdpUrl,
|
|
1621
|
+
targetId: tab.targetId,
|
|
1622
|
+
ssrfPolicy: ctx.state().resolved.ssrfPolicy,
|
|
1623
|
+
fn,
|
|
1624
|
+
ref,
|
|
1625
|
+
signal: req.signal
|
|
1626
|
+
};
|
|
1627
|
+
if (evalTimeoutMs !== void 0) evalRequest.timeoutMs = evalTimeoutMs;
|
|
1628
|
+
const result = await pw.evaluateViaPlaywright(evalRequest);
|
|
1629
|
+
return res.json({
|
|
1630
|
+
ok: true,
|
|
1631
|
+
targetId: tab.targetId,
|
|
1632
|
+
url: tab.url,
|
|
1633
|
+
result
|
|
1634
|
+
});
|
|
1635
|
+
}
|
|
1636
|
+
case "close": {
|
|
1637
|
+
if (isExistingSession) {
|
|
1638
|
+
await closeChromeMcpTab(profileName, tab.targetId, profileCtx.profile.userDataDir);
|
|
1639
|
+
return res.json({
|
|
1640
|
+
ok: true,
|
|
1641
|
+
targetId: tab.targetId
|
|
1642
|
+
});
|
|
1643
|
+
}
|
|
1644
|
+
const pw = await requirePwAi(res, `act:${kind}`);
|
|
1645
|
+
if (!pw) return;
|
|
1646
|
+
await pw.closePageViaPlaywright({
|
|
1647
|
+
cdpUrl,
|
|
1648
|
+
targetId: tab.targetId
|
|
1649
|
+
});
|
|
1650
|
+
return res.json({
|
|
1651
|
+
ok: true,
|
|
1652
|
+
targetId: tab.targetId
|
|
1653
|
+
});
|
|
1654
|
+
}
|
|
1655
|
+
case "batch": {
|
|
1656
|
+
if (isExistingSession) return jsonError(res, 501, "existing-session batch is not supported yet; send actions individually.");
|
|
1657
|
+
const pw = await requirePwAi(res, `act:${kind}`);
|
|
1658
|
+
if (!pw) return;
|
|
1659
|
+
let actions;
|
|
1660
|
+
try {
|
|
1661
|
+
actions = Array.isArray(body.actions) ? body.actions.map(normalizeBatchAction) : [];
|
|
1662
|
+
} catch (err) {
|
|
1663
|
+
return jsonError(res, 400, formatErrorMessage(err));
|
|
1664
|
+
}
|
|
1665
|
+
if (!actions.length) return jsonError(res, 400, "actions are required");
|
|
1666
|
+
if (countBatchActions(actions) > MAX_BATCH_ACTIONS) return jsonError(res, 400, `batch exceeds maximum of ${MAX_BATCH_ACTIONS} actions`);
|
|
1667
|
+
const targetIdError = validateBatchTargetIds(actions, tab.targetId);
|
|
1668
|
+
if (targetIdError) return jsonError(res, 403, targetIdError);
|
|
1669
|
+
const stopOnError = toBoolean(body.stopOnError) ?? true;
|
|
1670
|
+
const result = await pw.batchViaPlaywright({
|
|
1671
|
+
cdpUrl,
|
|
1672
|
+
targetId: tab.targetId,
|
|
1673
|
+
ssrfPolicy: ctx.state().resolved.ssrfPolicy,
|
|
1674
|
+
actions,
|
|
1675
|
+
stopOnError,
|
|
1676
|
+
evaluateEnabled
|
|
1677
|
+
});
|
|
1678
|
+
return res.json({
|
|
1679
|
+
ok: true,
|
|
1680
|
+
targetId: tab.targetId,
|
|
1681
|
+
results: result.results
|
|
1682
|
+
});
|
|
1683
|
+
}
|
|
1684
|
+
default: return jsonError(res, 400, "unsupported kind");
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
});
|
|
1688
|
+
});
|
|
1689
|
+
registerBrowserAgentActHookRoutes(app, ctx);
|
|
1690
|
+
registerBrowserAgentActDownloadRoutes(app, ctx);
|
|
1691
|
+
app.post("/response/body", async (req, res) => {
|
|
1692
|
+
const body = readBody(req);
|
|
1693
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
1694
|
+
const url = toStringOrEmpty(body.url);
|
|
1695
|
+
const timeoutMs = toNumber(body.timeoutMs);
|
|
1696
|
+
const maxChars = toNumber(body.maxChars);
|
|
1697
|
+
if (!url) return jsonError(res, 400, "url is required");
|
|
1698
|
+
await withRouteTabContext({
|
|
1699
|
+
req,
|
|
1700
|
+
res,
|
|
1701
|
+
ctx,
|
|
1702
|
+
targetId,
|
|
1703
|
+
run: async ({ profileCtx, cdpUrl, tab }) => {
|
|
1704
|
+
if (getBrowserProfileCapabilities(profileCtx.profile).usesChromeMcp) return jsonError(res, 501, "response body is not supported for existing-session profiles yet.");
|
|
1705
|
+
const pw = await requirePwAi(res, "response body");
|
|
1706
|
+
if (!pw) return;
|
|
1707
|
+
const result = await pw.responseBodyViaPlaywright({
|
|
1708
|
+
cdpUrl,
|
|
1709
|
+
targetId: tab.targetId,
|
|
1710
|
+
url,
|
|
1711
|
+
timeoutMs: timeoutMs ?? void 0,
|
|
1712
|
+
maxChars: maxChars ?? void 0
|
|
1713
|
+
});
|
|
1714
|
+
res.json({
|
|
1715
|
+
ok: true,
|
|
1716
|
+
targetId: tab.targetId,
|
|
1717
|
+
response: result
|
|
1718
|
+
});
|
|
1719
|
+
}
|
|
1720
|
+
});
|
|
1721
|
+
});
|
|
1722
|
+
app.post("/highlight", async (req, res) => {
|
|
1723
|
+
const body = readBody(req);
|
|
1724
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
1725
|
+
const ref = toStringOrEmpty(body.ref);
|
|
1726
|
+
if (!ref) return jsonError(res, 400, "ref is required");
|
|
1727
|
+
await withRouteTabContext({
|
|
1728
|
+
req,
|
|
1729
|
+
res,
|
|
1730
|
+
ctx,
|
|
1731
|
+
targetId,
|
|
1732
|
+
run: async ({ profileCtx, cdpUrl, tab }) => {
|
|
1733
|
+
if (getBrowserProfileCapabilities(profileCtx.profile).usesChromeMcp) {
|
|
1734
|
+
await evaluateChromeMcpScript({
|
|
1735
|
+
profileName: profileCtx.profile.name,
|
|
1736
|
+
userDataDir: profileCtx.profile.userDataDir,
|
|
1737
|
+
targetId: tab.targetId,
|
|
1738
|
+
args: [ref],
|
|
1739
|
+
fn: `(el) => {
|
|
1740
|
+
if (!(el instanceof Element)) {
|
|
1741
|
+
return false;
|
|
1742
|
+
}
|
|
1743
|
+
el.scrollIntoView({ block: "center", inline: "center" });
|
|
1744
|
+
const previousOutline = el.style.outline;
|
|
1745
|
+
const previousOffset = el.style.outlineOffset;
|
|
1746
|
+
el.style.outline = "3px solid #FF4500";
|
|
1747
|
+
el.style.outlineOffset = "2px";
|
|
1748
|
+
setTimeout(() => {
|
|
1749
|
+
el.style.outline = previousOutline;
|
|
1750
|
+
el.style.outlineOffset = previousOffset;
|
|
1751
|
+
}, 2000);
|
|
1752
|
+
return true;
|
|
1753
|
+
}`
|
|
1754
|
+
});
|
|
1755
|
+
return res.json({
|
|
1756
|
+
ok: true,
|
|
1757
|
+
targetId: tab.targetId
|
|
1758
|
+
});
|
|
1759
|
+
}
|
|
1760
|
+
const pw = await requirePwAi(res, "highlight");
|
|
1761
|
+
if (!pw) return;
|
|
1762
|
+
await pw.highlightViaPlaywright({
|
|
1763
|
+
cdpUrl,
|
|
1764
|
+
targetId: tab.targetId,
|
|
1765
|
+
ref
|
|
1766
|
+
});
|
|
1767
|
+
res.json({
|
|
1768
|
+
ok: true,
|
|
1769
|
+
targetId: tab.targetId
|
|
1770
|
+
});
|
|
1771
|
+
}
|
|
1772
|
+
});
|
|
1773
|
+
});
|
|
1774
|
+
}
|
|
1775
|
+
//#endregion
|
|
1776
|
+
//#region extensions/browser/src/browser/routes/agent.debug.ts
|
|
1777
|
+
function registerBrowserAgentDebugRoutes(app, ctx) {
|
|
1778
|
+
app.get("/console", async (req, res) => {
|
|
1779
|
+
const targetId = resolveTargetIdFromQuery(req.query);
|
|
1780
|
+
const level = typeof req.query.level === "string" ? req.query.level : "";
|
|
1781
|
+
await withPlaywrightRouteContext({
|
|
1782
|
+
req,
|
|
1783
|
+
res,
|
|
1784
|
+
ctx,
|
|
1785
|
+
targetId,
|
|
1786
|
+
feature: "console messages",
|
|
1787
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
1788
|
+
const messages = await pw.getConsoleMessagesViaPlaywright({
|
|
1789
|
+
cdpUrl,
|
|
1790
|
+
targetId: tab.targetId,
|
|
1791
|
+
level: normalizeOptionalString(level)
|
|
1792
|
+
});
|
|
1793
|
+
res.json({
|
|
1794
|
+
ok: true,
|
|
1795
|
+
messages,
|
|
1796
|
+
targetId: tab.targetId
|
|
1797
|
+
});
|
|
1798
|
+
}
|
|
1799
|
+
});
|
|
1800
|
+
});
|
|
1801
|
+
app.get("/errors", async (req, res) => {
|
|
1802
|
+
const targetId = resolveTargetIdFromQuery(req.query);
|
|
1803
|
+
const clear = toBoolean(req.query.clear) ?? false;
|
|
1804
|
+
await withPlaywrightRouteContext({
|
|
1805
|
+
req,
|
|
1806
|
+
res,
|
|
1807
|
+
ctx,
|
|
1808
|
+
targetId,
|
|
1809
|
+
feature: "page errors",
|
|
1810
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
1811
|
+
const result = await pw.getPageErrorsViaPlaywright({
|
|
1812
|
+
cdpUrl,
|
|
1813
|
+
targetId: tab.targetId,
|
|
1814
|
+
clear
|
|
1815
|
+
});
|
|
1816
|
+
res.json({
|
|
1817
|
+
ok: true,
|
|
1818
|
+
targetId: tab.targetId,
|
|
1819
|
+
...result
|
|
1820
|
+
});
|
|
1821
|
+
}
|
|
1822
|
+
});
|
|
1823
|
+
});
|
|
1824
|
+
app.get("/requests", async (req, res) => {
|
|
1825
|
+
const targetId = resolveTargetIdFromQuery(req.query);
|
|
1826
|
+
const filter = typeof req.query.filter === "string" ? req.query.filter : "";
|
|
1827
|
+
const clear = toBoolean(req.query.clear) ?? false;
|
|
1828
|
+
await withPlaywrightRouteContext({
|
|
1829
|
+
req,
|
|
1830
|
+
res,
|
|
1831
|
+
ctx,
|
|
1832
|
+
targetId,
|
|
1833
|
+
feature: "network requests",
|
|
1834
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
1835
|
+
const result = await pw.getNetworkRequestsViaPlaywright({
|
|
1836
|
+
cdpUrl,
|
|
1837
|
+
targetId: tab.targetId,
|
|
1838
|
+
filter: normalizeOptionalString(filter),
|
|
1839
|
+
clear
|
|
1840
|
+
});
|
|
1841
|
+
res.json({
|
|
1842
|
+
ok: true,
|
|
1843
|
+
targetId: tab.targetId,
|
|
1844
|
+
...result
|
|
1845
|
+
});
|
|
1846
|
+
}
|
|
1847
|
+
});
|
|
1848
|
+
});
|
|
1849
|
+
app.post("/trace/start", async (req, res) => {
|
|
1850
|
+
const body = readBody(req);
|
|
1851
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
1852
|
+
const screenshots = toBoolean(body.screenshots) ?? void 0;
|
|
1853
|
+
const snapshots = toBoolean(body.snapshots) ?? void 0;
|
|
1854
|
+
const sources = toBoolean(body.sources) ?? void 0;
|
|
1855
|
+
await withPlaywrightRouteContext({
|
|
1856
|
+
req,
|
|
1857
|
+
res,
|
|
1858
|
+
ctx,
|
|
1859
|
+
targetId,
|
|
1860
|
+
feature: "trace start",
|
|
1861
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
1862
|
+
await pw.traceStartViaPlaywright({
|
|
1863
|
+
cdpUrl,
|
|
1864
|
+
targetId: tab.targetId,
|
|
1865
|
+
screenshots,
|
|
1866
|
+
snapshots,
|
|
1867
|
+
sources
|
|
1868
|
+
});
|
|
1869
|
+
res.json({
|
|
1870
|
+
ok: true,
|
|
1871
|
+
targetId: tab.targetId
|
|
1872
|
+
});
|
|
1873
|
+
}
|
|
1874
|
+
});
|
|
1875
|
+
});
|
|
1876
|
+
app.post("/trace/stop", async (req, res) => {
|
|
1877
|
+
const body = readBody(req);
|
|
1878
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
1879
|
+
const out = toStringOrEmpty(body.path) || "";
|
|
1880
|
+
await withPlaywrightRouteContext({
|
|
1881
|
+
req,
|
|
1882
|
+
res,
|
|
1883
|
+
ctx,
|
|
1884
|
+
targetId,
|
|
1885
|
+
feature: "trace stop",
|
|
1886
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
1887
|
+
const tracePath = await resolveWritableOutputPathOrRespond({
|
|
1888
|
+
res,
|
|
1889
|
+
rootDir: DEFAULT_TRACE_DIR,
|
|
1890
|
+
requestedPath: out,
|
|
1891
|
+
scopeLabel: "trace directory",
|
|
1892
|
+
defaultFileName: `browser-trace-${crypto.randomUUID()}.zip`,
|
|
1893
|
+
ensureRootDir: true
|
|
1894
|
+
});
|
|
1895
|
+
if (!tracePath) return;
|
|
1896
|
+
await pw.traceStopViaPlaywright({
|
|
1897
|
+
cdpUrl,
|
|
1898
|
+
targetId: tab.targetId,
|
|
1899
|
+
path: tracePath
|
|
1900
|
+
});
|
|
1901
|
+
res.json({
|
|
1902
|
+
ok: true,
|
|
1903
|
+
targetId: tab.targetId,
|
|
1904
|
+
path: path.resolve(tracePath)
|
|
1905
|
+
});
|
|
1906
|
+
}
|
|
1907
|
+
});
|
|
1908
|
+
});
|
|
1909
|
+
}
|
|
1910
|
+
//#endregion
|
|
1911
|
+
//#region extensions/browser/src/browser/chrome-mcp.snapshot.ts
|
|
1912
|
+
function normalizeRole(node) {
|
|
1913
|
+
return normalizeLowercaseStringOrEmpty(node.role) || "generic";
|
|
1914
|
+
}
|
|
1915
|
+
function escapeQuoted(value) {
|
|
1916
|
+
return value.replaceAll("\\", "\\\\").replaceAll("\"", "\\\"");
|
|
1917
|
+
}
|
|
1918
|
+
function shouldIncludeNode(params) {
|
|
1919
|
+
if (params.options?.interactive && !INTERACTIVE_ROLES.has(params.role)) return false;
|
|
1920
|
+
if (params.options?.compact && STRUCTURAL_ROLES.has(params.role) && !params.name) return false;
|
|
1921
|
+
return true;
|
|
1922
|
+
}
|
|
1923
|
+
function shouldCreateRef(role, name) {
|
|
1924
|
+
return INTERACTIVE_ROLES.has(role) || CONTENT_ROLES.has(role) && Boolean(name);
|
|
1925
|
+
}
|
|
1926
|
+
function createDuplicateTracker() {
|
|
1927
|
+
return {
|
|
1928
|
+
counts: /* @__PURE__ */ new Map(),
|
|
1929
|
+
keysByRef: /* @__PURE__ */ new Map(),
|
|
1930
|
+
duplicates: /* @__PURE__ */ new Set()
|
|
1931
|
+
};
|
|
1932
|
+
}
|
|
1933
|
+
function registerRef(tracker, ref, role, name) {
|
|
1934
|
+
const key = `${role}:${name ?? ""}`;
|
|
1935
|
+
const count = tracker.counts.get(key) ?? 0;
|
|
1936
|
+
tracker.counts.set(key, count + 1);
|
|
1937
|
+
tracker.keysByRef.set(ref, key);
|
|
1938
|
+
if (count > 0) {
|
|
1939
|
+
tracker.duplicates.add(key);
|
|
1940
|
+
return count;
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
function flattenChromeMcpSnapshotToAriaNodes(root, limit = 500) {
|
|
1944
|
+
const boundedLimit = Math.max(1, Math.min(2e3, Math.floor(limit)));
|
|
1945
|
+
const out = [];
|
|
1946
|
+
const visit = (node, depth) => {
|
|
1947
|
+
if (out.length >= boundedLimit) return;
|
|
1948
|
+
const ref = normalizeString(node.id);
|
|
1949
|
+
if (ref) out.push({
|
|
1950
|
+
ref,
|
|
1951
|
+
role: normalizeRole(node),
|
|
1952
|
+
name: normalizeString(node.name) ?? "",
|
|
1953
|
+
value: normalizeString(node.value),
|
|
1954
|
+
description: normalizeString(node.description),
|
|
1955
|
+
depth
|
|
1956
|
+
});
|
|
1957
|
+
for (const child of node.children ?? []) {
|
|
1958
|
+
visit(child, depth + 1);
|
|
1959
|
+
if (out.length >= boundedLimit) return;
|
|
1960
|
+
}
|
|
1961
|
+
};
|
|
1962
|
+
visit(root, 0);
|
|
1963
|
+
return out;
|
|
1964
|
+
}
|
|
1965
|
+
function buildAiSnapshotFromChromeMcpSnapshot(params) {
|
|
1966
|
+
const refs = {};
|
|
1967
|
+
const tracker = createDuplicateTracker();
|
|
1968
|
+
const lines = [];
|
|
1969
|
+
const visit = (node, depth) => {
|
|
1970
|
+
const role = normalizeRole(node);
|
|
1971
|
+
const name = normalizeString(node.name);
|
|
1972
|
+
const value = normalizeString(node.value);
|
|
1973
|
+
const description = normalizeString(node.description);
|
|
1974
|
+
const maxDepth = params.options?.maxDepth;
|
|
1975
|
+
if (maxDepth !== void 0 && depth > maxDepth) return;
|
|
1976
|
+
if (shouldIncludeNode({
|
|
1977
|
+
role,
|
|
1978
|
+
name,
|
|
1979
|
+
options: params.options
|
|
1980
|
+
})) {
|
|
1981
|
+
let line = `${" ".repeat(depth)}- ${role}`;
|
|
1982
|
+
if (name) line += ` "${escapeQuoted(name)}"`;
|
|
1983
|
+
const ref = normalizeString(node.id);
|
|
1984
|
+
if (ref && shouldCreateRef(role, name)) {
|
|
1985
|
+
const nth = registerRef(tracker, ref, role, name);
|
|
1986
|
+
refs[ref] = nth === void 0 ? {
|
|
1987
|
+
role,
|
|
1988
|
+
name
|
|
1989
|
+
} : {
|
|
1990
|
+
role,
|
|
1991
|
+
name,
|
|
1992
|
+
nth
|
|
1993
|
+
};
|
|
1994
|
+
line += ` [ref=${ref}]`;
|
|
1995
|
+
}
|
|
1996
|
+
if (value) line += ` value="${escapeQuoted(value)}"`;
|
|
1997
|
+
if (description) line += ` description="${escapeQuoted(description)}"`;
|
|
1998
|
+
lines.push(line);
|
|
1999
|
+
}
|
|
2000
|
+
for (const child of node.children ?? []) visit(child, depth + 1);
|
|
2001
|
+
};
|
|
2002
|
+
visit(params.root, 0);
|
|
2003
|
+
for (const [ref, data] of Object.entries(refs)) {
|
|
2004
|
+
const key = tracker.keysByRef.get(ref);
|
|
2005
|
+
if (key && !tracker.duplicates.has(key)) delete data.nth;
|
|
2006
|
+
}
|
|
2007
|
+
let snapshot = lines.join("\n");
|
|
2008
|
+
let truncated = false;
|
|
2009
|
+
const maxChars = typeof params.maxChars === "number" && Number.isFinite(params.maxChars) && params.maxChars > 0 ? Math.floor(params.maxChars) : void 0;
|
|
2010
|
+
if (maxChars && snapshot.length > maxChars) {
|
|
2011
|
+
snapshot = `${snapshot.slice(0, maxChars)}\n\n[...TRUNCATED - page too large]`;
|
|
2012
|
+
truncated = true;
|
|
2013
|
+
}
|
|
2014
|
+
const stats = getRoleSnapshotStats(snapshot, refs);
|
|
2015
|
+
return truncated ? {
|
|
2016
|
+
snapshot,
|
|
2017
|
+
truncated,
|
|
2018
|
+
refs,
|
|
2019
|
+
stats
|
|
2020
|
+
} : {
|
|
2021
|
+
snapshot,
|
|
2022
|
+
refs,
|
|
2023
|
+
stats
|
|
2024
|
+
};
|
|
2025
|
+
}
|
|
2026
|
+
//#endregion
|
|
2027
|
+
//#region extensions/browser/src/browser/screenshot.ts
|
|
2028
|
+
const DEFAULT_BROWSER_SCREENSHOT_MAX_SIDE = 2e3;
|
|
2029
|
+
const DEFAULT_BROWSER_SCREENSHOT_MAX_BYTES = 5 * 1024 * 1024;
|
|
2030
|
+
async function normalizeBrowserScreenshot(buffer, opts) {
|
|
2031
|
+
const maxSide = Math.max(1, Math.round(opts?.maxSide ?? 2e3));
|
|
2032
|
+
const maxBytes = Math.max(1, Math.round(opts?.maxBytes ?? 5242880));
|
|
2033
|
+
const meta = await getImageMetadata(buffer);
|
|
2034
|
+
const width = Number(meta?.width ?? 0);
|
|
2035
|
+
const height = Number(meta?.height ?? 0);
|
|
2036
|
+
const maxDim = Math.max(width, height);
|
|
2037
|
+
if (buffer.byteLength <= maxBytes && (maxDim === 0 || width <= maxSide && height <= maxSide)) return { buffer };
|
|
2038
|
+
const sideGrid = buildImageResizeSideGrid(maxSide, maxDim > 0 ? Math.min(maxSide, maxDim) : maxSide);
|
|
2039
|
+
let smallest = null;
|
|
2040
|
+
for (const side of sideGrid) for (const quality of IMAGE_REDUCE_QUALITY_STEPS) {
|
|
2041
|
+
const out = await resizeToJpeg({
|
|
2042
|
+
buffer,
|
|
2043
|
+
maxSide: side,
|
|
2044
|
+
quality,
|
|
2045
|
+
withoutEnlargement: true
|
|
2046
|
+
});
|
|
2047
|
+
if (!smallest || out.byteLength < smallest.size) smallest = {
|
|
2048
|
+
buffer: out,
|
|
2049
|
+
size: out.byteLength
|
|
2050
|
+
};
|
|
2051
|
+
if (out.byteLength <= maxBytes) return {
|
|
2052
|
+
buffer: out,
|
|
2053
|
+
contentType: "image/jpeg"
|
|
2054
|
+
};
|
|
2055
|
+
}
|
|
2056
|
+
const best = smallest?.buffer ?? buffer;
|
|
2057
|
+
throw new Error(`Browser screenshot could not be reduced below ${(maxBytes / (1024 * 1024)).toFixed(0)}MB (got ${(best.byteLength / (1024 * 1024)).toFixed(2)}MB)`);
|
|
2058
|
+
}
|
|
2059
|
+
//#endregion
|
|
2060
|
+
//#region extensions/browser/src/browser/routes/agent.snapshot.plan.ts
|
|
2061
|
+
function resolveSnapshotPlan(params) {
|
|
2062
|
+
const mode = params.query.mode === "efficient" ? "efficient" : void 0;
|
|
2063
|
+
const labels = toBoolean(params.query.labels) ?? void 0;
|
|
2064
|
+
const explicitFormat = params.query.format === "aria" ? "aria" : params.query.format === "ai" ? "ai" : void 0;
|
|
2065
|
+
const format = resolveDefaultSnapshotFormat({
|
|
2066
|
+
profile: params.profile,
|
|
2067
|
+
hasPlaywright: params.hasPlaywright,
|
|
2068
|
+
explicitFormat,
|
|
2069
|
+
mode
|
|
2070
|
+
});
|
|
2071
|
+
const limitRaw = readStringValue(params.query.limit);
|
|
2072
|
+
const hasMaxChars = Object.hasOwn(params.query, "maxChars");
|
|
2073
|
+
const maxCharsRaw = readStringValue(params.query.maxChars);
|
|
2074
|
+
const limit = Number.isFinite(Number(limitRaw)) ? Number(limitRaw) : void 0;
|
|
2075
|
+
const maxChars = Number.isFinite(Number(maxCharsRaw)) && Number(maxCharsRaw) > 0 ? Math.floor(Number(maxCharsRaw)) : void 0;
|
|
2076
|
+
const resolvedMaxChars = format === "ai" ? hasMaxChars ? maxChars : mode === "efficient" ? DEFAULT_AI_SNAPSHOT_EFFICIENT_MAX_CHARS : DEFAULT_AI_SNAPSHOT_MAX_CHARS : void 0;
|
|
2077
|
+
const interactiveRaw = toBoolean(params.query.interactive);
|
|
2078
|
+
const compactRaw = toBoolean(params.query.compact);
|
|
2079
|
+
const depthRaw = toNumber(params.query.depth);
|
|
2080
|
+
const refsModeRaw = toStringOrEmpty(params.query.refs).trim();
|
|
2081
|
+
const refsMode = refsModeRaw === "aria" ? "aria" : refsModeRaw === "role" ? "role" : void 0;
|
|
2082
|
+
const interactive = interactiveRaw ?? (mode === "efficient" ? true : void 0);
|
|
2083
|
+
const compact = compactRaw ?? (mode === "efficient" ? true : void 0);
|
|
2084
|
+
const depth = depthRaw ?? (mode === "efficient" ? 6 : void 0);
|
|
2085
|
+
const selectorValue = normalizeOptionalString(toStringOrEmpty(params.query.selector));
|
|
2086
|
+
const frameSelectorValue = normalizeOptionalString(toStringOrEmpty(params.query.frame));
|
|
2087
|
+
return {
|
|
2088
|
+
format,
|
|
2089
|
+
mode,
|
|
2090
|
+
labels,
|
|
2091
|
+
limit,
|
|
2092
|
+
resolvedMaxChars,
|
|
2093
|
+
interactive,
|
|
2094
|
+
compact,
|
|
2095
|
+
depth,
|
|
2096
|
+
refsMode,
|
|
2097
|
+
selectorValue,
|
|
2098
|
+
frameSelectorValue,
|
|
2099
|
+
wantsRoleSnapshot: labels === true || mode === "efficient" || interactive === true || compact === true || depth !== void 0 || Boolean(selectorValue) || Boolean(frameSelectorValue)
|
|
2100
|
+
};
|
|
2101
|
+
}
|
|
2102
|
+
//#endregion
|
|
2103
|
+
//#region extensions/browser/src/browser/routes/agent.snapshot.ts
|
|
2104
|
+
const CHROME_MCP_OVERLAY_ATTR = "data-kaijibot-mcp-overlay";
|
|
2105
|
+
async function clearChromeMcpOverlay(params) {
|
|
2106
|
+
await evaluateChromeMcpScript({
|
|
2107
|
+
profileName: params.profileName,
|
|
2108
|
+
userDataDir: params.userDataDir,
|
|
2109
|
+
targetId: params.targetId,
|
|
2110
|
+
fn: `() => {
|
|
2111
|
+
document.querySelectorAll("[${CHROME_MCP_OVERLAY_ATTR}]").forEach((node) => node.remove());
|
|
2112
|
+
return true;
|
|
2113
|
+
}`
|
|
2114
|
+
}).catch(() => {});
|
|
2115
|
+
}
|
|
2116
|
+
async function renderChromeMcpLabels(params) {
|
|
2117
|
+
const refList = JSON.stringify(params.refs);
|
|
2118
|
+
const result = await evaluateChromeMcpScript({
|
|
2119
|
+
profileName: params.profileName,
|
|
2120
|
+
userDataDir: params.userDataDir,
|
|
2121
|
+
targetId: params.targetId,
|
|
2122
|
+
args: params.refs,
|
|
2123
|
+
fn: `(...elements) => {
|
|
2124
|
+
const refs = ${refList};
|
|
2125
|
+
document.querySelectorAll("[${CHROME_MCP_OVERLAY_ATTR}]").forEach((node) => node.remove());
|
|
2126
|
+
const root = document.createElement("div");
|
|
2127
|
+
root.setAttribute("${CHROME_MCP_OVERLAY_ATTR}", "labels");
|
|
2128
|
+
root.style.position = "fixed";
|
|
2129
|
+
root.style.inset = "0";
|
|
2130
|
+
root.style.pointerEvents = "none";
|
|
2131
|
+
root.style.zIndex = "2147483647";
|
|
2132
|
+
let labels = 0;
|
|
2133
|
+
let skipped = 0;
|
|
2134
|
+
elements.forEach((el, index) => {
|
|
2135
|
+
if (!(el instanceof Element)) {
|
|
2136
|
+
skipped += 1;
|
|
2137
|
+
return;
|
|
2138
|
+
}
|
|
2139
|
+
const rect = el.getBoundingClientRect();
|
|
2140
|
+
if (rect.width <= 0 && rect.height <= 0) {
|
|
2141
|
+
skipped += 1;
|
|
2142
|
+
return;
|
|
2143
|
+
}
|
|
2144
|
+
labels += 1;
|
|
2145
|
+
const badge = document.createElement("div");
|
|
2146
|
+
badge.setAttribute("${CHROME_MCP_OVERLAY_ATTR}", "label");
|
|
2147
|
+
badge.textContent = refs[index] || String(labels);
|
|
2148
|
+
badge.style.position = "fixed";
|
|
2149
|
+
badge.style.left = \`\${Math.max(0, rect.left)}px\`;
|
|
2150
|
+
badge.style.top = \`\${Math.max(0, rect.top)}px\`;
|
|
2151
|
+
badge.style.transform = "translateY(-100%)";
|
|
2152
|
+
badge.style.padding = "2px 6px";
|
|
2153
|
+
badge.style.borderRadius = "999px";
|
|
2154
|
+
badge.style.background = "#FF4500";
|
|
2155
|
+
badge.style.color = "#fff";
|
|
2156
|
+
badge.style.font = "600 12px ui-monospace, SFMono-Regular, Menlo, monospace";
|
|
2157
|
+
badge.style.boxShadow = "0 2px 6px rgba(0,0,0,0.35)";
|
|
2158
|
+
badge.style.whiteSpace = "nowrap";
|
|
2159
|
+
root.appendChild(badge);
|
|
2160
|
+
});
|
|
2161
|
+
document.documentElement.appendChild(root);
|
|
2162
|
+
return { labels, skipped };
|
|
2163
|
+
}`
|
|
2164
|
+
});
|
|
2165
|
+
return {
|
|
2166
|
+
labels: result && typeof result === "object" && typeof result.labels === "number" ? result.labels : 0,
|
|
2167
|
+
skipped: result && typeof result === "object" && typeof result.skipped === "number" ? result.skipped : 0
|
|
2168
|
+
};
|
|
2169
|
+
}
|
|
2170
|
+
async function saveNormalizedScreenshotResponse(params) {
|
|
2171
|
+
const normalized = await normalizeBrowserScreenshot(params.buffer, {
|
|
2172
|
+
maxSide: DEFAULT_BROWSER_SCREENSHOT_MAX_SIDE,
|
|
2173
|
+
maxBytes: DEFAULT_BROWSER_SCREENSHOT_MAX_BYTES
|
|
2174
|
+
});
|
|
2175
|
+
await saveBrowserMediaResponse({
|
|
2176
|
+
res: params.res,
|
|
2177
|
+
buffer: normalized.buffer,
|
|
2178
|
+
contentType: normalized.contentType ?? `image/${params.type}`,
|
|
2179
|
+
maxBytes: DEFAULT_BROWSER_SCREENSHOT_MAX_BYTES,
|
|
2180
|
+
targetId: params.targetId,
|
|
2181
|
+
url: params.url
|
|
2182
|
+
});
|
|
2183
|
+
}
|
|
2184
|
+
async function saveBrowserMediaResponse(params) {
|
|
2185
|
+
await ensureMediaDir();
|
|
2186
|
+
const saved = await saveMediaBuffer(params.buffer, params.contentType, "browser", params.maxBytes);
|
|
2187
|
+
params.res.json({
|
|
2188
|
+
ok: true,
|
|
2189
|
+
path: path.resolve(saved.path),
|
|
2190
|
+
targetId: params.targetId,
|
|
2191
|
+
url: params.url
|
|
2192
|
+
});
|
|
2193
|
+
}
|
|
2194
|
+
/** Resolve the correct targetId after a navigation that may trigger a renderer swap. */
|
|
2195
|
+
async function resolveTargetIdAfterNavigate(opts) {
|
|
2196
|
+
let currentTargetId = opts.oldTargetId;
|
|
2197
|
+
try {
|
|
2198
|
+
const pickReplacement = (tabs, options) => {
|
|
2199
|
+
if (tabs.some((tab) => tab.targetId === opts.oldTargetId)) return opts.oldTargetId;
|
|
2200
|
+
const byUrl = tabs.filter((tab) => tab.url === opts.navigatedUrl);
|
|
2201
|
+
if (byUrl.length === 1) return byUrl[0]?.targetId ?? opts.oldTargetId;
|
|
2202
|
+
const uniqueReplacement = byUrl.filter((tab) => tab.targetId !== opts.oldTargetId);
|
|
2203
|
+
if (uniqueReplacement.length === 1) return uniqueReplacement[0]?.targetId ?? opts.oldTargetId;
|
|
2204
|
+
if (options?.allowSingleTabFallback && tabs.length === 1) return tabs[0]?.targetId ?? opts.oldTargetId;
|
|
2205
|
+
return opts.oldTargetId;
|
|
2206
|
+
};
|
|
2207
|
+
currentTargetId = pickReplacement(await opts.listTabs());
|
|
2208
|
+
if (currentTargetId === opts.oldTargetId) {
|
|
2209
|
+
await new Promise((r) => setTimeout(r, 800));
|
|
2210
|
+
currentTargetId = pickReplacement(await opts.listTabs(), { allowSingleTabFallback: true });
|
|
2211
|
+
}
|
|
2212
|
+
} catch {}
|
|
2213
|
+
return currentTargetId;
|
|
2214
|
+
}
|
|
2215
|
+
function registerBrowserAgentSnapshotRoutes(app, ctx) {
|
|
2216
|
+
app.post("/navigate", async (req, res) => {
|
|
2217
|
+
const body = readBody(req);
|
|
2218
|
+
const url = toStringOrEmpty(body.url);
|
|
2219
|
+
const targetId = toStringOrEmpty(body.targetId) || void 0;
|
|
2220
|
+
if (!url) return jsonError(res, 400, "url is required");
|
|
2221
|
+
await withRouteTabContext({
|
|
2222
|
+
req,
|
|
2223
|
+
res,
|
|
2224
|
+
ctx,
|
|
2225
|
+
targetId,
|
|
2226
|
+
run: async ({ profileCtx, tab, cdpUrl }) => {
|
|
2227
|
+
if (getBrowserProfileCapabilities(profileCtx.profile).usesChromeMcp) {
|
|
2228
|
+
const ssrfPolicyOpts = withBrowserNavigationPolicy(ctx.state().resolved.ssrfPolicy);
|
|
2229
|
+
await assertBrowserNavigationAllowed({
|
|
2230
|
+
url,
|
|
2231
|
+
...ssrfPolicyOpts
|
|
2232
|
+
});
|
|
2233
|
+
const result = await navigateChromeMcpPage({
|
|
2234
|
+
profileName: profileCtx.profile.name,
|
|
2235
|
+
userDataDir: profileCtx.profile.userDataDir,
|
|
2236
|
+
targetId: tab.targetId,
|
|
2237
|
+
url
|
|
2238
|
+
});
|
|
2239
|
+
await assertBrowserNavigationResultAllowed({
|
|
2240
|
+
url: result.url,
|
|
2241
|
+
...ssrfPolicyOpts
|
|
2242
|
+
});
|
|
2243
|
+
return res.json({
|
|
2244
|
+
ok: true,
|
|
2245
|
+
targetId: tab.targetId,
|
|
2246
|
+
...result
|
|
2247
|
+
});
|
|
2248
|
+
}
|
|
2249
|
+
const pw = await requirePwAi(res, "navigate");
|
|
2250
|
+
if (!pw) return;
|
|
2251
|
+
const result = await pw.navigateViaPlaywright({
|
|
2252
|
+
cdpUrl,
|
|
2253
|
+
targetId: tab.targetId,
|
|
2254
|
+
url,
|
|
2255
|
+
...withBrowserNavigationPolicy(ctx.state().resolved.ssrfPolicy)
|
|
2256
|
+
});
|
|
2257
|
+
const currentTargetId = await resolveTargetIdAfterNavigate({
|
|
2258
|
+
oldTargetId: tab.targetId,
|
|
2259
|
+
navigatedUrl: result.url,
|
|
2260
|
+
listTabs: () => profileCtx.listTabs()
|
|
2261
|
+
});
|
|
2262
|
+
res.json({
|
|
2263
|
+
ok: true,
|
|
2264
|
+
targetId: currentTargetId,
|
|
2265
|
+
...result
|
|
2266
|
+
});
|
|
2267
|
+
}
|
|
2268
|
+
});
|
|
2269
|
+
});
|
|
2270
|
+
app.post("/pdf", async (req, res) => {
|
|
2271
|
+
const targetId = toStringOrEmpty(readBody(req).targetId) || void 0;
|
|
2272
|
+
const profileCtx = resolveProfileContext(req, res, ctx);
|
|
2273
|
+
if (!profileCtx) return;
|
|
2274
|
+
if (getBrowserProfileCapabilities(profileCtx.profile).usesChromeMcp) return jsonError(res, 501, "pdf is not supported for existing-session profiles yet; use screenshot/snapshot instead.");
|
|
2275
|
+
await withPlaywrightRouteContext({
|
|
2276
|
+
req,
|
|
2277
|
+
res,
|
|
2278
|
+
ctx,
|
|
2279
|
+
targetId,
|
|
2280
|
+
feature: "pdf",
|
|
2281
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
2282
|
+
const pdf = await pw.pdfViaPlaywright({
|
|
2283
|
+
cdpUrl,
|
|
2284
|
+
targetId: tab.targetId
|
|
2285
|
+
});
|
|
2286
|
+
await saveBrowserMediaResponse({
|
|
2287
|
+
res,
|
|
2288
|
+
buffer: pdf.buffer,
|
|
2289
|
+
contentType: "application/pdf",
|
|
2290
|
+
maxBytes: pdf.buffer.byteLength,
|
|
2291
|
+
targetId: tab.targetId,
|
|
2292
|
+
url: tab.url
|
|
2293
|
+
});
|
|
2294
|
+
}
|
|
2295
|
+
});
|
|
2296
|
+
});
|
|
2297
|
+
app.post("/screenshot", async (req, res) => {
|
|
2298
|
+
const body = readBody(req);
|
|
2299
|
+
const targetId = toStringOrEmpty(body.targetId) || void 0;
|
|
2300
|
+
const fullPage = toBoolean(body.fullPage) ?? false;
|
|
2301
|
+
const ref = toStringOrEmpty(body.ref) || void 0;
|
|
2302
|
+
const element = toStringOrEmpty(body.element) || void 0;
|
|
2303
|
+
const type = body.type === "jpeg" ? "jpeg" : "png";
|
|
2304
|
+
if (fullPage && (ref || element)) return jsonError(res, 400, "fullPage is not supported for element screenshots");
|
|
2305
|
+
await withRouteTabContext({
|
|
2306
|
+
req,
|
|
2307
|
+
res,
|
|
2308
|
+
ctx,
|
|
2309
|
+
targetId,
|
|
2310
|
+
run: async ({ profileCtx, tab, cdpUrl }) => {
|
|
2311
|
+
if (getBrowserProfileCapabilities(profileCtx.profile).usesChromeMcp) {
|
|
2312
|
+
if (element) return jsonError(res, 400, "element screenshots are not supported for existing-session profiles; use ref from snapshot.");
|
|
2313
|
+
await saveNormalizedScreenshotResponse({
|
|
2314
|
+
res,
|
|
2315
|
+
buffer: await takeChromeMcpScreenshot({
|
|
2316
|
+
profileName: profileCtx.profile.name,
|
|
2317
|
+
userDataDir: profileCtx.profile.userDataDir,
|
|
2318
|
+
targetId: tab.targetId,
|
|
2319
|
+
uid: ref,
|
|
2320
|
+
fullPage,
|
|
2321
|
+
format: type
|
|
2322
|
+
}),
|
|
2323
|
+
type,
|
|
2324
|
+
targetId: tab.targetId,
|
|
2325
|
+
url: tab.url
|
|
2326
|
+
});
|
|
2327
|
+
return;
|
|
2328
|
+
}
|
|
2329
|
+
let buffer;
|
|
2330
|
+
if (shouldUsePlaywrightForScreenshot({
|
|
2331
|
+
profile: profileCtx.profile,
|
|
2332
|
+
wsUrl: tab.wsUrl,
|
|
2333
|
+
ref,
|
|
2334
|
+
element
|
|
2335
|
+
})) {
|
|
2336
|
+
const pw = await requirePwAi(res, "screenshot");
|
|
2337
|
+
if (!pw) return;
|
|
2338
|
+
buffer = (await pw.takeScreenshotViaPlaywright({
|
|
2339
|
+
cdpUrl,
|
|
2340
|
+
targetId: tab.targetId,
|
|
2341
|
+
ref,
|
|
2342
|
+
element,
|
|
2343
|
+
fullPage,
|
|
2344
|
+
type
|
|
2345
|
+
})).buffer;
|
|
2346
|
+
} else buffer = await captureScreenshot({
|
|
2347
|
+
wsUrl: tab.wsUrl ?? "",
|
|
2348
|
+
fullPage,
|
|
2349
|
+
format: type,
|
|
2350
|
+
quality: type === "jpeg" ? 85 : void 0
|
|
2351
|
+
});
|
|
2352
|
+
await saveNormalizedScreenshotResponse({
|
|
2353
|
+
res,
|
|
2354
|
+
buffer,
|
|
2355
|
+
type,
|
|
2356
|
+
targetId: tab.targetId,
|
|
2357
|
+
url: tab.url
|
|
2358
|
+
});
|
|
2359
|
+
}
|
|
2360
|
+
});
|
|
2361
|
+
});
|
|
2362
|
+
app.get("/snapshot", async (req, res) => {
|
|
2363
|
+
const profileCtx = resolveProfileContext(req, res, ctx);
|
|
2364
|
+
if (!profileCtx) return;
|
|
2365
|
+
const targetId = typeof req.query.targetId === "string" ? req.query.targetId.trim() : "";
|
|
2366
|
+
const hasPlaywright = Boolean(await getPwAiModule());
|
|
2367
|
+
const plan = resolveSnapshotPlan({
|
|
2368
|
+
profile: profileCtx.profile,
|
|
2369
|
+
query: req.query,
|
|
2370
|
+
hasPlaywright
|
|
2371
|
+
});
|
|
2372
|
+
try {
|
|
2373
|
+
const tab = await profileCtx.ensureTabAvailable(targetId || void 0);
|
|
2374
|
+
if ((plan.labels || plan.mode === "efficient") && plan.format === "aria") return jsonError(res, 400, "labels/mode=efficient require format=ai");
|
|
2375
|
+
if (getBrowserProfileCapabilities(profileCtx.profile).usesChromeMcp) {
|
|
2376
|
+
if (plan.selectorValue || plan.frameSelectorValue) return jsonError(res, 400, "selector/frame snapshots are not supported for existing-session profiles; snapshot the whole page and use refs.");
|
|
2377
|
+
const snapshot = await takeChromeMcpSnapshot({
|
|
2378
|
+
profileName: profileCtx.profile.name,
|
|
2379
|
+
userDataDir: profileCtx.profile.userDataDir,
|
|
2380
|
+
targetId: tab.targetId
|
|
2381
|
+
});
|
|
2382
|
+
if (plan.format === "aria") return res.json({
|
|
2383
|
+
ok: true,
|
|
2384
|
+
format: "aria",
|
|
2385
|
+
targetId: tab.targetId,
|
|
2386
|
+
url: tab.url,
|
|
2387
|
+
nodes: flattenChromeMcpSnapshotToAriaNodes(snapshot, plan.limit)
|
|
2388
|
+
});
|
|
2389
|
+
const built = buildAiSnapshotFromChromeMcpSnapshot({
|
|
2390
|
+
root: snapshot,
|
|
2391
|
+
options: {
|
|
2392
|
+
interactive: plan.interactive ?? void 0,
|
|
2393
|
+
compact: plan.compact ?? void 0,
|
|
2394
|
+
maxDepth: plan.depth ?? void 0
|
|
2395
|
+
},
|
|
2396
|
+
maxChars: plan.resolvedMaxChars
|
|
2397
|
+
});
|
|
2398
|
+
if (plan.labels) {
|
|
2399
|
+
const refs = Object.keys(built.refs);
|
|
2400
|
+
const labelResult = await renderChromeMcpLabels({
|
|
2401
|
+
profileName: profileCtx.profile.name,
|
|
2402
|
+
userDataDir: profileCtx.profile.userDataDir,
|
|
2403
|
+
targetId: tab.targetId,
|
|
2404
|
+
refs
|
|
2405
|
+
});
|
|
2406
|
+
try {
|
|
2407
|
+
const normalized = await normalizeBrowserScreenshot(await takeChromeMcpScreenshot({
|
|
2408
|
+
profileName: profileCtx.profile.name,
|
|
2409
|
+
userDataDir: profileCtx.profile.userDataDir,
|
|
2410
|
+
targetId: tab.targetId,
|
|
2411
|
+
format: "png"
|
|
2412
|
+
}), {
|
|
2413
|
+
maxSide: DEFAULT_BROWSER_SCREENSHOT_MAX_SIDE,
|
|
2414
|
+
maxBytes: DEFAULT_BROWSER_SCREENSHOT_MAX_BYTES
|
|
2415
|
+
});
|
|
2416
|
+
await ensureMediaDir();
|
|
2417
|
+
const saved = await saveMediaBuffer(normalized.buffer, normalized.contentType ?? "image/png", "browser", DEFAULT_BROWSER_SCREENSHOT_MAX_BYTES);
|
|
2418
|
+
return res.json({
|
|
2419
|
+
ok: true,
|
|
2420
|
+
format: "ai",
|
|
2421
|
+
targetId: tab.targetId,
|
|
2422
|
+
url: tab.url,
|
|
2423
|
+
labels: true,
|
|
2424
|
+
labelsCount: labelResult.labels,
|
|
2425
|
+
labelsSkipped: labelResult.skipped,
|
|
2426
|
+
imagePath: path.resolve(saved.path),
|
|
2427
|
+
imageType: normalized.contentType?.includes("jpeg") ? "jpeg" : "png",
|
|
2428
|
+
...built
|
|
2429
|
+
});
|
|
2430
|
+
} finally {
|
|
2431
|
+
await clearChromeMcpOverlay({
|
|
2432
|
+
profileName: profileCtx.profile.name,
|
|
2433
|
+
userDataDir: profileCtx.profile.userDataDir,
|
|
2434
|
+
targetId: tab.targetId
|
|
2435
|
+
});
|
|
2436
|
+
}
|
|
2437
|
+
}
|
|
2438
|
+
return res.json({
|
|
2439
|
+
ok: true,
|
|
2440
|
+
format: "ai",
|
|
2441
|
+
targetId: tab.targetId,
|
|
2442
|
+
url: tab.url,
|
|
2443
|
+
...built
|
|
2444
|
+
});
|
|
2445
|
+
}
|
|
2446
|
+
if (plan.format === "ai") {
|
|
2447
|
+
const pw = await requirePwAi(res, "ai snapshot");
|
|
2448
|
+
if (!pw) return;
|
|
2449
|
+
const roleSnapshotArgs = {
|
|
2450
|
+
cdpUrl: profileCtx.profile.cdpUrl,
|
|
2451
|
+
targetId: tab.targetId,
|
|
2452
|
+
selector: plan.selectorValue,
|
|
2453
|
+
frameSelector: plan.frameSelectorValue,
|
|
2454
|
+
refsMode: plan.refsMode,
|
|
2455
|
+
ssrfPolicy: ctx.state().resolved.ssrfPolicy,
|
|
2456
|
+
options: {
|
|
2457
|
+
interactive: plan.interactive ?? void 0,
|
|
2458
|
+
compact: plan.compact ?? void 0,
|
|
2459
|
+
maxDepth: plan.depth ?? void 0
|
|
2460
|
+
}
|
|
2461
|
+
};
|
|
2462
|
+
const snap = plan.wantsRoleSnapshot ? await pw.snapshotRoleViaPlaywright(roleSnapshotArgs) : await pw.snapshotAiViaPlaywright({
|
|
2463
|
+
cdpUrl: profileCtx.profile.cdpUrl,
|
|
2464
|
+
targetId: tab.targetId,
|
|
2465
|
+
ssrfPolicy: ctx.state().resolved.ssrfPolicy,
|
|
2466
|
+
...typeof plan.resolvedMaxChars === "number" ? { maxChars: plan.resolvedMaxChars } : {}
|
|
2467
|
+
}).catch(async (err) => {
|
|
2468
|
+
if (String(err).toLowerCase().includes("_snapshotforai")) return await pw.snapshotRoleViaPlaywright(roleSnapshotArgs);
|
|
2469
|
+
throw err;
|
|
2470
|
+
});
|
|
2471
|
+
if (plan.labels) {
|
|
2472
|
+
const labeled = await pw.screenshotWithLabelsViaPlaywright({
|
|
2473
|
+
cdpUrl: profileCtx.profile.cdpUrl,
|
|
2474
|
+
targetId: tab.targetId,
|
|
2475
|
+
refs: "refs" in snap ? snap.refs : {},
|
|
2476
|
+
type: "png"
|
|
2477
|
+
});
|
|
2478
|
+
const normalized = await normalizeBrowserScreenshot(labeled.buffer, {
|
|
2479
|
+
maxSide: DEFAULT_BROWSER_SCREENSHOT_MAX_SIDE,
|
|
2480
|
+
maxBytes: DEFAULT_BROWSER_SCREENSHOT_MAX_BYTES
|
|
2481
|
+
});
|
|
2482
|
+
await ensureMediaDir();
|
|
2483
|
+
const saved = await saveMediaBuffer(normalized.buffer, normalized.contentType ?? "image/png", "browser", DEFAULT_BROWSER_SCREENSHOT_MAX_BYTES);
|
|
2484
|
+
const imageType = normalized.contentType?.includes("jpeg") ? "jpeg" : "png";
|
|
2485
|
+
return res.json({
|
|
2486
|
+
ok: true,
|
|
2487
|
+
format: plan.format,
|
|
2488
|
+
targetId: tab.targetId,
|
|
2489
|
+
url: tab.url,
|
|
2490
|
+
labels: true,
|
|
2491
|
+
labelsCount: labeled.labels,
|
|
2492
|
+
labelsSkipped: labeled.skipped,
|
|
2493
|
+
imagePath: path.resolve(saved.path),
|
|
2494
|
+
imageType,
|
|
2495
|
+
...snap
|
|
2496
|
+
});
|
|
2497
|
+
}
|
|
2498
|
+
return res.json({
|
|
2499
|
+
ok: true,
|
|
2500
|
+
format: plan.format,
|
|
2501
|
+
targetId: tab.targetId,
|
|
2502
|
+
url: tab.url,
|
|
2503
|
+
...snap
|
|
2504
|
+
});
|
|
2505
|
+
}
|
|
2506
|
+
const snap = shouldUsePlaywrightForAriaSnapshot({
|
|
2507
|
+
profile: profileCtx.profile,
|
|
2508
|
+
wsUrl: tab.wsUrl
|
|
2509
|
+
}) ? requirePwAi(res, "aria snapshot").then(async (pw) => {
|
|
2510
|
+
if (!pw) return null;
|
|
2511
|
+
return await pw.snapshotAriaViaPlaywright({
|
|
2512
|
+
cdpUrl: profileCtx.profile.cdpUrl,
|
|
2513
|
+
targetId: tab.targetId,
|
|
2514
|
+
limit: plan.limit,
|
|
2515
|
+
ssrfPolicy: ctx.state().resolved.ssrfPolicy
|
|
2516
|
+
});
|
|
2517
|
+
}) : snapshotAria({
|
|
2518
|
+
wsUrl: tab.wsUrl ?? "",
|
|
2519
|
+
limit: plan.limit
|
|
2520
|
+
});
|
|
2521
|
+
const resolved = await Promise.resolve(snap);
|
|
2522
|
+
if (!resolved) return;
|
|
2523
|
+
return res.json({
|
|
2524
|
+
ok: true,
|
|
2525
|
+
format: plan.format,
|
|
2526
|
+
targetId: tab.targetId,
|
|
2527
|
+
url: tab.url,
|
|
2528
|
+
...resolved
|
|
2529
|
+
});
|
|
2530
|
+
} catch (err) {
|
|
2531
|
+
handleRouteError(ctx, res, err);
|
|
2532
|
+
}
|
|
2533
|
+
});
|
|
2534
|
+
}
|
|
2535
|
+
//#endregion
|
|
2536
|
+
//#region extensions/browser/src/browser/routes/agent.storage.ts
|
|
2537
|
+
function parseStorageKind(raw) {
|
|
2538
|
+
if (raw === "local" || raw === "session") return raw;
|
|
2539
|
+
return null;
|
|
2540
|
+
}
|
|
2541
|
+
function parseStorageMutationRequest(kindParam, body) {
|
|
2542
|
+
return {
|
|
2543
|
+
kind: parseStorageKind(toStringOrEmpty(kindParam)),
|
|
2544
|
+
targetId: resolveTargetIdFromBody(body)
|
|
2545
|
+
};
|
|
2546
|
+
}
|
|
2547
|
+
function parseRequiredStorageMutationRequest(kindParam, body) {
|
|
2548
|
+
const parsed = parseStorageMutationRequest(kindParam, body);
|
|
2549
|
+
if (!parsed.kind) return null;
|
|
2550
|
+
return {
|
|
2551
|
+
kind: parsed.kind,
|
|
2552
|
+
targetId: parsed.targetId
|
|
2553
|
+
};
|
|
2554
|
+
}
|
|
2555
|
+
function parseStorageMutationOrRespond(res, kindParam, body) {
|
|
2556
|
+
const parsed = parseRequiredStorageMutationRequest(kindParam, body);
|
|
2557
|
+
if (!parsed) {
|
|
2558
|
+
jsonError(res, 400, "kind must be local|session");
|
|
2559
|
+
return null;
|
|
2560
|
+
}
|
|
2561
|
+
return parsed;
|
|
2562
|
+
}
|
|
2563
|
+
function parseStorageMutationFromRequest(req, res) {
|
|
2564
|
+
const body = readBody(req);
|
|
2565
|
+
const parsed = parseStorageMutationOrRespond(res, req.params.kind, body);
|
|
2566
|
+
if (!parsed) return null;
|
|
2567
|
+
return {
|
|
2568
|
+
body,
|
|
2569
|
+
parsed
|
|
2570
|
+
};
|
|
2571
|
+
}
|
|
2572
|
+
function registerBrowserAgentStorageRoutes(app, ctx) {
|
|
2573
|
+
app.get("/cookies", async (req, res) => {
|
|
2574
|
+
await withPlaywrightRouteContext({
|
|
2575
|
+
req,
|
|
2576
|
+
res,
|
|
2577
|
+
ctx,
|
|
2578
|
+
targetId: resolveTargetIdFromQuery(req.query),
|
|
2579
|
+
feature: "cookies",
|
|
2580
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
2581
|
+
const result = await pw.cookiesGetViaPlaywright({
|
|
2582
|
+
cdpUrl,
|
|
2583
|
+
targetId: tab.targetId
|
|
2584
|
+
});
|
|
2585
|
+
res.json({
|
|
2586
|
+
ok: true,
|
|
2587
|
+
targetId: tab.targetId,
|
|
2588
|
+
...result
|
|
2589
|
+
});
|
|
2590
|
+
}
|
|
2591
|
+
});
|
|
2592
|
+
});
|
|
2593
|
+
app.post("/cookies/set", async (req, res) => {
|
|
2594
|
+
const body = readBody(req);
|
|
2595
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
2596
|
+
const cookie = body.cookie && typeof body.cookie === "object" && !Array.isArray(body.cookie) ? body.cookie : null;
|
|
2597
|
+
if (!cookie) return jsonError(res, 400, "cookie is required");
|
|
2598
|
+
await withPlaywrightRouteContext({
|
|
2599
|
+
req,
|
|
2600
|
+
res,
|
|
2601
|
+
ctx,
|
|
2602
|
+
targetId,
|
|
2603
|
+
feature: "cookies set",
|
|
2604
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
2605
|
+
await pw.cookiesSetViaPlaywright({
|
|
2606
|
+
cdpUrl,
|
|
2607
|
+
targetId: tab.targetId,
|
|
2608
|
+
cookie: {
|
|
2609
|
+
name: toStringOrEmpty(cookie.name),
|
|
2610
|
+
value: toStringOrEmpty(cookie.value),
|
|
2611
|
+
url: toStringOrEmpty(cookie.url) || void 0,
|
|
2612
|
+
domain: toStringOrEmpty(cookie.domain) || void 0,
|
|
2613
|
+
path: toStringOrEmpty(cookie.path) || void 0,
|
|
2614
|
+
expires: toNumber(cookie.expires) ?? void 0,
|
|
2615
|
+
httpOnly: toBoolean(cookie.httpOnly) ?? void 0,
|
|
2616
|
+
secure: toBoolean(cookie.secure) ?? void 0,
|
|
2617
|
+
sameSite: cookie.sameSite === "Lax" || cookie.sameSite === "None" || cookie.sameSite === "Strict" ? cookie.sameSite : void 0
|
|
2618
|
+
}
|
|
2619
|
+
});
|
|
2620
|
+
res.json({
|
|
2621
|
+
ok: true,
|
|
2622
|
+
targetId: tab.targetId
|
|
2623
|
+
});
|
|
2624
|
+
}
|
|
2625
|
+
});
|
|
2626
|
+
});
|
|
2627
|
+
app.post("/cookies/clear", async (req, res) => {
|
|
2628
|
+
await withPlaywrightRouteContext({
|
|
2629
|
+
req,
|
|
2630
|
+
res,
|
|
2631
|
+
ctx,
|
|
2632
|
+
targetId: resolveTargetIdFromBody(readBody(req)),
|
|
2633
|
+
feature: "cookies clear",
|
|
2634
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
2635
|
+
await pw.cookiesClearViaPlaywright({
|
|
2636
|
+
cdpUrl,
|
|
2637
|
+
targetId: tab.targetId
|
|
2638
|
+
});
|
|
2639
|
+
res.json({
|
|
2640
|
+
ok: true,
|
|
2641
|
+
targetId: tab.targetId
|
|
2642
|
+
});
|
|
2643
|
+
}
|
|
2644
|
+
});
|
|
2645
|
+
});
|
|
2646
|
+
app.get("/storage/:kind", async (req, res) => {
|
|
2647
|
+
const kind = parseStorageKind(toStringOrEmpty(req.params.kind));
|
|
2648
|
+
if (!kind) return jsonError(res, 400, "kind must be local|session");
|
|
2649
|
+
const targetId = resolveTargetIdFromQuery(req.query);
|
|
2650
|
+
const key = toStringOrEmpty(req.query.key);
|
|
2651
|
+
await withPlaywrightRouteContext({
|
|
2652
|
+
req,
|
|
2653
|
+
res,
|
|
2654
|
+
ctx,
|
|
2655
|
+
targetId,
|
|
2656
|
+
feature: "storage get",
|
|
2657
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
2658
|
+
const result = await pw.storageGetViaPlaywright({
|
|
2659
|
+
cdpUrl,
|
|
2660
|
+
targetId: tab.targetId,
|
|
2661
|
+
kind,
|
|
2662
|
+
key: normalizeOptionalString(key)
|
|
2663
|
+
});
|
|
2664
|
+
res.json({
|
|
2665
|
+
ok: true,
|
|
2666
|
+
targetId: tab.targetId,
|
|
2667
|
+
...result
|
|
2668
|
+
});
|
|
2669
|
+
}
|
|
2670
|
+
});
|
|
2671
|
+
});
|
|
2672
|
+
app.post("/storage/:kind/set", async (req, res) => {
|
|
2673
|
+
const mutation = parseStorageMutationFromRequest(req, res);
|
|
2674
|
+
if (!mutation) return;
|
|
2675
|
+
const key = toStringOrEmpty(mutation.body.key);
|
|
2676
|
+
if (!key) return jsonError(res, 400, "key is required");
|
|
2677
|
+
const value = typeof mutation.body.value === "string" ? mutation.body.value : "";
|
|
2678
|
+
await withPlaywrightRouteContext({
|
|
2679
|
+
req,
|
|
2680
|
+
res,
|
|
2681
|
+
ctx,
|
|
2682
|
+
targetId: mutation.parsed.targetId,
|
|
2683
|
+
feature: "storage set",
|
|
2684
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
2685
|
+
await pw.storageSetViaPlaywright({
|
|
2686
|
+
cdpUrl,
|
|
2687
|
+
targetId: tab.targetId,
|
|
2688
|
+
kind: mutation.parsed.kind,
|
|
2689
|
+
key,
|
|
2690
|
+
value
|
|
2691
|
+
});
|
|
2692
|
+
res.json({
|
|
2693
|
+
ok: true,
|
|
2694
|
+
targetId: tab.targetId
|
|
2695
|
+
});
|
|
2696
|
+
}
|
|
2697
|
+
});
|
|
2698
|
+
});
|
|
2699
|
+
app.post("/storage/:kind/clear", async (req, res) => {
|
|
2700
|
+
const mutation = parseStorageMutationFromRequest(req, res);
|
|
2701
|
+
if (!mutation) return;
|
|
2702
|
+
await withPlaywrightRouteContext({
|
|
2703
|
+
req,
|
|
2704
|
+
res,
|
|
2705
|
+
ctx,
|
|
2706
|
+
targetId: mutation.parsed.targetId,
|
|
2707
|
+
feature: "storage clear",
|
|
2708
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
2709
|
+
await pw.storageClearViaPlaywright({
|
|
2710
|
+
cdpUrl,
|
|
2711
|
+
targetId: tab.targetId,
|
|
2712
|
+
kind: mutation.parsed.kind
|
|
2713
|
+
});
|
|
2714
|
+
res.json({
|
|
2715
|
+
ok: true,
|
|
2716
|
+
targetId: tab.targetId
|
|
2717
|
+
});
|
|
2718
|
+
}
|
|
2719
|
+
});
|
|
2720
|
+
});
|
|
2721
|
+
app.post("/set/offline", async (req, res) => {
|
|
2722
|
+
const body = readBody(req);
|
|
2723
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
2724
|
+
const offline = toBoolean(body.offline);
|
|
2725
|
+
if (offline === void 0) return jsonError(res, 400, "offline is required");
|
|
2726
|
+
await withPlaywrightRouteContext({
|
|
2727
|
+
req,
|
|
2728
|
+
res,
|
|
2729
|
+
ctx,
|
|
2730
|
+
targetId,
|
|
2731
|
+
feature: "offline",
|
|
2732
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
2733
|
+
await pw.setOfflineViaPlaywright({
|
|
2734
|
+
cdpUrl,
|
|
2735
|
+
targetId: tab.targetId,
|
|
2736
|
+
offline
|
|
2737
|
+
});
|
|
2738
|
+
res.json({
|
|
2739
|
+
ok: true,
|
|
2740
|
+
targetId: tab.targetId
|
|
2741
|
+
});
|
|
2742
|
+
}
|
|
2743
|
+
});
|
|
2744
|
+
});
|
|
2745
|
+
app.post("/set/headers", async (req, res) => {
|
|
2746
|
+
const body = readBody(req);
|
|
2747
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
2748
|
+
const headers = body.headers && typeof body.headers === "object" && !Array.isArray(body.headers) ? body.headers : null;
|
|
2749
|
+
if (!headers) return jsonError(res, 400, "headers is required");
|
|
2750
|
+
const parsed = {};
|
|
2751
|
+
for (const [k, v] of Object.entries(headers)) if (typeof v === "string") parsed[k] = v;
|
|
2752
|
+
await withPlaywrightRouteContext({
|
|
2753
|
+
req,
|
|
2754
|
+
res,
|
|
2755
|
+
ctx,
|
|
2756
|
+
targetId,
|
|
2757
|
+
feature: "headers",
|
|
2758
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
2759
|
+
await pw.setExtraHTTPHeadersViaPlaywright({
|
|
2760
|
+
cdpUrl,
|
|
2761
|
+
targetId: tab.targetId,
|
|
2762
|
+
headers: parsed
|
|
2763
|
+
});
|
|
2764
|
+
res.json({
|
|
2765
|
+
ok: true,
|
|
2766
|
+
targetId: tab.targetId
|
|
2767
|
+
});
|
|
2768
|
+
}
|
|
2769
|
+
});
|
|
2770
|
+
});
|
|
2771
|
+
app.post("/set/credentials", async (req, res) => {
|
|
2772
|
+
const body = readBody(req);
|
|
2773
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
2774
|
+
const clear = toBoolean(body.clear) ?? false;
|
|
2775
|
+
const username = toStringOrEmpty(body.username) || void 0;
|
|
2776
|
+
const password = readStringValue(body.password);
|
|
2777
|
+
await withPlaywrightRouteContext({
|
|
2778
|
+
req,
|
|
2779
|
+
res,
|
|
2780
|
+
ctx,
|
|
2781
|
+
targetId,
|
|
2782
|
+
feature: "http credentials",
|
|
2783
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
2784
|
+
await pw.setHttpCredentialsViaPlaywright({
|
|
2785
|
+
cdpUrl,
|
|
2786
|
+
targetId: tab.targetId,
|
|
2787
|
+
username,
|
|
2788
|
+
password,
|
|
2789
|
+
clear
|
|
2790
|
+
});
|
|
2791
|
+
res.json({
|
|
2792
|
+
ok: true,
|
|
2793
|
+
targetId: tab.targetId
|
|
2794
|
+
});
|
|
2795
|
+
}
|
|
2796
|
+
});
|
|
2797
|
+
});
|
|
2798
|
+
app.post("/set/geolocation", async (req, res) => {
|
|
2799
|
+
const body = readBody(req);
|
|
2800
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
2801
|
+
const clear = toBoolean(body.clear) ?? false;
|
|
2802
|
+
const latitude = toNumber(body.latitude);
|
|
2803
|
+
const longitude = toNumber(body.longitude);
|
|
2804
|
+
const accuracy = toNumber(body.accuracy) ?? void 0;
|
|
2805
|
+
const origin = toStringOrEmpty(body.origin) || void 0;
|
|
2806
|
+
await withPlaywrightRouteContext({
|
|
2807
|
+
req,
|
|
2808
|
+
res,
|
|
2809
|
+
ctx,
|
|
2810
|
+
targetId,
|
|
2811
|
+
feature: "geolocation",
|
|
2812
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
2813
|
+
await pw.setGeolocationViaPlaywright({
|
|
2814
|
+
cdpUrl,
|
|
2815
|
+
targetId: tab.targetId,
|
|
2816
|
+
latitude,
|
|
2817
|
+
longitude,
|
|
2818
|
+
accuracy,
|
|
2819
|
+
origin,
|
|
2820
|
+
clear
|
|
2821
|
+
});
|
|
2822
|
+
res.json({
|
|
2823
|
+
ok: true,
|
|
2824
|
+
targetId: tab.targetId
|
|
2825
|
+
});
|
|
2826
|
+
}
|
|
2827
|
+
});
|
|
2828
|
+
});
|
|
2829
|
+
app.post("/set/media", async (req, res) => {
|
|
2830
|
+
const body = readBody(req);
|
|
2831
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
2832
|
+
const schemeRaw = toStringOrEmpty(body.colorScheme);
|
|
2833
|
+
const colorScheme = schemeRaw === "dark" || schemeRaw === "light" || schemeRaw === "no-preference" ? schemeRaw : schemeRaw === "none" ? null : void 0;
|
|
2834
|
+
if (colorScheme === void 0) return jsonError(res, 400, "colorScheme must be dark|light|no-preference|none");
|
|
2835
|
+
await withPlaywrightRouteContext({
|
|
2836
|
+
req,
|
|
2837
|
+
res,
|
|
2838
|
+
ctx,
|
|
2839
|
+
targetId,
|
|
2840
|
+
feature: "media emulation",
|
|
2841
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
2842
|
+
await pw.emulateMediaViaPlaywright({
|
|
2843
|
+
cdpUrl,
|
|
2844
|
+
targetId: tab.targetId,
|
|
2845
|
+
colorScheme
|
|
2846
|
+
});
|
|
2847
|
+
res.json({
|
|
2848
|
+
ok: true,
|
|
2849
|
+
targetId: tab.targetId
|
|
2850
|
+
});
|
|
2851
|
+
}
|
|
2852
|
+
});
|
|
2853
|
+
});
|
|
2854
|
+
app.post("/set/timezone", async (req, res) => {
|
|
2855
|
+
const body = readBody(req);
|
|
2856
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
2857
|
+
const timezoneId = toStringOrEmpty(body.timezoneId);
|
|
2858
|
+
if (!timezoneId) return jsonError(res, 400, "timezoneId is required");
|
|
2859
|
+
await withPlaywrightRouteContext({
|
|
2860
|
+
req,
|
|
2861
|
+
res,
|
|
2862
|
+
ctx,
|
|
2863
|
+
targetId,
|
|
2864
|
+
feature: "timezone",
|
|
2865
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
2866
|
+
await pw.setTimezoneViaPlaywright({
|
|
2867
|
+
cdpUrl,
|
|
2868
|
+
targetId: tab.targetId,
|
|
2869
|
+
timezoneId
|
|
2870
|
+
});
|
|
2871
|
+
res.json({
|
|
2872
|
+
ok: true,
|
|
2873
|
+
targetId: tab.targetId
|
|
2874
|
+
});
|
|
2875
|
+
}
|
|
2876
|
+
});
|
|
2877
|
+
});
|
|
2878
|
+
app.post("/set/locale", async (req, res) => {
|
|
2879
|
+
const body = readBody(req);
|
|
2880
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
2881
|
+
const locale = toStringOrEmpty(body.locale);
|
|
2882
|
+
if (!locale) return jsonError(res, 400, "locale is required");
|
|
2883
|
+
await withPlaywrightRouteContext({
|
|
2884
|
+
req,
|
|
2885
|
+
res,
|
|
2886
|
+
ctx,
|
|
2887
|
+
targetId,
|
|
2888
|
+
feature: "locale",
|
|
2889
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
2890
|
+
await pw.setLocaleViaPlaywright({
|
|
2891
|
+
cdpUrl,
|
|
2892
|
+
targetId: tab.targetId,
|
|
2893
|
+
locale
|
|
2894
|
+
});
|
|
2895
|
+
res.json({
|
|
2896
|
+
ok: true,
|
|
2897
|
+
targetId: tab.targetId
|
|
2898
|
+
});
|
|
2899
|
+
}
|
|
2900
|
+
});
|
|
2901
|
+
});
|
|
2902
|
+
app.post("/set/device", async (req, res) => {
|
|
2903
|
+
const body = readBody(req);
|
|
2904
|
+
const targetId = resolveTargetIdFromBody(body);
|
|
2905
|
+
const name = toStringOrEmpty(body.name);
|
|
2906
|
+
if (!name) return jsonError(res, 400, "name is required");
|
|
2907
|
+
await withPlaywrightRouteContext({
|
|
2908
|
+
req,
|
|
2909
|
+
res,
|
|
2910
|
+
ctx,
|
|
2911
|
+
targetId,
|
|
2912
|
+
feature: "device emulation",
|
|
2913
|
+
run: async ({ cdpUrl, tab, pw }) => {
|
|
2914
|
+
await pw.setDeviceViaPlaywright({
|
|
2915
|
+
cdpUrl,
|
|
2916
|
+
targetId: tab.targetId,
|
|
2917
|
+
name
|
|
2918
|
+
});
|
|
2919
|
+
res.json({
|
|
2920
|
+
ok: true,
|
|
2921
|
+
targetId: tab.targetId
|
|
2922
|
+
});
|
|
2923
|
+
}
|
|
2924
|
+
});
|
|
2925
|
+
});
|
|
2926
|
+
}
|
|
2927
|
+
//#endregion
|
|
2928
|
+
//#region extensions/browser/src/browser/routes/agent.ts
|
|
2929
|
+
function registerBrowserAgentRoutes(app, ctx) {
|
|
2930
|
+
registerBrowserAgentSnapshotRoutes(app, ctx);
|
|
2931
|
+
registerBrowserAgentActRoutes(app, ctx);
|
|
2932
|
+
registerBrowserAgentDebugRoutes(app, ctx);
|
|
2933
|
+
registerBrowserAgentStorageRoutes(app, ctx);
|
|
2934
|
+
}
|
|
2935
|
+
const PROFILE_NAME_REGEX = /^[a-z0-9][a-z0-9-]*$/;
|
|
2936
|
+
function isValidProfileName(name) {
|
|
2937
|
+
if (!name || name.length > 64) return false;
|
|
2938
|
+
return PROFILE_NAME_REGEX.test(name);
|
|
2939
|
+
}
|
|
2940
|
+
function allocateCdpPort(usedPorts, range) {
|
|
2941
|
+
const start = range?.start ?? 18800;
|
|
2942
|
+
const end = range?.end ?? 18899;
|
|
2943
|
+
if (!Number.isFinite(start) || !Number.isFinite(end) || start <= 0 || end <= 0) return null;
|
|
2944
|
+
if (start > end) return null;
|
|
2945
|
+
for (let port = start; port <= end; port++) if (!usedPorts.has(port)) return port;
|
|
2946
|
+
return null;
|
|
2947
|
+
}
|
|
2948
|
+
function getUsedPorts(profiles) {
|
|
2949
|
+
if (!profiles) return /* @__PURE__ */ new Set();
|
|
2950
|
+
const used = /* @__PURE__ */ new Set();
|
|
2951
|
+
for (const profile of Object.values(profiles)) {
|
|
2952
|
+
if (typeof profile.cdpPort === "number") {
|
|
2953
|
+
used.add(profile.cdpPort);
|
|
2954
|
+
continue;
|
|
2955
|
+
}
|
|
2956
|
+
const rawUrl = profile.cdpUrl?.trim();
|
|
2957
|
+
if (!rawUrl) continue;
|
|
2958
|
+
try {
|
|
2959
|
+
const parsed = new URL(rawUrl);
|
|
2960
|
+
const port = parsed.port && Number.parseInt(parsed.port, 10) > 0 ? Number.parseInt(parsed.port, 10) : parsed.protocol === "https:" ? 443 : 80;
|
|
2961
|
+
if (!Number.isNaN(port) && port > 0 && port <= 65535) used.add(port);
|
|
2962
|
+
} catch {}
|
|
2963
|
+
}
|
|
2964
|
+
return used;
|
|
2965
|
+
}
|
|
2966
|
+
const PROFILE_COLORS = [
|
|
2967
|
+
"#FF4500",
|
|
2968
|
+
"#0066CC",
|
|
2969
|
+
"#00AA00",
|
|
2970
|
+
"#9933FF",
|
|
2971
|
+
"#FF6699",
|
|
2972
|
+
"#00CCCC",
|
|
2973
|
+
"#FF9900",
|
|
2974
|
+
"#6666FF",
|
|
2975
|
+
"#CC3366",
|
|
2976
|
+
"#339966"
|
|
2977
|
+
];
|
|
2978
|
+
function allocateColor(usedColors) {
|
|
2979
|
+
for (const color of PROFILE_COLORS) if (!usedColors.has(color.toUpperCase())) return color;
|
|
2980
|
+
return PROFILE_COLORS[usedColors.size % PROFILE_COLORS.length] ?? PROFILE_COLORS[0];
|
|
2981
|
+
}
|
|
2982
|
+
function getUsedColors(profiles) {
|
|
2983
|
+
if (!profiles) return /* @__PURE__ */ new Set();
|
|
2984
|
+
return new Set(Object.values(profiles).map((p) => p.color.toUpperCase()));
|
|
2985
|
+
}
|
|
2986
|
+
//#endregion
|
|
2987
|
+
//#region extensions/browser/src/browser/trash.ts
|
|
2988
|
+
async function movePathToTrash(targetPath) {
|
|
2989
|
+
try {
|
|
2990
|
+
await runExec("trash", [targetPath], { timeoutMs: 1e4 });
|
|
2991
|
+
return targetPath;
|
|
2992
|
+
} catch {
|
|
2993
|
+
const trashDir = path.join(os.homedir(), ".Trash");
|
|
2994
|
+
fs.mkdirSync(trashDir, { recursive: true });
|
|
2995
|
+
const base = path.basename(targetPath);
|
|
2996
|
+
let dest = path.join(trashDir, `${base}-${Date.now()}`);
|
|
2997
|
+
if (fs.existsSync(dest)) dest = path.join(trashDir, `${base}-${Date.now()}-${generateSecureToken(6)}`);
|
|
2998
|
+
fs.renameSync(targetPath, dest);
|
|
2999
|
+
return dest;
|
|
3000
|
+
}
|
|
3001
|
+
}
|
|
3002
|
+
//#endregion
|
|
3003
|
+
//#region extensions/browser/src/browser/profiles-service.ts
|
|
3004
|
+
const HEX_COLOR_RE = /^#[0-9A-Fa-f]{6}$/;
|
|
3005
|
+
const cdpPortRange = (resolved) => {
|
|
3006
|
+
const start = resolved.cdpPortRangeStart;
|
|
3007
|
+
const end = resolved.cdpPortRangeEnd;
|
|
3008
|
+
if (typeof start === "number" && Number.isFinite(start) && Number.isInteger(start) && typeof end === "number" && Number.isFinite(end) && Number.isInteger(end) && start > 0 && end >= start && end <= 65535) return {
|
|
3009
|
+
start,
|
|
3010
|
+
end
|
|
3011
|
+
};
|
|
3012
|
+
return deriveDefaultBrowserCdpPortRange(resolved.controlPort);
|
|
3013
|
+
};
|
|
3014
|
+
function createBrowserProfilesService(ctx) {
|
|
3015
|
+
const listProfiles = async () => {
|
|
3016
|
+
return await ctx.listProfiles();
|
|
3017
|
+
};
|
|
3018
|
+
const createProfile = async (params) => {
|
|
3019
|
+
const name = params.name.trim();
|
|
3020
|
+
const rawCdpUrl = normalizeOptionalString(params.cdpUrl);
|
|
3021
|
+
const rawUserDataDir = normalizeOptionalString(params.userDataDir);
|
|
3022
|
+
const normalizedUserDataDir = rawUserDataDir ? resolveUserPath(rawUserDataDir) : void 0;
|
|
3023
|
+
const driver = params.driver === "existing-session" ? "existing-session" : void 0;
|
|
3024
|
+
if (!isValidProfileName(name)) throw new BrowserValidationError("invalid profile name: use lowercase letters, numbers, and hyphens only");
|
|
3025
|
+
const state = ctx.state();
|
|
3026
|
+
const resolvedProfiles = state.resolved.profiles;
|
|
3027
|
+
if (name in resolvedProfiles) throw new BrowserConflictError(`profile "${name}" already exists`);
|
|
3028
|
+
const cfg = loadConfig();
|
|
3029
|
+
const rawProfiles = cfg.browser?.profiles ?? {};
|
|
3030
|
+
if (name in rawProfiles) throw new BrowserConflictError(`profile "${name}" already exists`);
|
|
3031
|
+
const usedColors = getUsedColors(resolvedProfiles);
|
|
3032
|
+
const profileColor = params.color && HEX_COLOR_RE.test(params.color) ? params.color : allocateColor(usedColors);
|
|
3033
|
+
let profileConfig;
|
|
3034
|
+
if (normalizedUserDataDir && driver !== "existing-session") throw new BrowserValidationError("driver=existing-session is required when userDataDir is provided");
|
|
3035
|
+
if (normalizedUserDataDir && !fs.existsSync(normalizedUserDataDir)) throw new BrowserValidationError(`browser user data directory not found: ${normalizedUserDataDir}`);
|
|
3036
|
+
if (rawCdpUrl) {
|
|
3037
|
+
let parsed;
|
|
3038
|
+
try {
|
|
3039
|
+
parsed = parseBrowserHttpUrl(rawCdpUrl, "browser.profiles.cdpUrl");
|
|
3040
|
+
await assertCdpEndpointAllowed(parsed.normalized, state.resolved.ssrfPolicy);
|
|
3041
|
+
} catch (err) {
|
|
3042
|
+
throw new BrowserValidationError(formatErrorMessage(err));
|
|
3043
|
+
}
|
|
3044
|
+
if (driver === "existing-session") throw new BrowserValidationError("driver=existing-session does not accept cdpUrl; it attaches via the Chrome MCP auto-connect flow");
|
|
3045
|
+
profileConfig = {
|
|
3046
|
+
cdpUrl: parsed.normalized,
|
|
3047
|
+
...driver ? { driver } : {},
|
|
3048
|
+
color: profileColor
|
|
3049
|
+
};
|
|
3050
|
+
} else if (driver === "existing-session") profileConfig = {
|
|
3051
|
+
driver,
|
|
3052
|
+
attachOnly: true,
|
|
3053
|
+
...normalizedUserDataDir ? { userDataDir: normalizedUserDataDir } : {},
|
|
3054
|
+
color: profileColor
|
|
3055
|
+
};
|
|
3056
|
+
else {
|
|
3057
|
+
const cdpPort = allocateCdpPort(getUsedPorts(resolvedProfiles), cdpPortRange(state.resolved));
|
|
3058
|
+
if (cdpPort === null) throw new BrowserResourceExhaustedError("no available CDP ports in range");
|
|
3059
|
+
profileConfig = {
|
|
3060
|
+
cdpPort,
|
|
3061
|
+
...driver ? { driver } : {},
|
|
3062
|
+
color: profileColor
|
|
3063
|
+
};
|
|
3064
|
+
}
|
|
3065
|
+
await writeConfigFile({
|
|
3066
|
+
...cfg,
|
|
3067
|
+
browser: {
|
|
3068
|
+
...cfg.browser,
|
|
3069
|
+
profiles: {
|
|
3070
|
+
...rawProfiles,
|
|
3071
|
+
[name]: profileConfig
|
|
3072
|
+
}
|
|
3073
|
+
}
|
|
3074
|
+
});
|
|
3075
|
+
state.resolved.profiles[name] = profileConfig;
|
|
3076
|
+
const resolved = resolveProfile(state.resolved, name);
|
|
3077
|
+
if (!resolved) throw new BrowserProfileNotFoundError(`profile "${name}" not found after creation`);
|
|
3078
|
+
const capabilities = getBrowserProfileCapabilities(resolved);
|
|
3079
|
+
return {
|
|
3080
|
+
ok: true,
|
|
3081
|
+
profile: name,
|
|
3082
|
+
transport: capabilities.usesChromeMcp ? "chrome-mcp" : "cdp",
|
|
3083
|
+
cdpPort: capabilities.usesChromeMcp ? null : resolved.cdpPort,
|
|
3084
|
+
cdpUrl: capabilities.usesChromeMcp ? null : resolved.cdpUrl,
|
|
3085
|
+
userDataDir: resolved.userDataDir ?? null,
|
|
3086
|
+
color: resolved.color,
|
|
3087
|
+
isRemote: !resolved.cdpIsLoopback
|
|
3088
|
+
};
|
|
3089
|
+
};
|
|
3090
|
+
const deleteProfile = async (nameRaw) => {
|
|
3091
|
+
const name = nameRaw.trim();
|
|
3092
|
+
if (!name) throw new BrowserValidationError("profile name is required");
|
|
3093
|
+
if (!isValidProfileName(name)) throw new BrowserValidationError("invalid profile name");
|
|
3094
|
+
const state = ctx.state();
|
|
3095
|
+
const cfg = loadConfig();
|
|
3096
|
+
const profiles = cfg.browser?.profiles ?? {};
|
|
3097
|
+
if (name === (cfg.browser?.defaultProfile ?? state.resolved.defaultProfile)) throw new BrowserValidationError(`cannot delete the default profile "${name}"; change browser.defaultProfile first`);
|
|
3098
|
+
if (!(name in profiles)) throw new BrowserProfileNotFoundError(`profile "${name}" not found`);
|
|
3099
|
+
let deleted = false;
|
|
3100
|
+
const resolved = resolveProfile(state.resolved, name);
|
|
3101
|
+
if (resolved?.cdpIsLoopback && resolved.driver === "kaijibot") {
|
|
3102
|
+
try {
|
|
3103
|
+
await ctx.forProfile(name).stopRunningBrowser();
|
|
3104
|
+
} catch {}
|
|
3105
|
+
const userDataDir = resolveKaijiBotUserDataDir(name);
|
|
3106
|
+
const profileDir = path.dirname(userDataDir);
|
|
3107
|
+
if (fs.existsSync(profileDir)) {
|
|
3108
|
+
await movePathToTrash(profileDir);
|
|
3109
|
+
deleted = true;
|
|
3110
|
+
}
|
|
3111
|
+
}
|
|
3112
|
+
const { [name]: _removed, ...remainingProfiles } = profiles;
|
|
3113
|
+
await writeConfigFile({
|
|
3114
|
+
...cfg,
|
|
3115
|
+
browser: {
|
|
3116
|
+
...cfg.browser,
|
|
3117
|
+
profiles: remainingProfiles
|
|
3118
|
+
}
|
|
3119
|
+
});
|
|
3120
|
+
delete state.resolved.profiles[name];
|
|
3121
|
+
state.profiles.delete(name);
|
|
3122
|
+
return {
|
|
3123
|
+
ok: true,
|
|
3124
|
+
profile: name,
|
|
3125
|
+
deleted
|
|
3126
|
+
};
|
|
3127
|
+
};
|
|
3128
|
+
return {
|
|
3129
|
+
listProfiles,
|
|
3130
|
+
createProfile,
|
|
3131
|
+
deleteProfile
|
|
3132
|
+
};
|
|
3133
|
+
}
|
|
3134
|
+
//#endregion
|
|
3135
|
+
//#region extensions/browser/src/browser/routes/basic.ts
|
|
3136
|
+
function handleBrowserRouteError(res, err) {
|
|
3137
|
+
const mapped = toBrowserErrorResponse(err);
|
|
3138
|
+
if (mapped) return jsonError(res, mapped.status, mapped.message);
|
|
3139
|
+
jsonError(res, 500, String(err));
|
|
3140
|
+
}
|
|
3141
|
+
async function withBasicProfileRoute(params) {
|
|
3142
|
+
const profileCtx = resolveProfileContext(params.req, params.res, params.ctx);
|
|
3143
|
+
if (!profileCtx) return;
|
|
3144
|
+
try {
|
|
3145
|
+
await params.run(profileCtx);
|
|
3146
|
+
} catch (err) {
|
|
3147
|
+
return handleBrowserRouteError(params.res, err);
|
|
3148
|
+
}
|
|
3149
|
+
}
|
|
3150
|
+
async function withProfilesServiceMutation(params) {
|
|
3151
|
+
try {
|
|
3152
|
+
const service = createBrowserProfilesService(params.ctx);
|
|
3153
|
+
const result = await params.run(service);
|
|
3154
|
+
params.res.json(result);
|
|
3155
|
+
} catch (err) {
|
|
3156
|
+
return handleBrowserRouteError(params.res, err);
|
|
3157
|
+
}
|
|
3158
|
+
}
|
|
3159
|
+
function registerBrowserBasicRoutes(app, ctx) {
|
|
3160
|
+
app.get("/profiles", async (_req, res) => {
|
|
3161
|
+
try {
|
|
3162
|
+
const profiles = await createBrowserProfilesService(ctx).listProfiles();
|
|
3163
|
+
res.json({ profiles });
|
|
3164
|
+
} catch (err) {
|
|
3165
|
+
jsonError(res, 500, String(err));
|
|
3166
|
+
}
|
|
3167
|
+
});
|
|
3168
|
+
app.get("/", async (req, res) => {
|
|
3169
|
+
let current;
|
|
3170
|
+
try {
|
|
3171
|
+
current = ctx.state();
|
|
3172
|
+
} catch {
|
|
3173
|
+
return jsonError(res, 503, "browser server not started");
|
|
3174
|
+
}
|
|
3175
|
+
const profileCtx = getProfileContext(req, ctx);
|
|
3176
|
+
if ("error" in profileCtx) return jsonError(res, profileCtx.status, profileCtx.error);
|
|
3177
|
+
try {
|
|
3178
|
+
const [cdpHttp, cdpReady] = await Promise.all([profileCtx.isHttpReachable(300), profileCtx.isReachable(600)]);
|
|
3179
|
+
const profileState = current.profiles.get(profileCtx.profile.name);
|
|
3180
|
+
const capabilities = getBrowserProfileCapabilities(profileCtx.profile);
|
|
3181
|
+
let detectedBrowser = null;
|
|
3182
|
+
let detectedExecutablePath = null;
|
|
3183
|
+
let detectError = null;
|
|
3184
|
+
try {
|
|
3185
|
+
const detected = resolveBrowserExecutableForPlatform(current.resolved, process.platform);
|
|
3186
|
+
if (detected) {
|
|
3187
|
+
detectedBrowser = detected.kind;
|
|
3188
|
+
detectedExecutablePath = detected.path;
|
|
3189
|
+
}
|
|
3190
|
+
} catch (err) {
|
|
3191
|
+
detectError = String(err);
|
|
3192
|
+
}
|
|
3193
|
+
res.json({
|
|
3194
|
+
enabled: current.resolved.enabled,
|
|
3195
|
+
profile: profileCtx.profile.name,
|
|
3196
|
+
driver: profileCtx.profile.driver,
|
|
3197
|
+
transport: capabilities.usesChromeMcp ? "chrome-mcp" : "cdp",
|
|
3198
|
+
running: cdpReady,
|
|
3199
|
+
cdpReady,
|
|
3200
|
+
cdpHttp,
|
|
3201
|
+
pid: capabilities.usesChromeMcp ? getChromeMcpPid(profileCtx.profile.name) : profileState?.running?.pid ?? null,
|
|
3202
|
+
cdpPort: capabilities.usesChromeMcp ? null : profileCtx.profile.cdpPort,
|
|
3203
|
+
cdpUrl: capabilities.usesChromeMcp ? null : profileCtx.profile.cdpUrl,
|
|
3204
|
+
chosenBrowser: profileState?.running?.exe.kind ?? null,
|
|
3205
|
+
detectedBrowser,
|
|
3206
|
+
detectedExecutablePath,
|
|
3207
|
+
detectError,
|
|
3208
|
+
userDataDir: profileState?.running?.userDataDir ?? profileCtx.profile.userDataDir ?? null,
|
|
3209
|
+
color: profileCtx.profile.color,
|
|
3210
|
+
headless: current.resolved.headless,
|
|
3211
|
+
noSandbox: current.resolved.noSandbox,
|
|
3212
|
+
executablePath: current.resolved.executablePath ?? null,
|
|
3213
|
+
attachOnly: profileCtx.profile.attachOnly
|
|
3214
|
+
});
|
|
3215
|
+
} catch (err) {
|
|
3216
|
+
const mapped = toBrowserErrorResponse(err);
|
|
3217
|
+
if (mapped) return jsonError(res, mapped.status, mapped.message);
|
|
3218
|
+
jsonError(res, 500, String(err));
|
|
3219
|
+
}
|
|
3220
|
+
});
|
|
3221
|
+
app.post("/start", async (req, res) => {
|
|
3222
|
+
await withBasicProfileRoute({
|
|
3223
|
+
req,
|
|
3224
|
+
res,
|
|
3225
|
+
ctx,
|
|
3226
|
+
run: async (profileCtx) => {
|
|
3227
|
+
await profileCtx.ensureBrowserAvailable();
|
|
3228
|
+
res.json({
|
|
3229
|
+
ok: true,
|
|
3230
|
+
profile: profileCtx.profile.name
|
|
3231
|
+
});
|
|
3232
|
+
}
|
|
3233
|
+
});
|
|
3234
|
+
});
|
|
3235
|
+
app.post("/stop", async (req, res) => {
|
|
3236
|
+
await withBasicProfileRoute({
|
|
3237
|
+
req,
|
|
3238
|
+
res,
|
|
3239
|
+
ctx,
|
|
3240
|
+
run: async (profileCtx) => {
|
|
3241
|
+
const result = await profileCtx.stopRunningBrowser();
|
|
3242
|
+
res.json({
|
|
3243
|
+
ok: true,
|
|
3244
|
+
stopped: result.stopped,
|
|
3245
|
+
profile: profileCtx.profile.name
|
|
3246
|
+
});
|
|
3247
|
+
}
|
|
3248
|
+
});
|
|
3249
|
+
});
|
|
3250
|
+
app.post("/reset-profile", async (req, res) => {
|
|
3251
|
+
await withBasicProfileRoute({
|
|
3252
|
+
req,
|
|
3253
|
+
res,
|
|
3254
|
+
ctx,
|
|
3255
|
+
run: async (profileCtx) => {
|
|
3256
|
+
const result = await profileCtx.resetProfile();
|
|
3257
|
+
res.json({
|
|
3258
|
+
ok: true,
|
|
3259
|
+
profile: profileCtx.profile.name,
|
|
3260
|
+
...result
|
|
3261
|
+
});
|
|
3262
|
+
}
|
|
3263
|
+
});
|
|
3264
|
+
});
|
|
3265
|
+
app.post("/profiles/create", async (req, res) => {
|
|
3266
|
+
const name = toStringOrEmpty(req.body?.name);
|
|
3267
|
+
const color = toStringOrEmpty(req.body?.color);
|
|
3268
|
+
const cdpUrl = toStringOrEmpty(req.body?.cdpUrl);
|
|
3269
|
+
const userDataDir = toStringOrEmpty(req.body?.userDataDir);
|
|
3270
|
+
const driver = toStringOrEmpty(req.body?.driver);
|
|
3271
|
+
if (!name) return jsonError(res, 400, "name is required");
|
|
3272
|
+
if (driver && driver !== "kaijibot" && driver !== "clawd" && driver !== "existing-session") return jsonError(res, 400, `unsupported profile driver "${driver}"; use "kaijibot", "clawd", or "existing-session"`);
|
|
3273
|
+
await withProfilesServiceMutation({
|
|
3274
|
+
res,
|
|
3275
|
+
ctx,
|
|
3276
|
+
run: async (service) => await service.createProfile({
|
|
3277
|
+
name,
|
|
3278
|
+
color: color || void 0,
|
|
3279
|
+
cdpUrl: cdpUrl || void 0,
|
|
3280
|
+
userDataDir: userDataDir || void 0,
|
|
3281
|
+
driver: driver === "existing-session" ? "existing-session" : driver === "kaijibot" || driver === "clawd" ? "kaijibot" : void 0
|
|
3282
|
+
})
|
|
3283
|
+
});
|
|
3284
|
+
});
|
|
3285
|
+
app.delete("/profiles/:name", async (req, res) => {
|
|
3286
|
+
const name = toStringOrEmpty(req.params.name);
|
|
3287
|
+
if (!name) return jsonError(res, 400, "profile name is required");
|
|
3288
|
+
await withProfilesServiceMutation({
|
|
3289
|
+
res,
|
|
3290
|
+
ctx,
|
|
3291
|
+
run: async (service) => await service.deleteProfile(name)
|
|
3292
|
+
});
|
|
3293
|
+
});
|
|
3294
|
+
}
|
|
3295
|
+
//#endregion
|
|
3296
|
+
//#region extensions/browser/src/browser/routes/tabs.ts
|
|
3297
|
+
function resolveTabsProfileContext(req, res, ctx) {
|
|
3298
|
+
const profileCtx = getProfileContext(req, ctx);
|
|
3299
|
+
if ("error" in profileCtx) {
|
|
3300
|
+
jsonError(res, profileCtx.status, profileCtx.error);
|
|
3301
|
+
return null;
|
|
3302
|
+
}
|
|
3303
|
+
return profileCtx;
|
|
3304
|
+
}
|
|
3305
|
+
function handleTabsRouteError(ctx, res, err, opts) {
|
|
3306
|
+
if (opts?.mapTabError) {
|
|
3307
|
+
const mapped = ctx.mapTabError(err);
|
|
3308
|
+
if (mapped) return jsonError(res, mapped.status, mapped.message);
|
|
3309
|
+
}
|
|
3310
|
+
return jsonError(res, 500, String(err));
|
|
3311
|
+
}
|
|
3312
|
+
async function withTabsProfileRoute(params) {
|
|
3313
|
+
const profileCtx = resolveTabsProfileContext(params.req, params.res, params.ctx);
|
|
3314
|
+
if (!profileCtx) return;
|
|
3315
|
+
try {
|
|
3316
|
+
await params.run(profileCtx);
|
|
3317
|
+
} catch (err) {
|
|
3318
|
+
handleTabsRouteError(params.ctx, params.res, err, { mapTabError: params.mapTabError });
|
|
3319
|
+
}
|
|
3320
|
+
}
|
|
3321
|
+
async function ensureBrowserRunning(profileCtx, res) {
|
|
3322
|
+
if (!await profileCtx.isReachable(300)) {
|
|
3323
|
+
jsonError(res, new BrowserProfileUnavailableError("browser not running").status, "browser not running");
|
|
3324
|
+
return false;
|
|
3325
|
+
}
|
|
3326
|
+
return true;
|
|
3327
|
+
}
|
|
3328
|
+
function resolveIndexedTab(tabs, index) {
|
|
3329
|
+
return typeof index === "number" ? tabs[index] : tabs.at(0);
|
|
3330
|
+
}
|
|
3331
|
+
function parseRequiredTargetId(res, rawTargetId) {
|
|
3332
|
+
const targetId = toStringOrEmpty(rawTargetId);
|
|
3333
|
+
if (!targetId) {
|
|
3334
|
+
jsonError(res, 400, "targetId is required");
|
|
3335
|
+
return null;
|
|
3336
|
+
}
|
|
3337
|
+
return targetId;
|
|
3338
|
+
}
|
|
3339
|
+
async function runTabTargetMutation(params) {
|
|
3340
|
+
await withTabsProfileRoute({
|
|
3341
|
+
req: params.req,
|
|
3342
|
+
res: params.res,
|
|
3343
|
+
ctx: params.ctx,
|
|
3344
|
+
mapTabError: true,
|
|
3345
|
+
run: async (profileCtx) => {
|
|
3346
|
+
if (!await ensureBrowserRunning(profileCtx, params.res)) return;
|
|
3347
|
+
await params.mutate(profileCtx, params.targetId);
|
|
3348
|
+
params.res.json({ ok: true });
|
|
3349
|
+
}
|
|
3350
|
+
});
|
|
3351
|
+
}
|
|
3352
|
+
function registerBrowserTabRoutes(app, ctx) {
|
|
3353
|
+
app.get("/tabs", async (req, res) => {
|
|
3354
|
+
await withTabsProfileRoute({
|
|
3355
|
+
req,
|
|
3356
|
+
res,
|
|
3357
|
+
ctx,
|
|
3358
|
+
run: async (profileCtx) => {
|
|
3359
|
+
if (!await profileCtx.isReachable(300)) return res.json({
|
|
3360
|
+
running: false,
|
|
3361
|
+
tabs: []
|
|
3362
|
+
});
|
|
3363
|
+
const tabs = await profileCtx.listTabs();
|
|
3364
|
+
res.json({
|
|
3365
|
+
running: true,
|
|
3366
|
+
tabs
|
|
3367
|
+
});
|
|
3368
|
+
}
|
|
3369
|
+
});
|
|
3370
|
+
});
|
|
3371
|
+
app.post("/tabs/open", async (req, res) => {
|
|
3372
|
+
const url = toStringOrEmpty(req.body?.url);
|
|
3373
|
+
if (!url) return jsonError(res, 400, "url is required");
|
|
3374
|
+
await withTabsProfileRoute({
|
|
3375
|
+
req,
|
|
3376
|
+
res,
|
|
3377
|
+
ctx,
|
|
3378
|
+
mapTabError: true,
|
|
3379
|
+
run: async (profileCtx) => {
|
|
3380
|
+
await assertBrowserNavigationAllowed({
|
|
3381
|
+
url,
|
|
3382
|
+
...withBrowserNavigationPolicy(ctx.state().resolved.ssrfPolicy)
|
|
3383
|
+
});
|
|
3384
|
+
await profileCtx.ensureBrowserAvailable();
|
|
3385
|
+
const tab = await profileCtx.openTab(url);
|
|
3386
|
+
res.json(tab);
|
|
3387
|
+
}
|
|
3388
|
+
});
|
|
3389
|
+
});
|
|
3390
|
+
app.post("/tabs/focus", async (req, res) => {
|
|
3391
|
+
const targetId = parseRequiredTargetId(res, req.body?.targetId);
|
|
3392
|
+
if (!targetId) return;
|
|
3393
|
+
await runTabTargetMutation({
|
|
3394
|
+
req,
|
|
3395
|
+
res,
|
|
3396
|
+
ctx,
|
|
3397
|
+
targetId,
|
|
3398
|
+
mutate: async (profileCtx, id) => {
|
|
3399
|
+
await profileCtx.focusTab(id);
|
|
3400
|
+
}
|
|
3401
|
+
});
|
|
3402
|
+
});
|
|
3403
|
+
app.delete("/tabs/:targetId", async (req, res) => {
|
|
3404
|
+
const targetId = parseRequiredTargetId(res, req.params.targetId);
|
|
3405
|
+
if (!targetId) return;
|
|
3406
|
+
await runTabTargetMutation({
|
|
3407
|
+
req,
|
|
3408
|
+
res,
|
|
3409
|
+
ctx,
|
|
3410
|
+
targetId,
|
|
3411
|
+
mutate: async (profileCtx, id) => {
|
|
3412
|
+
await profileCtx.closeTab(id);
|
|
3413
|
+
}
|
|
3414
|
+
});
|
|
3415
|
+
});
|
|
3416
|
+
app.post("/tabs/action", async (req, res) => {
|
|
3417
|
+
const action = toStringOrEmpty(req.body?.action);
|
|
3418
|
+
const index = toNumber(req.body?.index);
|
|
3419
|
+
await withTabsProfileRoute({
|
|
3420
|
+
req,
|
|
3421
|
+
res,
|
|
3422
|
+
ctx,
|
|
3423
|
+
mapTabError: true,
|
|
3424
|
+
run: async (profileCtx) => {
|
|
3425
|
+
if (action === "list") {
|
|
3426
|
+
if (!await profileCtx.isReachable(300)) return res.json({
|
|
3427
|
+
ok: true,
|
|
3428
|
+
tabs: []
|
|
3429
|
+
});
|
|
3430
|
+
const tabs = await profileCtx.listTabs();
|
|
3431
|
+
return res.json({
|
|
3432
|
+
ok: true,
|
|
3433
|
+
tabs
|
|
3434
|
+
});
|
|
3435
|
+
}
|
|
3436
|
+
if (action === "new") {
|
|
3437
|
+
await profileCtx.ensureBrowserAvailable();
|
|
3438
|
+
const tab = await profileCtx.openTab("about:blank");
|
|
3439
|
+
return res.json({
|
|
3440
|
+
ok: true,
|
|
3441
|
+
tab
|
|
3442
|
+
});
|
|
3443
|
+
}
|
|
3444
|
+
if (action === "close") {
|
|
3445
|
+
const target = resolveIndexedTab(await profileCtx.listTabs(), index);
|
|
3446
|
+
if (!target) throw new BrowserTabNotFoundError();
|
|
3447
|
+
await profileCtx.closeTab(target.targetId);
|
|
3448
|
+
return res.json({
|
|
3449
|
+
ok: true,
|
|
3450
|
+
targetId: target.targetId
|
|
3451
|
+
});
|
|
3452
|
+
}
|
|
3453
|
+
if (action === "select") {
|
|
3454
|
+
if (typeof index !== "number") return jsonError(res, 400, "index is required");
|
|
3455
|
+
const target = (await profileCtx.listTabs())[index];
|
|
3456
|
+
if (!target) throw new BrowserTabNotFoundError();
|
|
3457
|
+
await profileCtx.focusTab(target.targetId);
|
|
3458
|
+
return res.json({
|
|
3459
|
+
ok: true,
|
|
3460
|
+
targetId: target.targetId
|
|
3461
|
+
});
|
|
3462
|
+
}
|
|
3463
|
+
return jsonError(res, 400, "unknown tab action");
|
|
3464
|
+
}
|
|
3465
|
+
});
|
|
3466
|
+
});
|
|
3467
|
+
}
|
|
3468
|
+
//#endregion
|
|
3469
|
+
//#region extensions/browser/src/browser/routes/index.ts
|
|
3470
|
+
function registerBrowserRoutes(app, ctx) {
|
|
3471
|
+
registerBrowserBasicRoutes(app, ctx);
|
|
3472
|
+
registerBrowserTabRoutes(app, ctx);
|
|
3473
|
+
registerBrowserAgentRoutes(app, ctx);
|
|
3474
|
+
}
|
|
3475
|
+
//#endregion
|
|
3476
|
+
//#region extensions/browser/src/browser/config-refresh-source.ts
|
|
3477
|
+
function loadBrowserConfigForRuntimeRefresh() {
|
|
3478
|
+
return getRuntimeConfigSnapshot() ?? createConfigIO().loadConfig();
|
|
3479
|
+
}
|
|
3480
|
+
//#endregion
|
|
3481
|
+
//#region extensions/browser/src/browser/resolved-config-refresh.ts
|
|
3482
|
+
function changedProfileInvariants(current, next) {
|
|
3483
|
+
const changed = [];
|
|
3484
|
+
if (current.cdpUrl !== next.cdpUrl) changed.push("cdpUrl");
|
|
3485
|
+
if (current.cdpPort !== next.cdpPort) changed.push("cdpPort");
|
|
3486
|
+
if (current.driver !== next.driver) changed.push("driver");
|
|
3487
|
+
if (current.attachOnly !== next.attachOnly) changed.push("attachOnly");
|
|
3488
|
+
if (current.cdpIsLoopback !== next.cdpIsLoopback) changed.push("cdpIsLoopback");
|
|
3489
|
+
if ((current.userDataDir ?? "") !== (next.userDataDir ?? "")) changed.push("userDataDir");
|
|
3490
|
+
return changed;
|
|
3491
|
+
}
|
|
3492
|
+
function applyResolvedConfig(current, freshResolved) {
|
|
3493
|
+
current.resolved = {
|
|
3494
|
+
...freshResolved,
|
|
3495
|
+
evaluateEnabled: current.resolved.evaluateEnabled
|
|
3496
|
+
};
|
|
3497
|
+
for (const [name, runtime] of current.profiles) {
|
|
3498
|
+
const nextProfile = resolveProfile(freshResolved, name);
|
|
3499
|
+
if (nextProfile) {
|
|
3500
|
+
const changed = changedProfileInvariants(runtime.profile, nextProfile);
|
|
3501
|
+
if (changed.length > 0) {
|
|
3502
|
+
runtime.reconcile = {
|
|
3503
|
+
previousProfile: runtime.profile,
|
|
3504
|
+
reason: `profile invariants changed: ${changed.join(", ")}`
|
|
3505
|
+
};
|
|
3506
|
+
runtime.lastTargetId = null;
|
|
3507
|
+
}
|
|
3508
|
+
runtime.profile = nextProfile;
|
|
3509
|
+
continue;
|
|
3510
|
+
}
|
|
3511
|
+
runtime.reconcile = {
|
|
3512
|
+
previousProfile: runtime.profile,
|
|
3513
|
+
reason: "profile removed from config"
|
|
3514
|
+
};
|
|
3515
|
+
runtime.lastTargetId = null;
|
|
3516
|
+
if (!runtime.running) current.profiles.delete(name);
|
|
3517
|
+
}
|
|
3518
|
+
}
|
|
3519
|
+
function refreshResolvedBrowserConfigFromDisk(params) {
|
|
3520
|
+
if (!params.refreshConfigFromDisk) return;
|
|
3521
|
+
const cfg = loadBrowserConfigForRuntimeRefresh();
|
|
3522
|
+
const freshResolved = resolveBrowserConfig(cfg.browser, cfg);
|
|
3523
|
+
applyResolvedConfig(params.current, freshResolved);
|
|
3524
|
+
}
|
|
3525
|
+
function resolveBrowserProfileWithHotReload(params) {
|
|
3526
|
+
refreshResolvedBrowserConfigFromDisk({
|
|
3527
|
+
current: params.current,
|
|
3528
|
+
refreshConfigFromDisk: params.refreshConfigFromDisk,
|
|
3529
|
+
mode: "cached"
|
|
3530
|
+
});
|
|
3531
|
+
let profile = resolveProfile(params.current.resolved, params.name);
|
|
3532
|
+
if (profile) return profile;
|
|
3533
|
+
refreshResolvedBrowserConfigFromDisk({
|
|
3534
|
+
current: params.current,
|
|
3535
|
+
refreshConfigFromDisk: params.refreshConfigFromDisk,
|
|
3536
|
+
mode: "fresh"
|
|
3537
|
+
});
|
|
3538
|
+
profile = resolveProfile(params.current.resolved, params.name);
|
|
3539
|
+
return profile;
|
|
3540
|
+
}
|
|
3541
|
+
//#endregion
|
|
3542
|
+
//#region extensions/browser/src/browser/server-context.constants.ts
|
|
3543
|
+
const OPEN_TAB_DISCOVERY_WINDOW_MS = 2e3;
|
|
3544
|
+
const CDP_READY_AFTER_LAUNCH_WINDOW_MS = 8e3;
|
|
3545
|
+
//#endregion
|
|
3546
|
+
//#region extensions/browser/src/browser/server-context.lifecycle.ts
|
|
3547
|
+
function resolveIdleProfileStopOutcome(profile) {
|
|
3548
|
+
const capabilities = getBrowserProfileCapabilities(profile);
|
|
3549
|
+
if (profile.attachOnly || capabilities.isRemote) return {
|
|
3550
|
+
stopped: true,
|
|
3551
|
+
closePlaywright: true
|
|
3552
|
+
};
|
|
3553
|
+
return {
|
|
3554
|
+
stopped: false,
|
|
3555
|
+
closePlaywright: false
|
|
3556
|
+
};
|
|
3557
|
+
}
|
|
3558
|
+
async function closePlaywrightBrowserConnectionForProfile$1(cdpUrl) {
|
|
3559
|
+
try {
|
|
3560
|
+
await (await import("./pw-ai-Ld88tf39.js")).closePlaywrightBrowserConnection(cdpUrl ? { cdpUrl } : void 0);
|
|
3561
|
+
} catch {}
|
|
3562
|
+
}
|
|
3563
|
+
//#endregion
|
|
3564
|
+
//#region extensions/browser/src/browser/server-context.availability.ts
|
|
3565
|
+
function createProfileAvailability({ opts, profile, state, getProfileState, setProfileRunning }) {
|
|
3566
|
+
const capabilities = getBrowserProfileCapabilities(profile);
|
|
3567
|
+
const resolveTimeouts = (timeoutMs) => resolveCdpReachabilityTimeouts({
|
|
3568
|
+
profileIsLoopback: profile.cdpIsLoopback,
|
|
3569
|
+
timeoutMs,
|
|
3570
|
+
remoteHttpTimeoutMs: state().resolved.remoteCdpTimeoutMs,
|
|
3571
|
+
remoteHandshakeTimeoutMs: state().resolved.remoteCdpHandshakeTimeoutMs
|
|
3572
|
+
});
|
|
3573
|
+
const isReachable = async (timeoutMs) => {
|
|
3574
|
+
if (capabilities.usesChromeMcp) {
|
|
3575
|
+
await listChromeMcpTabs(profile.name, profile.userDataDir);
|
|
3576
|
+
return true;
|
|
3577
|
+
}
|
|
3578
|
+
const { httpTimeoutMs, wsTimeoutMs } = resolveTimeouts(timeoutMs);
|
|
3579
|
+
return await isChromeCdpReady(profile.cdpUrl, httpTimeoutMs, wsTimeoutMs, state().resolved.ssrfPolicy);
|
|
3580
|
+
};
|
|
3581
|
+
const isHttpReachable = async (timeoutMs) => {
|
|
3582
|
+
if (capabilities.usesChromeMcp) return await isReachable(timeoutMs);
|
|
3583
|
+
const { httpTimeoutMs } = resolveTimeouts(timeoutMs);
|
|
3584
|
+
return await isChromeReachable(profile.cdpUrl, httpTimeoutMs, state().resolved.ssrfPolicy);
|
|
3585
|
+
};
|
|
3586
|
+
const attachRunning = (running) => {
|
|
3587
|
+
setProfileRunning(running);
|
|
3588
|
+
running.proc.on("exit", () => {
|
|
3589
|
+
if (!opts.getState()) return;
|
|
3590
|
+
if (getProfileState().running?.pid === running.pid) setProfileRunning(null);
|
|
3591
|
+
});
|
|
3592
|
+
};
|
|
3593
|
+
const reconcileProfileRuntime = async () => {
|
|
3594
|
+
const profileState = getProfileState();
|
|
3595
|
+
const reconcile = profileState.reconcile;
|
|
3596
|
+
if (!reconcile) return;
|
|
3597
|
+
profileState.reconcile = null;
|
|
3598
|
+
profileState.lastTargetId = null;
|
|
3599
|
+
const previousProfile = reconcile.previousProfile;
|
|
3600
|
+
if (profileState.running) {
|
|
3601
|
+
await stopKaijiBotChrome(profileState.running).catch(() => {});
|
|
3602
|
+
setProfileRunning(null);
|
|
3603
|
+
}
|
|
3604
|
+
if (getBrowserProfileCapabilities(previousProfile).usesChromeMcp) await closeChromeMcpSession(previousProfile.name).catch(() => false);
|
|
3605
|
+
await closePlaywrightBrowserConnectionForProfile$1(previousProfile.cdpUrl);
|
|
3606
|
+
if (previousProfile.cdpUrl !== profile.cdpUrl) await closePlaywrightBrowserConnectionForProfile$1(profile.cdpUrl);
|
|
3607
|
+
};
|
|
3608
|
+
const waitForCdpReadyAfterLaunch = async () => {
|
|
3609
|
+
const deadlineMs = Date.now() + CDP_READY_AFTER_LAUNCH_WINDOW_MS;
|
|
3610
|
+
while (Date.now() < deadlineMs) {
|
|
3611
|
+
const remainingMs = Math.max(0, deadlineMs - Date.now());
|
|
3612
|
+
if (await isReachable(Math.max(75, Math.min(250, remainingMs)))) return;
|
|
3613
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
3614
|
+
}
|
|
3615
|
+
throw new Error(`Chrome CDP websocket for profile "${profile.name}" is not reachable after start.`);
|
|
3616
|
+
};
|
|
3617
|
+
const waitForChromeMcpReadyAfterAttach = async () => {
|
|
3618
|
+
const deadlineMs = Date.now() + CHROME_MCP_ATTACH_READY_WINDOW_MS;
|
|
3619
|
+
let lastError;
|
|
3620
|
+
while (Date.now() < deadlineMs) {
|
|
3621
|
+
try {
|
|
3622
|
+
await listChromeMcpTabs(profile.name, profile.userDataDir);
|
|
3623
|
+
return;
|
|
3624
|
+
} catch (err) {
|
|
3625
|
+
lastError = err;
|
|
3626
|
+
}
|
|
3627
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
3628
|
+
}
|
|
3629
|
+
const detail = lastError instanceof Error ? ` Last error: ${lastError.message}` : "";
|
|
3630
|
+
throw new BrowserProfileUnavailableError(`Chrome MCP existing-session attach for profile "${profile.name}" timed out waiting for tabs to become available. Approve the browser attach prompt, keep the browser open, and retry.${detail}`);
|
|
3631
|
+
};
|
|
3632
|
+
const ensureBrowserAvailable = async () => {
|
|
3633
|
+
await reconcileProfileRuntime();
|
|
3634
|
+
if (capabilities.usesChromeMcp) {
|
|
3635
|
+
if (profile.userDataDir && !fs.existsSync(profile.userDataDir)) throw new BrowserProfileUnavailableError(`Browser user data directory not found for profile "${profile.name}": ${profile.userDataDir}`);
|
|
3636
|
+
await ensureChromeMcpAvailable(profile.name, profile.userDataDir);
|
|
3637
|
+
await waitForChromeMcpReadyAfterAttach();
|
|
3638
|
+
return;
|
|
3639
|
+
}
|
|
3640
|
+
const current = state();
|
|
3641
|
+
const remoteCdp = capabilities.isRemote;
|
|
3642
|
+
const attachOnly = profile.attachOnly;
|
|
3643
|
+
const profileState = getProfileState();
|
|
3644
|
+
if (!await isHttpReachable()) {
|
|
3645
|
+
if ((attachOnly || remoteCdp) && opts.onEnsureAttachTarget) {
|
|
3646
|
+
await opts.onEnsureAttachTarget(profile);
|
|
3647
|
+
if (await isHttpReachable(1200)) return;
|
|
3648
|
+
}
|
|
3649
|
+
if (!attachOnly && !remoteCdp && profile.cdpIsLoopback && !profileState.running) {
|
|
3650
|
+
if (await isHttpReachable(1200) && await isReachable(1200)) return;
|
|
3651
|
+
}
|
|
3652
|
+
if (attachOnly || remoteCdp) throw new BrowserProfileUnavailableError(remoteCdp ? `Remote CDP for profile "${profile.name}" is not reachable at ${profile.cdpUrl}.` : `Browser attachOnly is enabled and profile "${profile.name}" is not running.`);
|
|
3653
|
+
const launched = await launchKaijiBotChrome(current.resolved, profile);
|
|
3654
|
+
attachRunning(launched);
|
|
3655
|
+
try {
|
|
3656
|
+
await waitForCdpReadyAfterLaunch();
|
|
3657
|
+
} catch (err) {
|
|
3658
|
+
await stopKaijiBotChrome(launched).catch(() => {});
|
|
3659
|
+
setProfileRunning(null);
|
|
3660
|
+
throw err;
|
|
3661
|
+
}
|
|
3662
|
+
return;
|
|
3663
|
+
}
|
|
3664
|
+
if (await isReachable()) return;
|
|
3665
|
+
if (attachOnly || remoteCdp) {
|
|
3666
|
+
if (opts.onEnsureAttachTarget) {
|
|
3667
|
+
await opts.onEnsureAttachTarget(profile);
|
|
3668
|
+
if (await isReachable(1200)) return;
|
|
3669
|
+
}
|
|
3670
|
+
if (remoteCdp && await isReachable(1200)) return;
|
|
3671
|
+
throw new BrowserProfileUnavailableError(remoteCdp ? `Remote CDP websocket for profile "${profile.name}" is not reachable.` : `Browser attachOnly is enabled and CDP websocket for profile "${profile.name}" is not reachable.`);
|
|
3672
|
+
}
|
|
3673
|
+
if (!profileState.running) throw new BrowserProfileUnavailableError(`Port ${profile.cdpPort} is in use for profile "${profile.name}" but not by kaijibot. Run action=reset-profile profile=${profile.name} to kill the process.`);
|
|
3674
|
+
await stopKaijiBotChrome(profileState.running);
|
|
3675
|
+
setProfileRunning(null);
|
|
3676
|
+
attachRunning(await launchKaijiBotChrome(current.resolved, profile));
|
|
3677
|
+
if (!await isReachable(600)) throw new Error(`Chrome CDP websocket for profile "${profile.name}" is not reachable after restart.`);
|
|
3678
|
+
};
|
|
3679
|
+
const stopRunningBrowser = async () => {
|
|
3680
|
+
await reconcileProfileRuntime();
|
|
3681
|
+
if (capabilities.usesChromeMcp) return { stopped: await closeChromeMcpSession(profile.name) };
|
|
3682
|
+
const profileState = getProfileState();
|
|
3683
|
+
if (!profileState.running) {
|
|
3684
|
+
const idleStop = resolveIdleProfileStopOutcome(profile);
|
|
3685
|
+
if (idleStop.closePlaywright) await closePlaywrightBrowserConnectionForProfile$1(profile.cdpUrl);
|
|
3686
|
+
return { stopped: idleStop.stopped };
|
|
3687
|
+
}
|
|
3688
|
+
await stopKaijiBotChrome(profileState.running);
|
|
3689
|
+
setProfileRunning(null);
|
|
3690
|
+
return { stopped: true };
|
|
3691
|
+
};
|
|
3692
|
+
return {
|
|
3693
|
+
isHttpReachable,
|
|
3694
|
+
isReachable,
|
|
3695
|
+
ensureBrowserAvailable,
|
|
3696
|
+
stopRunningBrowser
|
|
3697
|
+
};
|
|
3698
|
+
}
|
|
3699
|
+
//#endregion
|
|
3700
|
+
//#region extensions/browser/src/browser/server-context.reset.ts
|
|
3701
|
+
async function closePlaywrightBrowserConnectionForProfile(cdpUrl) {
|
|
3702
|
+
try {
|
|
3703
|
+
await (await import("./pw-ai-Ld88tf39.js")).closePlaywrightBrowserConnection(cdpUrl ? { cdpUrl } : void 0);
|
|
3704
|
+
} catch {}
|
|
3705
|
+
}
|
|
3706
|
+
function createProfileResetOps({ profile, getProfileState, stopRunningBrowser, isHttpReachable, resolveKaijiBotUserDataDir }) {
|
|
3707
|
+
const capabilities = getBrowserProfileCapabilities(profile);
|
|
3708
|
+
const resetProfile = async () => {
|
|
3709
|
+
if (!capabilities.supportsReset) throw new BrowserResetUnsupportedError(`reset-profile is only supported for local profiles (profile "${profile.name}" is remote).`);
|
|
3710
|
+
const userDataDir = resolveKaijiBotUserDataDir(profile.name);
|
|
3711
|
+
const profileState = getProfileState();
|
|
3712
|
+
if (await isHttpReachable(300) && !profileState.running) await closePlaywrightBrowserConnectionForProfile(profile.cdpUrl);
|
|
3713
|
+
if (profileState.running) await stopRunningBrowser();
|
|
3714
|
+
await closePlaywrightBrowserConnectionForProfile(profile.cdpUrl);
|
|
3715
|
+
if (!fs.existsSync(userDataDir)) return {
|
|
3716
|
+
moved: false,
|
|
3717
|
+
from: userDataDir
|
|
3718
|
+
};
|
|
3719
|
+
return {
|
|
3720
|
+
moved: true,
|
|
3721
|
+
from: userDataDir,
|
|
3722
|
+
to: await movePathToTrash(userDataDir)
|
|
3723
|
+
};
|
|
3724
|
+
};
|
|
3725
|
+
return { resetProfile };
|
|
3726
|
+
}
|
|
3727
|
+
//#endregion
|
|
3728
|
+
//#region extensions/browser/src/browser/target-id.ts
|
|
3729
|
+
function resolveTargetIdFromTabs(input, tabs) {
|
|
3730
|
+
const needle = input.trim();
|
|
3731
|
+
if (!needle) return {
|
|
3732
|
+
ok: false,
|
|
3733
|
+
reason: "not_found"
|
|
3734
|
+
};
|
|
3735
|
+
const exact = tabs.find((t) => t.targetId === needle);
|
|
3736
|
+
if (exact) return {
|
|
3737
|
+
ok: true,
|
|
3738
|
+
targetId: exact.targetId
|
|
3739
|
+
};
|
|
3740
|
+
const lower = normalizeLowercaseStringOrEmpty(needle);
|
|
3741
|
+
const matches = tabs.map((t) => t.targetId).filter((id) => normalizeLowercaseStringOrEmpty(id).startsWith(lower));
|
|
3742
|
+
const only = matches.length === 1 ? matches[0] : void 0;
|
|
3743
|
+
if (only) return {
|
|
3744
|
+
ok: true,
|
|
3745
|
+
targetId: only
|
|
3746
|
+
};
|
|
3747
|
+
if (matches.length === 0) return {
|
|
3748
|
+
ok: false,
|
|
3749
|
+
reason: "not_found"
|
|
3750
|
+
};
|
|
3751
|
+
return {
|
|
3752
|
+
ok: false,
|
|
3753
|
+
reason: "ambiguous",
|
|
3754
|
+
matches
|
|
3755
|
+
};
|
|
3756
|
+
}
|
|
3757
|
+
//#endregion
|
|
3758
|
+
//#region extensions/browser/src/browser/server-context.selection.ts
|
|
3759
|
+
function createProfileSelectionOps({ profile, getProfileState, ensureBrowserAvailable, listTabs, openTab }) {
|
|
3760
|
+
const cdpHttpBase = normalizeCdpHttpBaseForJsonEndpoints(profile.cdpUrl);
|
|
3761
|
+
const capabilities = getBrowserProfileCapabilities(profile);
|
|
3762
|
+
const ensureTabAvailable = async (targetId) => {
|
|
3763
|
+
await ensureBrowserAvailable();
|
|
3764
|
+
const profileState = getProfileState();
|
|
3765
|
+
if ((await listTabs()).length === 0) await openTab("about:blank");
|
|
3766
|
+
const tabs = await listTabs();
|
|
3767
|
+
const candidates = capabilities.supportsPerTabWs ? tabs.filter((t) => Boolean(t.wsUrl)) : tabs;
|
|
3768
|
+
const resolveById = (raw) => {
|
|
3769
|
+
const resolved = resolveTargetIdFromTabs(raw, candidates);
|
|
3770
|
+
if (!resolved.ok) {
|
|
3771
|
+
if (resolved.reason === "ambiguous") return "AMBIGUOUS";
|
|
3772
|
+
return null;
|
|
3773
|
+
}
|
|
3774
|
+
return candidates.find((t) => t.targetId === resolved.targetId) ?? null;
|
|
3775
|
+
};
|
|
3776
|
+
const pickDefault = () => {
|
|
3777
|
+
const last = normalizeOptionalString(profileState.lastTargetId) ?? "";
|
|
3778
|
+
const lastResolved = last ? resolveById(last) : null;
|
|
3779
|
+
if (lastResolved && lastResolved !== "AMBIGUOUS") return lastResolved;
|
|
3780
|
+
return candidates.find((t) => (t.type ?? "page") === "page") ?? candidates.at(0) ?? null;
|
|
3781
|
+
};
|
|
3782
|
+
const chosen = targetId ? resolveById(targetId) : pickDefault();
|
|
3783
|
+
if (chosen === "AMBIGUOUS") throw new BrowserTargetAmbiguousError();
|
|
3784
|
+
if (!chosen) throw new BrowserTabNotFoundError();
|
|
3785
|
+
profileState.lastTargetId = chosen.targetId;
|
|
3786
|
+
return chosen;
|
|
3787
|
+
};
|
|
3788
|
+
const resolveTargetIdOrThrow = async (targetId) => {
|
|
3789
|
+
const resolved = resolveTargetIdFromTabs(targetId, await listTabs());
|
|
3790
|
+
if (!resolved.ok) {
|
|
3791
|
+
if (resolved.reason === "ambiguous") throw new BrowserTargetAmbiguousError();
|
|
3792
|
+
throw new BrowserTabNotFoundError();
|
|
3793
|
+
}
|
|
3794
|
+
return resolved.targetId;
|
|
3795
|
+
};
|
|
3796
|
+
const focusTab = async (targetId) => {
|
|
3797
|
+
const resolvedTargetId = await resolveTargetIdOrThrow(targetId);
|
|
3798
|
+
if (capabilities.usesChromeMcp) {
|
|
3799
|
+
await focusChromeMcpTab(profile.name, resolvedTargetId, profile.userDataDir);
|
|
3800
|
+
const profileState = getProfileState();
|
|
3801
|
+
profileState.lastTargetId = resolvedTargetId;
|
|
3802
|
+
return;
|
|
3803
|
+
}
|
|
3804
|
+
if (capabilities.usesPersistentPlaywright) {
|
|
3805
|
+
const focusPageByTargetIdViaPlaywright = (await getPwAiModule$1({ mode: "strict" }))?.focusPageByTargetIdViaPlaywright;
|
|
3806
|
+
if (typeof focusPageByTargetIdViaPlaywright === "function") {
|
|
3807
|
+
await focusPageByTargetIdViaPlaywright({
|
|
3808
|
+
cdpUrl: profile.cdpUrl,
|
|
3809
|
+
targetId: resolvedTargetId
|
|
3810
|
+
});
|
|
3811
|
+
const profileState = getProfileState();
|
|
3812
|
+
profileState.lastTargetId = resolvedTargetId;
|
|
3813
|
+
return;
|
|
3814
|
+
}
|
|
3815
|
+
}
|
|
3816
|
+
await fetchOk(appendCdpPath(cdpHttpBase, `/json/activate/${resolvedTargetId}`));
|
|
3817
|
+
const profileState = getProfileState();
|
|
3818
|
+
profileState.lastTargetId = resolvedTargetId;
|
|
3819
|
+
};
|
|
3820
|
+
const closeTab = async (targetId) => {
|
|
3821
|
+
const resolvedTargetId = await resolveTargetIdOrThrow(targetId);
|
|
3822
|
+
if (capabilities.usesChromeMcp) {
|
|
3823
|
+
await closeChromeMcpTab(profile.name, resolvedTargetId, profile.userDataDir);
|
|
3824
|
+
return;
|
|
3825
|
+
}
|
|
3826
|
+
if (capabilities.usesPersistentPlaywright) {
|
|
3827
|
+
const closePageByTargetIdViaPlaywright = (await getPwAiModule$1({ mode: "strict" }))?.closePageByTargetIdViaPlaywright;
|
|
3828
|
+
if (typeof closePageByTargetIdViaPlaywright === "function") {
|
|
3829
|
+
await closePageByTargetIdViaPlaywright({
|
|
3830
|
+
cdpUrl: profile.cdpUrl,
|
|
3831
|
+
targetId: resolvedTargetId
|
|
3832
|
+
});
|
|
3833
|
+
return;
|
|
3834
|
+
}
|
|
3835
|
+
}
|
|
3836
|
+
await fetchOk(appendCdpPath(cdpHttpBase, `/json/close/${resolvedTargetId}`));
|
|
3837
|
+
};
|
|
3838
|
+
return {
|
|
3839
|
+
ensureTabAvailable,
|
|
3840
|
+
focusTab,
|
|
3841
|
+
closeTab
|
|
3842
|
+
};
|
|
3843
|
+
}
|
|
3844
|
+
//#endregion
|
|
3845
|
+
//#region extensions/browser/src/browser/server-context.tab-ops.ts
|
|
3846
|
+
/**
|
|
3847
|
+
* Normalize a CDP WebSocket URL to use the correct base URL.
|
|
3848
|
+
*/
|
|
3849
|
+
function normalizeWsUrl(raw, cdpBaseUrl) {
|
|
3850
|
+
if (!raw) return;
|
|
3851
|
+
try {
|
|
3852
|
+
return normalizeCdpWsUrl(raw, cdpBaseUrl);
|
|
3853
|
+
} catch {
|
|
3854
|
+
return raw;
|
|
3855
|
+
}
|
|
3856
|
+
}
|
|
3857
|
+
function createProfileTabOps({ profile, state, getProfileState }) {
|
|
3858
|
+
const cdpHttpBase = normalizeCdpHttpBaseForJsonEndpoints(profile.cdpUrl);
|
|
3859
|
+
const capabilities = getBrowserProfileCapabilities(profile);
|
|
3860
|
+
const listTabs = async () => {
|
|
3861
|
+
if (capabilities.usesChromeMcp) return await listChromeMcpTabs(profile.name, profile.userDataDir);
|
|
3862
|
+
if (capabilities.usesPersistentPlaywright) {
|
|
3863
|
+
const listPagesViaPlaywright = (await getPwAiModule$1({ mode: "strict" }))?.listPagesViaPlaywright;
|
|
3864
|
+
if (typeof listPagesViaPlaywright === "function") return (await listPagesViaPlaywright({ cdpUrl: profile.cdpUrl })).map((p) => ({
|
|
3865
|
+
targetId: p.targetId,
|
|
3866
|
+
title: p.title,
|
|
3867
|
+
url: p.url,
|
|
3868
|
+
type: p.type
|
|
3869
|
+
}));
|
|
3870
|
+
}
|
|
3871
|
+
return (await fetchJson(appendCdpPath(cdpHttpBase, "/json/list"))).map((t) => ({
|
|
3872
|
+
targetId: t.id ?? "",
|
|
3873
|
+
title: t.title ?? "",
|
|
3874
|
+
url: t.url ?? "",
|
|
3875
|
+
wsUrl: normalizeWsUrl(t.webSocketDebuggerUrl, profile.cdpUrl),
|
|
3876
|
+
type: t.type
|
|
3877
|
+
})).filter((t) => Boolean(t.targetId));
|
|
3878
|
+
};
|
|
3879
|
+
const enforceManagedTabLimit = async (keepTargetId) => {
|
|
3880
|
+
const profileState = getProfileState();
|
|
3881
|
+
if (!capabilities.supportsManagedTabLimit || state().resolved.attachOnly || !profileState.running) return;
|
|
3882
|
+
const pageTabs = await listTabs().then((tabs) => tabs.filter((tab) => (tab.type ?? "page") === "page")).catch(() => []);
|
|
3883
|
+
if (pageTabs.length <= 8) return;
|
|
3884
|
+
const candidates = pageTabs.filter((tab) => tab.targetId !== keepTargetId);
|
|
3885
|
+
const excessCount = pageTabs.length - 8;
|
|
3886
|
+
for (const tab of candidates.slice(0, excessCount)) fetchOk(appendCdpPath(cdpHttpBase, `/json/close/${tab.targetId}`)).catch(() => {});
|
|
3887
|
+
};
|
|
3888
|
+
const triggerManagedTabLimit = (keepTargetId) => {
|
|
3889
|
+
enforceManagedTabLimit(keepTargetId).catch(() => {});
|
|
3890
|
+
};
|
|
3891
|
+
const openTab = async (url) => {
|
|
3892
|
+
const ssrfPolicyOpts = withBrowserNavigationPolicy(state().resolved.ssrfPolicy);
|
|
3893
|
+
if (capabilities.usesChromeMcp) {
|
|
3894
|
+
await assertBrowserNavigationAllowed({
|
|
3895
|
+
url,
|
|
3896
|
+
...ssrfPolicyOpts
|
|
3897
|
+
});
|
|
3898
|
+
const page = await openChromeMcpTab(profile.name, url, profile.userDataDir);
|
|
3899
|
+
const profileState = getProfileState();
|
|
3900
|
+
profileState.lastTargetId = page.targetId;
|
|
3901
|
+
await assertBrowserNavigationResultAllowed({
|
|
3902
|
+
url: page.url,
|
|
3903
|
+
...ssrfPolicyOpts
|
|
3904
|
+
});
|
|
3905
|
+
return page;
|
|
3906
|
+
}
|
|
3907
|
+
if (capabilities.usesPersistentPlaywright) {
|
|
3908
|
+
const createPageViaPlaywright = (await getPwAiModule$1({ mode: "strict" }))?.createPageViaPlaywright;
|
|
3909
|
+
if (typeof createPageViaPlaywright === "function") {
|
|
3910
|
+
const page = await createPageViaPlaywright({
|
|
3911
|
+
cdpUrl: profile.cdpUrl,
|
|
3912
|
+
url,
|
|
3913
|
+
...ssrfPolicyOpts
|
|
3914
|
+
});
|
|
3915
|
+
const profileState = getProfileState();
|
|
3916
|
+
profileState.lastTargetId = page.targetId;
|
|
3917
|
+
triggerManagedTabLimit(page.targetId);
|
|
3918
|
+
return {
|
|
3919
|
+
targetId: page.targetId,
|
|
3920
|
+
title: page.title,
|
|
3921
|
+
url: page.url,
|
|
3922
|
+
type: page.type
|
|
3923
|
+
};
|
|
3924
|
+
}
|
|
3925
|
+
}
|
|
3926
|
+
if (requiresInspectableBrowserNavigationRedirects(state().resolved.ssrfPolicy)) throw new InvalidBrowserNavigationUrlError("Navigation blocked: strict browser SSRF policy requires Playwright-backed redirect-hop inspection");
|
|
3927
|
+
const createdViaCdp = await createTargetViaCdp({
|
|
3928
|
+
cdpUrl: profile.cdpUrl,
|
|
3929
|
+
url,
|
|
3930
|
+
...ssrfPolicyOpts
|
|
3931
|
+
}).then((r) => r.targetId).catch(() => null);
|
|
3932
|
+
if (createdViaCdp) {
|
|
3933
|
+
const profileState = getProfileState();
|
|
3934
|
+
profileState.lastTargetId = createdViaCdp;
|
|
3935
|
+
const deadline = Date.now() + OPEN_TAB_DISCOVERY_WINDOW_MS;
|
|
3936
|
+
while (Date.now() < deadline) {
|
|
3937
|
+
const found = (await listTabs().catch(() => [])).find((t) => t.targetId === createdViaCdp);
|
|
3938
|
+
if (found) {
|
|
3939
|
+
await assertBrowserNavigationResultAllowed({
|
|
3940
|
+
url: found.url,
|
|
3941
|
+
...ssrfPolicyOpts
|
|
3942
|
+
});
|
|
3943
|
+
triggerManagedTabLimit(found.targetId);
|
|
3944
|
+
return found;
|
|
3945
|
+
}
|
|
3946
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
3947
|
+
}
|
|
3948
|
+
triggerManagedTabLimit(createdViaCdp);
|
|
3949
|
+
return {
|
|
3950
|
+
targetId: createdViaCdp,
|
|
3951
|
+
title: "",
|
|
3952
|
+
url,
|
|
3953
|
+
type: "page"
|
|
3954
|
+
};
|
|
3955
|
+
}
|
|
3956
|
+
const encoded = encodeURIComponent(url);
|
|
3957
|
+
const endpointUrl = new URL(appendCdpPath(cdpHttpBase, "/json/new"));
|
|
3958
|
+
await assertBrowserNavigationAllowed({
|
|
3959
|
+
url,
|
|
3960
|
+
...ssrfPolicyOpts
|
|
3961
|
+
});
|
|
3962
|
+
const endpoint = endpointUrl.search ? (() => {
|
|
3963
|
+
endpointUrl.searchParams.set("url", url);
|
|
3964
|
+
return endpointUrl.toString();
|
|
3965
|
+
})() : `${endpointUrl.toString()}?${encoded}`;
|
|
3966
|
+
const created = await fetchJson(endpoint, CDP_JSON_NEW_TIMEOUT_MS, { method: "PUT" }).catch(async (err) => {
|
|
3967
|
+
if (String(err).includes("HTTP 405")) return await fetchJson(endpoint, CDP_JSON_NEW_TIMEOUT_MS);
|
|
3968
|
+
throw err;
|
|
3969
|
+
});
|
|
3970
|
+
if (!created.id) throw new Error("Failed to open tab (missing id)");
|
|
3971
|
+
const profileState = getProfileState();
|
|
3972
|
+
profileState.lastTargetId = created.id;
|
|
3973
|
+
const resolvedUrl = created.url ?? url;
|
|
3974
|
+
await assertBrowserNavigationResultAllowed({
|
|
3975
|
+
url: resolvedUrl,
|
|
3976
|
+
...ssrfPolicyOpts
|
|
3977
|
+
});
|
|
3978
|
+
triggerManagedTabLimit(created.id);
|
|
3979
|
+
return {
|
|
3980
|
+
targetId: created.id,
|
|
3981
|
+
title: created.title ?? "",
|
|
3982
|
+
url: resolvedUrl,
|
|
3983
|
+
wsUrl: normalizeWsUrl(created.webSocketDebuggerUrl, profile.cdpUrl),
|
|
3984
|
+
type: created.type
|
|
3985
|
+
};
|
|
3986
|
+
};
|
|
3987
|
+
return {
|
|
3988
|
+
listTabs,
|
|
3989
|
+
openTab
|
|
3990
|
+
};
|
|
3991
|
+
}
|
|
3992
|
+
//#endregion
|
|
3993
|
+
//#region extensions/browser/src/browser/server-context.ts
|
|
3994
|
+
function listKnownProfileNames(state) {
|
|
3995
|
+
const names = new Set(Object.keys(state.resolved.profiles));
|
|
3996
|
+
for (const name of state.profiles.keys()) names.add(name);
|
|
3997
|
+
return [...names];
|
|
3998
|
+
}
|
|
3999
|
+
/**
|
|
4000
|
+
* Create a profile-scoped context for browser operations.
|
|
4001
|
+
*/
|
|
4002
|
+
function createProfileContext(opts, profile) {
|
|
4003
|
+
const state = () => {
|
|
4004
|
+
const current = opts.getState();
|
|
4005
|
+
if (!current) throw new Error("Browser server not started");
|
|
4006
|
+
return current;
|
|
4007
|
+
};
|
|
4008
|
+
const getProfileState = () => {
|
|
4009
|
+
const current = state();
|
|
4010
|
+
let profileState = current.profiles.get(profile.name);
|
|
4011
|
+
if (!profileState) {
|
|
4012
|
+
profileState = {
|
|
4013
|
+
profile,
|
|
4014
|
+
running: null,
|
|
4015
|
+
lastTargetId: null,
|
|
4016
|
+
reconcile: null
|
|
4017
|
+
};
|
|
4018
|
+
current.profiles.set(profile.name, profileState);
|
|
4019
|
+
}
|
|
4020
|
+
return profileState;
|
|
4021
|
+
};
|
|
4022
|
+
const setProfileRunning = (running) => {
|
|
4023
|
+
const profileState = getProfileState();
|
|
4024
|
+
profileState.running = running;
|
|
4025
|
+
};
|
|
4026
|
+
const { listTabs, openTab } = createProfileTabOps({
|
|
4027
|
+
profile,
|
|
4028
|
+
state,
|
|
4029
|
+
getProfileState
|
|
4030
|
+
});
|
|
4031
|
+
const { ensureBrowserAvailable, isHttpReachable, isReachable, stopRunningBrowser } = createProfileAvailability({
|
|
4032
|
+
opts,
|
|
4033
|
+
profile,
|
|
4034
|
+
state,
|
|
4035
|
+
getProfileState,
|
|
4036
|
+
setProfileRunning
|
|
4037
|
+
});
|
|
4038
|
+
const { ensureTabAvailable, focusTab, closeTab } = createProfileSelectionOps({
|
|
4039
|
+
profile,
|
|
4040
|
+
getProfileState,
|
|
4041
|
+
ensureBrowserAvailable,
|
|
4042
|
+
listTabs,
|
|
4043
|
+
openTab
|
|
4044
|
+
});
|
|
4045
|
+
const { resetProfile } = createProfileResetOps({
|
|
4046
|
+
profile,
|
|
4047
|
+
getProfileState,
|
|
4048
|
+
stopRunningBrowser,
|
|
4049
|
+
isHttpReachable,
|
|
4050
|
+
resolveKaijiBotUserDataDir
|
|
4051
|
+
});
|
|
4052
|
+
return {
|
|
4053
|
+
profile,
|
|
4054
|
+
ensureBrowserAvailable,
|
|
4055
|
+
ensureTabAvailable,
|
|
4056
|
+
isHttpReachable,
|
|
4057
|
+
isReachable,
|
|
4058
|
+
listTabs,
|
|
4059
|
+
openTab,
|
|
4060
|
+
focusTab,
|
|
4061
|
+
closeTab,
|
|
4062
|
+
stopRunningBrowser,
|
|
4063
|
+
resetProfile
|
|
4064
|
+
};
|
|
4065
|
+
}
|
|
4066
|
+
function createBrowserRouteContext(opts) {
|
|
4067
|
+
const refreshConfigFromDisk = opts.refreshConfigFromDisk === true;
|
|
4068
|
+
const state = () => {
|
|
4069
|
+
const current = opts.getState();
|
|
4070
|
+
if (!current) throw new Error("Browser server not started");
|
|
4071
|
+
return current;
|
|
4072
|
+
};
|
|
4073
|
+
const forProfile = (profileName) => {
|
|
4074
|
+
const current = state();
|
|
4075
|
+
const name = profileName ?? current.resolved.defaultProfile;
|
|
4076
|
+
const profile = resolveBrowserProfileWithHotReload({
|
|
4077
|
+
current,
|
|
4078
|
+
refreshConfigFromDisk,
|
|
4079
|
+
name
|
|
4080
|
+
});
|
|
4081
|
+
if (!profile) throw new BrowserProfileNotFoundError(`Profile "${name}" not found. Available profiles: ${Object.keys(current.resolved.profiles).join(", ") || "(none)"}`);
|
|
4082
|
+
return createProfileContext(opts, profile);
|
|
4083
|
+
};
|
|
4084
|
+
const listProfiles = async () => {
|
|
4085
|
+
const current = state();
|
|
4086
|
+
refreshResolvedBrowserConfigFromDisk({
|
|
4087
|
+
current,
|
|
4088
|
+
refreshConfigFromDisk,
|
|
4089
|
+
mode: "cached"
|
|
4090
|
+
});
|
|
4091
|
+
const result = [];
|
|
4092
|
+
for (const name of listKnownProfileNames(current)) {
|
|
4093
|
+
const profileState = current.profiles.get(name);
|
|
4094
|
+
const profile = resolveProfile(current.resolved, name) ?? profileState?.profile;
|
|
4095
|
+
if (!profile) continue;
|
|
4096
|
+
const capabilities = getBrowserProfileCapabilities(profile);
|
|
4097
|
+
let tabCount = 0;
|
|
4098
|
+
let running = false;
|
|
4099
|
+
const profileCtx = createProfileContext(opts, profile);
|
|
4100
|
+
if (capabilities.usesChromeMcp) try {
|
|
4101
|
+
running = await profileCtx.isReachable(300);
|
|
4102
|
+
if (running) tabCount = (await profileCtx.listTabs()).filter((t) => t.type === "page").length;
|
|
4103
|
+
} catch {}
|
|
4104
|
+
else if (profileState?.running) {
|
|
4105
|
+
running = true;
|
|
4106
|
+
try {
|
|
4107
|
+
tabCount = (await profileCtx.listTabs()).filter((t) => t.type === "page").length;
|
|
4108
|
+
} catch {}
|
|
4109
|
+
} else try {
|
|
4110
|
+
if (await isChromeReachable(profile.cdpUrl, 200, current.resolved.ssrfPolicy)) {
|
|
4111
|
+
running = true;
|
|
4112
|
+
tabCount = (await profileCtx.listTabs().catch(() => [])).filter((t) => t.type === "page").length;
|
|
4113
|
+
}
|
|
4114
|
+
} catch {}
|
|
4115
|
+
result.push({
|
|
4116
|
+
name,
|
|
4117
|
+
transport: capabilities.usesChromeMcp ? "chrome-mcp" : "cdp",
|
|
4118
|
+
cdpPort: capabilities.usesChromeMcp ? null : profile.cdpPort,
|
|
4119
|
+
cdpUrl: capabilities.usesChromeMcp ? null : profile.cdpUrl,
|
|
4120
|
+
color: profile.color,
|
|
4121
|
+
driver: profile.driver,
|
|
4122
|
+
running,
|
|
4123
|
+
tabCount,
|
|
4124
|
+
isDefault: name === current.resolved.defaultProfile,
|
|
4125
|
+
isRemote: !profile.cdpIsLoopback,
|
|
4126
|
+
missingFromConfig: !(name in current.resolved.profiles) || void 0,
|
|
4127
|
+
reconcileReason: profileState?.reconcile?.reason ?? null
|
|
4128
|
+
});
|
|
4129
|
+
}
|
|
4130
|
+
return result;
|
|
4131
|
+
};
|
|
4132
|
+
const getDefaultContext = () => forProfile();
|
|
4133
|
+
const mapTabError = (err) => {
|
|
4134
|
+
const browserMapped = toBrowserErrorResponse(err);
|
|
4135
|
+
if (browserMapped) return browserMapped;
|
|
4136
|
+
if (err instanceof SsrFBlockedError) return {
|
|
4137
|
+
status: 400,
|
|
4138
|
+
message: err.message
|
|
4139
|
+
};
|
|
4140
|
+
if (err instanceof InvalidBrowserNavigationUrlError) return {
|
|
4141
|
+
status: 400,
|
|
4142
|
+
message: err.message
|
|
4143
|
+
};
|
|
4144
|
+
return null;
|
|
4145
|
+
};
|
|
4146
|
+
return {
|
|
4147
|
+
state,
|
|
4148
|
+
forProfile,
|
|
4149
|
+
listProfiles,
|
|
4150
|
+
ensureBrowserAvailable: () => getDefaultContext().ensureBrowserAvailable(),
|
|
4151
|
+
ensureTabAvailable: (targetId) => getDefaultContext().ensureTabAvailable(targetId),
|
|
4152
|
+
isHttpReachable: (timeoutMs) => getDefaultContext().isHttpReachable(timeoutMs),
|
|
4153
|
+
isReachable: (timeoutMs) => getDefaultContext().isReachable(timeoutMs),
|
|
4154
|
+
listTabs: () => getDefaultContext().listTabs(),
|
|
4155
|
+
openTab: (url) => getDefaultContext().openTab(url),
|
|
4156
|
+
focusTab: (targetId) => getDefaultContext().focusTab(targetId),
|
|
4157
|
+
closeTab: (targetId) => getDefaultContext().closeTab(targetId),
|
|
4158
|
+
stopRunningBrowser: () => getDefaultContext().stopRunningBrowser(),
|
|
4159
|
+
resetProfile: () => getDefaultContext().resetProfile(),
|
|
4160
|
+
mapTabError
|
|
4161
|
+
};
|
|
4162
|
+
}
|
|
4163
|
+
//#endregion
|
|
4164
|
+
export { getBrowserProfileCapabilities as a, setBridgeAuthForPort as c, movePathToTrash as i, listKnownProfileNames as n, deleteBridgeAuthForPort as o, registerBrowserRoutes as r, getBridgeAuthForPort as s, createBrowserRouteContext as t };
|