@vellumai/assistant 0.6.1 → 0.6.3

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.
Files changed (463) hide show
  1. package/bun.lock +40 -40
  2. package/bunfig.toml +3 -0
  3. package/docker-entrypoint.sh +12 -2
  4. package/docs/architecture/memory.md +1 -1
  5. package/node_modules/@vellumai/ces-contracts/src/handles.ts +7 -9
  6. package/node_modules/@vellumai/ces-contracts/src/rpc.ts +42 -0
  7. package/openapi.yaml +184 -69
  8. package/package.json +41 -41
  9. package/scripts/generate-openapi.ts +1 -2
  10. package/src/__tests__/acp-session.test.ts +43 -0
  11. package/src/__tests__/app-builder-tool-scripts.test.ts +1 -0
  12. package/src/__tests__/app-executors.test.ts +1 -0
  13. package/src/__tests__/app-source-watcher.test.ts +37 -11
  14. package/src/__tests__/approval-routes-http.test.ts +178 -1
  15. package/src/__tests__/assistant-event-hub.test.ts +30 -0
  16. package/src/__tests__/browser-fill-credential.test.ts +229 -94
  17. package/src/__tests__/browser-manager.test.ts +40 -27
  18. package/src/__tests__/catalog-files.test.ts +862 -0
  19. package/src/__tests__/channel-approvals.test.ts +53 -0
  20. package/src/__tests__/checker.test.ts +104 -170
  21. package/src/__tests__/cli-command-risk-guard.test.ts +1 -1
  22. package/src/__tests__/config-managed-gemini-defaults.test.ts +326 -0
  23. package/src/__tests__/config-schema-cmd.test.ts +2 -2
  24. package/src/__tests__/config-schema.test.ts +125 -48
  25. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +23 -0
  26. package/src/__tests__/context-overflow-approval.test.ts +21 -6
  27. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -1
  28. package/src/__tests__/conversation-agent-loop.test.ts +1 -1
  29. package/src/__tests__/conversation-analysis-routes.test.ts +169 -0
  30. package/src/__tests__/conversation-attachments.test.ts +80 -4
  31. package/src/__tests__/conversation-confirmation-signals.test.ts +155 -0
  32. package/src/__tests__/conversation-directories-parse.test.ts +105 -0
  33. package/src/__tests__/conversation-fork-crud.test.ts +17 -0
  34. package/src/__tests__/conversation-history-web-search.test.ts +1 -0
  35. package/src/__tests__/conversation-host-access-routes.test.ts +229 -0
  36. package/src/__tests__/conversation-inject-context.test.ts +103 -0
  37. package/src/__tests__/conversation-queue.test.ts +45 -2
  38. package/src/__tests__/conversation-routes-disk-view.test.ts +5 -0
  39. package/src/__tests__/conversation-routes-guardian-reply.test.ts +16 -0
  40. package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
  41. package/src/__tests__/conversation-runtime-assembly.test.ts +269 -46
  42. package/src/__tests__/conversation-starter-routes.test.ts +126 -0
  43. package/src/__tests__/conversation-starters-cadence.test.ts +161 -0
  44. package/src/__tests__/conversation-store.test.ts +195 -0
  45. package/src/__tests__/conversation-workspace-cache-state.test.ts +193 -0
  46. package/src/__tests__/credential-execution-approval-bridge.test.ts +32 -3
  47. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  48. package/src/__tests__/credential-vault-unit.test.ts +4 -4
  49. package/src/__tests__/credential-vault.test.ts +152 -13
  50. package/src/__tests__/credentials-cli.test.ts +2 -2
  51. package/src/__tests__/date-context.test.ts +4 -4
  52. package/src/__tests__/embedding-managed-proxy-selection.test.ts +256 -0
  53. package/src/__tests__/extension-id-sync-guard.test.ts +155 -0
  54. package/src/__tests__/fixtures/mock-chrome-extension.ts +375 -0
  55. package/src/__tests__/gateway-only-guard.test.ts +3 -0
  56. package/src/__tests__/gemini-provider.test.ts +2 -2
  57. package/src/__tests__/guardian-routing-invariants.test.ts +70 -2
  58. package/src/__tests__/headless-browser-interactions.test.ts +707 -371
  59. package/src/__tests__/headless-browser-navigate.test.ts +389 -47
  60. package/src/__tests__/headless-browser-read-tools.test.ts +266 -103
  61. package/src/__tests__/headless-browser-snapshot.test.ts +240 -77
  62. package/src/__tests__/host-bash-proxy.test.ts +150 -1
  63. package/src/__tests__/host-browser-e2e-cloud.test.ts +462 -0
  64. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +286 -0
  65. package/src/__tests__/host-browser-e2e-self-hosted.test.ts +374 -0
  66. package/src/__tests__/host-browser-event-routes.test.ts +350 -0
  67. package/src/__tests__/host-browser-proxy.test.ts +444 -0
  68. package/src/__tests__/host-browser-routes.test.ts +198 -0
  69. package/src/__tests__/host-browser-ws-events-e2e.test.ts +320 -0
  70. package/src/__tests__/host-cu-proxy.test.ts +171 -1
  71. package/src/__tests__/host-file-proxy.test.ts +185 -1
  72. package/src/__tests__/host-file-read-tool.test.ts +52 -0
  73. package/src/__tests__/host-proxy-interface.test.ts +165 -0
  74. package/src/__tests__/host-shell-tool.test.ts +1 -11
  75. package/src/__tests__/http-user-message-parity.test.ts +1 -0
  76. package/src/__tests__/init-feature-flag-overrides.test.ts +167 -0
  77. package/src/__tests__/inline-command-runner.test.ts +7 -5
  78. package/src/__tests__/integration-status.test.ts +6 -7
  79. package/src/__tests__/list-messages-tool-merge.test.ts +37 -12
  80. package/src/__tests__/log-export-workspace.test.ts +190 -0
  81. package/src/__tests__/managed-credential-catalog-cli.test.ts +12 -14
  82. package/src/__tests__/mcp-client-auth.test.ts +40 -4
  83. package/src/__tests__/mcp-health-check.test.ts +10 -3
  84. package/src/__tests__/migration-cross-version-compatibility.test.ts +3 -1
  85. package/src/__tests__/migration-export-http.test.ts +61 -2
  86. package/src/__tests__/migration-export-streaming.test.ts +66 -0
  87. package/src/__tests__/migration-import-commit-http.test.ts +101 -1
  88. package/src/__tests__/native-host-marker-sync-guard.test.ts +157 -0
  89. package/src/__tests__/navigate-settings-tab.test.ts +14 -1
  90. package/src/__tests__/notification-broadcaster.test.ts +65 -0
  91. package/src/__tests__/oauth-apps-routes.test.ts +17 -12
  92. package/src/__tests__/oauth-cli.test.ts +707 -60
  93. package/src/__tests__/oauth-connect-orchestrator.test.ts +116 -24
  94. package/src/__tests__/oauth-provider-seed-logos.test.ts +23 -0
  95. package/src/__tests__/oauth-provider-serializer.test.ts +146 -10
  96. package/src/__tests__/oauth-provider-visibility.test.ts +19 -21
  97. package/src/__tests__/oauth-providers-routes.test.ts +50 -14
  98. package/src/__tests__/oauth-store.test.ts +1386 -182
  99. package/src/__tests__/oauth2-gateway-transport.test.ts +211 -20
  100. package/src/__tests__/onboarding-template-contract.test.ts +74 -55
  101. package/src/__tests__/openai-provider.test.ts +2 -2
  102. package/src/__tests__/outlook-categories.test.ts +1 -1
  103. package/src/__tests__/outlook-client-automation.test.ts +1 -1
  104. package/src/__tests__/outlook-compose-tools.test.ts +1 -1
  105. package/src/__tests__/outlook-email-watcher.test.ts +1 -1
  106. package/src/__tests__/outlook-follow-up.test.ts +1 -1
  107. package/src/__tests__/outlook-messaging-provider.test.ts +2 -2
  108. package/src/__tests__/outlook-trash.test.ts +1 -1
  109. package/src/__tests__/outlook-unsubscribe.test.ts +1 -1
  110. package/src/__tests__/permission-checker-host-gate.test.ts +74 -14
  111. package/src/__tests__/permission-mode.test.ts +28 -56
  112. package/src/__tests__/pkb-autoinject.test.ts +96 -0
  113. package/src/__tests__/platform-callback-registration.test.ts +19 -0
  114. package/src/__tests__/post-turn-tool-result-truncation.test.ts +296 -0
  115. package/src/__tests__/proxy-approval-callback.test.ts +18 -0
  116. package/src/__tests__/require-fresh-approval.test.ts +40 -3
  117. package/src/__tests__/sandbox-diagnostics.test.ts +1 -32
  118. package/src/__tests__/sanitize-config-for-transfer.test.ts +132 -0
  119. package/src/__tests__/schedule-routes.test.ts +162 -0
  120. package/src/__tests__/secret-detection-handler.test.ts +84 -0
  121. package/src/__tests__/secret-ingress-http.test.ts +1 -0
  122. package/src/__tests__/send-endpoint-busy.test.ts +3 -0
  123. package/src/__tests__/set-permission-mode.test.ts +13 -250
  124. package/src/__tests__/skills-file-content-endpoint.test.ts +670 -0
  125. package/src/__tests__/skills-files-catalog-fallback.test.ts +450 -0
  126. package/src/__tests__/slack-channel-config.test.ts +12 -15
  127. package/src/__tests__/subagent-detail.test.ts +44 -2
  128. package/src/__tests__/subagent-disposal.test.ts +1 -0
  129. package/src/__tests__/subagent-fork-notifications.test.ts +291 -0
  130. package/src/__tests__/subagent-fork-spawn.test.ts +384 -0
  131. package/src/__tests__/subagent-manager-notify.test.ts +1 -0
  132. package/src/__tests__/subagent-notify-parent.test.ts +1 -0
  133. package/src/__tests__/subagent-spawn-tool-fork.test.ts +411 -0
  134. package/src/__tests__/subagent-tools.test.ts +1 -0
  135. package/src/__tests__/subagent-types.test.ts +1 -0
  136. package/src/__tests__/system-prompt-ask-mode.test.ts +27 -71
  137. package/src/__tests__/system-prompt.test.ts +72 -1
  138. package/src/__tests__/task-scheduler.test.ts +32 -6
  139. package/src/__tests__/telegram-config.test.ts +10 -13
  140. package/src/__tests__/terminal-sandbox.test.ts +1 -1
  141. package/src/__tests__/terminal-tools.test.ts +11 -5
  142. package/src/__tests__/test-preload.ts +14 -0
  143. package/src/__tests__/tool-approval-handler.test.ts +73 -0
  144. package/src/__tests__/tool-domain-event-publisher.test.ts +0 -1
  145. package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -8
  146. package/src/__tests__/tool-executor.test.ts +0 -1
  147. package/src/__tests__/tool-side-effects-slack-dm.test.ts +22 -0
  148. package/src/__tests__/top-level-renderer.test.ts +73 -1
  149. package/src/__tests__/transport-hints-queue.test.ts +62 -0
  150. package/src/__tests__/trust-store.test.ts +4 -4
  151. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +109 -0
  152. package/src/__tests__/v2-consent-policy.test.ts +103 -0
  153. package/src/__tests__/workspace-migration-030-seed-pkb-autoinject.test.ts +168 -0
  154. package/src/__tests__/workspace-policy.test.ts +2 -7
  155. package/src/acp/client-handler.ts +30 -4
  156. package/src/agent/loop.ts +12 -35
  157. package/src/approvals/guardian-request-resolvers.ts +21 -15
  158. package/src/browser-session/__tests__/manager.test.ts +297 -0
  159. package/src/browser-session/backends/cdp-inspect.ts +30 -0
  160. package/src/browser-session/backends/extension.ts +26 -0
  161. package/src/browser-session/backends/local.ts +24 -0
  162. package/src/browser-session/events.ts +164 -0
  163. package/src/browser-session/index.ts +27 -0
  164. package/src/browser-session/manager.ts +159 -0
  165. package/src/browser-session/types.ts +28 -0
  166. package/src/channels/__tests__/types.test.ts +134 -0
  167. package/src/channels/types.ts +55 -0
  168. package/src/cli/__tests__/run-assistant-command.ts +34 -7
  169. package/src/cli/__tests__/unknown-command.test.ts +33 -0
  170. package/src/cli/commands/browser-relay.ts +339 -409
  171. package/src/cli/commands/credentials.ts +3 -3
  172. package/src/cli/commands/default-action.ts +68 -1
  173. package/src/cli/commands/email.ts +18 -13
  174. package/src/cli/commands/mcp.ts +16 -4
  175. package/src/cli/commands/oauth/__tests__/connect.test.ts +68 -41
  176. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +21 -21
  177. package/src/cli/commands/oauth/__tests__/mode.test.ts +17 -17
  178. package/src/cli/commands/oauth/__tests__/ping.test.ts +16 -16
  179. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +31 -33
  180. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +329 -0
  181. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +116 -12
  182. package/src/cli/commands/oauth/__tests__/status.test.ts +10 -10
  183. package/src/cli/commands/oauth/__tests__/token.test.ts +7 -7
  184. package/src/cli/commands/oauth/apps.ts +7 -4
  185. package/src/cli/commands/oauth/connect.ts +16 -2
  186. package/src/cli/commands/oauth/disconnect.ts +1 -1
  187. package/src/cli/commands/oauth/providers.ts +200 -36
  188. package/src/cli/commands/oauth/shared.ts +5 -5
  189. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +259 -0
  190. package/src/cli/commands/platform/__tests__/connect.test.ts +1 -1
  191. package/src/cli/commands/platform/__tests__/disconnect.test.ts +1 -1
  192. package/src/cli/commands/platform/__tests__/status.test.ts +1 -1
  193. package/src/cli/commands/platform/index.ts +107 -10
  194. package/src/cli/commands/usage.ts +10 -9
  195. package/src/cli/lib/daemon-credential-client.ts +4 -0
  196. package/src/cli/program.ts +10 -3
  197. package/src/config/assistant-feature-flags.ts +59 -55
  198. package/src/config/bundled-skills/app-builder/SKILL.md +33 -173
  199. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +105 -0
  200. package/src/config/bundled-skills/app-builder/references/INTERACTION_HOOKS.md +56 -0
  201. package/src/config/bundled-skills/app-builder/references/WIDGETS.md +125 -0
  202. package/src/config/bundled-skills/contacts/SKILL.md +3 -0
  203. package/src/config/bundled-skills/document/SKILL.md +4 -0
  204. package/src/config/bundled-skills/gmail/SKILL.md +12 -7
  205. package/src/config/bundled-skills/gmail/TOOLS.json +1 -1
  206. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +2 -1
  207. package/src/config/bundled-skills/outlook/SKILL.md +7 -0
  208. package/src/config/bundled-skills/settings/TOOLS.json +1 -1
  209. package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +8 -3
  210. package/src/config/bundled-skills/subagent/SKILL.md +21 -0
  211. package/src/config/bundled-skills/subagent/TOOLS.json +8 -4
  212. package/src/config/bundled-skills/tasks/SKILL.md +5 -0
  213. package/src/config/env-registry.ts +14 -0
  214. package/src/config/env.ts +21 -0
  215. package/src/config/feature-flag-registry.json +46 -7
  216. package/src/config/loader.ts +56 -1
  217. package/src/config/sanitize-for-transfer.ts +47 -0
  218. package/src/config/schema.ts +46 -5
  219. package/src/config/schemas/host-browser.ts +66 -0
  220. package/src/config/schemas/memory-lifecycle.ts +1 -1
  221. package/src/config/schemas/memory-retrieval.ts +103 -0
  222. package/src/config/schemas/security.ts +0 -6
  223. package/src/config/schemas/services.ts +16 -0
  224. package/src/config/types.ts +0 -1
  225. package/src/context/post-turn-tool-result-truncation.ts +176 -0
  226. package/src/context/window-manager.ts +19 -1
  227. package/src/credential-execution/approval-bridge.ts +49 -16
  228. package/src/credential-execution/managed-catalog.ts +3 -7
  229. package/src/daemon/__tests__/conversation-tool-setup.test.ts +186 -0
  230. package/src/daemon/app-source-watcher.ts +35 -0
  231. package/src/daemon/config-watcher.ts +6 -2
  232. package/src/daemon/context-overflow-approval.ts +5 -1
  233. package/src/daemon/conversation-agent-loop-handlers.ts +17 -2
  234. package/src/daemon/conversation-agent-loop.ts +74 -19
  235. package/src/daemon/conversation-attachments.ts +40 -1
  236. package/src/daemon/conversation-messaging.ts +3 -0
  237. package/src/daemon/conversation-process.ts +66 -3
  238. package/src/daemon/conversation-queue-manager.ts +8 -0
  239. package/src/daemon/conversation-runtime-assembly.ts +159 -20
  240. package/src/daemon/conversation-surfaces.ts +78 -12
  241. package/src/daemon/conversation-tool-setup.ts +74 -11
  242. package/src/daemon/conversation-workspace.ts +12 -0
  243. package/src/daemon/conversation.ts +227 -11
  244. package/src/daemon/date-context.ts +10 -10
  245. package/src/daemon/first-greeting.ts +3 -2
  246. package/src/daemon/handlers/conversations.ts +9 -139
  247. package/src/daemon/handlers/shared.ts +65 -0
  248. package/src/daemon/handlers/skills.ts +232 -37
  249. package/src/daemon/host-bash-proxy.ts +48 -13
  250. package/src/daemon/host-browser-proxy.ts +191 -0
  251. package/src/daemon/host-cu-proxy.ts +36 -11
  252. package/src/daemon/host-file-proxy.ts +57 -9
  253. package/src/daemon/lifecycle.ts +86 -12
  254. package/src/daemon/message-protocol.ts +7 -0
  255. package/src/daemon/message-types/conversations.ts +59 -13
  256. package/src/daemon/message-types/host-browser.ts +100 -0
  257. package/src/daemon/message-types/messages.ts +5 -6
  258. package/src/daemon/message-types/notifications.ts +12 -0
  259. package/src/daemon/message-types/settings.ts +12 -0
  260. package/src/daemon/message-types/skills.ts +10 -0
  261. package/src/daemon/message-types/subagents.ts +2 -0
  262. package/src/daemon/server.ts +112 -35
  263. package/src/daemon/tool-side-effects.ts +6 -0
  264. package/src/daemon/transport-hints.ts +14 -0
  265. package/src/inbound/platform-callback-registration.ts +18 -17
  266. package/src/index.ts +1 -1
  267. package/src/mcp/client.ts +59 -24
  268. package/src/memory/app-store.ts +31 -1
  269. package/src/memory/conversation-crud.ts +38 -10
  270. package/src/memory/conversation-directories.ts +39 -0
  271. package/src/memory/conversation-group-migration.ts +65 -5
  272. package/src/memory/conversation-starters-cadence.ts +76 -0
  273. package/src/memory/conversation-title-service.ts +5 -2
  274. package/src/memory/db-init.ts +12 -0
  275. package/src/memory/embedding-backend.test.ts +75 -0
  276. package/src/memory/embedding-backend.ts +131 -5
  277. package/src/memory/embedding-gemini.test.ts +54 -0
  278. package/src/memory/embedding-gemini.ts +20 -9
  279. package/src/memory/embedding-local.ts +177 -18
  280. package/src/memory/graph/capability-seed.ts +3 -5
  281. package/src/memory/graph/consolidation.ts +10 -23
  282. package/src/memory/graph/extraction-job.ts +15 -0
  283. package/src/memory/graph/retriever.ts +40 -22
  284. package/src/memory/graph/store.test.ts +7 -3
  285. package/src/memory/graph/store.ts +47 -12
  286. package/src/memory/group-crud.ts +25 -9
  287. package/src/memory/llm-usage-store.ts +45 -4
  288. package/src/memory/migrations/213-oauth-providers-scope-separator.ts +13 -0
  289. package/src/memory/migrations/214-oauth-providers-refresh-url.ts +11 -0
  290. package/src/memory/migrations/215-oauth-providers-revoke.ts +14 -0
  291. package/src/memory/migrations/216-oauth-providers-token-auth-method.ts +30 -0
  292. package/src/memory/migrations/217-conversation-host-access.ts +40 -0
  293. package/src/memory/migrations/218-oauth-providers-logo-url.ts +11 -0
  294. package/src/memory/migrations/index.ts +6 -0
  295. package/src/memory/migrations/registry.ts +8 -0
  296. package/src/memory/schema/conversations.ts +1 -0
  297. package/src/memory/schema/oauth.ts +18 -13
  298. package/src/messaging/provider.ts +1 -1
  299. package/src/notifications/broadcaster.ts +6 -0
  300. package/src/notifications/conversation-pairing.ts +12 -4
  301. package/src/notifications/emit-signal.ts +14 -0
  302. package/src/notifications/signal.ts +11 -0
  303. package/src/oauth/AGENTS.md +76 -0
  304. package/src/oauth/__tests__/identity-verifier.test.ts +24 -19
  305. package/src/oauth/__tests__/seed-providers-managed.test.ts +32 -0
  306. package/src/oauth/byo-connection.test.ts +8 -8
  307. package/src/oauth/byo-connection.ts +7 -7
  308. package/src/oauth/connect-orchestrator.ts +23 -21
  309. package/src/oauth/connect-types.ts +3 -3
  310. package/src/oauth/connection-resolver.test.ts +17 -4
  311. package/src/oauth/connection-resolver.ts +16 -16
  312. package/src/oauth/connection.ts +1 -1
  313. package/src/oauth/manual-token-connection.ts +13 -13
  314. package/src/oauth/oauth-store.ts +214 -100
  315. package/src/oauth/platform-connection.test.ts +5 -5
  316. package/src/oauth/platform-connection.ts +4 -4
  317. package/src/oauth/provider-serializer.ts +31 -5
  318. package/src/oauth/revoke.ts +76 -0
  319. package/src/oauth/seed-providers.ts +127 -87
  320. package/src/oauth/token-persistence.ts +1 -1
  321. package/src/permissions/checker.ts +3 -3
  322. package/src/permissions/defaults.ts +7 -8
  323. package/src/permissions/permission-mode.ts +4 -11
  324. package/src/permissions/prompter.ts +13 -3
  325. package/src/permissions/v2-consent-policy.ts +87 -0
  326. package/src/platform/client.ts +1 -1
  327. package/src/prompts/system-prompt.ts +18 -21
  328. package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +3 -65
  329. package/src/prompts/templates/BOOTSTRAP.md +59 -96
  330. package/src/prompts/templates/SOUL.md +11 -11
  331. package/src/providers/anthropic/client.ts +1 -0
  332. package/src/providers/types.ts +1 -1
  333. package/src/runtime/AGENTS.md +23 -0
  334. package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +715 -0
  335. package/src/runtime/__tests__/capability-tokens.test.ts +258 -0
  336. package/src/runtime/__tests__/chrome-extension-registry.test.ts +518 -0
  337. package/src/runtime/assistant-event-hub.ts +24 -2
  338. package/src/runtime/auth/__tests__/guard-tests.test.ts +1 -0
  339. package/src/runtime/auth/__tests__/middleware.test.ts +116 -1
  340. package/src/runtime/auth/__tests__/route-policy.test.ts +8 -0
  341. package/src/runtime/auth/middleware.ts +98 -0
  342. package/src/runtime/auth/route-policy.ts +6 -7
  343. package/src/runtime/auth/token-service.ts +8 -0
  344. package/src/runtime/capability-tokens.ts +414 -0
  345. package/src/runtime/channel-approvals.ts +18 -5
  346. package/src/runtime/chrome-extension-registry.ts +332 -0
  347. package/src/runtime/confirmation-request-guardian-bridge.ts +6 -0
  348. package/src/runtime/guardian-decision-types.ts +7 -0
  349. package/src/runtime/http-server.ts +425 -70
  350. package/src/runtime/migrations/__tests__/rebind-secrets-credentials.test.ts +172 -0
  351. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +276 -0
  352. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +162 -0
  353. package/src/runtime/migrations/migration-transport.ts +6 -0
  354. package/src/runtime/migrations/migration-wizard.ts +22 -2
  355. package/src/runtime/migrations/rebind-secrets-screen.ts +76 -15
  356. package/src/runtime/migrations/vbundle-builder.ts +145 -38
  357. package/src/runtime/migrations/vbundle-import-analyzer.ts +19 -0
  358. package/src/runtime/migrations/vbundle-importer.ts +55 -5
  359. package/src/runtime/pending-interactions.ts +29 -13
  360. package/src/runtime/routes/approval-routes.ts +90 -16
  361. package/src/runtime/routes/browser-cdp-routes.ts +229 -0
  362. package/src/runtime/routes/browser-extension-pair-routes.ts +497 -0
  363. package/src/runtime/routes/conversation-analysis-routes.ts +18 -5
  364. package/src/runtime/routes/conversation-management-routes.ts +108 -0
  365. package/src/runtime/routes/conversation-routes.ts +308 -28
  366. package/src/runtime/routes/conversation-starter-routes.ts +78 -16
  367. package/src/runtime/routes/group-routes.ts +22 -8
  368. package/src/runtime/routes/guardian-action-routes.ts +24 -13
  369. package/src/runtime/routes/host-browser-routes.ts +279 -0
  370. package/src/runtime/routes/host-file-routes.ts +9 -1
  371. package/src/runtime/routes/identity-routes.ts +259 -16
  372. package/src/runtime/routes/log-export/AGENTS.md +104 -0
  373. package/src/runtime/routes/log-export/__tests__/workspace-allowlist-error-contract.test.ts +103 -0
  374. package/src/runtime/routes/log-export/__tests__/workspace-allowlist.test.ts +716 -0
  375. package/src/runtime/routes/log-export/workspace-allowlist.ts +458 -0
  376. package/src/runtime/routes/log-export-routes.ts +60 -25
  377. package/src/runtime/routes/memory-item-routes.ts +1 -7
  378. package/src/runtime/routes/migration-routes.ts +87 -2
  379. package/src/runtime/routes/oauth-apps.ts +15 -17
  380. package/src/runtime/routes/oauth-providers.ts +4 -0
  381. package/src/runtime/routes/schedule-routes.ts +24 -11
  382. package/src/runtime/routes/settings-routes.ts +9 -97
  383. package/src/runtime/routes/skills-routes.ts +52 -2
  384. package/src/runtime/routes/subagents-routes.ts +14 -10
  385. package/src/runtime/routes/usage-routes.ts +8 -7
  386. package/src/runtime/routes/workspace-routes.test.ts +22 -0
  387. package/src/runtime/routes/workspace-routes.ts +8 -1
  388. package/src/runtime/routes/workspace-utils.ts +2 -0
  389. package/src/schedule/scheduler.ts +7 -5
  390. package/src/security/ces-credential-client.ts +20 -0
  391. package/src/security/ces-rpc-credential-backend.ts +17 -0
  392. package/src/security/credential-backend.ts +5 -0
  393. package/src/security/oauth2.ts +42 -25
  394. package/src/security/secure-keys.ts +118 -25
  395. package/src/security/token-manager.ts +23 -10
  396. package/src/skills/catalog-files.ts +492 -0
  397. package/src/skills/inline-command-runner.ts +12 -14
  398. package/src/subagent/manager.ts +131 -26
  399. package/src/subagent/types.ts +19 -0
  400. package/src/tools/apps/executors.ts +11 -2
  401. package/src/tools/browser/__tests__/auth-detector.test.ts +202 -108
  402. package/src/tools/browser/auth-detector.ts +43 -12
  403. package/src/tools/browser/browser-execution.ts +645 -340
  404. package/src/tools/browser/browser-manager.ts +36 -12
  405. package/src/tools/browser/cdp-client/__tests__/accessibility-snapshot.test.ts +318 -0
  406. package/src/tools/browser/cdp-client/__tests__/cdp-dom-helpers.test.ts +1175 -0
  407. package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +870 -0
  408. package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +330 -0
  409. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +377 -0
  410. package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-nested-frames.json +64 -0
  411. package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-simple.json +69 -0
  412. package/src/tools/browser/cdp-client/__tests__/local-cdp-client.test.ts +310 -0
  413. package/src/tools/browser/cdp-client/__tests__/types.test.ts +96 -0
  414. package/src/tools/browser/cdp-client/accessibility-snapshot.ts +387 -0
  415. package/src/tools/browser/cdp-client/cdp-dom-helpers.ts +695 -0
  416. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/discovery.test.ts +743 -0
  417. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +580 -0
  418. package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +578 -0
  419. package/src/tools/browser/cdp-client/cdp-inspect/ws-transport.ts +579 -0
  420. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +635 -0
  421. package/src/tools/browser/cdp-client/errors.ts +34 -0
  422. package/src/tools/browser/cdp-client/extension-cdp-client.ts +125 -0
  423. package/src/tools/browser/cdp-client/factory.ts +204 -0
  424. package/src/tools/browser/cdp-client/index.ts +14 -0
  425. package/src/tools/browser/cdp-client/local-cdp-client.ts +187 -0
  426. package/src/tools/browser/cdp-client/types.ts +52 -0
  427. package/src/tools/filesystem/edit.ts +1 -1
  428. package/src/tools/filesystem/list.ts +1 -1
  429. package/src/tools/filesystem/read.ts +1 -1
  430. package/src/tools/filesystem/write.ts +2 -1
  431. package/src/tools/host-filesystem/edit.ts +1 -1
  432. package/src/tools/host-filesystem/read.ts +12 -15
  433. package/src/tools/host-filesystem/write.ts +1 -1
  434. package/src/tools/host-terminal/host-shell.ts +21 -16
  435. package/src/tools/permission-checker.ts +77 -100
  436. package/src/tools/registry.ts +0 -2
  437. package/src/tools/secret-detection-handler.ts +34 -1
  438. package/src/tools/shared/filesystem/image-read.ts +61 -40
  439. package/src/tools/skills/sandbox-runner.ts +3 -6
  440. package/src/tools/subagent/spawn.ts +47 -3
  441. package/src/tools/subagent/status.ts +2 -0
  442. package/src/tools/system/register.ts +2 -16
  443. package/src/tools/terminal/safe-env.ts +7 -0
  444. package/src/tools/terminal/sandbox-diagnostics.ts +4 -4
  445. package/src/tools/terminal/sandbox.ts +4 -1
  446. package/src/tools/terminal/shell.ts +24 -21
  447. package/src/tools/tool-approval-handler.ts +48 -2
  448. package/src/tools/types.ts +2 -3
  449. package/src/util/platform.ts +14 -19
  450. package/src/watcher/provider-types.ts +1 -1
  451. package/src/workspace/migrations/029-seed-pkb.ts +1 -0
  452. package/src/workspace/migrations/030-seed-pkb-autoinject.ts +73 -0
  453. package/src/workspace/migrations/registry.ts +2 -0
  454. package/src/workspace/top-level-renderer.ts +19 -1
  455. package/src/__tests__/chrome-cdp.test.ts +0 -419
  456. package/src/__tests__/permission-mode-sse.test.ts +0 -418
  457. package/src/__tests__/permission-mode-store.test.ts +0 -277
  458. package/src/browser-extension-relay/protocol.ts +0 -63
  459. package/src/browser-extension-relay/server.ts +0 -203
  460. package/src/config/schemas/sandbox.ts +0 -14
  461. package/src/permissions/permission-mode-store.ts +0 -180
  462. package/src/tools/browser/chrome-cdp.ts +0 -239
  463. package/src/tools/system/set-permission-mode.ts +0 -103
@@ -3,48 +3,60 @@ import { describe, expect, it } from "bun:test";
3
3
  import {
4
4
  type AuthChallenge,
5
5
  detectAuthChallenge,
6
+ detectCaptchaChallenge,
6
7
  formatAuthChallenge,
7
8
  identifyService,
8
9
  isAuthUrl,
9
10
  } from "../auth-detector.js";
10
- import type { Page } from "../browser-manager.js";
11
+ import { CdpError } from "../cdp-client/errors.js";
12
+ import type { CdpClient } from "../cdp-client/types.js";
11
13
 
12
14
  // ── Helpers ──────────────────────────────────────────────────────────
13
15
 
14
16
  /**
15
- * Build a minimal mock Page whose `url()` returns the given URL and
16
- * `evaluate()` runs a callback that simulates a DOM structure.
17
+ * Programmable fake CdpClient used in place of a Playwright Page.
17
18
  *
18
- * `evaluateResult` is the value that `page.evaluate()` will resolve with,
19
- * matching the shape returned by the DOM_DETECT_EXPRESSION IIFE inside
20
- * auth-detector.ts.
19
+ * `urlValue` drives the response to `document.location.href` reads,
20
+ * `domResult` drives the auth-detector DOM IIFE, and `captchaResult`
21
+ * drives the CAPTCHA detector IIFE. Any of these can be replaced with
22
+ * a function to throw for specific call counts.
21
23
  */
22
- function mockPage(url: string, evaluateResult: unknown = null): Page {
24
+ function fakeCdp(opts: {
25
+ urlValue: string;
26
+ domResult?: unknown;
27
+ captchaResult?: boolean;
28
+ throwOn?: (expression: string) => boolean;
29
+ }): CdpClient {
23
30
  return {
24
- close: async () => {},
25
- isClosed: () => false,
26
- goto: async () => null,
27
- title: async () => "",
28
- url: () => url,
29
- evaluate: async (_expr: string) => evaluateResult,
30
- click: async () => {},
31
- fill: async () => {},
32
- press: async () => {},
33
- selectOption: async () => [] as string[],
34
- hover: async () => {},
35
- waitForSelector: async () => null,
36
- waitForFunction: async () => null,
37
- route: async () => {},
38
- unroute: async () => {},
39
- screenshot: async () => Buffer.from(""),
40
- keyboard: { press: async () => {} },
41
- mouse: {
42
- click: async () => {},
43
- move: async () => {},
44
- wheel: async () => {},
31
+ async send<T>(
32
+ method: string,
33
+ params?: Record<string, unknown>,
34
+ ): Promise<T> {
35
+ if (method !== "Runtime.evaluate") {
36
+ throw new Error(
37
+ `unexpected CDP method in auth-detector test: ${method}`,
38
+ );
39
+ }
40
+ const expression = String(
41
+ (params as Record<string, unknown>)?.["expression"] ?? "",
42
+ );
43
+ if (opts.throwOn?.(expression)) {
44
+ throw new CdpError("cdp_error", "synthetic failure", {
45
+ cdpMethod: method,
46
+ cdpParams: params,
47
+ });
48
+ }
49
+ if (expression === "document.location.href") {
50
+ return { result: { value: opts.urlValue } } as T;
51
+ }
52
+ // CAPTCHA detector expression starts with "(() => {\n // Cloudflare"
53
+ if (/just a moment/.test(expression)) {
54
+ return { result: { value: opts.captchaResult === true } } as T;
55
+ }
56
+ // Anything else is treated as the auth-detector DOM IIFE.
57
+ return { result: { value: opts.domResult ?? null } } as T;
45
58
  },
46
- bringToFront: async () => {},
47
- on: () => {},
59
+ dispose() {},
48
60
  };
49
61
  }
50
62
 
@@ -187,33 +199,39 @@ describe("isAuthUrl", () => {
187
199
 
188
200
  describe("detectAuthChallenge - login pages", () => {
189
201
  it("detects a generic login page with password input", async () => {
190
- const page = mockPage("https://example.com/login", {
191
- type: "login",
192
- fields: [
193
- { type: "email", selector: 'input[type="email"]', label: "email" },
194
- {
195
- type: "password",
196
- selector: 'input[type="password"]',
197
- label: "password",
198
- },
199
- ],
202
+ const cdp = fakeCdp({
203
+ urlValue: "https://example.com/login",
204
+ domResult: {
205
+ type: "login",
206
+ fields: [
207
+ { type: "email", selector: 'input[type="email"]', label: "email" },
208
+ {
209
+ type: "password",
210
+ selector: 'input[type="password"]',
211
+ label: "password",
212
+ },
213
+ ],
214
+ },
200
215
  });
201
216
 
202
- const result = await detectAuthChallenge(page);
217
+ const result = await detectAuthChallenge(cdp);
203
218
  expect(result).not.toBeNull();
204
219
  expect(result!.type).toBe("login");
205
220
  expect(result!.fields.some((f) => f.type === "password")).toBe(true);
206
221
  });
207
222
 
208
223
  it("detects Google email step via #identifierId", async () => {
209
- const page = mockPage("https://accounts.google.com/v3/signin/identifier", {
210
- type: "login",
211
- fields: [
212
- { type: "email", selector: "#identifierId", label: "Google email" },
213
- ],
224
+ const cdp = fakeCdp({
225
+ urlValue: "https://accounts.google.com/v3/signin/identifier",
226
+ domResult: {
227
+ type: "login",
228
+ fields: [
229
+ { type: "email", selector: "#identifierId", label: "Google email" },
230
+ ],
231
+ },
214
232
  });
215
233
 
216
- const result = await detectAuthChallenge(page);
234
+ const result = await detectAuthChallenge(cdp);
217
235
  expect(result).not.toBeNull();
218
236
  expect(result!.type).toBe("login");
219
237
  expect(result!.service).toBe("Google");
@@ -221,27 +239,33 @@ describe("detectAuthChallenge - login pages", () => {
221
239
  });
222
240
 
223
241
  it("detects Google password step", async () => {
224
- const page = mockPage("https://accounts.google.com/v3/signin/challenge", {
225
- type: "login",
226
- fields: [
227
- {
228
- type: "password",
229
- selector: 'input[type="password"][name="Passwd"]',
230
- label: "Google password",
231
- },
232
- ],
242
+ const cdp = fakeCdp({
243
+ urlValue: "https://accounts.google.com/v3/signin/challenge",
244
+ domResult: {
245
+ type: "login",
246
+ fields: [
247
+ {
248
+ type: "password",
249
+ selector: 'input[type="password"][name="Passwd"]',
250
+ label: "Google password",
251
+ },
252
+ ],
253
+ },
233
254
  });
234
255
 
235
- const result = await detectAuthChallenge(page);
256
+ const result = await detectAuthChallenge(cdp);
236
257
  expect(result).not.toBeNull();
237
258
  expect(result!.type).toBe("login");
238
259
  expect(result!.service).toBe("Google");
239
260
  });
240
261
 
241
262
  it("falls back to URL-only detection when DOM has no auth elements", async () => {
242
- const page = mockPage("https://accounts.google.com/ServiceLogin", null);
263
+ const cdp = fakeCdp({
264
+ urlValue: "https://accounts.google.com/ServiceLogin",
265
+ domResult: null,
266
+ });
243
267
 
244
- const result = await detectAuthChallenge(page);
268
+ const result = await detectAuthChallenge(cdp);
245
269
  expect(result).not.toBeNull();
246
270
  expect(result!.type).toBe("login");
247
271
  expect(result!.service).toBe("Google");
@@ -253,36 +277,42 @@ describe("detectAuthChallenge - login pages", () => {
253
277
 
254
278
  describe("detectAuthChallenge - 2FA pages", () => {
255
279
  it("detects a 2FA page with code input", async () => {
256
- const page = mockPage("https://accounts.google.com/signin/v2/challenge", {
257
- type: "2fa",
258
- fields: [
259
- {
260
- type: "code",
261
- selector: 'input[name="code"]',
262
- label: "verification code",
263
- },
264
- ],
280
+ const cdp = fakeCdp({
281
+ urlValue: "https://accounts.google.com/signin/v2/challenge",
282
+ domResult: {
283
+ type: "2fa",
284
+ fields: [
285
+ {
286
+ type: "code",
287
+ selector: 'input[name="code"]',
288
+ label: "verification code",
289
+ },
290
+ ],
291
+ },
265
292
  });
266
293
 
267
- const result = await detectAuthChallenge(page);
294
+ const result = await detectAuthChallenge(cdp);
268
295
  expect(result).not.toBeNull();
269
296
  expect(result!.type).toBe("2fa");
270
297
  expect(result!.fields.some((f) => f.type === "code")).toBe(true);
271
298
  });
272
299
 
273
300
  it("detects 2FA via text patterns even without specific input", async () => {
274
- const page = mockPage("https://example.com/verify", {
275
- type: "2fa",
276
- fields: [
277
- {
278
- type: "code",
279
- selector: "",
280
- label: "verification code (text detected)",
281
- },
282
- ],
301
+ const cdp = fakeCdp({
302
+ urlValue: "https://example.com/verify",
303
+ domResult: {
304
+ type: "2fa",
305
+ fields: [
306
+ {
307
+ type: "code",
308
+ selector: "",
309
+ label: "verification code (text detected)",
310
+ },
311
+ ],
312
+ },
283
313
  });
284
314
 
285
- const result = await detectAuthChallenge(page);
315
+ const result = await detectAuthChallenge(cdp);
286
316
  expect(result).not.toBeNull();
287
317
  expect(result!.type).toBe("2fa");
288
318
  });
@@ -292,18 +322,21 @@ describe("detectAuthChallenge - 2FA pages", () => {
292
322
 
293
323
  describe("detectAuthChallenge - OAuth consent", () => {
294
324
  it("detects an OAuth consent page with Allow button", async () => {
295
- const page = mockPage("https://accounts.google.com/o/oauth2/v2/auth", {
296
- type: "oauth_consent",
297
- fields: [
298
- {
299
- type: "approval",
300
- selector: "#submit_approve_access",
301
- label: "Allow",
302
- },
303
- ],
325
+ const cdp = fakeCdp({
326
+ urlValue: "https://accounts.google.com/o/oauth2/v2/auth",
327
+ domResult: {
328
+ type: "oauth_consent",
329
+ fields: [
330
+ {
331
+ type: "approval",
332
+ selector: "#submit_approve_access",
333
+ label: "Allow",
334
+ },
335
+ ],
336
+ },
304
337
  });
305
338
 
306
- const result = await detectAuthChallenge(page);
339
+ const result = await detectAuthChallenge(cdp);
307
340
  expect(result).not.toBeNull();
308
341
  expect(result!.type).toBe("oauth_consent");
309
342
  expect(result!.service).toBe("Google");
@@ -311,12 +344,15 @@ describe("detectAuthChallenge - OAuth consent", () => {
311
344
  });
312
345
 
313
346
  it("detects consent with Approve button", async () => {
314
- const page = mockPage("https://github.com/login/oauth/authorize", {
315
- type: "oauth_consent",
316
- fields: [{ type: "approval", selector: "button", label: "Approve" }],
347
+ const cdp = fakeCdp({
348
+ urlValue: "https://github.com/login/oauth/authorize",
349
+ domResult: {
350
+ type: "oauth_consent",
351
+ fields: [{ type: "approval", selector: "button", label: "Approve" }],
352
+ },
317
353
  });
318
354
 
319
- const result = await detectAuthChallenge(page);
355
+ const result = await detectAuthChallenge(cdp);
320
356
  expect(result).not.toBeNull();
321
357
  expect(result!.type).toBe("oauth_consent");
322
358
  });
@@ -326,36 +362,94 @@ describe("detectAuthChallenge - OAuth consent", () => {
326
362
 
327
363
  describe("detectAuthChallenge - non-auth pages", () => {
328
364
  it("returns null for a regular page", async () => {
329
- const page = mockPage("https://example.com/dashboard", null);
365
+ const cdp = fakeCdp({
366
+ urlValue: "https://example.com/dashboard",
367
+ domResult: null,
368
+ });
330
369
 
331
- const result = await detectAuthChallenge(page);
370
+ const result = await detectAuthChallenge(cdp);
332
371
  expect(result).toBeNull();
333
372
  });
334
373
 
335
374
  it("returns null for a regular github.com page with no auth elements", async () => {
336
- const page = mockPage(
337
- "https://github.com/vellum-ai/vellum-assistant",
338
- null,
339
- );
375
+ const cdp = fakeCdp({
376
+ urlValue: "https://github.com/vellum-ai/vellum-assistant",
377
+ domResult: null,
378
+ });
340
379
 
341
- const result = await detectAuthChallenge(page);
380
+ const result = await detectAuthChallenge(cdp);
342
381
  expect(result).toBeNull();
343
382
  });
344
383
 
345
384
  it("returns null for a regular page with no auth elements", async () => {
346
- const page = mockPage("https://news.ycombinator.com/", null);
385
+ const cdp = fakeCdp({
386
+ urlValue: "https://news.ycombinator.com/",
387
+ domResult: null,
388
+ });
347
389
 
348
- const result = await detectAuthChallenge(page);
390
+ const result = await detectAuthChallenge(cdp);
349
391
  expect(result).toBeNull();
350
392
  });
351
393
 
352
- it("returns null when page.evaluate throws", async () => {
353
- const page = mockPage("https://example.com/login", null);
354
- page.evaluate = async () => {
355
- throw new Error("page closed");
356
- };
394
+ it("returns null when Runtime.evaluate throws a CdpError", async () => {
395
+ const cdp = fakeCdp({
396
+ urlValue: "https://example.com/login",
397
+ domResult: null,
398
+ throwOn: (expr) =>
399
+ !expr.startsWith("document.location.href") &&
400
+ !/just a moment/.test(expr),
401
+ });
402
+
403
+ const result = await detectAuthChallenge(cdp);
404
+ expect(result).toBeNull();
405
+ });
406
+
407
+ it("returns null when getCurrentUrl throws a CdpError", async () => {
408
+ const cdp = fakeCdp({
409
+ urlValue: "https://example.com/login",
410
+ domResult: null,
411
+ throwOn: (expr) => expr === "document.location.href",
412
+ });
413
+
414
+ const result = await detectAuthChallenge(cdp);
415
+ expect(result).toBeNull();
416
+ });
417
+ });
418
+
419
+ // ── CAPTCHA detection ────────────────────────────────────────────────
420
+
421
+ describe("detectCaptchaChallenge", () => {
422
+ it("returns a captcha AuthChallenge when the IIFE returns true", async () => {
423
+ const cdp = fakeCdp({
424
+ urlValue: "https://example.com/blocked",
425
+ captchaResult: true,
426
+ });
427
+
428
+ const result = await detectCaptchaChallenge(cdp);
429
+ expect(result).not.toBeNull();
430
+ expect(result!.type).toBe("captcha");
431
+ expect(result!.url).toBe("https://example.com/blocked");
432
+ expect(result!.fields).toEqual([]);
433
+ });
434
+
435
+ it("returns null when the IIFE returns false", async () => {
436
+ const cdp = fakeCdp({
437
+ urlValue: "https://example.com/home",
438
+ captchaResult: false,
439
+ });
440
+
441
+ const result = await detectCaptchaChallenge(cdp);
442
+ expect(result).toBeNull();
443
+ });
444
+
445
+ it("returns null when Runtime.evaluate throws", async () => {
446
+ const cdp = fakeCdp({
447
+ urlValue: "https://example.com/home",
448
+ captchaResult: true,
449
+ throwOn: (expr) => /just a moment/.test(expr),
450
+ });
357
451
 
358
- const result = await detectAuthChallenge(page);
452
+ const result = await detectCaptchaChallenge(cdp);
359
453
  expect(result).toBeNull();
360
454
  });
361
455
  });
@@ -1,4 +1,8 @@
1
- import type { Page } from "./browser-manager.js";
1
+ import {
2
+ evaluateExpression,
3
+ getCurrentUrl,
4
+ } from "./cdp-client/cdp-dom-helpers.js";
5
+ import type { CdpClient } from "./cdp-client/types.js";
2
6
 
3
7
  export type AuthChallengeType = "login" | "2fa" | "oauth_consent" | "captcha";
4
8
 
@@ -106,7 +110,7 @@ interface DomDetectionResult {
106
110
  * DOM elements. Returns a serialisable result or null.
107
111
  *
108
112
  * The expression is a self-contained IIFE so it can be passed as a string
109
- * to `page.evaluate()`.
113
+ * to `Runtime.evaluate()` via {@link evaluateExpression}.
110
114
  */
111
115
  const DOM_DETECT_EXPRESSION = `(() => {
112
116
  const fields = [];
@@ -259,23 +263,38 @@ const CAPTCHA_DETECT_EXPRESSION = `(() => {
259
263
  /**
260
264
  * Detect whether the current page presents a CAPTCHA or Cloudflare
261
265
  * challenge that requires human interaction.
266
+ *
267
+ * Migrated to CDP: runs {@link CAPTCHA_DETECT_EXPRESSION} via
268
+ * `Runtime.evaluate` and reads the current URL via
269
+ * {@link getCurrentUrl}. Errors (including {@link CdpError}) are
270
+ * swallowed and reported as "no challenge" so the caller can treat
271
+ * this as best-effort detection.
262
272
  */
263
273
  export async function detectCaptchaChallenge(
264
- page: Page,
274
+ cdp: CdpClient,
275
+ signal?: AbortSignal,
265
276
  ): Promise<AuthChallenge | null> {
266
277
  try {
267
- const isCaptcha = (await page.evaluate(
278
+ const isCaptcha = await evaluateExpression<boolean>(
279
+ cdp,
268
280
  CAPTCHA_DETECT_EXPRESSION,
269
- )) as boolean;
281
+ {},
282
+ signal,
283
+ );
270
284
  if (isCaptcha) {
285
+ const url = await getCurrentUrl(cdp, signal);
271
286
  return {
272
287
  type: "captcha",
273
288
  fields: [],
274
- url: page.url(),
289
+ url,
275
290
  };
276
291
  }
277
292
  return null;
278
293
  } catch {
294
+ // Best-effort detection: swallow CdpError (aborted / disposed /
295
+ // transport failures) and any other runtime error so a failed
296
+ // probe is reported as "no challenge detected" instead of
297
+ // bubbling up through navigation.
279
298
  return null;
280
299
  }
281
300
  }
@@ -290,19 +309,29 @@ export async function detectCaptchaChallenge(
290
309
  *
291
310
  * Returns an {@link AuthChallenge} if a challenge is detected, or `null`
292
311
  * if the page does not appear to be an auth page.
312
+ *
313
+ * Migrated to CDP: runs {@link DOM_DETECT_EXPRESSION} via
314
+ * `Runtime.evaluate` and reads the current URL via
315
+ * {@link getCurrentUrl}. Errors (including {@link CdpError}) are
316
+ * swallowed and reported as "no challenge" so the caller can treat
317
+ * this as best-effort detection.
293
318
  */
294
319
  export async function detectAuthChallenge(
295
- page: Page,
320
+ cdp: CdpClient,
321
+ signal?: AbortSignal,
296
322
  ): Promise<AuthChallenge | null> {
297
323
  try {
298
- const currentUrl = page.url();
324
+ const currentUrl = await getCurrentUrl(cdp, signal);
299
325
  const service = identifyService(currentUrl);
300
326
  const urlIsAuth = isAuthUrl(currentUrl);
301
327
 
302
- // DOM-based detection
303
- const domResult = (await page.evaluate(
328
+ // DOM-based detection via Runtime.evaluate
329
+ const domResult = await evaluateExpression<DomDetectionResult | null>(
330
+ cdp,
304
331
  DOM_DETECT_EXPRESSION,
305
- )) as DomDetectionResult | null;
332
+ {},
333
+ signal,
334
+ );
306
335
 
307
336
  if (domResult) {
308
337
  return {
@@ -326,7 +355,9 @@ export async function detectAuthChallenge(
326
355
 
327
356
  return null;
328
357
  } catch {
329
- // If page.evaluate throws (e.g. page closed, navigation), treat as no challenge
358
+ // If Runtime.evaluate throws (e.g. page closed, navigation,
359
+ // aborted, disposed) — or any other CDP/transport failure — treat
360
+ // as no challenge. Matches the pre-CDP best-effort semantics.
330
361
  return null;
331
362
  }
332
363
  }