@vellumai/assistant 0.6.2 → 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 (396) hide show
  1. package/bun.lock +40 -40
  2. package/bunfig.toml +3 -0
  3. package/docs/architecture/memory.md +1 -1
  4. package/node_modules/@vellumai/ces-contracts/src/rpc.ts +42 -0
  5. package/openapi.yaml +184 -69
  6. package/package.json +41 -41
  7. package/scripts/generate-openapi.ts +1 -2
  8. package/src/__tests__/acp-session.test.ts +43 -0
  9. package/src/__tests__/app-builder-tool-scripts.test.ts +1 -0
  10. package/src/__tests__/app-executors.test.ts +1 -0
  11. package/src/__tests__/app-source-watcher.test.ts +37 -11
  12. package/src/__tests__/approval-routes-http.test.ts +178 -1
  13. package/src/__tests__/browser-fill-credential.test.ts +229 -94
  14. package/src/__tests__/browser-manager.test.ts +40 -27
  15. package/src/__tests__/catalog-files.test.ts +862 -0
  16. package/src/__tests__/channel-approvals.test.ts +53 -0
  17. package/src/__tests__/config-managed-gemini-defaults.test.ts +326 -0
  18. package/src/__tests__/config-schema-cmd.test.ts +2 -2
  19. package/src/__tests__/config-schema.test.ts +125 -48
  20. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +23 -0
  21. package/src/__tests__/context-overflow-approval.test.ts +16 -1
  22. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -1
  23. package/src/__tests__/conversation-agent-loop.test.ts +1 -1
  24. package/src/__tests__/conversation-analysis-routes.test.ts +2 -2
  25. package/src/__tests__/conversation-attachments.test.ts +80 -4
  26. package/src/__tests__/conversation-confirmation-signals.test.ts +155 -0
  27. package/src/__tests__/conversation-fork-crud.test.ts +17 -0
  28. package/src/__tests__/conversation-history-web-search.test.ts +1 -0
  29. package/src/__tests__/conversation-host-access-routes.test.ts +229 -0
  30. package/src/__tests__/conversation-inject-context.test.ts +103 -0
  31. package/src/__tests__/conversation-queue.test.ts +45 -2
  32. package/src/__tests__/conversation-routes-disk-view.test.ts +5 -0
  33. package/src/__tests__/conversation-routes-guardian-reply.test.ts +16 -0
  34. package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
  35. package/src/__tests__/conversation-runtime-assembly.test.ts +269 -46
  36. package/src/__tests__/conversation-starter-routes.test.ts +126 -0
  37. package/src/__tests__/conversation-starters-cadence.test.ts +161 -0
  38. package/src/__tests__/conversation-store.test.ts +195 -0
  39. package/src/__tests__/conversation-workspace-cache-state.test.ts +193 -0
  40. package/src/__tests__/credential-execution-approval-bridge.test.ts +32 -1
  41. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  42. package/src/__tests__/credential-vault-unit.test.ts +4 -4
  43. package/src/__tests__/credential-vault.test.ts +152 -13
  44. package/src/__tests__/credentials-cli.test.ts +2 -2
  45. package/src/__tests__/date-context.test.ts +4 -4
  46. package/src/__tests__/embedding-managed-proxy-selection.test.ts +256 -0
  47. package/src/__tests__/extension-id-sync-guard.test.ts +155 -0
  48. package/src/__tests__/fixtures/mock-chrome-extension.ts +375 -0
  49. package/src/__tests__/gateway-only-guard.test.ts +3 -0
  50. package/src/__tests__/gemini-provider.test.ts +2 -2
  51. package/src/__tests__/guardian-routing-invariants.test.ts +70 -2
  52. package/src/__tests__/headless-browser-interactions.test.ts +707 -371
  53. package/src/__tests__/headless-browser-navigate.test.ts +389 -47
  54. package/src/__tests__/headless-browser-read-tools.test.ts +266 -103
  55. package/src/__tests__/headless-browser-snapshot.test.ts +240 -77
  56. package/src/__tests__/host-bash-proxy.test.ts +150 -1
  57. package/src/__tests__/host-browser-e2e-cloud.test.ts +462 -0
  58. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +286 -0
  59. package/src/__tests__/host-browser-e2e-self-hosted.test.ts +374 -0
  60. package/src/__tests__/host-browser-event-routes.test.ts +350 -0
  61. package/src/__tests__/host-browser-proxy.test.ts +444 -0
  62. package/src/__tests__/host-browser-routes.test.ts +198 -0
  63. package/src/__tests__/host-browser-ws-events-e2e.test.ts +320 -0
  64. package/src/__tests__/host-cu-proxy.test.ts +171 -1
  65. package/src/__tests__/host-file-proxy.test.ts +185 -1
  66. package/src/__tests__/host-file-read-tool.test.ts +52 -0
  67. package/src/__tests__/host-proxy-interface.test.ts +165 -0
  68. package/src/__tests__/host-shell-tool.test.ts +1 -11
  69. package/src/__tests__/http-user-message-parity.test.ts +1 -0
  70. package/src/__tests__/integration-status.test.ts +6 -7
  71. package/src/__tests__/list-messages-tool-merge.test.ts +37 -12
  72. package/src/__tests__/mcp-client-auth.test.ts +40 -4
  73. package/src/__tests__/mcp-health-check.test.ts +10 -3
  74. package/src/__tests__/migration-cross-version-compatibility.test.ts +3 -1
  75. package/src/__tests__/migration-export-http.test.ts +61 -2
  76. package/src/__tests__/migration-export-streaming.test.ts +66 -0
  77. package/src/__tests__/migration-import-commit-http.test.ts +101 -1
  78. package/src/__tests__/native-host-marker-sync-guard.test.ts +157 -0
  79. package/src/__tests__/oauth-apps-routes.test.ts +17 -12
  80. package/src/__tests__/oauth-cli.test.ts +707 -60
  81. package/src/__tests__/oauth-connect-orchestrator.test.ts +116 -24
  82. package/src/__tests__/oauth-provider-seed-logos.test.ts +23 -0
  83. package/src/__tests__/oauth-provider-serializer.test.ts +146 -10
  84. package/src/__tests__/oauth-provider-visibility.test.ts +19 -21
  85. package/src/__tests__/oauth-providers-routes.test.ts +50 -14
  86. package/src/__tests__/oauth-store.test.ts +1386 -182
  87. package/src/__tests__/oauth2-gateway-transport.test.ts +211 -20
  88. package/src/__tests__/onboarding-template-contract.test.ts +75 -57
  89. package/src/__tests__/openai-provider.test.ts +2 -2
  90. package/src/__tests__/outlook-categories.test.ts +1 -1
  91. package/src/__tests__/outlook-client-automation.test.ts +1 -1
  92. package/src/__tests__/outlook-compose-tools.test.ts +1 -1
  93. package/src/__tests__/outlook-email-watcher.test.ts +1 -1
  94. package/src/__tests__/outlook-follow-up.test.ts +1 -1
  95. package/src/__tests__/outlook-messaging-provider.test.ts +2 -2
  96. package/src/__tests__/outlook-trash.test.ts +1 -1
  97. package/src/__tests__/outlook-unsubscribe.test.ts +1 -1
  98. package/src/__tests__/permission-checker-host-gate.test.ts +74 -14
  99. package/src/__tests__/permission-mode.test.ts +28 -56
  100. package/src/__tests__/platform-callback-registration.test.ts +19 -0
  101. package/src/__tests__/post-turn-tool-result-truncation.test.ts +296 -0
  102. package/src/__tests__/proxy-approval-callback.test.ts +18 -0
  103. package/src/__tests__/require-fresh-approval.test.ts +40 -1
  104. package/src/__tests__/sanitize-config-for-transfer.test.ts +132 -0
  105. package/src/__tests__/schedule-routes.test.ts +162 -0
  106. package/src/__tests__/secret-detection-handler.test.ts +84 -0
  107. package/src/__tests__/secret-ingress-http.test.ts +1 -0
  108. package/src/__tests__/send-endpoint-busy.test.ts +3 -0
  109. package/src/__tests__/set-permission-mode.test.ts +13 -250
  110. package/src/__tests__/skills-file-content-endpoint.test.ts +670 -0
  111. package/src/__tests__/skills-files-catalog-fallback.test.ts +450 -0
  112. package/src/__tests__/slack-channel-config.test.ts +12 -15
  113. package/src/__tests__/subagent-detail.test.ts +44 -2
  114. package/src/__tests__/subagent-disposal.test.ts +1 -0
  115. package/src/__tests__/subagent-fork-notifications.test.ts +291 -0
  116. package/src/__tests__/subagent-fork-spawn.test.ts +384 -0
  117. package/src/__tests__/subagent-manager-notify.test.ts +1 -0
  118. package/src/__tests__/subagent-notify-parent.test.ts +1 -0
  119. package/src/__tests__/subagent-spawn-tool-fork.test.ts +411 -0
  120. package/src/__tests__/subagent-tools.test.ts +1 -0
  121. package/src/__tests__/subagent-types.test.ts +1 -0
  122. package/src/__tests__/system-prompt-ask-mode.test.ts +27 -71
  123. package/src/__tests__/system-prompt.test.ts +72 -1
  124. package/src/__tests__/task-scheduler.test.ts +32 -6
  125. package/src/__tests__/telegram-config.test.ts +10 -13
  126. package/src/__tests__/terminal-tools.test.ts +9 -0
  127. package/src/__tests__/tool-approval-handler.test.ts +73 -0
  128. package/src/__tests__/tool-side-effects-slack-dm.test.ts +22 -0
  129. package/src/__tests__/top-level-renderer.test.ts +73 -1
  130. package/src/__tests__/transport-hints-queue.test.ts +14 -29
  131. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +109 -0
  132. package/src/__tests__/v2-consent-policy.test.ts +103 -0
  133. package/src/acp/client-handler.ts +30 -4
  134. package/src/agent/loop.ts +12 -6
  135. package/src/approvals/guardian-request-resolvers.ts +21 -15
  136. package/src/browser-session/__tests__/manager.test.ts +297 -0
  137. package/src/browser-session/backends/cdp-inspect.ts +30 -0
  138. package/src/browser-session/backends/extension.ts +26 -0
  139. package/src/browser-session/backends/local.ts +24 -0
  140. package/src/browser-session/events.ts +164 -0
  141. package/src/browser-session/index.ts +27 -0
  142. package/src/browser-session/manager.ts +159 -0
  143. package/src/browser-session/types.ts +28 -0
  144. package/src/channels/__tests__/types.test.ts +134 -0
  145. package/src/channels/types.ts +53 -3
  146. package/src/cli/commands/browser-relay.ts +339 -409
  147. package/src/cli/commands/credentials.ts +3 -3
  148. package/src/cli/commands/email.ts +18 -13
  149. package/src/cli/commands/mcp.ts +16 -4
  150. package/src/cli/commands/oauth/__tests__/connect.test.ts +44 -44
  151. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +21 -21
  152. package/src/cli/commands/oauth/__tests__/mode.test.ts +17 -17
  153. package/src/cli/commands/oauth/__tests__/ping.test.ts +16 -16
  154. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +31 -33
  155. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +329 -0
  156. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +116 -12
  157. package/src/cli/commands/oauth/__tests__/status.test.ts +10 -10
  158. package/src/cli/commands/oauth/__tests__/token.test.ts +7 -7
  159. package/src/cli/commands/oauth/apps.ts +7 -4
  160. package/src/cli/commands/oauth/connect.ts +6 -3
  161. package/src/cli/commands/oauth/disconnect.ts +1 -1
  162. package/src/cli/commands/oauth/providers.ts +200 -36
  163. package/src/cli/commands/oauth/shared.ts +5 -5
  164. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +259 -0
  165. package/src/cli/commands/platform/index.ts +107 -10
  166. package/src/cli/commands/usage.ts +10 -9
  167. package/src/cli/lib/daemon-credential-client.ts +4 -0
  168. package/src/cli/program.ts +1 -1
  169. package/src/config/bundled-skills/app-builder/SKILL.md +26 -249
  170. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +105 -0
  171. package/src/config/bundled-skills/app-builder/references/INTERACTION_HOOKS.md +56 -0
  172. package/src/config/bundled-skills/app-builder/references/WIDGETS.md +125 -0
  173. package/src/config/bundled-skills/contacts/SKILL.md +3 -0
  174. package/src/config/bundled-skills/document/SKILL.md +4 -0
  175. package/src/config/bundled-skills/gmail/SKILL.md +1 -1
  176. package/src/config/bundled-skills/outlook/SKILL.md +7 -0
  177. package/src/config/bundled-skills/subagent/SKILL.md +21 -0
  178. package/src/config/bundled-skills/subagent/TOOLS.json +8 -4
  179. package/src/config/bundled-skills/tasks/SKILL.md +5 -0
  180. package/src/config/env-registry.ts +14 -0
  181. package/src/config/env.ts +21 -0
  182. package/src/config/feature-flag-registry.json +44 -5
  183. package/src/config/loader.ts +56 -1
  184. package/src/config/sanitize-for-transfer.ts +47 -0
  185. package/src/config/schema.ts +46 -5
  186. package/src/config/schemas/host-browser.ts +66 -0
  187. package/src/config/schemas/memory-lifecycle.ts +1 -1
  188. package/src/config/schemas/memory-retrieval.ts +103 -0
  189. package/src/config/schemas/security.ts +0 -6
  190. package/src/config/schemas/services.ts +8 -0
  191. package/src/config/types.ts +0 -1
  192. package/src/context/post-turn-tool-result-truncation.ts +176 -0
  193. package/src/context/window-manager.ts +19 -1
  194. package/src/credential-execution/approval-bridge.ts +49 -15
  195. package/src/daemon/__tests__/conversation-tool-setup.test.ts +186 -0
  196. package/src/daemon/app-source-watcher.ts +35 -0
  197. package/src/daemon/context-overflow-approval.ts +5 -0
  198. package/src/daemon/conversation-agent-loop-handlers.ts +17 -2
  199. package/src/daemon/conversation-agent-loop.ts +58 -24
  200. package/src/daemon/conversation-attachments.ts +40 -0
  201. package/src/daemon/conversation-process.ts +48 -1
  202. package/src/daemon/conversation-runtime-assembly.ts +118 -36
  203. package/src/daemon/conversation-surfaces.ts +37 -36
  204. package/src/daemon/conversation-tool-setup.ts +74 -8
  205. package/src/daemon/conversation-workspace.ts +12 -0
  206. package/src/daemon/conversation.ts +226 -8
  207. package/src/daemon/date-context.ts +10 -10
  208. package/src/daemon/first-greeting.ts +3 -2
  209. package/src/daemon/handlers/conversations.ts +9 -140
  210. package/src/daemon/handlers/shared.ts +58 -0
  211. package/src/daemon/handlers/skills.ts +232 -37
  212. package/src/daemon/host-bash-proxy.ts +48 -13
  213. package/src/daemon/host-browser-proxy.ts +191 -0
  214. package/src/daemon/host-cu-proxy.ts +36 -11
  215. package/src/daemon/host-file-proxy.ts +57 -9
  216. package/src/daemon/lifecycle.ts +65 -11
  217. package/src/daemon/message-protocol.ts +7 -0
  218. package/src/daemon/message-types/conversations.ts +55 -13
  219. package/src/daemon/message-types/host-browser.ts +100 -0
  220. package/src/daemon/message-types/messages.ts +5 -5
  221. package/src/daemon/message-types/skills.ts +10 -0
  222. package/src/daemon/message-types/subagents.ts +2 -0
  223. package/src/daemon/server.ts +92 -12
  224. package/src/daemon/tool-side-effects.ts +6 -0
  225. package/src/daemon/transport-hints.ts +5 -24
  226. package/src/inbound/platform-callback-registration.ts +18 -17
  227. package/src/mcp/client.ts +59 -24
  228. package/src/memory/app-store.ts +31 -1
  229. package/src/memory/conversation-crud.ts +23 -0
  230. package/src/memory/conversation-starters-cadence.ts +76 -0
  231. package/src/memory/conversation-title-service.ts +5 -2
  232. package/src/memory/db-init.ts +12 -0
  233. package/src/memory/embedding-backend.test.ts +75 -0
  234. package/src/memory/embedding-backend.ts +131 -5
  235. package/src/memory/embedding-gemini.test.ts +54 -0
  236. package/src/memory/embedding-gemini.ts +20 -9
  237. package/src/memory/embedding-local.ts +176 -17
  238. package/src/memory/graph/consolidation.ts +10 -23
  239. package/src/memory/graph/extraction-job.ts +15 -0
  240. package/src/memory/graph/retriever.ts +40 -22
  241. package/src/memory/graph/store.test.ts +7 -3
  242. package/src/memory/graph/store.ts +47 -12
  243. package/src/memory/llm-usage-store.ts +45 -4
  244. package/src/memory/migrations/213-oauth-providers-scope-separator.ts +13 -0
  245. package/src/memory/migrations/214-oauth-providers-refresh-url.ts +11 -0
  246. package/src/memory/migrations/215-oauth-providers-revoke.ts +14 -0
  247. package/src/memory/migrations/216-oauth-providers-token-auth-method.ts +30 -0
  248. package/src/memory/migrations/217-conversation-host-access.ts +40 -0
  249. package/src/memory/migrations/218-oauth-providers-logo-url.ts +11 -0
  250. package/src/memory/migrations/index.ts +6 -0
  251. package/src/memory/migrations/registry.ts +8 -0
  252. package/src/memory/schema/conversations.ts +1 -0
  253. package/src/memory/schema/oauth.ts +18 -13
  254. package/src/oauth/AGENTS.md +76 -0
  255. package/src/oauth/__tests__/identity-verifier.test.ts +24 -19
  256. package/src/oauth/__tests__/seed-providers-managed.test.ts +32 -0
  257. package/src/oauth/byo-connection.test.ts +8 -8
  258. package/src/oauth/byo-connection.ts +7 -7
  259. package/src/oauth/connect-orchestrator.ts +23 -21
  260. package/src/oauth/connect-types.ts +3 -3
  261. package/src/oauth/connection-resolver.test.ts +17 -4
  262. package/src/oauth/connection-resolver.ts +16 -16
  263. package/src/oauth/connection.ts +1 -1
  264. package/src/oauth/manual-token-connection.ts +13 -13
  265. package/src/oauth/oauth-store.ts +214 -100
  266. package/src/oauth/platform-connection.test.ts +3 -3
  267. package/src/oauth/platform-connection.ts +4 -4
  268. package/src/oauth/provider-serializer.ts +31 -5
  269. package/src/oauth/revoke.ts +76 -0
  270. package/src/oauth/seed-providers.ts +126 -87
  271. package/src/oauth/token-persistence.ts +1 -1
  272. package/src/permissions/permission-mode.ts +4 -11
  273. package/src/permissions/prompter.ts +13 -1
  274. package/src/permissions/v2-consent-policy.ts +87 -0
  275. package/src/prompts/system-prompt.ts +18 -21
  276. package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +3 -65
  277. package/src/prompts/templates/BOOTSTRAP.md +59 -105
  278. package/src/providers/anthropic/client.ts +1 -0
  279. package/src/providers/types.ts +1 -1
  280. package/src/runtime/AGENTS.md +23 -0
  281. package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +715 -0
  282. package/src/runtime/__tests__/capability-tokens.test.ts +258 -0
  283. package/src/runtime/__tests__/chrome-extension-registry.test.ts +518 -0
  284. package/src/runtime/assistant-event-hub.ts +2 -2
  285. package/src/runtime/auth/__tests__/guard-tests.test.ts +1 -0
  286. package/src/runtime/auth/__tests__/middleware.test.ts +116 -1
  287. package/src/runtime/auth/__tests__/route-policy.test.ts +8 -0
  288. package/src/runtime/auth/middleware.ts +98 -0
  289. package/src/runtime/auth/route-policy.ts +6 -7
  290. package/src/runtime/capability-tokens.ts +414 -0
  291. package/src/runtime/channel-approvals.ts +18 -5
  292. package/src/runtime/chrome-extension-registry.ts +332 -0
  293. package/src/runtime/confirmation-request-guardian-bridge.ts +6 -0
  294. package/src/runtime/guardian-decision-types.ts +7 -0
  295. package/src/runtime/http-server.ts +425 -70
  296. package/src/runtime/migrations/__tests__/rebind-secrets-credentials.test.ts +172 -0
  297. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +276 -0
  298. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +162 -0
  299. package/src/runtime/migrations/migration-transport.ts +6 -0
  300. package/src/runtime/migrations/migration-wizard.ts +22 -2
  301. package/src/runtime/migrations/rebind-secrets-screen.ts +76 -15
  302. package/src/runtime/migrations/vbundle-builder.ts +145 -38
  303. package/src/runtime/migrations/vbundle-import-analyzer.ts +19 -0
  304. package/src/runtime/migrations/vbundle-importer.ts +55 -5
  305. package/src/runtime/pending-interactions.ts +29 -13
  306. package/src/runtime/routes/approval-routes.ts +90 -16
  307. package/src/runtime/routes/browser-cdp-routes.ts +229 -0
  308. package/src/runtime/routes/browser-extension-pair-routes.ts +497 -0
  309. package/src/runtime/routes/conversation-analysis-routes.ts +2 -1
  310. package/src/runtime/routes/conversation-management-routes.ts +108 -0
  311. package/src/runtime/routes/conversation-routes.ts +301 -27
  312. package/src/runtime/routes/conversation-starter-routes.ts +78 -16
  313. package/src/runtime/routes/guardian-action-routes.ts +24 -13
  314. package/src/runtime/routes/host-browser-routes.ts +279 -0
  315. package/src/runtime/routes/host-file-routes.ts +9 -1
  316. package/src/runtime/routes/identity-routes.ts +259 -16
  317. package/src/runtime/routes/log-export-routes.ts +42 -22
  318. package/src/runtime/routes/memory-item-routes.ts +1 -7
  319. package/src/runtime/routes/migration-routes.ts +87 -2
  320. package/src/runtime/routes/oauth-apps.ts +15 -17
  321. package/src/runtime/routes/oauth-providers.ts +4 -0
  322. package/src/runtime/routes/schedule-routes.ts +24 -11
  323. package/src/runtime/routes/settings-routes.ts +9 -97
  324. package/src/runtime/routes/skills-routes.ts +52 -2
  325. package/src/runtime/routes/subagents-routes.ts +14 -10
  326. package/src/runtime/routes/usage-routes.ts +8 -7
  327. package/src/runtime/routes/workspace-routes.test.ts +22 -0
  328. package/src/runtime/routes/workspace-routes.ts +8 -1
  329. package/src/runtime/routes/workspace-utils.ts +2 -0
  330. package/src/schedule/scheduler.ts +7 -5
  331. package/src/security/ces-credential-client.ts +20 -0
  332. package/src/security/ces-rpc-credential-backend.ts +17 -0
  333. package/src/security/credential-backend.ts +5 -0
  334. package/src/security/oauth2.ts +42 -25
  335. package/src/security/secure-keys.ts +118 -25
  336. package/src/security/token-manager.ts +23 -10
  337. package/src/skills/catalog-files.ts +492 -0
  338. package/src/subagent/manager.ts +131 -26
  339. package/src/subagent/types.ts +19 -0
  340. package/src/tools/apps/executors.ts +11 -2
  341. package/src/tools/browser/__tests__/auth-detector.test.ts +202 -108
  342. package/src/tools/browser/auth-detector.ts +43 -12
  343. package/src/tools/browser/browser-execution.ts +645 -340
  344. package/src/tools/browser/browser-manager.ts +36 -12
  345. package/src/tools/browser/cdp-client/__tests__/accessibility-snapshot.test.ts +318 -0
  346. package/src/tools/browser/cdp-client/__tests__/cdp-dom-helpers.test.ts +1175 -0
  347. package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +870 -0
  348. package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +330 -0
  349. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +377 -0
  350. package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-nested-frames.json +64 -0
  351. package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-simple.json +69 -0
  352. package/src/tools/browser/cdp-client/__tests__/local-cdp-client.test.ts +310 -0
  353. package/src/tools/browser/cdp-client/__tests__/types.test.ts +96 -0
  354. package/src/tools/browser/cdp-client/accessibility-snapshot.ts +387 -0
  355. package/src/tools/browser/cdp-client/cdp-dom-helpers.ts +695 -0
  356. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/discovery.test.ts +743 -0
  357. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +580 -0
  358. package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +578 -0
  359. package/src/tools/browser/cdp-client/cdp-inspect/ws-transport.ts +579 -0
  360. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +635 -0
  361. package/src/tools/browser/cdp-client/errors.ts +34 -0
  362. package/src/tools/browser/cdp-client/extension-cdp-client.ts +125 -0
  363. package/src/tools/browser/cdp-client/factory.ts +204 -0
  364. package/src/tools/browser/cdp-client/index.ts +14 -0
  365. package/src/tools/browser/cdp-client/local-cdp-client.ts +187 -0
  366. package/src/tools/browser/cdp-client/types.ts +52 -0
  367. package/src/tools/filesystem/edit.ts +1 -1
  368. package/src/tools/filesystem/list.ts +1 -1
  369. package/src/tools/filesystem/read.ts +1 -1
  370. package/src/tools/filesystem/write.ts +2 -1
  371. package/src/tools/host-filesystem/edit.ts +1 -1
  372. package/src/tools/host-filesystem/read.ts +12 -15
  373. package/src/tools/host-filesystem/write.ts +1 -1
  374. package/src/tools/host-terminal/host-shell.ts +21 -16
  375. package/src/tools/permission-checker.ts +77 -82
  376. package/src/tools/registry.ts +0 -2
  377. package/src/tools/secret-detection-handler.ts +34 -0
  378. package/src/tools/shared/filesystem/image-read.ts +61 -40
  379. package/src/tools/subagent/spawn.ts +47 -3
  380. package/src/tools/subagent/status.ts +2 -0
  381. package/src/tools/system/register.ts +2 -16
  382. package/src/tools/terminal/safe-env.ts +7 -0
  383. package/src/tools/terminal/shell.ts +21 -16
  384. package/src/tools/tool-approval-handler.ts +48 -2
  385. package/src/tools/types.ts +2 -0
  386. package/src/util/platform.ts +14 -19
  387. package/src/workspace/top-level-renderer.ts +19 -1
  388. package/src/__tests__/chrome-cdp.test.ts +0 -419
  389. package/src/__tests__/permission-mode-sse.test.ts +0 -418
  390. package/src/__tests__/permission-mode-store.test.ts +0 -277
  391. package/src/browser-extension-relay/protocol.ts +0 -63
  392. package/src/browser-extension-relay/server.ts +0 -203
  393. package/src/config/schemas/sandbox.ts +0 -14
  394. package/src/permissions/permission-mode-store.ts +0 -180
  395. package/src/tools/browser/chrome-cdp.ts +0 -239
  396. package/src/tools/system/set-permission-mode.ts +0 -103
@@ -13,6 +13,11 @@ import { z } from "zod";
13
13
  import { getConversationByKey } from "../../memory/conversation-key-store.js";
14
14
  import { addRule } from "../../permissions/trust-store.js";
15
15
  import type { UserDecision } from "../../permissions/types.js";
16
+ import {
17
+ isConversationHostAccessDecision,
18
+ isConversationHostAccessEnablePrompt,
19
+ isPermissionControlsV2Enabled,
20
+ } from "../../permissions/v2-consent-policy.js";
16
21
  import { getTool } from "../../tools/registry.js";
17
22
  import { getLogger } from "../../util/logger.js";
18
23
  import { requireBoundGuardian } from "../auth/require-bound-guardian.js";
@@ -23,6 +28,39 @@ import * as pendingInteractions from "../pending-interactions.js";
23
28
 
24
29
  const log = getLogger("approval-routes");
25
30
 
31
+ function canonicalizeV2ConfirmDecision(params: {
32
+ decision: string;
33
+ interaction: NonNullable<ReturnType<typeof pendingInteractions.get>>;
34
+ }): UserDecision | null {
35
+ const { decision, interaction } = params;
36
+ if (decision === "allow" || decision === "deny") {
37
+ return decision;
38
+ }
39
+
40
+ const details = interaction.confirmationDetails;
41
+ if (!details || isConversationHostAccessEnablePrompt(details)) {
42
+ return null;
43
+ }
44
+
45
+ if (
46
+ (decision === "allow_10m" || decision === "allow_conversation") &&
47
+ details.temporaryOptionsAvailable?.includes(decision)
48
+ ) {
49
+ return "allow";
50
+ }
51
+
52
+ if (
53
+ (decision === "always_allow" ||
54
+ decision === "always_allow_high_risk" ||
55
+ decision === "always_deny") &&
56
+ details.persistentDecisionsAllowed
57
+ ) {
58
+ return decision === "always_deny" ? "deny" : "allow";
59
+ }
60
+
61
+ return null;
62
+ }
63
+
26
64
  /**
27
65
  * POST /v1/confirm — resolve a pending confirmation by requestId.
28
66
  * Requires AuthContext with guardian-bound actor.
@@ -47,6 +85,25 @@ export async function handleConfirm(
47
85
  return httpError("BAD_REQUEST", "requestId is required", 400);
48
86
  }
49
87
 
88
+ const peeked = pendingInteractions.get(requestId);
89
+ if (!peeked) {
90
+ log.warn(
91
+ { requestId, decision },
92
+ "Confirmation POST for unknown requestId (already consumed or never registered)",
93
+ );
94
+ return httpError(
95
+ "NOT_FOUND",
96
+ "No pending interaction found for this requestId",
97
+ 404,
98
+ );
99
+ }
100
+
101
+ const v2Enabled = isPermissionControlsV2Enabled();
102
+ const effectiveDecision = v2Enabled
103
+ ? typeof decision === "string"
104
+ ? canonicalizeV2ConfirmDecision({ decision, interaction: peeked })
105
+ : null
106
+ : decision;
50
107
  const validConfirmDecisions = [
51
108
  "allow",
52
109
  "allow_10m",
@@ -57,28 +114,37 @@ export async function handleConfirm(
57
114
  "always_allow_high_risk",
58
115
  ];
59
116
  if (
60
- typeof decision !== "string" ||
61
- !validConfirmDecisions.includes(decision)
117
+ (v2Enabled && effectiveDecision == null) ||
118
+ (!v2Enabled &&
119
+ (typeof decision !== "string" ||
120
+ !validConfirmDecisions.includes(decision)))
62
121
  ) {
63
122
  return httpError(
64
123
  "BAD_REQUEST",
65
- `decision must be one of: ${validConfirmDecisions.join(", ")}`,
124
+ v2Enabled
125
+ ? "decision must resolve to allow or deny under permission-controls-v2"
126
+ : `decision must be one of: ${validConfirmDecisions.join(", ")}`,
66
127
  400,
67
128
  );
68
129
  }
69
130
 
70
- // Peek first (non-destructive) so validation failures don't consume the
71
- // pending interaction — the client can retry with corrected values.
72
- const peeked = pendingInteractions.get(requestId);
73
- if (!peeked) {
74
- log.warn(
75
- { requestId, decision },
76
- "Confirmation POST for unknown requestId (already consumed or never registered)",
131
+ if (
132
+ peeked.confirmationDetails &&
133
+ isConversationHostAccessEnablePrompt(peeked.confirmationDetails) &&
134
+ !isConversationHostAccessDecision(effectiveDecision as UserDecision)
135
+ ) {
136
+ return httpError(
137
+ "FORBIDDEN",
138
+ "Conversation host-access prompts only accept allow or deny",
139
+ 403,
77
140
  );
141
+ }
142
+
143
+ if (v2Enabled && (selectedPattern || selectedScope)) {
78
144
  return httpError(
79
- "NOT_FOUND",
80
- "No pending interaction found for this requestId",
81
- 404,
145
+ "FORBIDDEN",
146
+ "Scoped or persistent approval selections are not supported under permission-controls-v2",
147
+ 403,
82
148
  );
83
149
  }
84
150
 
@@ -138,7 +204,7 @@ export async function handleConfirm(
138
204
  log.info(
139
205
  {
140
206
  requestId,
141
- decision,
207
+ decision: effectiveDecision,
142
208
  toolName: interaction.confirmationDetails?.toolName,
143
209
  conversationId: interaction.conversationId,
144
210
  },
@@ -147,13 +213,13 @@ export async function handleConfirm(
147
213
 
148
214
  // ACP permissions: resolve directly without a Conversation object.
149
215
  if (interaction.directResolve) {
150
- interaction.directResolve(decision as UserDecision);
216
+ interaction.directResolve(effectiveDecision as UserDecision);
151
217
  return Response.json({ accepted: true });
152
218
  }
153
219
 
154
220
  interaction.conversation!.handleConfirmationResponse(
155
221
  requestId,
156
- decision as UserDecision,
222
+ effectiveDecision as UserDecision,
157
223
  selectedPattern,
158
224
  selectedScope,
159
225
  undefined,
@@ -233,6 +299,14 @@ export async function handleTrustRule(
233
299
  const authError = requireBoundGuardian(authContext);
234
300
  if (authError) return authError;
235
301
 
302
+ if (isPermissionControlsV2Enabled()) {
303
+ return httpError(
304
+ "FORBIDDEN",
305
+ "Persistent trust rules are not supported under permission-controls-v2",
306
+ 403,
307
+ );
308
+ }
309
+
236
310
  const body = (await req.json()) as {
237
311
  requestId?: string;
238
312
  pattern?: string;
@@ -0,0 +1,229 @@
1
+ /**
2
+ * Route handler for the `assistant browser chrome relay` CLI shim.
3
+ *
4
+ * Accepts a single CDP command from out-of-process callers (the CLI
5
+ * subprocess spawned by skill scripts) and routes it to the user's
6
+ * Chrome via the connected chrome-extension WebSocket. The legacy
7
+ * relay CLI was deleted with PR #24329; this route is the runtime
8
+ * surface that lets the in-tree Amazon and Influencer skills keep
9
+ * shelling out to `assistant browser chrome relay <action>` until
10
+ * they migrate onto the new CDP-based skill API.
11
+ *
12
+ * Round-trip:
13
+ * 1. Caller POSTs `{ cdpMethod, cdpParams, cdpSessionId }`.
14
+ * 2. We register a pending interaction with a `directBrowserResolve`
15
+ * callback (no Conversation attached) and push a host_browser_request
16
+ * frame onto the connected chrome-extension WebSocket.
17
+ * 3. The chrome extension drives chrome.debugger and POSTs the result
18
+ * to /v1/host-browser-result.
19
+ * 4. host-browser-routes invokes our directBrowserResolve callback,
20
+ * which resolves the awaiting promise here.
21
+ * 5. We return `{ result | error }` to the caller.
22
+ *
23
+ * If no chrome extension is connected we fail fast with 503 — the legacy
24
+ * Amazon/Influencer scripts treat that as a recoverable error and prompt
25
+ * the user to load the extension.
26
+ */
27
+ import { v4 as uuid } from "uuid";
28
+ import { z } from "zod";
29
+
30
+ import { findGuardianForChannel } from "../../contacts/contact-store.js";
31
+ import type { ServerMessage } from "../../daemon/message-protocol.js";
32
+ import { getLogger } from "../../util/logger.js";
33
+ import { getChromeExtensionRegistry } from "../chrome-extension-registry.js";
34
+ import { httpError } from "../http-errors.js";
35
+ import type { RouteDefinition } from "../http-router.js";
36
+ import * as pendingInteractions from "../pending-interactions.js";
37
+
38
+ const log = getLogger("browser-cdp-routes");
39
+
40
+ /** Default per-call timeout while waiting for the chrome-extension result POST. */
41
+ const DEFAULT_TIMEOUT_MS = 30_000;
42
+
43
+ /** Synthetic conversation id stamped on host_browser_request envelopes from the CLI shim. */
44
+ const CLI_FAKE_CONVERSATION_ID = "cli-browser-relay";
45
+
46
+ const RequestBody = z.object({
47
+ cdpMethod: z.string().min(1),
48
+ cdpParams: z.record(z.string(), z.unknown()).optional(),
49
+ cdpSessionId: z.string().optional(),
50
+ /** Optional client-side timeout hint, in milliseconds. */
51
+ timeoutMs: z.number().int().positive().max(120_000).optional(),
52
+ });
53
+
54
+ const ResponseBody = z.object({
55
+ result: z.unknown().optional(),
56
+ error: z
57
+ .object({
58
+ code: z.string(),
59
+ message: z.string(),
60
+ })
61
+ .optional(),
62
+ });
63
+
64
+ /**
65
+ * Resolve the local guardian principal id used as the chrome-extension
66
+ * registry key. Mirrors the lookup performed by
67
+ * /v1/browser-extension-pair so the registry get() / send() calls hit
68
+ * the same key.
69
+ */
70
+ function resolveLocalGuardianId(): string | null {
71
+ try {
72
+ const result = findGuardianForChannel("vellum");
73
+ if (result?.contact.principalId) {
74
+ return result.contact.principalId;
75
+ }
76
+ } catch (err) {
77
+ log.warn({ err }, "Failed to look up local vellum guardian");
78
+ }
79
+ return null;
80
+ }
81
+
82
+ /**
83
+ * POST /v1/browser-cdp — drive a single CDP command through the chrome-
84
+ * extension proxy on behalf of an out-of-process CLI caller.
85
+ *
86
+ * Authenticated like other /v1/* routes (the route policy below requires
87
+ * `settings.write`, which the CLI shim's daemon-delivery JWT carries via
88
+ * the `gateway_service_v1` profile).
89
+ */
90
+ export async function handleBrowserCdp(req: Request): Promise<Response> {
91
+ let body: unknown;
92
+ try {
93
+ body = await req.json();
94
+ } catch {
95
+ return httpError("BAD_REQUEST", "invalid JSON body", 400);
96
+ }
97
+
98
+ const parsed = RequestBody.safeParse(body);
99
+ if (!parsed.success) {
100
+ return httpError(
101
+ "BAD_REQUEST",
102
+ `invalid request body: ${parsed.error.message}`,
103
+ 400,
104
+ );
105
+ }
106
+
107
+ const { cdpMethod, cdpParams, cdpSessionId, timeoutMs } = parsed.data;
108
+
109
+ const guardianId = resolveLocalGuardianId();
110
+ if (!guardianId) {
111
+ return Response.json(
112
+ {
113
+ error: {
114
+ code: "EXTENSION_NOT_CONNECTED",
115
+ message:
116
+ "No local vellum guardian — load the chrome extension and pair it first",
117
+ },
118
+ },
119
+ { status: 503 },
120
+ );
121
+ }
122
+
123
+ const registry = getChromeExtensionRegistry();
124
+ if (!registry.get(guardianId)) {
125
+ return Response.json(
126
+ {
127
+ error: {
128
+ code: "EXTENSION_NOT_CONNECTED",
129
+ message:
130
+ "No chrome extension connected for the local guardian — open Chrome, load the Vellum extension, and click Connect",
131
+ },
132
+ },
133
+ { status: 503 },
134
+ );
135
+ }
136
+
137
+ const requestId = uuid();
138
+ const effectiveTimeoutMs = timeoutMs ?? DEFAULT_TIMEOUT_MS;
139
+
140
+ const result = await new Promise<{ content: string; isError: boolean }>(
141
+ (resolve) => {
142
+ const timer = setTimeout(() => {
143
+ // Drain the pending interaction so a late-arriving POST from
144
+ // the extension lands in 404 territory rather than resolving a
145
+ // promise no one is awaiting.
146
+ pendingInteractions.resolve(requestId);
147
+ resolve({
148
+ content: `Timed out waiting for chrome extension result after ${effectiveTimeoutMs}ms`,
149
+ isError: true,
150
+ });
151
+ }, effectiveTimeoutMs);
152
+
153
+ pendingInteractions.register(requestId, {
154
+ conversation: null,
155
+ conversationId: CLI_FAKE_CONVERSATION_ID,
156
+ kind: "host_browser",
157
+ directBrowserResolve: (response) => {
158
+ clearTimeout(timer);
159
+ resolve(response);
160
+ },
161
+ });
162
+
163
+ const envelope: ServerMessage = {
164
+ type: "host_browser_request",
165
+ requestId,
166
+ conversationId: CLI_FAKE_CONVERSATION_ID,
167
+ cdpMethod,
168
+ cdpParams,
169
+ ...(cdpSessionId !== undefined ? { cdpSessionId } : {}),
170
+ timeout_seconds: Math.ceil(effectiveTimeoutMs / 1000),
171
+ } as ServerMessage;
172
+
173
+ const ok = registry.send(guardianId, envelope);
174
+ if (!ok) {
175
+ clearTimeout(timer);
176
+ pendingInteractions.resolve(requestId);
177
+ resolve({
178
+ content:
179
+ "Failed to send host_browser_request to chrome extension (no active connection)",
180
+ isError: true,
181
+ });
182
+ }
183
+ },
184
+ );
185
+
186
+ if (result.isError) {
187
+ return Response.json(
188
+ {
189
+ error: {
190
+ code: "CDP_ERROR",
191
+ message: result.content,
192
+ },
193
+ },
194
+ { status: 502 },
195
+ );
196
+ }
197
+
198
+ // The chrome extension serializes the CDP result via JSON.stringify(frame.result).
199
+ // Parse it back here so the CLI shim sees a structured object instead of
200
+ // a string-wrapped JSON blob.
201
+ let parsedResult: unknown;
202
+ try {
203
+ parsedResult = JSON.parse(result.content);
204
+ } catch {
205
+ parsedResult = result.content;
206
+ }
207
+
208
+ return Response.json({ result: parsedResult });
209
+ }
210
+
211
+ // ---------------------------------------------------------------------------
212
+ // Route definitions
213
+ // ---------------------------------------------------------------------------
214
+
215
+ export function browserCdpRouteDefinitions(): RouteDefinition[] {
216
+ return [
217
+ {
218
+ endpoint: "browser-cdp",
219
+ method: "POST",
220
+ summary: "Drive a single CDP command via the chrome extension",
221
+ description:
222
+ "Routes a Chrome DevTools Protocol command through the connected chrome extension. Used by the `assistant browser chrome relay` CLI shim that the in-tree Amazon and Influencer skills shell out to.",
223
+ tags: ["browser"],
224
+ requestBody: RequestBody,
225
+ responseBody: ResponseBody,
226
+ handler: async ({ req }) => handleBrowserCdp(req),
227
+ },
228
+ ];
229
+ }