@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
@@ -0,0 +1,259 @@
1
+ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
2
+
3
+ // ---------------------------------------------------------------------------
4
+ // Mock state
5
+ // ---------------------------------------------------------------------------
6
+
7
+ let mockResolvePlatformCallbackRegistrationContext: () => Promise<
8
+ Record<string, unknown>
9
+ > = async () => ({
10
+ isPlatform: false,
11
+ platformBaseUrl: "",
12
+ assistantId: "",
13
+ hasInternalApiKey: false,
14
+ hasAssistantApiKey: false,
15
+ authHeader: null,
16
+ enabled: false,
17
+ });
18
+
19
+ // ---------------------------------------------------------------------------
20
+ // Mocks
21
+ // ---------------------------------------------------------------------------
22
+
23
+ mock.module("../../../../inbound/platform-callback-registration.js", () => ({
24
+ resolvePlatformCallbackRegistrationContext: () =>
25
+ mockResolvePlatformCallbackRegistrationContext(),
26
+ registerCallbackRoute: async () => "",
27
+ shouldUsePlatformCallbacks: () => false,
28
+ resolveCallbackUrl: async () => "",
29
+ }));
30
+
31
+ mock.module("../../../lib/daemon-credential-client.js", () => ({
32
+ getSecureKeyViaDaemon: async () => undefined,
33
+ deleteSecureKeyViaDaemon: async () => "not-found" as const,
34
+ setSecureKeyViaDaemon: async () => false,
35
+ getProviderKeyViaDaemon: async () => undefined,
36
+ getSecureKeyResultViaDaemon: async () => ({
37
+ value: undefined,
38
+ unreachable: false,
39
+ }),
40
+ }));
41
+
42
+ mock.module("../../../../util/logger.js", () => ({
43
+ getLogger: () => ({
44
+ info: () => {},
45
+ warn: () => {},
46
+ error: () => {},
47
+ debug: () => {},
48
+ }),
49
+ getCliLogger: () => ({
50
+ info: () => {},
51
+ warn: () => {},
52
+ error: () => {},
53
+ debug: () => {},
54
+ }),
55
+ initLogger: () => {},
56
+ truncateForLog: (value: string, maxLen = 500) =>
57
+ value.length > maxLen ? value.slice(0, maxLen) + "..." : value,
58
+ pruneOldLogFiles: () => 0,
59
+ }));
60
+
61
+ mock.module("../../../../config/loader.js", () => ({
62
+ API_KEY_PROVIDERS: [] as const,
63
+ getConfig: () => ({
64
+ permissions: { mode: "workspace" },
65
+ skills: { load: { extraDirs: [] } },
66
+ sandbox: { enabled: true },
67
+ }),
68
+ loadConfig: () => ({}),
69
+ invalidateConfigCache: () => {},
70
+ saveConfig: () => {},
71
+ loadRawConfig: () => ({}),
72
+ saveRawConfig: () => {},
73
+ getNestedValue: () => undefined,
74
+ setNestedValue: () => {},
75
+ applyNestedDefaults: (config: unknown) => config,
76
+ deepMergeMissing: () => false,
77
+ deepMergeOverwrite: () => {},
78
+ mergeDefaultWorkspaceConfig: () => {},
79
+ }));
80
+
81
+ // ---------------------------------------------------------------------------
82
+ // Import shared test utility (after mocks are registered)
83
+ // ---------------------------------------------------------------------------
84
+
85
+ const { runAssistantCommandFull } =
86
+ await import("../../../__tests__/run-assistant-command.js");
87
+
88
+ // ---------------------------------------------------------------------------
89
+ // Fetch mock
90
+ // ---------------------------------------------------------------------------
91
+
92
+ const originalFetch = globalThis.fetch;
93
+
94
+ afterEach(() => {
95
+ globalThis.fetch = originalFetch;
96
+ });
97
+
98
+ // ---------------------------------------------------------------------------
99
+ // Helpers
100
+ // ---------------------------------------------------------------------------
101
+
102
+ function connectedContext(
103
+ overrides: Record<string, unknown> = {},
104
+ ): Record<string, unknown> {
105
+ return {
106
+ isPlatform: false,
107
+ platformBaseUrl: "https://dev-platform.vellum.ai",
108
+ assistantId: "019d6d4f-6dbd-779f-91d3-cb273b9429a5",
109
+ hasInternalApiKey: false,
110
+ hasAssistantApiKey: true,
111
+ authHeader: "Api-Key vak_test123",
112
+ enabled: false,
113
+ ...overrides,
114
+ };
115
+ }
116
+
117
+ function mockFetchJson(body: unknown, status = 200): void {
118
+ globalThis.fetch = (async () =>
119
+ new Response(JSON.stringify(body), {
120
+ status,
121
+ headers: { "Content-Type": "application/json" },
122
+ })) as unknown as typeof globalThis.fetch;
123
+ }
124
+
125
+ // ---------------------------------------------------------------------------
126
+ // Tests
127
+ // ---------------------------------------------------------------------------
128
+
129
+ describe("assistant platform callback-routes list", () => {
130
+ beforeEach(() => {
131
+ mockResolvePlatformCallbackRegistrationContext = async () =>
132
+ connectedContext();
133
+ process.exitCode = 0;
134
+ });
135
+
136
+ afterEach(() => {
137
+ process.exitCode = 0;
138
+ });
139
+
140
+ test("returns empty list when no routes registered", async () => {
141
+ mockFetchJson([]);
142
+
143
+ const { stdout } = await runAssistantCommandFull(
144
+ "platform",
145
+ "callback-routes",
146
+ "list",
147
+ "--json",
148
+ );
149
+
150
+ expect(process.exitCode ?? 0).toBe(0);
151
+ const parsed = JSON.parse(stdout);
152
+ expect(parsed.ok).toBe(true);
153
+ expect(parsed.routes).toEqual([]);
154
+ });
155
+
156
+ test("returns registered routes", async () => {
157
+ const routes = [
158
+ {
159
+ id: "route-1",
160
+ assistant_id: "019d6d4f-6dbd-779f-91d3-cb273b9429a5",
161
+ type: "email",
162
+ callback_path: "019d6d4f-6dbd-779f-91d3-cb273b9429a5/webhooks/email",
163
+ callback_url:
164
+ "https://dev-platform.vellum.ai/v1/gateway/callbacks/019d6d4f-6dbd-779f-91d3-cb273b9429a5/webhooks/email/",
165
+ },
166
+ {
167
+ id: "route-2",
168
+ assistant_id: "019d6d4f-6dbd-779f-91d3-cb273b9429a5",
169
+ type: "telegram",
170
+ callback_path: "019d6d4f-6dbd-779f-91d3-cb273b9429a5/webhooks/telegram",
171
+ callback_url:
172
+ "https://dev-platform.vellum.ai/v1/gateway/callbacks/019d6d4f-6dbd-779f-91d3-cb273b9429a5/webhooks/telegram/",
173
+ },
174
+ ];
175
+ mockFetchJson(routes);
176
+
177
+ const { stdout } = await runAssistantCommandFull(
178
+ "platform",
179
+ "callback-routes",
180
+ "list",
181
+ "--json",
182
+ );
183
+
184
+ expect(process.exitCode ?? 0).toBe(0);
185
+ const parsed = JSON.parse(stdout);
186
+ expect(parsed.ok).toBe(true);
187
+ expect(parsed.routes).toHaveLength(2);
188
+ expect(parsed.routes[0].type).toBe("email");
189
+ expect(parsed.routes[1].type).toBe("telegram");
190
+ });
191
+
192
+ test("fails when platform credentials are missing", async () => {
193
+ mockResolvePlatformCallbackRegistrationContext = async () => ({
194
+ isPlatform: false,
195
+ platformBaseUrl: "",
196
+ assistantId: "",
197
+ hasInternalApiKey: false,
198
+ hasAssistantApiKey: false,
199
+ authHeader: null,
200
+ enabled: false,
201
+ });
202
+
203
+ const { stdout } = await runAssistantCommandFull(
204
+ "platform",
205
+ "callback-routes",
206
+ "list",
207
+ "--json",
208
+ );
209
+
210
+ expect(process.exitCode).toBe(1);
211
+ const parsed = JSON.parse(stdout);
212
+ expect(parsed.ok).toBe(false);
213
+ expect(parsed.error).toContain("Platform credentials not available");
214
+ });
215
+
216
+ test("handles platform HTTP error", async () => {
217
+ mockFetchJson({ detail: "Unauthorized" }, 401);
218
+
219
+ const { stdout } = await runAssistantCommandFull(
220
+ "platform",
221
+ "callback-routes",
222
+ "list",
223
+ "--json",
224
+ );
225
+
226
+ expect(process.exitCode).toBe(1);
227
+ const parsed = JSON.parse(stdout);
228
+ expect(parsed.ok).toBe(false);
229
+ expect(parsed.error).toContain("HTTP 401");
230
+ });
231
+
232
+ test("works for self-hosted assistants with connected credentials", async () => {
233
+ mockResolvePlatformCallbackRegistrationContext = async () =>
234
+ connectedContext({ isPlatform: false, enabled: false });
235
+
236
+ mockFetchJson([
237
+ {
238
+ id: "route-1",
239
+ assistant_id: "019d6d4f-6dbd-779f-91d3-cb273b9429a5",
240
+ type: "email",
241
+ callback_path: "019d6d4f-6dbd-779f-91d3-cb273b9429a5/webhooks/email",
242
+ callback_url:
243
+ "https://dev-platform.vellum.ai/v1/gateway/callbacks/019d6d4f-6dbd-779f-91d3-cb273b9429a5/webhooks/email/",
244
+ },
245
+ ]);
246
+
247
+ const { stdout } = await runAssistantCommandFull(
248
+ "platform",
249
+ "callback-routes",
250
+ "list",
251
+ "--json",
252
+ );
253
+
254
+ expect(process.exitCode ?? 0).toBe(0);
255
+ const parsed = JSON.parse(stdout);
256
+ expect(parsed.ok).toBe(true);
257
+ expect(parsed.routes).toHaveLength(1);
258
+ });
259
+ });
@@ -109,7 +109,7 @@ async function runCommand(
109
109
  process.exitCode = 0;
110
110
 
111
111
  try {
112
- const program = buildCliProgram();
112
+ const program = await buildCliProgram();
113
113
  program.exitOverride();
114
114
  program.configureOutput({
115
115
  writeErr: () => {},
@@ -130,7 +130,7 @@ async function runCommand(
130
130
  process.exitCode = 0;
131
131
 
132
132
  try {
133
- const program = buildCliProgram();
133
+ const program = await buildCliProgram();
134
134
  program.exitOverride();
135
135
  program.configureOutput({
136
136
  writeErr: () => {},
@@ -110,7 +110,7 @@ async function runCommand(
110
110
  process.exitCode = 0;
111
111
 
112
112
  try {
113
- const program = buildCliProgram();
113
+ const program = await buildCliProgram();
114
114
  program.exitOverride();
115
115
  program.configureOutput({
116
116
  writeErr: () => {},
@@ -24,9 +24,10 @@ The platform subsystem manages the connection to Vellum Platform. Use
24
24
  'connect', 'status', and 'disconnect' to manage platform credentials.
25
25
  Any assistant using the managed LLM proxy can use these commands.
26
26
 
27
- When IS_PLATFORM=true (platform-managed deployments), external service
28
- callbacks (Telegram webhooks, Twilio webhooks, OAuth redirects) also
29
- route through the platform's gateway proxy via 'callback-routes'.
27
+ External service callbacks (Telegram webhooks, Twilio webhooks, email,
28
+ OAuth redirects) route through the platform's gateway proxy via
29
+ 'callback-routes'. Works for both platform-managed and self-hosted
30
+ assistants.
30
31
 
31
32
  Examples:
32
33
  $ assistant platform status --json
@@ -64,6 +65,8 @@ Fields:
64
65
  hasInternalApiKey Whether PLATFORM_INTERNAL_API_KEY is set (boolean,
65
66
  value not disclosed)
66
67
  hasAssistantApiKey Whether a stored assistant API key is available
68
+ hasWebhookSecret Whether a stored webhook secret is available (needed
69
+ for email and other inbound webhook channels)
67
70
  available Whether callback registration prerequisites are satisfied
68
71
  connected Whether platform credentials are stored (boolean)
69
72
  organizationId The platform organization ID (from stored credentials)
@@ -109,6 +112,10 @@ Examples:
109
112
  )
110
113
  )?.trim() ?? "";
111
114
 
115
+ const hasWebhookSecret = !!(await getSecureKeyViaDaemon(
116
+ credentialKey("vellum", "webhook_secret"),
117
+ ));
118
+
112
119
  const connected = !!storedBaseUrl && hasStoredApiKey;
113
120
 
114
121
  const result = {
@@ -117,6 +124,7 @@ Examples:
117
124
  assistantId: context.assistantId,
118
125
  hasInternalApiKey: context.hasInternalApiKey,
119
126
  hasAssistantApiKey: context.hasAssistantApiKey,
127
+ hasWebhookSecret,
120
128
  available: context.enabled,
121
129
  connected,
122
130
  organizationId: organizationId || null,
@@ -135,6 +143,9 @@ Examples:
135
143
  log.info(
136
144
  `Assistant API key: ${result.hasAssistantApiKey ? "set" : "not set"}`,
137
145
  );
146
+ log.info(
147
+ `Webhook secret: ${result.hasWebhookSecret ? "set" : "not set (run ensure-registration to provision)"}`,
148
+ );
138
149
  log.info(
139
150
  `Callback registration available: ${result.available ? "yes" : "no"}`,
140
151
  );
@@ -167,11 +178,13 @@ Examples:
167
178
  "after",
168
179
  `
169
180
  Callback routes tell the platform gateway how to forward inbound provider
170
- webhooks to the correct platform-managed assistant instance. Each route maps a
171
- callback path and type to a stable external URL that external services
172
- (Telegram, Twilio, OAuth providers) should use.
181
+ webhooks to the correct assistant instance. Each route maps a callback path
182
+ and type to a stable external URL that external services (Telegram, Twilio,
183
+ email, OAuth providers) should use.
173
184
 
174
185
  Examples:
186
+ $ assistant platform callback-routes list
187
+ $ assistant platform callback-routes list --json
175
188
  $ assistant platform callback-routes register --path webhooks/telegram --type telegram --json
176
189
  $ assistant platform callback-routes register --path webhooks/twilio/voice --type twilio_voice --json`,
177
190
  );
@@ -210,9 +223,10 @@ Known callback path/type combinations:
210
223
  --path webhooks/twilio/status --type twilio_status
211
224
  --path oauth/callback --type oauth
212
225
 
213
- Requires a platform-managed environment (IS_PLATFORM=true) with
214
- VELLUM_PLATFORM_URL and PLATFORM_ASSISTANT_ID configured. Returns the
215
- platform-provided stable callback URL that external services should use.
226
+ Works for both platform-managed and self-hosted assistants. Requires
227
+ VELLUM_PLATFORM_URL and PLATFORM_ASSISTANT_ID (from environment or stored
228
+ credentials via 'assistant platform connect'). Returns the platform-provided
229
+ stable callback URL that external services should use.
216
230
 
217
231
  Examples:
218
232
  $ assistant platform callback-routes register --path webhooks/telegram --type telegram --json
@@ -225,7 +239,7 @@ Examples:
225
239
  writeOutput(cmd, {
226
240
  ok: false,
227
241
  error:
228
- "Platform callbacks not available — missing platform registration context",
242
+ "Platform callbacks not available — missing platform base URL, assistant ID, or API key. Run 'assistant platform connect' or ensure credentials are configured.",
229
243
  });
230
244
  process.exitCode = 1;
231
245
  return;
@@ -249,4 +263,87 @@ Examples:
249
263
  process.exitCode = 1;
250
264
  }
251
265
  });
266
+
267
+ // ---------------------------------------------------------------------------
268
+ // callback-routes list
269
+ // ---------------------------------------------------------------------------
270
+
271
+ callbackRoutes
272
+ .command("list")
273
+ .description("List registered callback routes for this assistant")
274
+ .addHelpText(
275
+ "after",
276
+ `
277
+ Lists all callback routes registered with the platform for this assistant.
278
+ Shows the route type, callback URL, and path for each registered webhook.
279
+
280
+ Requires platform credentials (run 'assistant platform connect' first or
281
+ ensure IS_PLATFORM, VELLUM_PLATFORM_URL, and PLATFORM_ASSISTANT_ID are set).
282
+
283
+ Examples:
284
+ $ assistant platform callback-routes list
285
+ $ assistant platform callback-routes list --json`,
286
+ )
287
+ .action(async (_opts: Record<string, unknown>, cmd: Command) => {
288
+ try {
289
+ const context = await resolvePlatformCallbackRegistrationContext();
290
+ if (!context.platformBaseUrl || !context.authHeader) {
291
+ writeOutput(cmd, {
292
+ ok: false,
293
+ error:
294
+ "Platform credentials not available — run 'assistant platform connect' or set VELLUM_PLATFORM_URL",
295
+ });
296
+ process.exitCode = 1;
297
+ return;
298
+ }
299
+
300
+ const url = `${context.platformBaseUrl}/v1/internal/gateway/callback-routes/`;
301
+ const response = await fetch(url, {
302
+ method: "GET",
303
+ headers: {
304
+ Authorization: context.authHeader,
305
+ Accept: "application/json",
306
+ },
307
+ signal: AbortSignal.timeout(10_000),
308
+ });
309
+
310
+ if (!response.ok) {
311
+ const detail = await response.text().catch(() => "");
312
+ writeOutput(cmd, {
313
+ ok: false,
314
+ error: `Failed to list callback routes (HTTP ${response.status}): ${detail}`,
315
+ });
316
+ process.exitCode = 1;
317
+ return;
318
+ }
319
+
320
+ const routes = (await response.json()) as Array<{
321
+ id: string;
322
+ assistant_id: string;
323
+ type: string;
324
+ callback_path: string;
325
+ callback_url: string;
326
+ }>;
327
+
328
+ if (shouldOutputJson(cmd)) {
329
+ writeOutput(cmd, { ok: true, routes });
330
+ } else {
331
+ if (routes.length === 0) {
332
+ log.info("No callback routes registered.");
333
+ } else {
334
+ log.info(`${routes.length} callback route(s) registered:\n`);
335
+ for (const route of routes) {
336
+ log.info(` Type: ${route.type}`);
337
+ log.info(` URL: ${route.callback_url}`);
338
+ log.info(` Path: ${route.callback_path}`);
339
+ log.info("");
340
+ }
341
+ }
342
+ }
343
+ } catch (err) {
344
+ const message = err instanceof Error ? err.message : String(err);
345
+ writeOutput(cmd, { ok: false, error: message });
346
+ process.exitCode = 1;
347
+ }
348
+ });
252
349
  }
@@ -267,24 +267,25 @@ Examples:
267
267
 
268
268
  usage
269
269
  .command("breakdown")
270
- .description("Grouped breakdown by actor, provider, or model")
270
+ .description("Grouped breakdown by actor, provider, model, or conversation")
271
271
  .option(...rangeOption)
272
272
  .option(...fromOption)
273
273
  .option(...toOption)
274
274
  .option(...jsonOption)
275
275
  .option(
276
276
  "-g, --group-by <dimension>",
277
- "Grouping dimension: actor, provider, model",
277
+ "Grouping dimension: actor, provider, model, conversation",
278
278
  "model",
279
279
  )
280
280
  .addHelpText(
281
281
  "after",
282
282
  `
283
283
  Grouping dimensions:
284
- actor Groups by the subsystem that made the call (main_agent,
285
- title_generator, etc.)
286
- provider Groups by LLM provider (anthropic, openai, etc.)
287
- model Groups by model name (claude-sonnet-4-20250514, etc.)
284
+ actor Groups by the subsystem that made the call (main_agent,
285
+ title_generator, etc.)
286
+ provider Groups by LLM provider (anthropic, openai, etc.)
287
+ model Groups by model name (claude-sonnet-4-20250514, etc.)
288
+ conversation Groups by conversation ID
288
289
 
289
290
  Shows one row per group with input/output tokens, estimated cost, and
290
291
  call count. Rows are sorted by cost descending.
@@ -302,10 +303,10 @@ Examples:
302
303
  json?: boolean;
303
304
  groupBy: string;
304
305
  }) => {
305
- const validDimensions = new Set(["actor", "provider", "model"]);
306
+ const validDimensions = new Set(["actor", "provider", "model", "conversation"]);
306
307
  if (!validDimensions.has(opts.groupBy)) {
307
308
  log.error(
308
- `Invalid --group-by value: '${opts.groupBy}'. Must be one of: actor, provider, model`,
309
+ `Invalid --group-by value: '${opts.groupBy}'. Must be one of: actor, provider, model, conversation`,
309
310
  );
310
311
  process.exit(1);
311
312
  }
@@ -313,7 +314,7 @@ Examples:
313
314
  const { from, to } = resolveRange(opts);
314
315
  const breakdown = getUsageGroupBreakdown(
315
316
  { from, to },
316
- opts.groupBy as "actor" | "provider" | "model",
317
+ opts.groupBy as "actor" | "provider" | "model" | "conversation",
317
318
  );
318
319
  if (opts.json) {
319
320
  log.info(JSON.stringify({ breakdown }, null, 2));
@@ -30,6 +30,9 @@ import { getLogger } from "../../util/logger.js";
30
30
  const log = getLogger("daemon-credential-client");
31
31
  const CREDENTIAL_KEY_PREFIX = "credential/";
32
32
 
33
+ /** Hard timeout for daemon HTTP requests to prevent CLI commands from hanging. */
34
+ const DAEMON_FETCH_TIMEOUT_MS = 60_000;
35
+
33
36
  const PROVIDER_ENV_VARS: Record<string, string> = PROVIDER_ENV_VAR_NAMES;
34
37
 
35
38
  // ---------------------------------------------------------------------------
@@ -64,6 +67,7 @@ async function daemonFetch(
64
67
  Authorization: `Bearer ${token}`,
65
68
  "Content-Type": "application/json",
66
69
  },
70
+ signal: AbortSignal.timeout(DAEMON_FETCH_TIMEOUT_MS),
67
71
  });
68
72
 
69
73
  if (!res.ok) {
@@ -1,5 +1,6 @@
1
1
  import { Command } from "commander";
2
2
 
3
+ import { initFeatureFlagOverrides } from "../config/assistant-feature-flags.js";
3
4
  import { getConfig } from "../config/loader.js";
4
5
  import { isEmailEnabled } from "../email/feature-gate.js";
5
6
  import { registerHooksCommand } from "../hooks/cli.js";
@@ -33,13 +34,19 @@ import { registerSkillsCommand } from "./commands/skills.js";
33
34
  import { registerTrustCommand } from "./commands/trust.js";
34
35
  import { registerUsageCommand } from "./commands/usage.js";
35
36
 
36
- export function buildCliProgram(): Command {
37
+ /**
38
+ * Build the CLI program tree. Pre-populates the feature flag cache from
39
+ * the gateway so flag-gated commands are registered correctly.
40
+ */
41
+ export async function buildCliProgram(): Promise<Command> {
42
+ await initFeatureFlagOverrides();
37
43
  const program = new Command();
38
44
 
39
45
  program
40
46
  .name("assistant")
41
47
  .description("Local AI assistant")
42
- .version(APP_VERSION);
48
+ .version(APP_VERSION)
49
+ .allowExcessArguments(true);
43
50
 
44
51
  program.addHelpText(
45
52
  "after",
@@ -53,6 +60,7 @@ Examples:
53
60
 
54
61
  registerDefaultAction(program);
55
62
  registerBashCommand(program);
63
+ registerBrowserRelayCommand(program);
56
64
  registerConversationsCommand(program);
57
65
  registerConfigCommand(program);
58
66
  registerKeysCommand(program);
@@ -78,7 +86,6 @@ Examples:
78
86
  registerOAuthCommand(program);
79
87
  registerRoutesCommand(program);
80
88
  registerSkillsCommand(program);
81
- registerBrowserRelayCommand(program);
82
89
  registerUsageCommand(program);
83
90
 
84
91
  registerShotgunCommand(program);