@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
@@ -49,6 +49,7 @@ const MAX_LOG_PAYLOAD_BYTES = 10 * 1024 * 1024;
49
49
  interface ExportRequestBody {
50
50
  auditLimit?: number;
51
51
  conversationId?: string; // scope to a single conversation
52
+ full?: boolean; // include all conversation data (messages + LLM logs) — use for test data debugging
52
53
  startTime?: number; // epoch ms — lower bound (inclusive)
53
54
  endTime?: number; // epoch ms — upper bound (inclusive)
54
55
  }
@@ -67,7 +68,7 @@ async function handleExport(body: ExportRequestBody): Promise<Response> {
67
68
  const staging = mkdtempSync(join(tmpdir(), "vellum-export-"));
68
69
 
69
70
  try {
70
- const { conversationId, startTime, endTime } = body;
71
+ const { conversationId, full, startTime, endTime } = body;
71
72
 
72
73
  // --- Audit data ---
73
74
  const limit = body.auditLimit ?? 1000;
@@ -98,14 +99,19 @@ async function handleExport(body: ExportRequestBody): Promise<Response> {
98
99
  "utf-8",
99
100
  );
100
101
 
101
- // --- Conversation-scoped data tables ---
102
- if (conversationId) {
102
+ // --- Conversation data tables ---
103
+ // Included when scoped to a single conversation OR when all conversations are requested.
104
+ if (conversationId || full) {
105
+ const conversationFilter = conversationId
106
+ ? [eq(messages.conversationId, conversationId)]
107
+ : [];
108
+
103
109
  const messageRows = db
104
110
  .select()
105
111
  .from(messages)
106
112
  .where(
107
113
  and(
108
- eq(messages.conversationId, conversationId),
114
+ ...conversationFilter,
109
115
  startTime ? gte(messages.createdAt, startTime) : undefined,
110
116
  endTime ? lte(messages.createdAt, endTime) : undefined,
111
117
  ),
@@ -118,12 +124,16 @@ async function handleExport(body: ExportRequestBody): Promise<Response> {
118
124
  "utf-8",
119
125
  );
120
126
 
127
+ const llmConversationFilter = conversationId
128
+ ? [eq(llmRequestLogs.conversationId, conversationId)]
129
+ : [];
130
+
121
131
  const llmLogRows = db
122
132
  .select()
123
133
  .from(llmRequestLogs)
124
134
  .where(
125
135
  and(
126
- eq(llmRequestLogs.conversationId, conversationId),
136
+ ...llmConversationFilter,
127
137
  startTime ? gte(llmRequestLogs.createdAt, startTime) : undefined,
128
138
  endTime ? lte(llmRequestLogs.createdAt, endTime) : undefined,
129
139
  ),
@@ -136,12 +146,16 @@ async function handleExport(body: ExportRequestBody): Promise<Response> {
136
146
  "utf-8",
137
147
  );
138
148
 
149
+ const usageConversationFilter = conversationId
150
+ ? [eq(llmUsageEvents.conversationId, conversationId)]
151
+ : [];
152
+
139
153
  const usageRows = db
140
154
  .select()
141
155
  .from(llmUsageEvents)
142
156
  .where(
143
157
  and(
144
- eq(llmUsageEvents.conversationId, conversationId),
158
+ ...usageConversationFilter,
145
159
  startTime ? gte(llmUsageEvents.createdAt, startTime) : undefined,
146
160
  endTime ? lte(llmUsageEvents.createdAt, endTime) : undefined,
147
161
  ),
@@ -265,22 +279,21 @@ async function handleExport(body: ExportRequestBody): Promise<Response> {
265
279
  }
266
280
 
267
281
  // --- Export manifest ---
268
- const manifest = conversationId
269
- ? {
270
- type: "conversation-export" as const,
271
- conversationId,
272
- assistantVersion: APP_VERSION,
273
- commitSha: COMMIT_SHA,
274
- ...(startTime !== undefined ? { startTime } : {}),
275
- ...(endTime !== undefined ? { endTime } : {}),
276
- exportedAt: new Date().toISOString(),
277
- }
278
- : {
279
- type: "global-export" as const,
280
- assistantVersion: APP_VERSION,
281
- commitSha: COMMIT_SHA,
282
- exportedAt: new Date().toISOString(),
283
- };
282
+ const manifestType = conversationId
283
+ ? ("conversation-export" as const)
284
+ : full
285
+ ? ("full-export" as const)
286
+ : ("global-export" as const);
287
+ const manifest = {
288
+ type: manifestType,
289
+ ...(conversationId ? { conversationId } : {}),
290
+ ...(full ? { full: true } : {}),
291
+ assistantVersion: APP_VERSION,
292
+ commitSha: COMMIT_SHA,
293
+ ...(startTime !== undefined ? { startTime } : {}),
294
+ ...(endTime !== undefined ? { endTime } : {}),
295
+ exportedAt: new Date().toISOString(),
296
+ };
284
297
  writeFileSync(
285
298
  join(staging, "export-manifest.json"),
286
299
  JSON.stringify(manifest, null, 2),
@@ -294,6 +307,7 @@ async function handleExport(body: ExportRequestBody): Promise<Response> {
294
307
  totalBytes,
295
308
  hasConfig: configSnapshot !== undefined,
296
309
  conversationId: conversationId ?? null,
310
+ full: full ?? false,
297
311
  workspaceEntries: workspaceResult.entries.length,
298
312
  workspaceBytes: workspaceResult.totalBytes,
299
313
  },
@@ -441,6 +455,12 @@ export function logExportRouteDefinitions(): RouteDefinition[] {
441
455
  .string()
442
456
  .optional()
443
457
  .describe("Scope to a single conversation"),
458
+ full: z
459
+ .boolean()
460
+ .optional()
461
+ .describe(
462
+ "Full export — include messages, LLM request logs, and usage events for all conversations. Use for test data debugging.",
463
+ ),
444
464
  startTime: z.number().optional().describe("Lower bound epoch ms"),
445
465
  endTime: z.number().optional().describe("Upper bound epoch ms"),
446
466
  });
@@ -712,15 +712,9 @@ export async function handleDeleteMemoryItem(
712
712
  return httpError("NOT_FOUND", "Memory item not found", 404);
713
713
  }
714
714
 
715
- // Hard-delete the node (cascades to edges and triggers via FK)
715
+ // Soft-delete the node (deleteNode sets fidelity='gone' and enqueues Qdrant cleanup)
716
716
  deleteNode(id);
717
717
 
718
- // Clean up Qdrant vectors asynchronously
719
- enqueueMemoryJob("delete_qdrant_vectors", {
720
- targetType: "graph_node",
721
- targetId: id,
722
- });
723
-
724
718
  return new Response(null, { status: 204 });
725
719
  }
726
720
 
@@ -21,6 +21,11 @@ import { invalidateConfigCache } from "../../config/loader.js";
21
21
  import { getDb, resetDb } from "../../memory/db-connection.js";
22
22
  import { validateMigrationState } from "../../memory/migrations/validate-migration-state.js";
23
23
  import { clearCache as clearTrustCache } from "../../permissions/trust-store.js";
24
+ import {
25
+ bulkSetSecureKeysAsync,
26
+ getSecureKeyResultAsync,
27
+ listSecureKeysAsync,
28
+ } from "../../security/secure-keys.js";
24
29
  import { getLogger } from "../../util/logger.js";
25
30
  import {
26
31
  getDbPath,
@@ -34,7 +39,10 @@ import {
34
39
  analyzeImport,
35
40
  DefaultPathResolver,
36
41
  } from "../migrations/vbundle-import-analyzer.js";
37
- import { commitImport } from "../migrations/vbundle-importer.js";
42
+ import {
43
+ commitImport,
44
+ extractCredentialsFromBundle,
45
+ } from "../migrations/vbundle-importer.js";
38
46
  import { validateVBundle } from "../migrations/vbundle-validator.js";
39
47
 
40
48
  const log = getLogger("migration-routes");
@@ -146,6 +154,27 @@ export async function handleMigrationExport(req: Request): Promise<Response> {
146
154
  let cleanup: (() => Promise<void>) | undefined;
147
155
 
148
156
  try {
157
+ // Read all stored credentials to include in the export bundle
158
+ const credentialList = await listSecureKeysAsync();
159
+ const credentials: Array<{ account: string; value: string }> = [];
160
+ if (credentialList.unreachable) {
161
+ log.warn(
162
+ "Credential store is unreachable — export will not include credentials",
163
+ );
164
+ } else {
165
+ for (const account of credentialList.accounts) {
166
+ const result = await getSecureKeyResultAsync(account);
167
+ if (result.unreachable) {
168
+ log.warn(
169
+ { account },
170
+ "Credential store unreachable when reading credential — skipping",
171
+ );
172
+ } else if (result.value != null) {
173
+ credentials.push({ account, value: result.value });
174
+ }
175
+ }
176
+ }
177
+
149
178
  const result = await streamExportVBundle({
150
179
  // hooksDir is intentionally omitted — hooks now live under workspace/hooks/
151
180
  // and are included in the workspace walk. Passing hooksDir separately would
@@ -153,6 +182,7 @@ export async function handleMigrationExport(req: Request): Promise<Response> {
153
182
  workspaceDir: getWorkspaceDir(),
154
183
  source: "runtime-export",
155
184
  description,
185
+ credentials,
156
186
  checkpoint: () => {
157
187
  const dbPath = getDbPath();
158
188
  try {
@@ -196,6 +226,7 @@ export async function handleMigrationExport(req: Request): Promise<Response> {
196
226
  "Content-Length": String(size),
197
227
  "X-Vbundle-Schema-Version": manifest.schema_version,
198
228
  "X-Vbundle-Manifest-Sha256": manifest.manifest_sha256,
229
+ "X-Vbundle-Credentials-Included": String(credentials.length),
199
230
  },
200
231
  });
201
232
  } catch (err) {
@@ -444,6 +475,57 @@ export async function handleMigrationImport(req: Request): Promise<Response> {
444
475
  );
445
476
  }
446
477
 
478
+ // Import credentials from the bundle into CES (non-blocking — failures
479
+ // are logged as warnings but do not fail the overall import).
480
+ let credentialsImported:
481
+ | {
482
+ total: number;
483
+ succeeded: number;
484
+ failed: number;
485
+ failedAccounts: string[];
486
+ }
487
+ | undefined;
488
+
489
+ if (validation.entries) {
490
+ const bundleCredentials = extractCredentialsFromBundle(
491
+ validation.entries,
492
+ validation.manifest!,
493
+ );
494
+ if (bundleCredentials.length > 0) {
495
+ try {
496
+ const credResults = await bulkSetSecureKeysAsync(bundleCredentials);
497
+ const failedResults = credResults.filter((r) => !r.ok);
498
+ if (failedResults.length > 0) {
499
+ log.warn(
500
+ { failed: failedResults.map((f) => f.account) },
501
+ "Some credentials failed to import",
502
+ );
503
+ }
504
+ log.info(
505
+ { total: bundleCredentials.length, failed: failedResults.length },
506
+ "Credential import complete",
507
+ );
508
+ const succeeded = bundleCredentials.length - failedResults.length;
509
+ credentialsImported = {
510
+ total: bundleCredentials.length,
511
+ succeeded,
512
+ failed: failedResults.length,
513
+ failedAccounts: failedResults.map((f) => f.account),
514
+ };
515
+ if (failedResults.length > 0) {
516
+ result.report.warnings.push(
517
+ `Imported ${succeeded} credential(s), ${failedResults.length} failed`,
518
+ );
519
+ }
520
+ } catch (err) {
521
+ log.warn({ err }, "Credential import failed entirely");
522
+ result.report.warnings.push(
523
+ `Credential import failed: ${err instanceof Error ? err.message : String(err)}`,
524
+ );
525
+ }
526
+ }
527
+ }
528
+
447
529
  // Invalidate in-process caches so imported settings.json and trust.json take effect
448
530
  invalidateConfigCache();
449
531
  clearTrustCache();
@@ -463,7 +545,10 @@ export async function handleMigrationImport(req: Request): Promise<Response> {
463
545
  // Don't fail the import if validation itself errors
464
546
  }
465
547
 
466
- return Response.json(result.report);
548
+ return Response.json({
549
+ ...result.report,
550
+ ...(credentialsImported ? { credentialsImported } : {}),
551
+ });
467
552
  } catch (err) {
468
553
  log.error({ err }, "Unexpected error during import commit");
469
554
  return httpError(
@@ -60,8 +60,8 @@ export function oauthAppsRouteDefinitions(): RouteDefinition[] {
60
60
  endpoint: "oauth/apps",
61
61
  method: "GET",
62
62
  handler: ({ url }) => {
63
- const providerKey = url.searchParams.get("provider_key");
64
- if (!providerKey) {
63
+ const provider = url.searchParams.get("provider_key");
64
+ if (!provider) {
65
65
  return httpError(
66
66
  "BAD_REQUEST",
67
67
  "provider_key query parameter is required",
@@ -70,20 +70,18 @@ export function oauthAppsRouteDefinitions(): RouteDefinition[] {
70
70
  }
71
71
 
72
72
  const allApps = listApps();
73
- const filtered = allApps.filter(
74
- (row) => row.providerKey === providerKey,
75
- );
73
+ const filtered = allApps.filter((row) => row.provider === provider);
76
74
 
77
- const providerRow = getProvider(providerKey);
78
- const provider = providerRow
75
+ const providerRow = getProvider(provider);
76
+ const providerSummary = providerRow
79
77
  ? serializeProviderSummary(providerRow)
80
78
  : null;
81
79
 
82
80
  return Response.json({
83
- provider,
81
+ provider: providerSummary,
84
82
  apps: filtered.map((row) => ({
85
83
  id: row.id,
86
- provider_key: row.providerKey,
84
+ provider_key: row.provider,
87
85
  client_id: row.clientId,
88
86
  created_at: row.createdAt,
89
87
  updated_at: row.updatedAt,
@@ -138,7 +136,7 @@ export function oauthAppsRouteDefinitions(): RouteDefinition[] {
138
136
  {
139
137
  app: {
140
138
  id: app.id,
141
- provider_key: app.providerKey,
139
+ provider_key: app.provider,
142
140
  client_id: app.clientId,
143
141
  created_at: app.createdAt,
144
142
  updated_at: app.updatedAt,
@@ -165,9 +163,9 @@ export function oauthAppsRouteDefinitions(): RouteDefinition[] {
165
163
  }
166
164
 
167
165
  // Disconnect all connections for this app first to clean up tokens.
168
- const connections = listConnections(app.providerKey, app.clientId);
166
+ const connections = listConnections(app.provider, app.clientId);
169
167
  for (const conn of connections) {
170
- await disconnectOAuthProvider(app.providerKey, app.clientId, conn.id);
168
+ await disconnectOAuthProvider(app.provider, app.clientId, conn.id);
171
169
  }
172
170
 
173
171
  await deleteApp(params.id);
@@ -190,12 +188,12 @@ export function oauthAppsRouteDefinitions(): RouteDefinition[] {
190
188
  );
191
189
  }
192
190
 
193
- const connections = listConnections(app.providerKey, app.clientId);
191
+ const connections = listConnections(app.provider, app.clientId);
194
192
 
195
193
  return Response.json({
196
194
  connections: connections.map((row) => ({
197
195
  id: row.id,
198
- provider_key: row.providerKey,
196
+ provider_key: row.provider,
199
197
  account_info: row.accountInfo,
200
198
  granted_scopes: parseGrantedScopes(row.grantedScopes),
201
199
  status: row.status,
@@ -223,7 +221,7 @@ export function oauthAppsRouteDefinitions(): RouteDefinition[] {
223
221
  }
224
222
 
225
223
  const result = await disconnectOAuthProvider(
226
- conn.providerKey,
224
+ conn.provider,
227
225
  undefined,
228
226
  conn.id,
229
227
  );
@@ -282,7 +280,7 @@ export function oauthAppsRouteDefinitions(): RouteDefinition[] {
282
280
  const clientSecret = await getAppClientSecret(app);
283
281
 
284
282
  const result = await orchestrateOAuthConnect({
285
- service: app.providerKey,
283
+ service: app.provider,
286
284
  clientId: app.clientId,
287
285
  clientSecret,
288
286
  requestedScopes: body.scopes,
@@ -292,7 +290,7 @@ export function oauthAppsRouteDefinitions(): RouteDefinition[] {
292
290
 
293
291
  if (result.success && result.deferred) {
294
292
  return Response.json({
295
- auth_url: result.authUrl,
293
+ auth_url: result.authorizeUrl,
296
294
  state: result.state,
297
295
  });
298
296
  }
@@ -44,6 +44,10 @@ export function oauthProvidersRouteDefinitions(): RouteDefinition[] {
44
44
  },
45
45
 
46
46
  // GET /v1/oauth/providers/:providerKey — Get a single provider.
47
+ // The path parameter name `providerKey` is preserved for backward
48
+ // compatibility with the published OpenAPI spec (operationId
49
+ // `oauth_providers_by_providerKey_get`). The actual URL the client hits
50
+ // (`/v1/oauth/providers/google`) is unchanged either way.
47
51
  {
48
52
  endpoint: "oauth/providers/:providerKey",
49
53
  method: "GET",
@@ -25,6 +25,10 @@ import type { RouteDefinition } from "../http-router.js";
25
25
  import type { SendMessageDeps } from "../http-types.js";
26
26
 
27
27
  const log = getLogger("schedule-routes");
28
+ const SCHEDULE_GUARDIAN_TRUST_CONTEXT = {
29
+ sourceChannel: "vellum",
30
+ trustClass: "guardian",
31
+ } as const;
28
32
 
29
33
  // ---------------------------------------------------------------------------
30
34
  // Handlers
@@ -202,17 +206,23 @@ async function handleRunScheduleNow(
202
206
  );
203
207
  }
204
208
  const conversation =
205
- await sendMessageDeps.getOrCreateConversation(conversationId);
209
+ await sendMessageDeps.getOrCreateConversation(conversationId, {
210
+ trustContext: SCHEDULE_GUARDIAN_TRUST_CONTEXT,
211
+ });
206
212
  conversation.taskRunId = taskRunId;
207
- await conversation.processMessage(
208
- message,
209
- [],
210
- () => {}, // no event callback for HTTP mode
211
- undefined,
212
- undefined,
213
- undefined,
214
- { isInteractive: false },
215
- );
213
+ try {
214
+ await conversation.processMessage(
215
+ message,
216
+ [],
217
+ () => {}, // no event callback for HTTP mode
218
+ undefined,
219
+ undefined,
220
+ undefined,
221
+ { isInteractive: false },
222
+ );
223
+ } finally {
224
+ conversation.taskRunId = undefined;
225
+ }
216
226
  },
217
227
  );
218
228
 
@@ -276,7 +286,10 @@ async function handleRunScheduleNow(
276
286
  throw new Error("sendMessageDeps not available for schedule execution");
277
287
  }
278
288
  const activeConversation =
279
- await sendMessageDeps.getOrCreateConversation(conversationId);
289
+ await sendMessageDeps.getOrCreateConversation(conversationId, {
290
+ trustContext: SCHEDULE_GUARDIAN_TRUST_CONTEXT,
291
+ });
292
+ activeConversation.taskRunId = undefined;
280
293
  await activeConversation.processMessage(
281
294
  schedule.message,
282
295
  [],
@@ -12,16 +12,11 @@ import { join } from "node:path";
12
12
 
13
13
  import { z } from "zod";
14
14
 
15
- import { isAssistantFeatureFlagEnabled } from "../../config/assistant-feature-flags.js";
16
15
  import {
17
16
  getPlatformBaseUrl,
18
17
  setIngressPublicBaseUrl,
19
18
  } from "../../config/env.js";
20
- import {
21
- getConfig,
22
- loadRawConfig,
23
- saveRawConfig,
24
- } from "../../config/loader.js";
19
+ import { loadRawConfig, saveRawConfig } from "../../config/loader.js";
25
20
  import { loadSkillCatalog } from "../../config/skills.js";
26
21
  import {
27
22
  computeGatewayTarget,
@@ -41,12 +36,6 @@ import {
41
36
  generateAllowlistOptions,
42
37
  generateScopeOptions,
43
38
  } from "../../permissions/checker.js";
44
- import {
45
- getMode,
46
- onModeChanged,
47
- setAskBeforeActing,
48
- setHostAccess,
49
- } from "../../permissions/permission-mode-store.js";
50
39
  import { getSecureKeyAsync } from "../../security/secure-keys.js";
51
40
  import { parseToolManifestFile } from "../../skills/tool-manifest.js";
52
41
  import {
@@ -72,24 +61,6 @@ import { resolveWorkspacePath } from "./workspace-utils.js";
72
61
 
73
62
  const log = getLogger("settings-routes");
74
63
 
75
- // ---------------------------------------------------------------------------
76
- // Permission mode SSE broadcast
77
- // ---------------------------------------------------------------------------
78
-
79
- onModeChanged((mode) => {
80
- assistantEventHub
81
- .publish(
82
- buildAssistantEvent(DAEMON_INTERNAL_ASSISTANT_ID, {
83
- type: "permission_mode_update",
84
- askBeforeActing: mode.askBeforeActing,
85
- hostAccess: mode.hostAccess,
86
- }),
87
- )
88
- .catch((err) => {
89
- log.warn({ err }, "Failed to publish permission_mode_update event");
90
- });
91
- });
92
-
93
64
  // ---------------------------------------------------------------------------
94
65
  // Voice config
95
66
  // ---------------------------------------------------------------------------
@@ -240,7 +211,7 @@ async function handleOAuthConnectStart(body: {
240
211
  try {
241
212
  // For HTTP, we cannot send `open_url` mid-request. The auth URL is
242
213
  // returned to the client to open.
243
- let authUrl: string | undefined;
214
+ let authorizeUrl: string | undefined;
244
215
 
245
216
  const result = await orchestrateOAuthConnect({
246
217
  service,
@@ -250,7 +221,7 @@ async function handleOAuthConnectStart(body: {
250
221
  callbackTransport: "loopback",
251
222
  isInteractive: true,
252
223
  openUrl: (url: string) => {
253
- authUrl = url;
224
+ authorizeUrl = url;
254
225
  },
255
226
  onDeferredComplete: (deferredResult) => {
256
227
  // Prefer accountInfo from oauth-store when available.
@@ -309,7 +280,9 @@ async function handleOAuthConnectStart(body: {
309
280
  return Response.json({
310
281
  ok: true,
311
282
  deferred: true,
312
- authUrl: result.authUrl,
283
+ // Wire key stays `authUrl` for backward compatibility with existing
284
+ // clients; the internal field on `result` is `authorizeUrl`.
285
+ authUrl: result.authorizeUrl,
313
286
  });
314
287
  }
315
288
 
@@ -326,7 +299,9 @@ async function handleOAuthConnectStart(body: {
326
299
  ok: true,
327
300
  grantedScopes: result.grantedScopes,
328
301
  accountInfo: responseAccountInfo,
329
- ...(authUrl ? { authUrl } : {}),
302
+ // Wire key stays `authUrl` for backward compatibility with existing
303
+ // clients; the local variable was renamed to `authorizeUrl`.
304
+ ...(authorizeUrl ? { authUrl: authorizeUrl } : {}),
330
305
  });
331
306
  } catch (err) {
332
307
  const message = err instanceof Error ? err.message : String(err);
@@ -921,68 +896,5 @@ export function settingsRouteDefinitions(): RouteDefinition[] {
921
896
  }
922
897
  },
923
898
  },
924
-
925
- // Permission mode (GET always available; PUT gated on feature flag)
926
- {
927
- endpoint: "permission-mode",
928
- method: "GET",
929
- policyKey: "permission-mode:GET",
930
- summary: "Get permission mode",
931
- description:
932
- "Return the current two-axis permission mode (askBeforeActing, hostAccess).",
933
- tags: ["settings"],
934
- responseBody: z.object({
935
- askBeforeActing: z.boolean(),
936
- hostAccess: z.boolean(),
937
- }),
938
- handler: () => {
939
- const mode = getMode();
940
- return Response.json({
941
- askBeforeActing: mode.askBeforeActing,
942
- hostAccess: mode.hostAccess,
943
- });
944
- },
945
- },
946
- {
947
- endpoint: "permission-mode",
948
- method: "PUT",
949
- policyKey: "permission-mode",
950
- summary: "Update permission mode",
951
- description:
952
- "Update the two-axis permission mode. Requires the permission-controls-v2 feature flag.",
953
- tags: ["settings"],
954
- requestBody: z.object({
955
- askBeforeActing: z.boolean().optional(),
956
- hostAccess: z.boolean().optional(),
957
- }),
958
- responseBody: z.object({
959
- askBeforeActing: z.boolean(),
960
- hostAccess: z.boolean(),
961
- }),
962
- handler: async ({ req }) => {
963
- const config = getConfig();
964
- if (!isAssistantFeatureFlagEnabled("permission-controls-v2", config)) {
965
- return httpError("NOT_FOUND", "Not found", 404);
966
- }
967
-
968
- const body = (await req.json()) as {
969
- askBeforeActing?: boolean;
970
- hostAccess?: boolean;
971
- };
972
-
973
- if (typeof body.askBeforeActing === "boolean") {
974
- setAskBeforeActing(body.askBeforeActing);
975
- }
976
- if (typeof body.hostAccess === "boolean") {
977
- setHostAccess(body.hostAccess);
978
- }
979
-
980
- const mode = getMode();
981
- return Response.json({
982
- askBeforeActing: mode.askBeforeActing,
983
- hostAccess: mode.hostAccess,
984
- });
985
- },
986
- },
987
899
  ];
988
900
  }