@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
@@ -312,7 +312,7 @@ Examples:
312
312
  });
313
313
  }
314
314
 
315
- // Build a lookup of oauth connections keyed by providerKey for enrichment.
315
+ // Build a lookup of oauth connections keyed by provider for enrichment.
316
316
  // listConnections() returns rows in no guaranteed order, so we compare
317
317
  // createdAt to keep the most recent active connection per provider —
318
318
  // matching the behaviour of getConnectionByProvider() used by inspect.
@@ -320,9 +320,9 @@ Examples:
320
320
  const connectionsByProvider = new Map<string, OAuthConnectionRow>();
321
321
  for (const conn of allConnections) {
322
322
  if (conn.status !== "active") continue;
323
- const existing = connectionsByProvider.get(conn.providerKey);
323
+ const existing = connectionsByProvider.get(conn.provider);
324
324
  if (!existing || conn.createdAt > existing.createdAt) {
325
- connectionsByProvider.set(conn.providerKey, conn);
325
+ connectionsByProvider.set(conn.provider, conn);
326
326
  }
327
327
  }
328
328
 
@@ -5,10 +5,77 @@ import { shouldAutoStartDaemon } from "../../daemon/connection-policy.js";
5
5
  import { ensureDaemonRunning } from "../../daemon/lifecycle.js";
6
6
 
7
7
  export function registerDefaultAction(program: Command): void {
8
- program.action(async () => {
8
+ program.action(async (_options: unknown, cmd: Command) => {
9
+ // Commander routes unknown subcommands to the root action as positional
10
+ // args instead of raising an error. Detect this case and fail with a
11
+ // helpful message so users don't silently get the interactive CLI when
12
+ // they mistype a command name.
13
+ if (cmd.args.length > 0) {
14
+ const unknown = cmd.args[0];
15
+ const available = cmd.commands.map((c) => c.name());
16
+ const suggestion = findClosestCommand(unknown, available);
17
+ const lines = [`unknown command '${unknown}'`];
18
+ if (suggestion) {
19
+ lines.push(`(Did you mean '${suggestion}'?)`);
20
+ }
21
+ lines.push(`Run 'assistant --help' to see a list of available commands.`);
22
+ cmd.error(lines.join("\n"), {
23
+ code: "commander.unknownCommand",
24
+ exitCode: 1,
25
+ });
26
+ return;
27
+ }
28
+
9
29
  if (shouldAutoStartDaemon()) {
10
30
  await ensureDaemonRunning();
11
31
  }
12
32
  await startCli();
13
33
  });
14
34
  }
35
+
36
+ /**
37
+ * Find the closest matching command name using Levenshtein distance.
38
+ * Returns the best match if the distance is ≤ 40% of the longer string's
39
+ * length, otherwise returns undefined.
40
+ */
41
+ function findClosestCommand(
42
+ input: string,
43
+ candidates: string[],
44
+ ): string | undefined {
45
+ let best: string | undefined;
46
+ let bestDist = Infinity;
47
+
48
+ for (const name of candidates) {
49
+ const dist = levenshtein(input.toLowerCase(), name.toLowerCase());
50
+ if (dist < bestDist) {
51
+ bestDist = dist;
52
+ best = name;
53
+ }
54
+ }
55
+
56
+ // Only suggest if the edit distance is at most 40% of the longer string
57
+ const maxLen = Math.max(input.length, best?.length ?? 0);
58
+ if (best && bestDist <= Math.ceil(maxLen * 0.4)) {
59
+ return best;
60
+ }
61
+ return undefined;
62
+ }
63
+
64
+ function levenshtein(a: string, b: string): number {
65
+ const m = a.length;
66
+ const n = b.length;
67
+ const dp: number[][] = Array.from({ length: m + 1 }, () =>
68
+ Array(n + 1).fill(0),
69
+ );
70
+ for (let i = 0; i <= m; i++) dp[i][0] = i;
71
+ for (let j = 0; j <= n; j++) dp[0][j] = j;
72
+ for (let i = 1; i <= m; i++) {
73
+ for (let j = 1; j <= n; j++) {
74
+ dp[i][j] =
75
+ a[i - 1] === b[j - 1]
76
+ ? dp[i - 1][j - 1]
77
+ : 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]);
78
+ }
79
+ }
80
+ return dp[m][n];
81
+ }
@@ -2,6 +2,7 @@ import { readFileSync, writeFileSync } from "node:fs";
2
2
 
3
3
  import type { Command } from "commander";
4
4
 
5
+ import { getAssistantDomain } from "../../config/env.js";
5
6
  import { VellumPlatformClient } from "../../platform/client.js";
6
7
  import { getCliLogger } from "../logger.js";
7
8
  import { shouldOutputJson, writeOutput } from "../output.js";
@@ -9,15 +10,19 @@ import { shouldOutputJson, writeOutput } from "../output.js";
9
10
  const log = getCliLogger("email");
10
11
 
11
12
  export function registerEmailCommand(program: Command): void {
13
+ const domain = getAssistantDomain();
12
14
  const email = program
13
15
  .command("email")
14
- .description("Email channel operations")
16
+ .description(
17
+ `Get your own email address (@${domain}) — register, send, receive, and manage email natively`,
18
+ )
15
19
  .option("--json", "Machine-readable compact JSON output");
16
20
 
17
21
  email.addHelpText(
18
22
  "after",
19
23
  `
20
- Manage the assistant's email channel on the Vellum platform.
24
+ Set up and manage this assistant's native email address on the Vellum
25
+ platform. No third-party email provider or browser sign-up needed.
21
26
 
22
27
  Examples:
23
28
  $ assistant email register mybot
@@ -30,12 +35,12 @@ Examples:
30
35
 
31
36
  email
32
37
  .command("register <username>")
33
- .description("Register an @vellum.me email address for this assistant")
38
+ .description(`Register an @${domain} email address for this assistant`)
34
39
  .addHelpText(
35
40
  "after",
36
41
  `
37
42
  Arguments:
38
- username The local part of the email address (e.g. "mybot" → mybot@vellum.me)
43
+ username The local part of the email address (e.g. "mybot" → mybot@${domain})
39
44
 
40
45
  Registers a new email address on the Vellum platform for the current
41
46
  assistant. Each assistant can have one email address. The address is
@@ -43,10 +48,10 @@ immediately active for receiving inbound email.
43
48
 
44
49
  Examples:
45
50
  $ assistant email register mybot
46
- ✓ Registered mybot@vellum.me
51
+ ✓ Registered mybot@${domain}
47
52
 
48
53
  $ assistant email register support --json
49
- {"address":"support@vellum.me","id":"...","created_at":"..."}`,
54
+ {"address":"support@${domain}","id":"...","created_at":"..."}`,
50
55
  )
51
56
  .action(async (username: string, _opts: unknown, cmd: Command) => {
52
57
  try {
@@ -122,14 +127,14 @@ immediately available for reuse.
122
127
 
123
128
  Examples:
124
129
  $ assistant email unregister
125
- Remove mybot@vellum.me? (y/N) y
126
- ✓ Unregistered mybot@vellum.me
130
+ Remove mybot@${domain}? (y/N) y
131
+ ✓ Unregistered mybot@${domain}
127
132
 
128
133
  $ assistant email unregister --confirm
129
- ✓ Unregistered mybot@vellum.me
134
+ ✓ Unregistered mybot@${domain}
130
135
 
131
136
  $ assistant email unregister --json
132
- {"unregistered":"mybot@vellum.me"}`,
137
+ {"unregistered":"mybot@${domain}"}`,
133
138
  )
134
139
  .action(async (_opts: { confirm?: boolean }, cmd: Command) => {
135
140
  try {
@@ -222,12 +227,12 @@ current usage and quota information from the platform.
222
227
 
223
228
  Examples:
224
229
  $ assistant email status
225
- Address: mybot@vellum.me
230
+ Address: mybot@${domain}
226
231
  Status: active
227
232
  Sent: 12 / 100 (daily)
228
233
 
229
234
  $ assistant email status --json
230
- {"address":"mybot@vellum.me","status":"active","usage":{"sent_today":12,"daily_limit":100}}`,
235
+ {"address":"mybot@${domain}","status":"active","usage":{"sent_today":12,"daily_limit":100}}`,
231
236
  )
232
237
  .action(async (_opts: unknown, cmd: Command) => {
233
238
  try {
@@ -446,7 +451,7 @@ or --format json for the full message object.
446
451
  Examples:
447
452
  $ assistant email download msg_abc123
448
453
  From: user@example.com
449
- To: mybot@vellum.me
454
+ To: mybot@${domain}
450
455
  Subject: Hello
451
456
  Date: 2026-04-05 12:00:00
452
457
 
@@ -34,13 +34,25 @@ export async function checkServerHealth(
34
34
  }),
35
35
  ]);
36
36
 
37
- if (!client.isConnected) {
38
- return "! Needs authentication";
37
+ if (client.isConnected) {
38
+ await client.disconnect();
39
+ return "\u2713 Connected";
40
+ }
41
+
42
+ // connect() swallows errors — check lastError to distinguish auth from
43
+ // transport failures (DNS, TLS, 500, stdio crash, etc.).
44
+ const err = client.lastError;
45
+ if (err) {
46
+ const message = err.message;
47
+ if (message.includes("timeout")) {
48
+ return "\u2717 Timed out";
49
+ }
50
+ return `\u2717 Error: ${message}`;
39
51
  }
40
52
 
41
- await client.disconnect();
42
- return "\u2713 Connected";
53
+ return "! Needs authentication";
43
54
  } catch (err) {
55
+ // Only the external timeout Promise can throw here (connect() never does).
44
56
  try {
45
57
  await client.disconnect();
46
58
  } catch {
@@ -264,9 +264,9 @@ describe("assistant oauth connect", () => {
264
264
 
265
265
  test("managed mode with --no-browser: prints connect URL", async () => {
266
266
  mockGetProvider = () => ({
267
- providerKey: "google",
268
- authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
269
- tokenUrl: "https://oauth2.googleapis.com/token",
267
+ provider: "google",
268
+ authorizeUrl: "https://accounts.google.com/o/oauth2/v2/auth",
269
+ tokenExchangeUrl: "https://oauth2.googleapis.com/token",
270
270
  managedServiceConfigKey: "google-oauth",
271
271
  });
272
272
  mockIsManagedMode = () => true;
@@ -301,9 +301,9 @@ describe("assistant oauth connect", () => {
301
301
 
302
302
  test("managed mode default: opens browser and polls for new connection", async () => {
303
303
  mockGetProvider = () => ({
304
- providerKey: "google",
305
- authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
306
- tokenUrl: "https://oauth2.googleapis.com/token",
304
+ provider: "google",
305
+ authorizeUrl: "https://accounts.google.com/o/oauth2/v2/auth",
306
+ tokenExchangeUrl: "https://oauth2.googleapis.com/token",
307
307
  managedServiceConfigKey: "google-oauth",
308
308
  });
309
309
  mockIsManagedMode = () => true;
@@ -357,9 +357,9 @@ describe("assistant oauth connect", () => {
357
357
 
358
358
  test("BYO mode with --no-browser: prints auth URL", async () => {
359
359
  mockGetProvider = () => ({
360
- providerKey: "google",
361
- authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
362
- tokenUrl: "https://oauth2.googleapis.com/token",
360
+ provider: "google",
361
+ authorizeUrl: "https://accounts.google.com/o/oauth2/v2/auth",
362
+ tokenExchangeUrl: "https://oauth2.googleapis.com/token",
363
363
  managedServiceConfigKey: null,
364
364
  });
365
365
  mockIsManagedMode = () => false;
@@ -368,7 +368,7 @@ describe("assistant oauth connect", () => {
368
368
  id: "app-1",
369
369
  clientId: "byo-client-id",
370
370
  clientSecretCredentialPath: "oauth_app/app-1/client_secret",
371
- providerKey: "google",
371
+ provider: "google",
372
372
  createdAt: 0,
373
373
  updatedAt: 0,
374
374
  });
@@ -376,7 +376,7 @@ describe("assistant oauth connect", () => {
376
376
  mockOrchestrateOAuthConnect = async () => ({
377
377
  success: true,
378
378
  deferred: true,
379
- authUrl: "https://accounts.google.com/o/oauth2/v2/auth?state=abc",
379
+ authorizeUrl: "https://accounts.google.com/o/oauth2/v2/auth?state=abc",
380
380
  state: "abc",
381
381
  service: "google",
382
382
  });
@@ -403,9 +403,9 @@ describe("assistant oauth connect", () => {
403
403
 
404
404
  test("BYO mode default calls orchestrator with isInteractive: true", async () => {
405
405
  mockGetProvider = () => ({
406
- providerKey: "google",
407
- authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
408
- tokenUrl: "https://oauth2.googleapis.com/token",
406
+ provider: "google",
407
+ authorizeUrl: "https://accounts.google.com/o/oauth2/v2/auth",
408
+ tokenExchangeUrl: "https://oauth2.googleapis.com/token",
409
409
  managedServiceConfigKey: null,
410
410
  });
411
411
  mockIsManagedMode = () => false;
@@ -414,7 +414,7 @@ describe("assistant oauth connect", () => {
414
414
  id: "app-1",
415
415
  clientId: "test-id",
416
416
  clientSecretCredentialPath: "oauth_app/app-1/client_secret",
417
- providerKey: "google",
417
+ provider: "google",
418
418
  createdAt: 0,
419
419
  updatedAt: 0,
420
420
  });
@@ -455,9 +455,9 @@ describe("assistant oauth connect", () => {
455
455
 
456
456
  test("BYO mode: missing app with --client-id returns error with hint", async () => {
457
457
  mockGetProvider = () => ({
458
- providerKey: "google",
459
- authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
460
- tokenUrl: "https://oauth2.googleapis.com/token",
458
+ provider: "google",
459
+ authorizeUrl: "https://accounts.google.com/o/oauth2/v2/auth",
460
+ tokenExchangeUrl: "https://oauth2.googleapis.com/token",
461
461
  managedServiceConfigKey: null,
462
462
  });
463
463
  mockIsManagedMode = () => false;
@@ -483,9 +483,9 @@ describe("assistant oauth connect", () => {
483
483
 
484
484
  test("BYO mode: no client_id found returns error with hint", async () => {
485
485
  mockGetProvider = () => ({
486
- providerKey: "google",
487
- authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
488
- tokenUrl: "https://oauth2.googleapis.com/token",
486
+ provider: "google",
487
+ authorizeUrl: "https://accounts.google.com/o/oauth2/v2/auth",
488
+ tokenExchangeUrl: "https://oauth2.googleapis.com/token",
489
489
  managedServiceConfigKey: null,
490
490
  });
491
491
  mockIsManagedMode = () => false;
@@ -509,9 +509,9 @@ describe("assistant oauth connect", () => {
509
509
 
510
510
  test("--client-id is silently ignored in managed mode", async () => {
511
511
  mockGetProvider = () => ({
512
- providerKey: "google",
513
- authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
514
- tokenUrl: "https://oauth2.googleapis.com/token",
512
+ provider: "google",
513
+ authorizeUrl: "https://accounts.google.com/o/oauth2/v2/auth",
514
+ tokenExchangeUrl: "https://oauth2.googleapis.com/token",
515
515
  managedServiceConfigKey: "google-oauth",
516
516
  });
517
517
  mockIsManagedMode = () => true;
@@ -547,9 +547,9 @@ describe("assistant oauth connect", () => {
547
547
 
548
548
  test("JSON output for deferred case includes ok, deferred, authUrl, service", async () => {
549
549
  mockGetProvider = () => ({
550
- providerKey: "slack",
551
- authUrl: "https://slack.com/oauth/v2/authorize",
552
- tokenUrl: "https://slack.com/api/oauth.v2.access",
550
+ provider: "slack",
551
+ authorizeUrl: "https://slack.com/oauth/v2/authorize",
552
+ tokenExchangeUrl: "https://slack.com/api/oauth.v2.access",
553
553
  managedServiceConfigKey: null,
554
554
  });
555
555
  mockIsManagedMode = () => false;
@@ -558,7 +558,7 @@ describe("assistant oauth connect", () => {
558
558
  id: "app-slack",
559
559
  clientId: "slack-client-id",
560
560
  clientSecretCredentialPath: "oauth_app/app-slack/client_secret",
561
- providerKey: "slack",
561
+ provider: "slack",
562
562
  createdAt: 0,
563
563
  updatedAt: 0,
564
564
  });
@@ -566,7 +566,7 @@ describe("assistant oauth connect", () => {
566
566
  mockOrchestrateOAuthConnect = async () => ({
567
567
  success: true,
568
568
  deferred: true,
569
- authUrl: "https://slack.com/oauth/v2/authorize?state=xyz",
569
+ authorizeUrl: "https://slack.com/oauth/v2/authorize?state=xyz",
570
570
  state: "xyz",
571
571
  service: "slack",
572
572
  });
@@ -591,9 +591,9 @@ describe("assistant oauth connect", () => {
591
591
 
592
592
  test("JSON output for completed case includes ok, grantedScopes, accountInfo", async () => {
593
593
  mockGetProvider = () => ({
594
- providerKey: "google",
595
- authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
596
- tokenUrl: "https://oauth2.googleapis.com/token",
594
+ provider: "google",
595
+ authorizeUrl: "https://accounts.google.com/o/oauth2/v2/auth",
596
+ tokenExchangeUrl: "https://oauth2.googleapis.com/token",
597
597
  managedServiceConfigKey: null,
598
598
  });
599
599
  mockIsManagedMode = () => false;
@@ -602,7 +602,7 @@ describe("assistant oauth connect", () => {
602
602
  id: "app-1",
603
603
  clientId: "completed-client-id",
604
604
  clientSecretCredentialPath: "oauth_app/app-1/client_secret",
605
- providerKey: "google",
605
+ provider: "google",
606
606
  createdAt: 0,
607
607
  updatedAt: 0,
608
608
  });
@@ -635,9 +635,9 @@ describe("assistant oauth connect", () => {
635
635
 
636
636
  test("BYO mode: client_secret required but missing returns error with hint", async () => {
637
637
  mockGetProvider = () => ({
638
- providerKey: "google",
639
- authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
640
- tokenUrl: "https://oauth2.googleapis.com/token",
638
+ provider: "google",
639
+ authorizeUrl: "https://accounts.google.com/o/oauth2/v2/auth",
640
+ tokenExchangeUrl: "https://oauth2.googleapis.com/token",
641
641
  tokenEndpointAuthMethod: "client_secret_post",
642
642
  managedServiceConfigKey: null,
643
643
  requiresClientSecret: 1,
@@ -648,7 +648,7 @@ describe("assistant oauth connect", () => {
648
648
  id: "app-1",
649
649
  clientId: "test-id",
650
650
  clientSecretCredentialPath: "oauth_app/app-1/client_secret",
651
- providerKey: "google",
651
+ provider: "google",
652
652
  createdAt: 0,
653
653
  updatedAt: 0,
654
654
  });
@@ -668,15 +668,42 @@ describe("assistant oauth connect", () => {
668
668
  expect(parsed.error).toContain("apps upsert");
669
669
  });
670
670
 
671
+ // -------------------------------------------------------------------------
672
+ // Manual-token providers (slack_channel, telegram)
673
+ // -------------------------------------------------------------------------
674
+
675
+ test("manual-token provider returns error directing to credentials command", async () => {
676
+ mockGetProvider = () => ({
677
+ provider: "slack_channel",
678
+ authorizeUrl: "urn:manual-token",
679
+ tokenExchangeUrl: "urn:manual-token",
680
+ managedServiceConfigKey: null,
681
+ });
682
+ mockIsManagedMode = () => false;
683
+
684
+ const { exitCode, stdout } = await runCommand([
685
+ "connect",
686
+ "slack_channel",
687
+ "--json",
688
+ ]);
689
+ expect(exitCode).toBe(1);
690
+ const parsed = JSON.parse(stdout);
691
+ expect(parsed.ok).toBe(false);
692
+ expect(parsed.error).toContain("manual token configuration");
693
+ expect(parsed.error).toContain("assistant credentials set");
694
+ expect(parsed.error).toContain("--service");
695
+ expect(parsed.error).toContain("--field");
696
+ });
697
+
671
698
  // -------------------------------------------------------------------------
672
699
  // Orchestrator error propagation
673
700
  // -------------------------------------------------------------------------
674
701
 
675
702
  test("BYO mode: orchestrator error propagates correctly", async () => {
676
703
  mockGetProvider = () => ({
677
- providerKey: "google",
678
- authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
679
- tokenUrl: "https://oauth2.googleapis.com/token",
704
+ provider: "google",
705
+ authorizeUrl: "https://accounts.google.com/o/oauth2/v2/auth",
706
+ tokenExchangeUrl: "https://oauth2.googleapis.com/token",
680
707
  managedServiceConfigKey: null,
681
708
  });
682
709
  mockIsManagedMode = () => false;
@@ -685,7 +712,7 @@ describe("assistant oauth connect", () => {
685
712
  id: "app-1",
686
713
  clientId: "client-id",
687
714
  clientSecretCredentialPath: "oauth_app/app-1/client_secret",
688
- providerKey: "google",
715
+ provider: "google",
689
716
  createdAt: 0,
690
717
  updatedAt: 0,
691
718
  });
@@ -15,19 +15,19 @@ let mockGetConnection: (
15
15
  ) => Record<string, unknown> | undefined = () => undefined;
16
16
 
17
17
  let mockGetActiveConnection: (
18
- providerKey: string,
18
+ provider: string,
19
19
  opts?: { account?: string },
20
20
  ) => Record<string, unknown> | undefined = () => undefined;
21
21
 
22
22
  let mockListActiveConnectionsByProvider: (
23
- providerKey: string,
23
+ provider: string,
24
24
  ) => Array<Record<string, unknown>> = () => [];
25
25
 
26
26
  let mockDisconnectOAuthProviderResult: "disconnected" | "not-found" | "error" =
27
27
  "disconnected";
28
28
 
29
29
  let mockDisconnectOAuthProviderCalls: Array<{
30
- providerKey: string;
30
+ provider: string;
31
31
  account: string | undefined;
32
32
  connectionId: string | undefined;
33
33
  }> = [];
@@ -64,17 +64,17 @@ mock.module("../../../../config/loader.js", () => ({
64
64
  mock.module("../../../../oauth/oauth-store.js", () => ({
65
65
  getProvider: (key: string) => mockGetProvider(key),
66
66
  getConnection: (id: string) => mockGetConnection(id),
67
- getActiveConnection: (providerKey: string, opts?: { account?: string }) =>
68
- mockGetActiveConnection(providerKey, opts),
69
- listActiveConnectionsByProvider: (providerKey: string) =>
70
- mockListActiveConnectionsByProvider(providerKey),
67
+ getActiveConnection: (provider: string, opts?: { account?: string }) =>
68
+ mockGetActiveConnection(provider, opts),
69
+ listActiveConnectionsByProvider: (provider: string) =>
70
+ mockListActiveConnectionsByProvider(provider),
71
71
  disconnectOAuthProvider: async (
72
- providerKey: string,
72
+ provider: string,
73
73
  account?: string,
74
74
  connectionId?: string,
75
75
  ) => {
76
76
  mockDisconnectOAuthProviderCalls.push({
77
- providerKey,
77
+ provider,
78
78
  account,
79
79
  connectionId,
80
80
  });
@@ -295,7 +295,7 @@ describe("assistant oauth disconnect", () => {
295
295
 
296
296
  test("both --account and --connection-id returns error", async () => {
297
297
  mockGetProvider = () => ({
298
- providerKey: "google",
298
+ provider: "google",
299
299
  managedServiceConfigKey: null,
300
300
  });
301
301
 
@@ -323,7 +323,7 @@ describe("assistant oauth disconnect", () => {
323
323
  describe("managed mode", () => {
324
324
  beforeEach(() => {
325
325
  mockGetProvider = () => ({
326
- providerKey: "google",
326
+ provider: "google",
327
327
  managedServiceConfigKey: "google-oauth",
328
328
  });
329
329
  mockIsManagedMode = () => true;
@@ -484,7 +484,7 @@ describe("assistant oauth disconnect", () => {
484
484
  describe("BYO mode", () => {
485
485
  beforeEach(() => {
486
486
  mockGetProvider = () => ({
487
- providerKey: "google",
487
+ provider: "google",
488
488
  managedServiceConfigKey: null,
489
489
  });
490
490
  mockIsManagedMode = () => false;
@@ -494,7 +494,7 @@ describe("assistant oauth disconnect", () => {
494
494
  mockListActiveConnectionsByProvider = () => [
495
495
  {
496
496
  id: "conn-1",
497
- providerKey: "google",
497
+ provider: "google",
498
498
  accountInfo: "user@gmail.com",
499
499
  status: "active",
500
500
  },
@@ -514,16 +514,16 @@ describe("assistant oauth disconnect", () => {
514
514
 
515
515
  // Verify disconnectOAuthProvider was called
516
516
  expect(mockDisconnectOAuthProviderCalls).toHaveLength(1);
517
- expect(mockDisconnectOAuthProviderCalls[0].providerKey).toBe("google");
517
+ expect(mockDisconnectOAuthProviderCalls[0].provider).toBe("google");
518
518
  expect(mockDisconnectOAuthProviderCalls[0].connectionId).toBe("conn-1");
519
519
  });
520
520
 
521
521
  test("--account matches accountInfo", async () => {
522
- mockGetActiveConnection = (providerKey, opts) => {
522
+ mockGetActiveConnection = (_provider, opts) => {
523
523
  if (opts?.account === "user@gmail.com") {
524
524
  return {
525
525
  id: "conn-1",
526
- providerKey: "google",
526
+ provider: "google",
527
527
  accountInfo: "user@gmail.com",
528
528
  status: "active",
529
529
  };
@@ -567,7 +567,7 @@ describe("assistant oauth disconnect", () => {
567
567
  if (id === "conn-123") {
568
568
  return {
569
569
  id: "conn-123",
570
- providerKey: "google",
570
+ provider: "google",
571
571
  accountInfo: "user@gmail.com",
572
572
  status: "active",
573
573
  };
@@ -593,7 +593,7 @@ describe("assistant oauth disconnect", () => {
593
593
  if (id === "conn-slack") {
594
594
  return {
595
595
  id: "conn-slack",
596
- providerKey: "slack",
596
+ provider: "slack",
597
597
  accountInfo: null,
598
598
  status: "active",
599
599
  };
@@ -619,13 +619,13 @@ describe("assistant oauth disconnect", () => {
619
619
  mockListActiveConnectionsByProvider = () => [
620
620
  {
621
621
  id: "conn-1",
622
- providerKey: "google",
622
+ provider: "google",
623
623
  accountInfo: "user1@gmail.com",
624
624
  status: "active",
625
625
  },
626
626
  {
627
627
  id: "conn-2",
628
- providerKey: "google",
628
+ provider: "google",
629
629
  accountInfo: "user2@gmail.com",
630
630
  status: "active",
631
631
  },
@@ -666,7 +666,7 @@ describe("assistant oauth disconnect", () => {
666
666
  mockListActiveConnectionsByProvider = () => [
667
667
  {
668
668
  id: "conn-1",
669
- providerKey: "google",
669
+ provider: "google",
670
670
  accountInfo: null,
671
671
  status: "active",
672
672
  },