@vellumai/assistant 0.12.3-staging.1 → 0.12.3-staging.2

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 (560) hide show
  1. package/ARCHITECTURE.md +43 -29
  2. package/Dockerfile +63 -0
  3. package/docs/architecture/security.md +10 -5
  4. package/docs/architecture/turn-actor.md +2 -0
  5. package/docs/desktop-browser-cli.md +45 -4
  6. package/docs/live-voice-task-outcomes.md +100 -0
  7. package/docs/mode-sessions.md +183 -0
  8. package/docs/voice-input-diagnostics.md +58 -0
  9. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +2 -1
  10. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  11. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/integration-categories.ts +36 -0
  12. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +2 -1
  13. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  14. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/integration-categories.ts +36 -0
  15. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +20 -0
  16. package/node_modules/@vellumai/gateway-client/src/index.ts +4 -1
  17. package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +38 -7
  18. package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +5 -6
  19. package/node_modules/@vellumai/service-contracts/package.json +2 -1
  20. package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  21. package/node_modules/@vellumai/service-contracts/src/integration-categories.ts +36 -0
  22. package/node_modules/@vellumai/slack-text/src/index.ts +4 -8
  23. package/openapi.yaml +665 -14
  24. package/package.json +1 -1
  25. package/scripts/smoke-desktop-browser-cli.ts +10 -26
  26. package/scripts/smoke-desktop-window-theme.ts +2 -3
  27. package/src/__tests__/agent-loop-output-hooks.test.ts +150 -1
  28. package/src/__tests__/agent-loop-provider-error-recording.test.ts +87 -19
  29. package/src/__tests__/annotate-activity-metadata.test.ts +3 -1
  30. package/src/__tests__/annotate-risk-options.test.ts +2 -0
  31. package/src/__tests__/answered-question-persistence.test.ts +2 -0
  32. package/src/__tests__/anthropic-gateway-shared.test.ts +22 -0
  33. package/src/__tests__/approval-message-composer.test.ts +1 -118
  34. package/src/__tests__/approval-routes-http.test.ts +3 -0
  35. package/src/__tests__/assistant-event-hub-connection-history.test.ts +111 -0
  36. package/src/__tests__/assistant-event-hub-targeted.test.ts +50 -0
  37. package/src/__tests__/assistant-event-targeting.test.ts +186 -0
  38. package/src/__tests__/assistant-stream-state.test.ts +29 -9
  39. package/src/__tests__/browser-fill-credential.test.ts +11 -22
  40. package/src/__tests__/btw-routes.test.ts +4 -1
  41. package/src/__tests__/build-persisted-content.test.ts +1 -1
  42. package/src/__tests__/call-conversation-messages.test.ts +5 -0
  43. package/src/__tests__/call-recovery.test.ts +7 -2
  44. package/src/__tests__/call-routes-http.test.ts +12 -0
  45. package/src/__tests__/call-store.test.ts +7 -2
  46. package/src/__tests__/channel-retry-sweep.test.ts +9 -0
  47. package/src/__tests__/chat-reveal-guard-priming.test.ts +2 -0
  48. package/src/__tests__/checker.test.ts +11 -3
  49. package/src/__tests__/client-os-metadata-persistence.test.ts +35 -1
  50. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +0 -25
  51. package/src/__tests__/computer-use-tools.test.ts +1 -233
  52. package/src/__tests__/config-model-image-provider.test.ts +39 -0
  53. package/src/__tests__/config-schema.test.ts +16 -0
  54. package/src/__tests__/config-watcher.test.ts +24 -0
  55. package/src/__tests__/context-search-agent-runner.test.ts +260 -1
  56. package/src/__tests__/context-search-fanout.test.ts +1 -1
  57. package/src/__tests__/context-search-types.test.ts +7 -7
  58. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +8 -2
  59. package/src/__tests__/conversation-agent-loop-fatal-cleanup.test.ts +2 -0
  60. package/src/__tests__/conversation-agent-loop.test.ts +546 -16
  61. package/src/__tests__/conversation-app-control-lifecycle.test.ts +53 -1
  62. package/src/__tests__/conversation-evictor.test.ts +62 -37
  63. package/src/__tests__/conversation-history-boundary-repair-failure.test.ts +174 -0
  64. package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +2 -0
  65. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +2 -0
  66. package/src/__tests__/conversation-retry-route.test.ts +22 -0
  67. package/src/__tests__/conversation-routes-disk-view.test.ts +2 -0
  68. package/src/__tests__/conversation-routes-enabled-plugins.test.ts +2 -0
  69. package/src/__tests__/conversation-routes-guardian-reply.test.ts +10 -0
  70. package/src/__tests__/conversation-routes-hidden-queue.test.ts +2 -0
  71. package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -0
  72. package/src/__tests__/conversation-runtime-assembly.test.ts +29 -0
  73. package/src/__tests__/conversation-surface-snapshots.test.ts +543 -0
  74. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +151 -0
  75. package/src/__tests__/conversation-surfaces-point-at-budget.test.ts +63 -1
  76. package/src/__tests__/conversation-tool-setup-attribution.test.ts +23 -0
  77. package/src/__tests__/conversation-undo.test.ts +61 -0
  78. package/src/__tests__/credential-execution-client.test.ts +6 -6
  79. package/src/__tests__/credential-prompt-route.test.ts +35 -3
  80. package/src/__tests__/cu-unified-flow.test.ts +82 -1
  81. package/src/__tests__/db-mode-sessions-migration.test.ts +175 -0
  82. package/src/__tests__/deterministic-verification-control-plane.test.ts +2 -0
  83. package/src/__tests__/dm-backfill.test.ts +91 -1
  84. package/src/__tests__/document-create-route.test.ts +88 -0
  85. package/src/__tests__/document-sync-tags.test.ts +27 -0
  86. package/src/__tests__/emit-signal-routing-intent.test.ts +142 -2
  87. package/src/__tests__/events-tail-route.test.ts +25 -0
  88. package/src/__tests__/evict-conversations-for-reload.test.ts +57 -8
  89. package/src/__tests__/guardian-action-sweep.test.ts +16 -0
  90. package/src/__tests__/guardian-dispatch.test.ts +13 -0
  91. package/src/__tests__/headless-browser-interactions.test.ts +64 -20
  92. package/src/__tests__/heartbeat-service.test.ts +2 -59
  93. package/src/__tests__/helpers/mock-conversation.ts +21 -0
  94. package/src/__tests__/helpers/native-web-search-harness.ts +2 -0
  95. package/src/__tests__/helpers/verification-sessions-ipc-sim.ts +5 -0
  96. package/src/__tests__/host-cu-proxy.test.ts +46 -2
  97. package/src/__tests__/http-user-message-parity.test.ts +2 -0
  98. package/src/__tests__/image-credentials.test.ts +49 -0
  99. package/src/__tests__/image-service-dispatcher.test.ts +45 -0
  100. package/src/__tests__/inference-profile-session-handler.test.ts +1 -1
  101. package/src/__tests__/interrupt-on-send.test.ts +57 -43
  102. package/src/__tests__/interrupt-turn-note.test.ts +5 -6
  103. package/src/__tests__/llm-catalog-parity.test.ts +2 -2
  104. package/src/__tests__/media-generate-image.test.ts +49 -1
  105. package/src/__tests__/message-provenance-contact-id.test.ts +69 -0
  106. package/src/__tests__/migration-export-to-gcs.test.ts +142 -0
  107. package/src/__tests__/mode-session-history.test.ts +245 -0
  108. package/src/__tests__/mode-session-recovery.test.ts +222 -0
  109. package/src/__tests__/mode-session-wire.test.ts +141 -0
  110. package/src/__tests__/notification-guardian-path.test.ts +7 -0
  111. package/src/__tests__/notification-telegram-adapter.test.ts +2 -2
  112. package/src/__tests__/notification-vellum-adapter.test.ts +34 -0
  113. package/src/__tests__/oauth-provider-serializer.test.ts +12 -0
  114. package/src/__tests__/oauth-providers-routes.test.ts +1 -0
  115. package/src/__tests__/outbound-slack-persistence.test.ts +2 -0
  116. package/src/__tests__/persistence-secret-redaction.test.ts +2 -0
  117. package/src/__tests__/plugin-api-provider.test.ts +5 -0
  118. package/src/__tests__/plugin-api-resolve-credential.test.ts +97 -0
  119. package/src/__tests__/plugin-import-boundary-guard.test.ts +9 -0
  120. package/src/__tests__/process-message-display-content.test.ts +56 -0
  121. package/src/__tests__/reaction-persistence.test.ts +5 -0
  122. package/src/__tests__/request-secret-standalone-channel-gate.test.ts +25 -9
  123. package/src/__tests__/runtime-events-sse-reconnect.test.ts +1 -1
  124. package/src/__tests__/scripted-turn-metadata-persistence.test.ts +73 -0
  125. package/src/__tests__/secret-ingress-http.test.ts +2 -0
  126. package/src/__tests__/secure-keys.test.ts +43 -1
  127. package/src/__tests__/send-endpoint-busy.test.ts +163 -1
  128. package/src/__tests__/server-history-render.test.ts +91 -1
  129. package/src/__tests__/settings-routes.test.ts +50 -1
  130. package/src/__tests__/skill-script-runner-sandbox.test.ts +32 -0
  131. package/src/__tests__/subagent-fork-notifications.test.ts +1 -2
  132. package/src/__tests__/subagent-manager-notify.test.ts +1 -2
  133. package/src/__tests__/subagent-notify-parent.test.ts +146 -39
  134. package/src/__tests__/subagent-notify-stale-rebuild.test.ts +2 -4
  135. package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +2 -0
  136. package/src/__tests__/thread-backfill.test.ts +53 -0
  137. package/src/__tests__/tool-preview-lifecycle.test.ts +2 -0
  138. package/src/__tests__/tool-result-metadata-plumbing.test.ts +3 -1
  139. package/src/__tests__/tool-start-timestamp.test.ts +2 -0
  140. package/src/__tests__/twilio-routes.test.ts +1 -0
  141. package/src/__tests__/web-search-backend-failure.test.ts +1 -1
  142. package/src/activation/progress-store.test.ts +12 -7
  143. package/src/agent/loop.ts +99 -41
  144. package/src/api/events/assistant-turn-start.ts +3 -0
  145. package/src/api/events/generation-handoff.ts +2 -0
  146. package/src/api/events/message-complete.ts +2 -0
  147. package/src/api/events/notification-conversation-created.ts +14 -16
  148. package/src/api/events/notification-intent.ts +4 -2
  149. package/src/api/events/tool-result.ts +85 -0
  150. package/src/api/events/tool-use-start.ts +3 -0
  151. package/src/api/events/user-message-echo.ts +3 -0
  152. package/src/api/index.ts +31 -6
  153. package/src/api/mode-session.test.ts +131 -0
  154. package/src/api/mode-session.ts +148 -0
  155. package/src/api/remember-tool.ts +15 -0
  156. package/src/api/responses/conversation-message.ts +6 -0
  157. package/src/approvals/AGENTS.md +4 -2
  158. package/src/browser/__tests__/operations.test.ts +29 -0
  159. package/src/browser/operation-meta.ts +2 -1
  160. package/src/browser/operations.ts +29 -0
  161. package/src/browser/virtual-desktop-target.ts +2 -8
  162. package/src/bundler/bundle-signer.ts +1 -3
  163. package/src/calls/__tests__/barge-in-guard.test.ts +3 -0
  164. package/src/calls/__tests__/call-controller.test.ts +94 -0
  165. package/src/calls/__tests__/call-funnel-telemetry.test.ts +204 -0
  166. package/src/calls/__tests__/voice-control-protocol.test.ts +15 -0
  167. package/src/calls/__tests__/voice-escalation-judge.test.ts +209 -0
  168. package/src/calls/__tests__/voice-leg-coordinator.test.ts +168 -0
  169. package/src/{live-voice/__tests__/live-voice-metrics.test.ts → calls/__tests__/voice-metrics.test.ts} +32 -38
  170. package/src/calls/__tests__/voice-session-bridge.test.ts +576 -122
  171. package/src/calls/barge-in-guard.ts +5 -0
  172. package/src/calls/call-controller.ts +196 -1
  173. package/src/calls/call-domain.ts +4 -0
  174. package/src/calls/call-store.ts +87 -2
  175. package/src/calls/guardian-action-sweep.ts +22 -8
  176. package/src/calls/media-stream-audio-transcode.ts +1 -3
  177. package/src/calls/typesafe-noul.ts +156 -0
  178. package/src/calls/voice-control-protocol.ts +6 -0
  179. package/src/calls/voice-escalation-judge.ts +145 -0
  180. package/src/calls/voice-escalation-target.ts +10 -0
  181. package/src/calls/voice-leg-coordinator.ts +121 -3
  182. package/src/{live-voice/live-voice-metrics.ts → calls/voice-metrics.ts} +94 -87
  183. package/src/calls/voice-session-bridge.ts +256 -112
  184. package/src/calls/voice-triage-escalate.ts +7 -0
  185. package/src/cli/__tests__/roadmap-cli.test.ts +4 -41
  186. package/src/cli/commands/__tests__/notifications.test.ts +35 -10
  187. package/src/cli/commands/browser.help.ts +4 -5
  188. package/src/cli/commands/browser.ts +0 -1
  189. package/src/cli/commands/clients.help.ts +46 -0
  190. package/src/cli/commands/clients.ts +116 -0
  191. package/src/cli/commands/credentials.help.ts +6 -1
  192. package/src/cli/commands/notifications.help.ts +16 -2
  193. package/src/cli/commands/notifications.ts +30 -8
  194. package/src/cli/commands/roadmap.help.ts +18 -21
  195. package/src/cli/commands/roadmap.ts +4 -21
  196. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +5 -2
  197. package/src/cli/lib/bundled-marketplace.json +84 -34
  198. package/src/cli/lib/plugin-marketplace.ts +8 -0
  199. package/src/cli/lib/publish-plugin.ts +1 -2
  200. package/src/config/__tests__/default-provider.test.ts +3 -1
  201. package/src/config/__tests__/memory-retrospective-schema.test.ts +14 -1
  202. package/src/config/bundled-skills/computer-use/SKILL.md +1 -1
  203. package/src/config/bundled-skills/computer-use/TOOLS.json +89 -1
  204. package/src/config/bundled-skills/image-studio/SKILL.md +17 -2
  205. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +7 -11
  206. package/src/config/bundled-skills/sequences/TOOLS.json +1 -5
  207. package/src/config/call-site-defaults.ts +9 -0
  208. package/src/config/feature-flag-registry.json +16 -0
  209. package/src/config/profile-text-generation.test.ts +2 -2
  210. package/src/config/schemas/__tests__/tools.test.ts +31 -0
  211. package/src/config/schemas/call-site-catalog.ts +14 -0
  212. package/src/config/schemas/channels.ts +0 -18
  213. package/src/config/schemas/llm.ts +3 -1
  214. package/src/config/schemas/mcp.ts +2 -1
  215. package/src/config/schemas/memory-retrospective.ts +11 -2
  216. package/src/config/schemas/services.ts +15 -6
  217. package/src/config/schemas/tools.ts +10 -0
  218. package/src/config/session-groups-gate.ts +21 -0
  219. package/src/config/skills.ts +2 -6
  220. package/src/conversations/__tests__/message-consolidation.test.ts +149 -0
  221. package/src/conversations/message-consolidation.ts +102 -5
  222. package/src/credential-execution/ces-connect.test.ts +69 -0
  223. package/src/credential-execution/ces-connect.ts +115 -0
  224. package/src/credential-execution/ces-runtime.ts +55 -93
  225. package/src/credential-execution/executable-discovery.ts +1 -11
  226. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +10 -1
  227. package/src/daemon/__tests__/inference-profile-notification.test.ts +2 -0
  228. package/src/daemon/browser-mode-session.test.ts +402 -0
  229. package/src/daemon/browser-mode-session.ts +186 -0
  230. package/src/daemon/computer-use-mode-session.test.ts +210 -0
  231. package/src/daemon/computer-use-mode-session.ts +105 -0
  232. package/src/daemon/config-watcher.ts +10 -0
  233. package/src/daemon/conversation-agent-loop-handlers.ts +58 -10
  234. package/src/daemon/conversation-agent-loop.ts +219 -25
  235. package/src/daemon/conversation-evictor.ts +5 -24
  236. package/src/daemon/conversation-history.ts +10 -0
  237. package/src/daemon/conversation-interrupt-repair.ts +4 -43
  238. package/src/daemon/conversation-interrupt.ts +7 -11
  239. package/src/daemon/conversation-messaging.ts +58 -5
  240. package/src/daemon/conversation-mode-session.test.ts +1667 -0
  241. package/src/daemon/conversation-mode-session.ts +1008 -0
  242. package/src/daemon/conversation-process.ts +5 -0
  243. package/src/daemon/conversation-runtime-assembly.ts +10 -20
  244. package/src/daemon/conversation-skill-tools.ts +1 -0
  245. package/src/daemon/conversation-store.ts +4 -4
  246. package/src/daemon/conversation-surface-snapshots.ts +135 -0
  247. package/src/daemon/conversation-surfaces.ts +113 -5
  248. package/src/daemon/conversation-tool-setup.ts +8 -3
  249. package/src/daemon/conversation.ts +143 -41
  250. package/src/daemon/handlers/config-model.ts +7 -5
  251. package/src/daemon/handlers/shared.ts +55 -16
  252. package/src/daemon/host-cu-proxy.ts +51 -22
  253. package/src/daemon/lifecycle.ts +30 -13
  254. package/src/daemon/message-protocol.ts +0 -1
  255. package/src/daemon/message-provenance.ts +28 -4
  256. package/src/daemon/mode-session-startup-recovery.ts +23 -0
  257. package/src/daemon/mode-session-tracking.ts +54 -0
  258. package/src/daemon/process-message.ts +13 -4
  259. package/src/daemon/virtual-desktop-context.ts +21 -0
  260. package/src/desktop/__tests__/fake-desktop.ts +1 -0
  261. package/src/desktop/desktop-accessibility-script.ts +88 -0
  262. package/src/desktop/desktop-accessibility.test.ts +160 -0
  263. package/src/desktop/desktop-accessibility.ts +169 -0
  264. package/src/desktop/desktop-automation-lease.test.ts +76 -68
  265. package/src/desktop/desktop-automation-lease.ts +41 -50
  266. package/src/desktop/desktop-browser-endpoint.ts +4 -0
  267. package/src/desktop/desktop-computer-use-routing.test.ts +330 -0
  268. package/src/desktop/desktop-computer-use.test.ts +449 -0
  269. package/src/desktop/desktop-computer-use.ts +502 -0
  270. package/src/desktop/desktop-dependencies.ts +47 -293
  271. package/src/desktop/desktop-display.ts +2 -2
  272. package/src/desktop/desktop-panel-config.test.ts +13 -3
  273. package/src/desktop/desktop-panel-config.ts +109 -15
  274. package/src/desktop/desktop-session-manager.test.ts +69 -21
  275. package/src/desktop/desktop-session-manager.ts +76 -22
  276. package/src/desktop/desktop-stream-bridge.test.ts +11 -122
  277. package/src/desktop/desktop-stream-bridge.ts +6 -8
  278. package/src/desktop/desktop-window-theme.ts +5 -25
  279. package/src/desktop/virtual-desktop-feature.ts +52 -2
  280. package/src/desktop/virtual-desktop-platform.test.ts +5 -9
  281. package/src/documents/document-store.ts +23 -0
  282. package/src/heartbeat/__tests__/heartbeat-service.test.ts +22 -26
  283. package/src/heartbeat/heartbeat-service.ts +5 -33
  284. package/src/ipc/__tests__/browser-ipc.test.ts +215 -6
  285. package/src/ipc/assistant-server.ts +2 -0
  286. package/src/ipc/routes/__tests__/channel-reply-ipc-routes.test.ts +111 -0
  287. package/src/ipc/routes/channel-reply-ipc-routes.ts +73 -0
  288. package/src/live-voice/__tests__/continuation-judge.test.ts +151 -0
  289. package/src/live-voice/__tests__/live-activity-reporter.test.ts +154 -15
  290. package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +743 -31
  291. package/src/live-voice/__tests__/live-voice-look-follow-up.test.ts +191 -10
  292. package/src/live-voice/__tests__/live-voice-session-groups-gate.test.ts +87 -0
  293. package/src/live-voice/__tests__/live-voice-session-manager.test.ts +5 -1
  294. package/src/live-voice/__tests__/live-voice-sight-frame-echo.test.ts +41 -0
  295. package/src/live-voice/__tests__/live-voice-sight-frame.test.ts +1017 -9
  296. package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +224 -1
  297. package/src/live-voice/__tests__/live-voice-tts-session.test.ts +101 -0
  298. package/src/live-voice/__tests__/live-voice-tts.test.ts +44 -0
  299. package/src/live-voice/__tests__/live-voice-vad.test.ts +939 -75
  300. package/src/live-voice/__tests__/microphone-idle-gate.test.ts +87 -0
  301. package/src/live-voice/__tests__/session-controls.test.ts +23 -0
  302. package/src/live-voice/__tests__/task-outcomes.test.ts +117 -0
  303. package/src/live-voice/__tests__/voice-input-diagnostics.test.ts +117 -0
  304. package/src/live-voice/camera-mode-session.test.ts +265 -0
  305. package/src/live-voice/camera-mode-session.ts +277 -0
  306. package/src/live-voice/continuation-judge.ts +123 -0
  307. package/src/live-voice/live-activity-reporter.ts +115 -6
  308. package/src/live-voice/live-voice-manager.ts +36 -1
  309. package/src/live-voice/live-voice-photo.ts +88 -7
  310. package/src/live-voice/live-voice-session-manager.ts +15 -0
  311. package/src/live-voice/live-voice-session.ts +1443 -747
  312. package/src/live-voice/live-voice-tts.ts +22 -4
  313. package/src/live-voice/microphone-idle-gate.ts +56 -0
  314. package/src/live-voice/protocol.ts +171 -4
  315. package/src/live-voice/session-controls.ts +11 -3
  316. package/src/live-voice/task-outcomes.ts +131 -0
  317. package/src/live-voice/voice-input-diagnostics.ts +117 -0
  318. package/src/mcp/__tests__/manager-tool-caps.test.ts +63 -18
  319. package/src/mcp/__tests__/tool-caps.test.ts +28 -1
  320. package/src/mcp/manager.ts +3 -0
  321. package/src/mcp/tool-caps.ts +12 -4
  322. package/src/media/__tests__/image-models.test.ts +58 -0
  323. package/src/media/image-credentials.ts +5 -0
  324. package/src/media/image-models.ts +52 -0
  325. package/src/media/image-service.ts +8 -0
  326. package/src/media/openrouter-image-service.test.ts +133 -0
  327. package/src/media/openrouter-image-service.ts +153 -0
  328. package/src/media/types.ts +1 -1
  329. package/src/messaging/providers/__tests__/transport-dispatch.test.ts +65 -11
  330. package/src/messaging/providers/discord/send.ts +4 -17
  331. package/src/messaging/providers/discord/transport.ts +2 -2
  332. package/src/messaging/providers/outlook/client.ts +16 -22
  333. package/src/messaging/providers/telegram-bot/send.test.ts +236 -1
  334. package/src/messaging/providers/telegram-bot/send.ts +10 -7
  335. package/src/messaging/providers/telegram-bot/transport.ts +3 -10
  336. package/src/messaging/providers/whatsapp/send.test.ts +169 -4
  337. package/src/monitoring/__tests__/control.test.ts +17 -5
  338. package/src/monitoring/control.ts +15 -5
  339. package/src/notifications/AGENTS.md +1 -1
  340. package/src/notifications/README.md +83 -99
  341. package/src/notifications/__tests__/broadcaster.test.ts +1 -1
  342. package/src/notifications/__tests__/channel-allowlist.test.ts +39 -0
  343. package/src/notifications/__tests__/copy-composer.test.ts +1 -1
  344. package/src/notifications/__tests__/decision-engine.test.ts +79 -2
  345. package/src/notifications/__tests__/deterministic-checks.test.ts +10 -10
  346. package/src/notifications/__tests__/home-feed-side-effect.test.ts +93 -4
  347. package/src/notifications/__tests__/notification-utils.test.ts +18 -0
  348. package/src/notifications/adapters/macos.ts +37 -46
  349. package/src/notifications/broadcaster.ts +5 -6
  350. package/src/notifications/channel-allowlist.ts +44 -0
  351. package/src/notifications/copy-composer.ts +0 -23
  352. package/src/notifications/decision-engine.ts +24 -14
  353. package/src/notifications/deterministic-checks.ts +1 -1
  354. package/src/notifications/emit-signal.ts +123 -37
  355. package/src/notifications/home-feed-side-effect.ts +9 -7
  356. package/src/notifications/notification-utils.ts +19 -0
  357. package/src/notifications/signal.ts +4 -19
  358. package/src/notifications/types.ts +15 -0
  359. package/src/oauth/connection-resolver.ts +1 -2
  360. package/src/oauth/oauth-store.ts +1 -3
  361. package/src/oauth/provider-serializer.ts +7 -0
  362. package/src/oauth/seed-providers.ts +30 -0
  363. package/src/onboarding/onboarding-events-store.ts +99 -12
  364. package/src/persistence/__tests__/client-connection-events-store.test.ts +322 -0
  365. package/src/persistence/client-connection-events-store.ts +377 -0
  366. package/src/persistence/conversation-crud.ts +55 -6
  367. package/src/persistence/conversation-mode-sessions.test.ts +424 -0
  368. package/src/persistence/conversation-mode-sessions.ts +460 -0
  369. package/src/persistence/conversation-queries.ts +6 -19
  370. package/src/persistence/llm-usage-store.ts +3 -9
  371. package/src/persistence/message-metadata.ts +25 -0
  372. package/src/persistence/migrations/381-create-conversation-mode-sessions.ts +41 -0
  373. package/src/persistence/migrations/382-create-client-connection-events.ts +40 -0
  374. package/src/persistence/migrations/__tests__/382-create-client-connection-events.test.ts +56 -0
  375. package/src/persistence/schema/conversations.ts +67 -0
  376. package/src/persistence/schema/infrastructure.ts +29 -0
  377. package/src/persistence/steps.ts +17 -0
  378. package/src/plugin-api/__tests__/plugin-name-env.test.ts +249 -0
  379. package/src/plugin-api/effective-context-window.ts +33 -0
  380. package/src/plugin-api/index.ts +24 -5
  381. package/src/plugin-api/plugin-name-env.ts +125 -0
  382. package/src/plugin-api/resolve-credential.ts +79 -20
  383. package/src/plugin-api/vision-support.test.ts +22 -0
  384. package/src/plugin-api/vision-support.ts +17 -5
  385. package/src/plugins/__tests__/active-plugin-env.test.ts +136 -0
  386. package/src/plugins/active-plugin-env.ts +51 -0
  387. package/src/plugins/defaults/index.ts +24 -0
  388. package/src/plugins/defaults/memory/__tests__/archive-removal-framing.test.ts +64 -0
  389. package/src/plugins/defaults/memory/__tests__/worker-control.test.ts +19 -6
  390. package/src/plugins/defaults/memory/context-search/agent-protocol.ts +9 -12
  391. package/src/plugins/defaults/memory/context-search/agent-runner.ts +78 -22
  392. package/src/plugins/defaults/memory/context-search/format.ts +51 -7
  393. package/src/plugins/defaults/memory/context-search/limits.ts +10 -12
  394. package/src/plugins/defaults/memory/context-search/recall-input.ts +38 -0
  395. package/src/plugins/defaults/memory/context-search/search.ts +8 -14
  396. package/src/plugins/defaults/memory/context-search/sources/conversations.ts +1 -0
  397. package/src/plugins/defaults/memory/context-search/types.ts +1 -11
  398. package/src/plugins/defaults/memory/graph/__tests__/handle-remember-v2.test.ts +11 -4
  399. package/src/plugins/defaults/memory/graph/tool-handlers.ts +12 -21
  400. package/src/plugins/defaults/memory/graph/tools.ts +35 -64
  401. package/src/plugins/defaults/memory/src/memory-eval-routes.ts +2 -3
  402. package/src/plugins/defaults/memory/src/memory-item-routes.test.ts +5 -0
  403. package/src/plugins/defaults/memory/src/memory-item-routes.ts +2 -1
  404. package/src/plugins/defaults/memory/substrate/prompts/consolidation.ts +2 -2
  405. package/src/plugins/defaults/memory/tools.test.ts +124 -9
  406. package/src/plugins/defaults/memory/tools.ts +38 -11
  407. package/src/plugins/defaults/memory/v3/__tests__/pool-log-store.test.ts +165 -27
  408. package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +626 -27
  409. package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +46 -27
  410. package/src/plugins/defaults/memory/v3/orchestrate.ts +78 -38
  411. package/src/plugins/defaults/memory/v3/pool-log-store.ts +65 -79
  412. package/src/plugins/defaults/memory/v3/pool-select.test.ts +14 -5
  413. package/src/plugins/defaults/memory/v3/pool-select.ts +683 -44
  414. package/src/plugins/defaults/memory/worker-control.ts +15 -5
  415. package/src/plugins/defaults/task-progress/__tests__/registration.test.ts +70 -0
  416. package/src/plugins/defaults/task-progress/__tests__/task-progress-context.test.ts +380 -0
  417. package/src/plugins/defaults/task-progress/hooks/post-compact.ts +19 -0
  418. package/src/plugins/defaults/task-progress/hooks/user-prompt-submit.ts +24 -0
  419. package/src/plugins/defaults/task-progress/package.json +14 -0
  420. package/src/plugins/defaults/task-progress/src/apply-task-progress-context.ts +93 -0
  421. package/src/plugins/defaults/task-progress/src/format-task-progress-context.ts +67 -0
  422. package/src/providers/__tests__/context-overflow-error.test.ts +10 -0
  423. package/src/providers/__tests__/search-provider-catalog.test.ts +18 -0
  424. package/src/providers/anthropic/client.ts +10 -1
  425. package/src/providers/anthropic-gateway-shared.ts +6 -0
  426. package/src/providers/fetch-provider-catalog.ts +11 -0
  427. package/src/providers/gemini/client.ts +25 -8
  428. package/src/providers/inference/adapter-factory.ts +1 -1
  429. package/src/providers/jev/client.test.ts +10 -0
  430. package/src/providers/jev/client.ts +20 -4
  431. package/src/providers/model-catalog.ts +4 -3
  432. package/src/providers/openai/__tests__/chat-completions-extra-body.test.ts +94 -1
  433. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +106 -1
  434. package/src/providers/openai/__tests__/chat-template-flatten.test.ts +24 -0
  435. package/src/providers/openai/__tests__/google-thought-signature.test.ts +1 -2
  436. package/src/providers/openai/chat-completions-provider.ts +100 -29
  437. package/src/providers/openai/google-thought-signature.ts +0 -6
  438. package/src/providers/openai/responses-provider.ts +23 -1
  439. package/src/providers/ratelimit.ts +1 -3
  440. package/src/providers/search-provider-catalog.ts +24 -0
  441. package/src/providers/speech-to-text/__tests__/deepgram-flux-frames.test.ts +24 -0
  442. package/src/providers/speech-to-text/__tests__/deepgram-flux-realtime.test.ts +7 -1
  443. package/src/providers/speech-to-text/__tests__/vellum-managed-realtime.test.ts +50 -1
  444. package/src/providers/speech-to-text/deepgram-flux-frames.ts +11 -0
  445. package/src/providers/speech-to-text/vellum-managed-flux-realtime.ts +13 -0
  446. package/src/providers/types.ts +5 -0
  447. package/src/routes/control.ts +7 -5
  448. package/src/runtime/AGENTS.md +4 -2
  449. package/src/runtime/actor-trust-resolver.ts +3 -3
  450. package/src/runtime/agent-wake.ts +1 -1
  451. package/src/runtime/approval-message-composer.ts +3 -69
  452. package/src/runtime/assistant-event-hub.ts +73 -75
  453. package/src/runtime/assistant-event-publish-options.ts +7 -0
  454. package/src/runtime/assistant-event-targeting.ts +79 -0
  455. package/src/runtime/assistant-stream-state.ts +13 -100
  456. package/src/runtime/background-job-runner.ts +5 -5
  457. package/src/runtime/channel-retry-sweep.ts +1 -0
  458. package/src/runtime/guardian-action-message-composer.ts +8 -161
  459. package/src/runtime/guardian-reply-router.ts +28 -32
  460. package/src/runtime/http-types.ts +6 -0
  461. package/src/runtime/message-composer-types.ts +3 -61
  462. package/src/runtime/migrations/__tests__/vbundle-import-parity.test.ts +67 -1
  463. package/src/runtime/migrations/vbundle-builder.ts +24 -1
  464. package/src/runtime/migrations/vbundle-import-analyzer.ts +13 -4
  465. package/src/runtime/migrations/vbundle-import-policy.ts +10 -0
  466. package/src/runtime/migrations/vbundle-importer.ts +4 -1
  467. package/src/runtime/migrations/vbundle-streaming-importer.ts +4 -1
  468. package/src/runtime/migrations/vbundle-validator.ts +1 -0
  469. package/src/runtime/pending-interactions-mode-session.test.ts +62 -0
  470. package/src/runtime/pending-interactions.ts +29 -0
  471. package/src/runtime/routes/__tests__/client-history-routes.test.ts +104 -0
  472. package/src/runtime/routes/__tests__/image-generation-routes.test.ts +97 -0
  473. package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +1 -1
  474. package/src/runtime/routes/__tests__/roadmap-routes.test.ts +29 -6
  475. package/src/runtime/routes/browser-context.ts +31 -11
  476. package/src/runtime/routes/browser-routes.ts +43 -4
  477. package/src/runtime/routes/btw-routes.ts +9 -4
  478. package/src/runtime/routes/client-routes.ts +108 -0
  479. package/src/runtime/routes/conversation-management-routes.ts +4 -1
  480. package/src/runtime/routes/conversation-routes.ts +113 -27
  481. package/src/runtime/routes/credential-prompt-routes.ts +4 -3
  482. package/src/runtime/routes/credential-routes.ts +1 -2
  483. package/src/runtime/routes/desktop-setup-routes.test.ts +9 -18
  484. package/src/runtime/routes/desktop-setup-routes.ts +4 -6
  485. package/src/runtime/routes/documents-routes.ts +51 -0
  486. package/src/runtime/routes/email-routes.ts +3 -7
  487. package/src/runtime/routes/events-routes.ts +75 -54
  488. package/src/runtime/routes/identity-routes.ts +1 -5
  489. package/src/runtime/routes/image-generation-routes.ts +8 -14
  490. package/src/runtime/routes/inbound-message-handler.ts +35 -38
  491. package/src/runtime/routes/inbound-stages/backfill-sender-provenance.test.ts +168 -0
  492. package/src/runtime/routes/inbound-stages/backfill-sender-provenance.ts +96 -0
  493. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +38 -9
  494. package/src/runtime/routes/inbound-stages/background-dispatch.ts +2 -5
  495. package/src/runtime/routes/inbound-stages/reaction-intercept.ts +2 -0
  496. package/src/runtime/routes/llm-context-normalization.ts +1 -7
  497. package/src/runtime/routes/migration-routes.ts +73 -2
  498. package/src/runtime/routes/notification-routes.ts +10 -0
  499. package/src/runtime/routes/oauth-providers.ts +7 -0
  500. package/src/runtime/routes/plugins-routes.ts +6 -0
  501. package/src/runtime/routes/roadmap-routes.ts +47 -8
  502. package/src/runtime/routes/secret-routes.ts +1 -1
  503. package/src/runtime/routes/settings-routes.ts +10 -4
  504. package/src/runtime/routes/watcher-routes.ts +1 -3
  505. package/src/runtime/trust-class.test.ts +7 -6
  506. package/src/runtime/trust-class.ts +9 -17
  507. package/src/schedule/__tests__/worker-control.test.ts +36 -5
  508. package/src/schedule/worker-control.ts +15 -5
  509. package/src/security/secure-keys.ts +53 -103
  510. package/src/skills/clawhub.ts +3 -8
  511. package/src/skills/managed-store.ts +1 -5
  512. package/src/stt/types.ts +4 -0
  513. package/src/subagent/notify.ts +54 -34
  514. package/src/subagent/parent-notification.ts +6 -0
  515. package/src/telemetry/__tests__/phone-call-funnel.test.ts +72 -0
  516. package/src/telemetry/phone-call-funnel.ts +144 -0
  517. package/src/tools/__tests__/tool-schema-root-combinator-guard.test.ts +81 -0
  518. package/src/tools/ask-question/ask-question-tool.ts +6 -4
  519. package/src/tools/browser/browser-execution.ts +22 -59
  520. package/src/tools/browser/cdp-client/__tests__/cdp-dom-helpers.test.ts +561 -39
  521. package/src/tools/browser/cdp-client/cdp-dom-helpers.ts +435 -39
  522. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +1 -8
  523. package/src/tools/client-os.ts +15 -0
  524. package/src/tools/computer-use/skill-proxy-bridge.ts +1 -1
  525. package/src/tools/computer-use/target.ts +42 -0
  526. package/src/tools/document/document-tool.ts +13 -18
  527. package/src/tools/execution-target.ts +14 -16
  528. package/src/tools/host-terminal/host-shell.ts +4 -1
  529. package/src/tools/network/__tests__/web-fetch-tinyfish.test.ts +250 -0
  530. package/src/tools/network/__tests__/web-search.test.ts +203 -0
  531. package/src/tools/network/web-fetch.ts +274 -7
  532. package/src/tools/network/web-search.ts +468 -6
  533. package/src/tools/permission-checker.ts +3 -3
  534. package/src/tools/policy-context.ts +3 -1
  535. package/src/tools/skills/load.ts +2 -1
  536. package/src/tools/skills/sandbox-runner.ts +11 -2
  537. package/src/tools/skills/skill-script-runner.ts +7 -0
  538. package/src/tools/skills/skill-tool-factory.ts +15 -1
  539. package/src/tools/terminal/__tests__/safe-env.test.ts +11 -0
  540. package/src/tools/terminal/safe-env.ts +4 -0
  541. package/src/tools/terminal/shell.ts +2 -0
  542. package/src/tools/tool-approval-handler.ts +5 -1
  543. package/src/tools/tool-types.ts +3 -3
  544. package/src/tools/types.ts +8 -2
  545. package/src/util/__tests__/worker-process-command.test.ts +5 -4
  546. package/src/util/abort-reasons.ts +18 -26
  547. package/src/util/canonicalize-identity.test.ts +21 -0
  548. package/src/util/canonicalize-identity.ts +16 -0
  549. package/src/util/errors.ts +13 -3
  550. package/src/util/provider-error-patterns.ts +3 -0
  551. package/src/util/worker-process.ts +77 -35
  552. package/src/workspace/migrations/157-add-desktop-files-launcher.ts +94 -0
  553. package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +4 -10
  554. package/src/workspace/migrations/__tests__/157-add-desktop-files-launcher.test.ts +113 -0
  555. package/src/workspace/migrations/registry.ts +2 -0
  556. package/src/__tests__/computer-use-window-schema.test.ts +0 -24
  557. package/src/api/events/heartbeat-alert.ts +0 -20
  558. package/src/daemon/message-types/web-activity.ts +0 -65
  559. package/src/desktop/desktop-dependencies.test.ts +0 -131
  560. package/src/tools/computer-use/definitions.ts +0 -607
@@ -219,15 +219,15 @@ describe("roadmap writes", () => {
219
219
  });
220
220
  });
221
221
 
222
- test("update sends only the fields that were passed", async () => {
222
+ test("update forwards only the title and description it was given", async () => {
223
223
  nextResult = ITEM;
224
224
 
225
225
  await runAssistantCommandFull(
226
226
  "roadmap",
227
227
  "update",
228
228
  "dark-mode",
229
- "--status",
230
- "planned",
229
+ "--description",
230
+ "Follow the OS setting",
231
231
  );
232
232
 
233
233
  expect(calls[0]).toEqual({
@@ -236,49 +236,12 @@ describe("roadmap writes", () => {
236
236
  pathParams: { slug: "dark-mode" },
237
237
  body: {
238
238
  title: undefined,
239
- description: undefined,
240
- status: "planned",
241
- tags: undefined,
239
+ description: "Follow the OS setting",
242
240
  },
243
241
  },
244
242
  });
245
243
  });
246
244
 
247
- test("--clear-tags sends the empty set that --tag cannot express", async () => {
248
- nextResult = ITEM;
249
-
250
- await runAssistantCommandFull(
251
- "roadmap",
252
- "update",
253
- "dark-mode",
254
- "--clear-tags",
255
- );
256
-
257
- expect((calls[0].params as { body: { tags: string[] } }).body.tags).toEqual(
258
- [],
259
- );
260
- });
261
-
262
- test("--clear-tags with --tag is refused rather than silently picking one", async () => {
263
- nextResult = ITEM;
264
- process.exitCode = 0;
265
-
266
- // The complaint itself goes straight to stderr, which this harness does
267
- // not capture; what matters is that no update was forwarded.
268
- await runAssistantCommandFull(
269
- "roadmap",
270
- "update",
271
- "dark-mode",
272
- "--clear-tags",
273
- "--tag",
274
- "ui",
275
- );
276
-
277
- expect(calls).toHaveLength(0);
278
- expect(process.exitCode).toBe(1);
279
- process.exitCode = 0;
280
- });
281
-
282
245
  test("delete names the item it removed", async () => {
283
246
  nextResult = { slug: "dark-mode", deleted: true };
284
247
 
@@ -175,7 +175,7 @@ describe("notifications send", () => {
175
175
  "--source-channel",
176
176
  "assistant_tool",
177
177
  "--source-event-name",
178
- "user.send_notification",
178
+ "schedule.notify",
179
179
  "--message",
180
180
  "Hello",
181
181
  ]);
@@ -186,7 +186,7 @@ describe("notifications send", () => {
186
186
 
187
187
  const body = lastSendBody();
188
188
  expect(body.sourceChannel).toBe("assistant_tool");
189
- expect(body.sourceEventName).toBe("user.send_notification");
189
+ expect(body.sourceEventName).toBe("schedule.notify");
190
190
  const payload = body.contextPayload as Record<string, unknown>;
191
191
  expect(payload.requestedMessage).toBe("Hello");
192
192
  });
@@ -221,7 +221,7 @@ describe("notifications send", () => {
221
221
  "--source-channel",
222
222
  "assistant_tool",
223
223
  "--source-event-name",
224
- "user.send_notification",
224
+ "schedule.notify",
225
225
  "--message",
226
226
  "Hello",
227
227
  "--preferred-channels",
@@ -235,7 +235,7 @@ describe("notifications send", () => {
235
235
  expect(payload.preferredChannels).toEqual(["telegram", "slack"]);
236
236
  });
237
237
 
238
- test("send rejects invalid urgency", async () => {
238
+ test("send passes exclusive channel allowlist", async () => {
239
239
  const { parsed, exitCode } = await runCommand([
240
240
  "send",
241
241
  "--source-channel",
@@ -243,6 +243,31 @@ describe("notifications send", () => {
243
243
  "--source-event-name",
244
244
  "user.send_notification",
245
245
  "--message",
246
+ "Alarm",
247
+ "--channels",
248
+ "telegram",
249
+ "--urgent",
250
+ ]);
251
+
252
+ expect(exitCode).toBe(0);
253
+ expect(parsed.ok).toBe(true);
254
+ expect(parsed.selectedChannels).toEqual([]);
255
+ expect(parsed.deliveryResults).toEqual([]);
256
+ expect(parsed.receiptClass).toBe("unknown");
257
+
258
+ const payload = lastSendBody().contextPayload as Record<string, unknown>;
259
+ expect(payload.channelAllowlist).toEqual(["telegram"]);
260
+ expect(payload.preferredChannels).toBeUndefined();
261
+ });
262
+
263
+ test("send rejects invalid urgency", async () => {
264
+ const { parsed, exitCode } = await runCommand([
265
+ "send",
266
+ "--source-channel",
267
+ "assistant_tool",
268
+ "--source-event-name",
269
+ "schedule.notify",
270
+ "--message",
246
271
  "Hello",
247
272
  "--urgency",
248
273
  "invalid",
@@ -265,7 +290,7 @@ describe("notifications send", () => {
265
290
  "--source-channel",
266
291
  "water_reminder",
267
292
  "--source-event-name",
268
- "user.send_notification",
293
+ "schedule.notify",
269
294
  "--message",
270
295
  "Hello",
271
296
  ]);
@@ -300,7 +325,7 @@ describe("notifications send", () => {
300
325
  "--source-channel",
301
326
  "assistant_tool",
302
327
  "--source-event-name",
303
- "user.send_notification",
328
+ "schedule.notify",
304
329
  "--message",
305
330
  "Hi",
306
331
  "--conversation-id",
@@ -320,7 +345,7 @@ describe("notifications send", () => {
320
345
  "--source-channel",
321
346
  "assistant_tool",
322
347
  "--source-event-name",
323
- "user.send_notification",
348
+ "schedule.notify",
324
349
  "--message",
325
350
  "Hi",
326
351
  ]);
@@ -335,7 +360,7 @@ describe("notifications send", () => {
335
360
  "--source-channel",
336
361
  "assistant_tool",
337
362
  "--source-event-name",
338
- "user.send_notification",
363
+ "schedule.notify",
339
364
  "--message",
340
365
  "Hi",
341
366
  "--conversation-id",
@@ -359,7 +384,7 @@ describe("notifications send", () => {
359
384
  "--source-channel",
360
385
  "assistant_tool",
361
386
  "--source-event-name",
362
- "user.send_notification",
387
+ "schedule.notify",
363
388
  "--message",
364
389
  "Hello",
365
390
  ]);
@@ -384,7 +409,7 @@ describe("notifications send", () => {
384
409
  "--source-channel",
385
410
  "assistant_tool",
386
411
  "--source-event-name",
387
- "user.send_notification",
412
+ "schedule.notify",
388
413
  "--message",
389
414
  "Hello",
390
415
  ]);
@@ -138,11 +138,10 @@ Existing sessions and explicit backend/client choices take priority.
138
138
  not the user's Chrome. --desktop remains an alias for --virtual-desktop.
139
139
  Use --virtual-desktop for Chrome in the Desktop panel.
140
140
  Run navigate --url <url> directly to open a page.
141
- The assistant-desktop feature flag and completed installation are required.
142
- The first browser command installs missing components, starts Chrome, and completes
143
- the requested action in one call. Allow up to 600 seconds for this command when
144
- using bash (timeout_seconds: 600). Opening the Desktop panel also starts
145
- the same installation and shows progress. No separate setup command is needed.
141
+ The assistant-desktop feature flag and a desktop-enabled assistant image are required.
142
+ Chrome and desktop components are included in the image. The first browser command
143
+ starts Chrome and completes the requested action without downloading or installing
144
+ anything. Missing components require an assistant image update.
146
145
  Report other availability errors without switching to a personal computer.
147
146
  The assistant manages Chrome startup. Do not launch a separate desktop stack,
148
147
  install desktop packages, or drive webpages with shell-level xdotool.
@@ -168,7 +168,6 @@ function attachOperationAction(
168
168
  }
169
169
  }
170
170
 
171
- // First use can include virtual desktop installation and Chrome startup.
172
171
  const ipcResult = await cliIpcCall<BrowserExecuteResult>(
173
172
  "browser_execute",
174
173
  {
@@ -58,6 +58,7 @@ Examples:
58
58
  $ assistant clients list List all connected clients
59
59
  $ assistant clients list --json Machine-readable JSON output
60
60
  $ assistant clients list --capability host_bash Show only clients that can run host commands
61
+ $ assistant clients history Recent connection sessions and flaps
61
62
  $ assistant clients disconnect <clientId> Force-disconnect a client`,
62
63
  subcommands: [
63
64
  {
@@ -87,6 +88,51 @@ Examples:
87
88
  $ assistant clients list
88
89
  $ assistant clients list --capability host_bash
89
90
  $ assistant clients list --json | jq '.clients[0].capabilities'`,
91
+ },
92
+ {
93
+ name: "history",
94
+ description: "Show persisted client connection sessions",
95
+ options: [
96
+ {
97
+ flags: "--json",
98
+ description: "Machine-readable compact JSON output",
99
+ },
100
+ {
101
+ flags: "--client-id <id>",
102
+ description: "Restrict history to one client UUID",
103
+ },
104
+ {
105
+ flags: "--interface-id <id>",
106
+ description:
107
+ "Restrict history to one interface (e.g. chrome-extension)",
108
+ },
109
+ {
110
+ flags: "--since <when>",
111
+ description:
112
+ "ISO-8601 or epoch-ms lower bound. Sessions already open at this time are included.",
113
+ },
114
+ {
115
+ flags: "--limit <n>",
116
+ description: "Max coalesced sessions to return (1-500, default 50)",
117
+ },
118
+ ],
119
+ helpText: `
120
+ Options:
121
+ --json Output as compact JSON instead of a table.
122
+ --client-id <id> Only show history for this client UUID.
123
+ --interface-id <id> Only show history for this interface.
124
+ --since <when> Lower bound as ISO-8601 or epoch milliseconds.
125
+ Sessions already open at this time are included.
126
+ --limit <n> Max sessions after flap coalescing. Default 50.
127
+
128
+ Reconnects shorter than 60 seconds are flaps on the same session, not
129
+ separate outages. History starts when this assistant version first
130
+ records connections. It does not backfill earlier uptime.
131
+
132
+ Examples:
133
+ $ assistant clients history
134
+ $ assistant clients history --interface-id chrome-extension
135
+ $ assistant clients history --client-id client-123 --since 2026-09-01 --json`,
90
136
  },
91
137
  {
92
138
  name: "disconnect",
@@ -26,6 +26,23 @@ interface DisconnectClientResponse {
26
26
  disconnected: number;
27
27
  }
28
28
 
29
+ interface ClientHistorySessionJSON {
30
+ clientId: string;
31
+ interfaceId: string;
32
+ startedAt: string;
33
+ endedAt: string | null;
34
+ durationMs: number | null;
35
+ flapCount: number;
36
+ closeReason: string | null;
37
+ clientVersion: string | null;
38
+ sseWatchdog: boolean | null;
39
+ }
40
+
41
+ interface ListClientHistoryResponse {
42
+ sessions: ClientHistorySessionJSON[];
43
+ events: unknown[];
44
+ }
45
+
29
46
  export function registerClientsCommand(program: Command): void {
30
47
  registerCommand(program, {
31
48
  name: clientsHelp.name,
@@ -108,6 +125,85 @@ export function registerClientsCommand(program: Command): void {
108
125
  },
109
126
  );
110
127
 
128
+ subcommand(clients, "history").action(
129
+ async (
130
+ opts: {
131
+ json?: boolean;
132
+ clientId?: string;
133
+ interfaceId?: string;
134
+ since?: string;
135
+ limit?: string;
136
+ },
137
+ cmd: Command,
138
+ ) => {
139
+ const result = await cliIpcCall<ListClientHistoryResponse>(
140
+ "list_client_history",
141
+ optsToQueryParams(opts),
142
+ );
143
+
144
+ if (!result.ok) {
145
+ log.error(result.error ?? "Failed to load client history");
146
+ process.exitCode = 1;
147
+ return;
148
+ }
149
+
150
+ const response = result.result!;
151
+ if (opts.json) {
152
+ writeOutput(cmd, response);
153
+ return;
154
+ }
155
+
156
+ const sessions = response.sessions;
157
+ if (sessions.length === 0) {
158
+ log.info("No client connection history.");
159
+ return;
160
+ }
161
+
162
+ const header = [
163
+ "CLIENT ID",
164
+ "INTERFACE",
165
+ "STARTED",
166
+ "ENDED",
167
+ "DURATION",
168
+ "FLAPS",
169
+ "CLOSE",
170
+ "VERSION",
171
+ "WATCHDOG",
172
+ ];
173
+ const rows: string[][] = sessions.map((session) => [
174
+ session.clientId,
175
+ session.interfaceId,
176
+ formatRelativeTime(session.startedAt),
177
+ session.endedAt ? formatRelativeTime(session.endedAt) : "connected",
178
+ formatDuration(session.durationMs),
179
+ String(session.flapCount),
180
+ session.closeReason ?? "-",
181
+ session.clientVersion ?? "-",
182
+ session.sseWatchdog == null
183
+ ? "-"
184
+ : session.sseWatchdog
185
+ ? "yes"
186
+ : "no",
187
+ ]);
188
+
189
+ const colWidths = header.map((h: string, i: number) =>
190
+ Math.max(h.length, ...rows.map((r: string[]) => r[i].length)),
191
+ );
192
+ const pad = (s: string, w: number) => s.padEnd(w);
193
+ log.info(
194
+ header.map((h: string, i: number) => pad(h, colWidths[i])).join(" "),
195
+ );
196
+ log.info(colWidths.map((w: number) => "─".repeat(w)).join(" "));
197
+ for (const row of rows) {
198
+ log.info(
199
+ row
200
+ .map((c: string, i: number) => pad(c, colWidths[i]))
201
+ .join(" "),
202
+ );
203
+ }
204
+ },
205
+ );
206
+
111
207
  subcommand(clients, "disconnect").action(
112
208
  async (clientId: string, opts: { json?: boolean }, cmd: Command) => {
113
209
  const result = await cliIpcCall<DisconnectClientResponse>(
@@ -155,3 +251,23 @@ function formatRelativeTime(iso: string): string {
155
251
  const days = Math.floor(hr / 24);
156
252
  return `${days}d ago`;
157
253
  }
254
+
255
+ function formatDuration(ms: number | null): string {
256
+ if (ms == null || ms < 0) {
257
+ return "-";
258
+ }
259
+ const sec = Math.floor(ms / 1000);
260
+ if (sec < 60) {
261
+ return `${sec}s`;
262
+ }
263
+ const min = Math.floor(sec / 60);
264
+ if (min < 60) {
265
+ return `${min}m`;
266
+ }
267
+ const hr = Math.floor(min / 60);
268
+ if (hr < 24) {
269
+ return `${hr}h ${min % 60}m`;
270
+ }
271
+ const days = Math.floor(hr / 24);
272
+ return `${days}d ${hr % 24}h`;
273
+ }
@@ -294,7 +294,12 @@ web, etc.). The user enters the secret through the UI — it never passes throug
294
294
  the conversation or CLI output. On success the credential is stored in the
295
295
  encrypted vault with the specified metadata.
296
296
 
297
- Requires the assistant to be running with at least one connected client.
297
+ Requires the assistant to be running. The prompt renders in the conversation
298
+ this command runs from (the bash tool sets __CONVERSATION_ID). With no
299
+ conversation attached (a headless shell, Doctor's run_assistant_cli), no client
300
+ can show the card, so the command returns at once with a one-time collection
301
+ link (exit 75) to relay to the user, or an error when no link can be minted.
302
+ Never fall back to asking the user for the value in chat.
298
303
 
299
304
  This command BLOCKS until the user answers the prompt, so it returns only once
300
305
  the prompt has already closed. Tell the user what to paste BEFORE running it.
@@ -127,7 +127,12 @@ Examples:
127
127
  {
128
128
  flags: "--preferred-channels <channels>",
129
129
  description:
130
- "Comma-separated channel hints (e.g. vellum,telegram,slack)",
130
+ "Comma-separated channel hints (e.g. vellum,telegram,slack). Additive: vellum stays selected.",
131
+ },
132
+ {
133
+ flags: "--channels <channels>",
134
+ description:
135
+ "Exclusive channel allowlist (e.g. telegram). Replaces the default set. Urgent delivery does not add vellum or platform. Wins over --preferred-channels.",
131
136
  },
132
137
  {
133
138
  flags: "--session-id <id>",
@@ -162,7 +167,15 @@ Behavioral notes:
162
167
  is treated as critical and requires user action. Explicit --urgency /
163
168
  --requires-action flags still win for back-compat.
164
169
  - Without --urgent, --urgency defaults to low and --requires-action to false.
165
- - --preferred-channels are hints only; the decision engine may override them.
170
+ - --preferred-channels are additive hints; vellum stays in the selected set.
171
+ - --channels is an exclusive allowlist. Only those connected channels are
172
+ selected. Urgent delivery does not force vellum or platform, and Home
173
+ does not mirror unless vellum is in the list. When both flags are set,
174
+ --channels wins.
175
+ - --json includes selectedChannels, deliveryResults, and receiptClass.
176
+ receiptClass is the strongest delivery proof (provider_accepted,
177
+ gateway_accepted, client_os_posted, or unknown), not a promise the
178
+ user saw a banner.
166
179
  - --dedupe-key suppresses duplicate signals with the same key.
167
180
  - --conversation-id pins delivery to an existing vellum conversation
168
181
  deterministically. Other channels (telegram, slack) continue to use
@@ -171,6 +184,7 @@ Behavioral notes:
171
184
  Examples:
172
185
  $ assistant notifications send --message "Task complete"
173
186
  $ assistant notifications send --message "Pager: prod is down" --urgent
187
+ $ assistant notifications send --message "Alarm" --channels telegram --urgent
174
188
  $ assistant notifications send --message "Build green" --conversation-id 649c4645-3a6f-4ded-a713-504f02ca806b`,
175
189
  },
176
190
  {
@@ -32,6 +32,16 @@ interface ListHomeFeedPayload {
32
32
  updatedAt: string;
33
33
  }
34
34
 
35
+ function parseCommaSeparatedList(raw: string): string[] | undefined {
36
+ const items = raw
37
+ .split(",")
38
+ .map((item) => item.trim())
39
+ .filter((item) => {
40
+ return item.length > 0;
41
+ });
42
+ return items.length > 0 ? items : undefined;
43
+ }
44
+
35
45
  function parseBoundedInt(
36
46
  raw: string | undefined,
37
47
  label: string,
@@ -142,6 +152,7 @@ export function registerNotificationsCommand(program: Command): void {
142
152
  visibleInSourceNow: boolean;
143
153
  deadlineAt?: string;
144
154
  preferredChannels?: string;
155
+ channels?: string;
145
156
  sessionId?: string;
146
157
  dedupeKey?: string;
147
158
  deepLinkMetadata?: string;
@@ -220,14 +231,12 @@ export function registerNotificationsCommand(program: Command): void {
220
231
  deadlineAt = parsed;
221
232
  }
222
233
 
223
- // Parse --preferred-channels
224
- let preferredChannels: string[] | undefined;
225
- if (opts.preferredChannels) {
226
- preferredChannels = opts.preferredChannels
227
- .split(",")
228
- .map((ch) => ch.trim())
229
- .filter((ch) => ch.length > 0);
230
- }
234
+ const preferredChannels = opts.preferredChannels
235
+ ? parseCommaSeparatedList(opts.preferredChannels)
236
+ : undefined;
237
+ const channelAllowlist = opts.channels
238
+ ? parseCommaSeparatedList(opts.channels)
239
+ : undefined;
231
240
 
232
241
  // Parse --deep-link-metadata
233
242
  let deepLinkMetadata: Record<string, unknown> | undefined;
@@ -283,6 +292,9 @@ export function registerNotificationsCommand(program: Command): void {
283
292
  dispatched: boolean;
284
293
  deduplicated: boolean;
285
294
  reason: string;
295
+ selectedChannels?: string[];
296
+ deliveryResults?: unknown[];
297
+ receiptClass?: string;
286
298
  }>("emit_notification_signal", {
287
299
  body: {
288
300
  sourceChannel,
@@ -300,6 +312,7 @@ export function registerNotificationsCommand(program: Command): void {
300
312
  requestedBySource: sourceChannel,
301
313
  ...(opts.title ? { requestedTitle: opts.title } : {}),
302
314
  ...(preferredChannels?.length ? { preferredChannels } : {}),
315
+ ...(channelAllowlist?.length ? { channelAllowlist } : {}),
303
316
  ...(deepLinkMetadata ? { deepLinkMetadata } : {}),
304
317
  },
305
318
  ...(opts.dedupeKey ? { dedupeKey: opts.dedupeKey } : {}),
@@ -326,6 +339,9 @@ export function registerNotificationsCommand(program: Command): void {
326
339
  signalId: signal.signalId,
327
340
  dispatched: signal.dispatched,
328
341
  reason: signal.reason,
342
+ selectedChannels: signal.selectedChannels ?? [],
343
+ deliveryResults: signal.deliveryResults ?? [],
344
+ receiptClass: signal.receiptClass ?? "unknown",
329
345
  });
330
346
 
331
347
  if (!shouldOutputJson(cmd)) {
@@ -335,6 +351,12 @@ export function registerNotificationsCommand(program: Command): void {
335
351
  if (signal.reason) {
336
352
  log.info(` Reason: ${signal.reason}`);
337
353
  }
354
+ if (signal.selectedChannels && signal.selectedChannels.length > 0) {
355
+ log.info(` Channels: ${signal.selectedChannels.join(", ")}`);
356
+ }
357
+ if (signal.receiptClass) {
358
+ log.info(` Receipt: ${signal.receiptClass}`);
359
+ }
338
360
  }
339
361
  } catch (err) {
340
362
  const message = err instanceof Error ? err.message : String(err);
@@ -25,7 +25,7 @@ no verb to post one.
25
25
  Examples:
26
26
  $ assistant roadmap list --sort upvotes --limit 10
27
27
  $ assistant roadmap get scheduled-messages
28
- $ assistant roadmap create --title "Add dark mode" --tag ui
28
+ $ assistant roadmap create --title "Add dark mode" --tag area-interface
29
29
  $ assistant roadmap upvote scheduled-messages`,
30
30
  subcommands: [
31
31
  {
@@ -79,10 +79,13 @@ Examples:
79
79
  options: [
80
80
  {
81
81
  flags: "--title <title>",
82
- description: "Item title (required)",
82
+ description: "Item title, 1 to 200 characters (required)",
83
83
  required: true,
84
84
  },
85
- { flags: "--description <desc>", description: "Item description" },
85
+ {
86
+ flags: "--description <desc>",
87
+ description: "Item description, up to 5000 characters",
88
+ },
86
89
  {
87
90
  flags: "--tag <slug>",
88
91
  description:
@@ -97,41 +100,35 @@ accepted, since status is assigned by Vellum.
97
100
  Examples:
98
101
  $ assistant roadmap create --title "Add dark mode"
99
102
  $ assistant roadmap create --title "Recurring reminders" \\
100
- --description "Repeat a scheduled message weekly" --tag scheduling`,
103
+ --description "Repeat a scheduled message weekly" --tag area-assistant`,
101
104
  },
102
105
  {
103
106
  name: "update",
104
107
  args: "<slug>",
105
- description: "Update a roadmap item",
108
+ description:
109
+ "Edit the title or description of an item the assistant filed",
106
110
  options: [
107
- { flags: "--title <title>", description: "New title" },
108
- { flags: "--description <desc>", description: "New description" },
109
111
  {
110
- flags: "--status <status>",
111
- description: "New status (e.g. open, planned, in_progress, someday)",
112
- },
113
- {
114
- flags: "--tag <slug>",
115
- description: "Replacement tag slug, repeatable",
112
+ flags: "--title <title>",
113
+ description: "New title, 1 to 200 characters",
116
114
  },
117
115
  {
118
- flags: "--clear-tags",
119
- description: "Remove every tag (cannot be combined with --tag)",
116
+ flags: "--description <desc>",
117
+ description: "New description, up to 5000 characters",
120
118
  },
121
119
  ],
122
120
  helpText: `
123
121
  Arguments:
124
122
  <slug> Item slug, as printed in the URL by 'assistant roadmap list'
125
123
 
126
- At least one field is required. Passing --tag replaces the whole tag set
127
- rather than adding to it, so list every tag the item should end up with.
128
- Vellum decides which items an assistant may edit, so this fails for items the
129
- assistant does not own.
124
+ At least one of --title or --description is required. Only items this
125
+ assistant filed can be edited, and only while their status is still open.
126
+ Status and tags are set by Vellum staff, so an item's tags are chosen once,
127
+ on 'roadmap create'.
130
128
 
131
129
  Examples:
132
130
  $ assistant roadmap update dark-mode --description "Follow the OS setting"
133
- $ assistant roadmap update dark-mode --tag ui --tag theming
134
- $ assistant roadmap update dark-mode --clear-tags`,
131
+ $ assistant roadmap update dark-mode --title "Dark mode that follows the OS"`,
135
132
  },
136
133
  {
137
134
  name: "delete",