@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
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Provenance for backfilled Slack rows, resolved per sender.
3
+ *
4
+ * A backfilled row was written by someone other than the live inbound actor,
5
+ * so the live turn's trust context says nothing about it. Each sender is
6
+ * classified by the same gateway verdict live ingress uses
7
+ * (`resolve_inbound_trust`), so a backfilled row and a live row from the same
8
+ * person carry the same trust class and contact id. The verdict answers for
9
+ * the contact list at import time, which is when the row is written.
10
+ *
11
+ * When the verdict is unreadable or unusable, the row falls back to the
12
+ * guardian-address comparison, carries no contact id, and is marked
13
+ * `provenanceLookupFailed` so it stays distinguishable from a stranger.
14
+ *
15
+ * A read goes through `readInboundTrust`, so it also refreshes the
16
+ * member-verdict cache for that sender, as a live inbound read does.
17
+ */
18
+
19
+ import { readInboundTrust } from "../../../calls/inbound-trust-reader.js";
20
+ import type { ActorAuthorProvenance } from "../../../daemon/message-provenance.js";
21
+ import type { Message as ProviderMessage } from "../../../messaging/provider-types.js";
22
+ import { inboundIdentitiesMatch } from "../../../util/canonicalize-identity.js";
23
+ import type { TrustClass } from "../../trust-class.js";
24
+ import {
25
+ verdictMemberFromVerdict,
26
+ verdictUsability,
27
+ } from "../../trust-verdict-consumer.js";
28
+
29
+ export interface BackfilledSenderProvenance extends ActorAuthorProvenance {
30
+ provenanceTrustClass: TrustClass;
31
+ /** The lookup ran and returned no usable verdict; see `messageMetadataSchema`. */
32
+ provenanceLookupFailed?: true;
33
+ }
34
+
35
+ /**
36
+ * Resolves a backfilled message's sender provenance. One resolver serves one
37
+ * backfill pass and reads the gateway at most once per distinct sender.
38
+ */
39
+ export type BackfilledSenderProvenanceResolver = (
40
+ senderId: string | undefined,
41
+ ) => Promise<BackfilledSenderProvenance>;
42
+
43
+ export function createBackfilledSenderProvenanceResolver(
44
+ guardianExternalUserId: string | undefined,
45
+ messages: readonly ProviderMessage[],
46
+ ): BackfilledSenderProvenanceResolver {
47
+ const bySender = new Map<string, Promise<BackfilledSenderProvenance>>();
48
+ const resolve: BackfilledSenderProvenanceResolver = (senderId) => {
49
+ const trimmed = senderId?.trim();
50
+ if (!trimmed) {
51
+ return Promise.resolve({ provenanceTrustClass: "unknown" });
52
+ }
53
+ let pending = bySender.get(trimmed);
54
+ if (!pending) {
55
+ pending = resolveSenderProvenance(trimmed, guardianExternalUserId);
56
+ bySender.set(trimmed, pending);
57
+ }
58
+ return pending;
59
+ };
60
+ // Every sender's read starts now, so the pass waits on the slowest read
61
+ // rather than their sum. Bots included: a third-party bot's post is a user
62
+ // row, and singling out this assistant's own posts needs an async lookup.
63
+ // A read reports failure as a result, never a rejection.
64
+ for (const message of messages) {
65
+ void resolve(message.sender?.id);
66
+ }
67
+ return resolve;
68
+ }
69
+
70
+ async function resolveSenderProvenance(
71
+ senderId: string,
72
+ guardianExternalUserId: string | undefined,
73
+ ): Promise<BackfilledSenderProvenance> {
74
+ const read = await readInboundTrust({
75
+ channelType: "slack",
76
+ actorExternalId: senderId,
77
+ });
78
+ if (read.ok) {
79
+ const usability = verdictUsability(read.verdict);
80
+ if (usability.usable) {
81
+ const member = verdictMemberFromVerdict(usability.verdict);
82
+ return {
83
+ provenanceTrustClass: usability.verdict.trustClass,
84
+ ...(member ? { provenanceContactId: member.contactId } : {}),
85
+ };
86
+ }
87
+ }
88
+ return {
89
+ provenanceTrustClass:
90
+ guardianExternalUserId !== undefined &&
91
+ inboundIdentitiesMatch("slack", senderId, guardianExternalUserId)
92
+ ? "guardian"
93
+ : "unknown",
94
+ provenanceLookupFailed: true,
95
+ };
96
+ }
@@ -173,10 +173,10 @@ import {
173
173
  } from "../../../daemon/conversation-registry.js";
174
174
  import type { TrustContext } from "../../../daemon/trust-context-types.js";
175
175
  import type { MessageProcessor } from "../../http-types.js";
176
+ import { hasDeliverableAssistantText } from "../../no-response.js";
176
177
  import {
177
178
  isBoundGuardianActor,
178
179
  processChannelMessageInBackground,
179
- shouldShowActivityForText,
180
180
  shouldShowActivityImmediately,
181
181
  } from "./background-dispatch.js";
182
182
  import { __resetChannelTurnAdmissionForTests } from "./channel-turn-admission.js";
@@ -260,6 +260,35 @@ describe("processChannelMessageInBackground — reply delivery", () => {
260
260
  const flush = (): Promise<void> =>
261
261
  new Promise((resolve) => setTimeout(resolve, 10));
262
262
 
263
+ test("names the inbound sender as the persisted message's author", async () => {
264
+ let capturedAuthor: TrustContext | undefined;
265
+ const processMessage: MessageProcessor = async (
266
+ _conversationId,
267
+ _content,
268
+ options,
269
+ ) => {
270
+ capturedAuthor = options?.author;
271
+ return { messageId: "user-msg-author" };
272
+ };
273
+
274
+ processChannelMessageInBackground({
275
+ processMessage,
276
+ conversationId: "conv-author",
277
+ eventId: "evt-author",
278
+ content: "the export endpoint needs a scoped token",
279
+ sourceChannel: "slack",
280
+ sourceInterface: "slack",
281
+ externalChatId: "C-AUTHOR",
282
+ trustCtx,
283
+ metadataHints: [],
284
+ replyCallbackUrl: "https://example.test/deliver/slack?channel=C-AUTHOR",
285
+ });
286
+
287
+ await flush();
288
+
289
+ expect(capturedAuthor).toBe(trustCtx);
290
+ });
291
+
263
292
  test("records callback delivery failures without failing processing", async () => {
264
293
  const conversationId = "conv-delivery-failure";
265
294
  const channelId = "C-DELIVERY-FAILURE";
@@ -1070,14 +1099,14 @@ describe("channel activity timing", () => {
1070
1099
  });
1071
1100
 
1072
1101
  test("recognizes only deliverable text as a reason to show activity", () => {
1073
- expect(shouldShowActivityForText("")).toBe(false);
1074
- expect(shouldShowActivityForText(" ")).toBe(false);
1075
- expect(shouldShowActivityForText("<")).toBe(false);
1076
- expect(shouldShowActivityForText("<no_response")).toBe(false);
1077
- expect(shouldShowActivityForText("<no_response/>")).toBe(false);
1078
- expect(shouldShowActivityForText(" <no_response /> ")).toBe(false);
1079
- expect(shouldShowActivityForText("Real response.")).toBe(true);
1080
- expect(shouldShowActivityForText("<no_response/>\nReal response.")).toBe(
1102
+ expect(hasDeliverableAssistantText("")).toBe(false);
1103
+ expect(hasDeliverableAssistantText(" ")).toBe(false);
1104
+ expect(hasDeliverableAssistantText("<")).toBe(false);
1105
+ expect(hasDeliverableAssistantText("<no_response")).toBe(false);
1106
+ expect(hasDeliverableAssistantText("<no_response/>")).toBe(false);
1107
+ expect(hasDeliverableAssistantText(" <no_response /> ")).toBe(false);
1108
+ expect(hasDeliverableAssistantText("Real response.")).toBe(true);
1109
+ expect(hasDeliverableAssistantText("<no_response/>\nReal response.")).toBe(
1081
1110
  true,
1082
1111
  );
1083
1112
  });
@@ -286,6 +286,7 @@ export function processChannelMessageInBackground(
286
286
  },
287
287
  assistantId,
288
288
  trustContext: trustCtx,
289
+ author: trustCtx,
289
290
  isInteractive: resolveRoutingState(trustCtx).promptWaitingAllowed,
290
291
  ...(displayContent !== undefined ? { displayContent } : {}),
291
292
  ...(cmdIntent ? { commandIntent: cmdIntent } : {}),
@@ -452,10 +453,6 @@ type ChannelActivityController = {
452
453
  stop: () => void;
453
454
  };
454
455
 
455
- export function shouldShowActivityForText(text: string): boolean {
456
- return hasDeliverableAssistantText(text);
457
- }
458
-
459
456
  /**
460
457
  * Room shapes with one other participant, in each channel's own word for it.
461
458
  *
@@ -613,7 +610,7 @@ function startChannelActivity(params: {
613
610
  return;
614
611
  }
615
612
  observedAssistantText += msg.text;
616
- if (shouldShowActivityForText(observedAssistantText)) {
613
+ if (hasDeliverableAssistantText(observedAssistantText)) {
617
614
  show();
618
615
  }
619
616
  },
@@ -35,6 +35,7 @@ import { createApprovalCopyGenerator } from "../../../daemon/approval-generators
35
35
  import { findConversation } from "../../../daemon/conversation-registry.js";
36
36
  import { getDiskPressureStatus } from "../../../daemon/disk-pressure-guard.js";
37
37
  import { classifyDiskPressureTurnPolicy } from "../../../daemon/disk-pressure-policy.js";
38
+ import { actorAuthorProvenance } from "../../../daemon/message-provenance.js";
38
39
  import { processMessage } from "../../../daemon/process-message.js";
39
40
  import { renderReactionHistoryText } from "../../../daemon/reaction-history-render.js";
40
41
  import type { TrustContext } from "../../../daemon/trust-context-types.js";
@@ -544,6 +545,7 @@ async function persistReactionAsMessage(params: {
544
545
  {
545
546
  metadata: {
546
547
  ...provenanceFromTrustContext(params.trustCtx),
548
+ ...actorAuthorProvenance(params.trustCtx),
547
549
  ...buildReactionRowEnvelope(facts),
548
550
  },
549
551
  skipIndexing: true,
@@ -1025,7 +1025,7 @@ function anthropicMessageSections(
1025
1025
  toolName: asString(block.name) ?? asString(block.tool_use_id),
1026
1026
  data:
1027
1027
  type === "web_search_tool_result"
1028
- ? sanitizeAnthropicWebSearchToolResultData(block)
1028
+ ? sanitizeAnthropicStructuredValue(block)
1029
1029
  : undefined,
1030
1030
  text: collectAnthropicToolResultText(block),
1031
1031
  });
@@ -1397,12 +1397,6 @@ function collectAnthropicToolResultText(
1397
1397
  return collectAnthropicText(block.content);
1398
1398
  }
1399
1399
 
1400
- function sanitizeAnthropicWebSearchToolResultData(
1401
- block: Record<string, unknown>,
1402
- ): unknown {
1403
- return sanitizeAnthropicStructuredValue(block);
1404
- }
1405
-
1406
1400
  function sanitizeAnthropicStructuredValue(value: unknown): unknown {
1407
1401
  if (Array.isArray(value)) {
1408
1402
  return value.map((entry) => sanitizeAnthropicStructuredValue(entry));
@@ -20,11 +20,13 @@ import { createReadStream } from "node:fs";
20
20
  import { hostname } from "node:os";
21
21
  import { PassThrough, Readable } from "node:stream";
22
22
 
23
+ import { GatewayDebugExportIpcResponseSchema } from "@vellumai/gateway-client/gateway-ipc-contracts";
23
24
  import { z } from "zod";
24
25
 
25
26
  import { invalidateConfigCache } from "../../config/loader.js";
26
27
  import { resolvePlatformAssistantId } from "../../config/platform-identity.js";
27
28
  import { getAssistantName } from "../../daemon/identity-helpers.js";
29
+ import { ipcCallPersistent } from "../../ipc/gateway-client.js";
28
30
  import { runAsyncSqlite } from "../../persistence/db-async-query.js";
29
31
  import {
30
32
  getDb,
@@ -470,8 +472,40 @@ const EXPORT_TO_GCS_PUT_TIMEOUT_MS = 60 * 60 * 1000;
470
472
  const MigrationExportToGcsBody = z.object({
471
473
  upload_url: z.string().url(),
472
474
  description: z.string().optional(),
475
+ /**
476
+ * `debug`: a bundle for Vellum staff to inspect. Adds the gateway's
477
+ * database and recent logs under `gateway/`. `migration` is the default.
478
+ */
479
+ profile: z.enum(["migration", "debug"]).default("migration"),
473
480
  });
474
481
 
482
+ /** Archive path of the gateway's contribution to a debug bundle. */
483
+ export const GATEWAY_DEBUG_EXPORT_PATH = "gateway/export.tar.gz";
484
+
485
+ /**
486
+ * Ask the gateway for its debug archive over the local socket. The daemon
487
+ * cannot read the gateway's files itself: in local mode they sit in the
488
+ * protected directory beside the encryption keys, and in Docker on a volume
489
+ * the daemon does not mount.
490
+ */
491
+ async function collectGatewayDebugExport(): Promise<{
492
+ archivePath: string;
493
+ data: Uint8Array;
494
+ }> {
495
+ const raw = await ipcCallPersistent(
496
+ "gateway_debug_export",
497
+ {},
498
+ GATEWAY_DEBUG_EXPORT_TIMEOUT_MS,
499
+ );
500
+ const parsed = GatewayDebugExportIpcResponseSchema.parse(raw);
501
+ return {
502
+ archivePath: GATEWAY_DEBUG_EXPORT_PATH,
503
+ data: new Uint8Array(Buffer.from(parsed.archive_base64, "base64")),
504
+ };
505
+ }
506
+
507
+ const GATEWAY_DEBUG_EXPORT_TIMEOUT_MS = 120_000;
508
+
475
509
  /**
476
510
  * Collected credentials plus warning markers if the credential store was
477
511
  * unreachable. The caller surfaces the warning in logs; production callers
@@ -559,9 +593,10 @@ export async function handleMigrationExportToGcs({ body }: RouteHandlerArgs) {
559
593
  const parsed = MigrationExportToGcsBody.safeParse(body);
560
594
  if (!parsed.success) {
561
595
  throw new BadRequestError(
562
- "Request body must be { upload_url: string, description?: string } with a valid URL",
596
+ "Request body must be { upload_url: string, description?: string, profile?: 'migration' | 'debug' } with a valid URL",
563
597
  );
564
598
  }
599
+ const isDebugProfile = parsed.data.profile === "debug";
565
600
 
566
601
  // ── 2. Validate the upload URL. Never log `parsed.data.upload_url`.
567
602
  const validated = validateGcsSignedUrl(
@@ -608,8 +643,11 @@ export async function handleMigrationExportToGcs({ body }: RouteHandlerArgs) {
608
643
  // "managed"), and teleport clients re-provision platform identity after
609
644
  // a platform→local import — so redact instead of emitting a bundle the
610
645
  // importer is guaranteed to reject.
646
+ //
647
+ // A debug bundle goes to Vellum staff, so it never carries credentials
648
+ // either, whatever the deployment mode.
611
649
  let collected: CollectedCredentials;
612
- if (manifestInputs.origin.mode === "managed") {
650
+ if (manifestInputs.origin.mode === "managed" || isDebugProfile) {
613
651
  collected = {
614
652
  credentials: [],
615
653
  unreachable: false,
@@ -632,17 +670,44 @@ export async function handleMigrationExportToGcs({ body }: RouteHandlerArgs) {
632
670
  collected.perAccountUnreachable,
633
671
  );
634
672
 
673
+ if (isDebugProfile) {
674
+ manifestInputs = {
675
+ ...manifestInputs,
676
+ exportOptions: { ...manifestInputs.exportOptions, include_gateway: true },
677
+ };
678
+ }
679
+
635
680
  // ── 4. Enqueue the job. The runner captures the collected credentials.
636
681
  let job;
637
682
  try {
638
683
  job = migrationJobs.startJob("export", async () => {
639
684
  let cleanup: (() => Promise<void>) | undefined;
640
685
  try {
686
+ // The gateway snapshot can take a while on a large database, so it
687
+ // runs inside the job (after the export slot is held) rather than
688
+ // before the 202. A debug bundle without the gateway's data is not
689
+ // what staff asked for, so a failure fails the job and nothing is
690
+ // uploaded.
691
+ let extraFiles: Array<{ archivePath: string; data: Uint8Array }> = [];
692
+ if (isDebugProfile) {
693
+ try {
694
+ extraFiles = [await collectGatewayDebugExport()];
695
+ } catch (err) {
696
+ log.error({ err }, "Failed to collect the gateway's debug export");
697
+ const wrapped = new Error(
698
+ "The gateway did not provide its debug export; the bundle was not sent.",
699
+ );
700
+ (wrapped as { code?: string }).code = "gateway_debug_export_failed";
701
+ throw wrapped;
702
+ }
703
+ }
704
+
641
705
  const result = await streamExportVBundle({
642
706
  workspaceDir: getWorkspaceDir(),
643
707
  ...manifestInputs,
644
708
  secretsRedacted,
645
709
  credentials: collected.credentials,
710
+ extraFiles,
646
711
  checkpoint: checkpointDbsForExport,
647
712
  });
648
713
 
@@ -2402,6 +2467,12 @@ export const ROUTES: RouteDefinition[] = [
2402
2467
  .string()
2403
2468
  .optional()
2404
2469
  .describe("Human-readable export description."),
2470
+ profile: z
2471
+ .enum(["migration", "debug"])
2472
+ .optional()
2473
+ .describe(
2474
+ "Export profile. 'migration' (default) builds a teleport bundle. 'debug' builds a bundle for Vellum staff to open on a debug clone: no credentials, plus the gateway's database and logs under gateway/.",
2475
+ ),
2405
2476
  }),
2406
2477
  responseStatus: "202",
2407
2478
  responseBody: z.object({
@@ -14,6 +14,10 @@ import {
14
14
  NotificationSourceChannelSchema,
15
15
  RoutingIntentSchema,
16
16
  } from "../../notifications/signal.js";
17
+ import {
18
+ NotificationDeliveryResultSchema,
19
+ NotificationReceiptClassSchema,
20
+ } from "../../notifications/types.js";
17
21
  import { UrgencySchema } from "../../notifications/urgency.js";
18
22
  import { getDb } from "../../persistence/db-connection.js";
19
23
  import { notificationDeliveries } from "../../persistence/schema/index.js";
@@ -78,6 +82,9 @@ const EmitSignalResponse = z.object({
78
82
  dispatched: z.boolean(),
79
83
  deduplicated: z.boolean(),
80
84
  reason: z.string(),
85
+ selectedChannels: z.array(z.string()),
86
+ deliveryResults: z.array(NotificationDeliveryResultSchema),
87
+ receiptClass: NotificationReceiptClassSchema,
81
88
  });
82
89
 
83
90
  async function handleEmitSignal({ body = {} }: RouteHandlerArgs) {
@@ -94,6 +101,9 @@ async function handleEmitSignal({ body = {} }: RouteHandlerArgs) {
94
101
  dispatched: result.dispatched,
95
102
  deduplicated: result.deduplicated,
96
103
  reason: result.reason,
104
+ selectedChannels: result.selectedChannels,
105
+ deliveryResults: result.deliveryResults,
106
+ receiptClass: result.receiptClass,
97
107
  };
98
108
  }
99
109
 
@@ -6,6 +6,7 @@
6
6
  * the standard runtime auth middleware.
7
7
  */
8
8
 
9
+ import { INTEGRATION_CATEGORIES } from "@vellumai/service-contracts/integration-categories";
9
10
  import { z } from "zod";
10
11
 
11
12
  import { loadConfig } from "../../config/loader.js";
@@ -401,6 +402,12 @@ export const oauthProviderSummarySchema = z.object({
401
402
  supports_managed_mode: z.boolean(),
402
403
  managed_service_is_paid: z.boolean(),
403
404
  feature_flag: z.string().nullable(),
405
+ category: z
406
+ .enum(INTEGRATION_CATEGORIES)
407
+ .nullable()
408
+ .describe(
409
+ "Where the integrations catalog files the provider; null for a provider without a seed entry.",
410
+ ),
404
411
  tenant_host: z
405
412
  .object({
406
413
  pattern: z.string(),
@@ -226,6 +226,12 @@ const mcpPluginIntegrationSchema = z.object({
226
226
  }),
227
227
  logo: z.string(),
228
228
  oauthProvider: z.string().optional(),
229
+ category: z
230
+ .string()
231
+ .optional()
232
+ .describe(
233
+ "Where the integrations catalog files the entry: a slug from the shared integration-category vocabulary, passed through as the catalog declares it.",
234
+ ),
229
235
  });
230
236
 
231
237
  const pluginSearchMatchSchema = z.object({
@@ -379,16 +379,55 @@ const createRequestSchema = z.object({
379
379
  tags: z.array(z.string()).optional().describe("Tag slugs"),
380
380
  });
381
381
 
382
+ /** Item fields the roadmap service reserves for staff on an update. */
383
+ const STAFF_ONLY_UPDATE_FIELDS = new Set(["status", "tags"]);
384
+
385
+ function listFields(fields: string[]): string {
386
+ return `${fields.join(", ")} ${fields.length === 1 ? "is" : "are"}`;
387
+ }
388
+
389
+ /**
390
+ * Why an update carrying fields other than title and description is refused.
391
+ * A staff-only field and an unknown one need different remedies, so each is
392
+ * named for what it is.
393
+ */
394
+ function unsupportedUpdateFieldsMessage(keys: string[]): string {
395
+ const staffOnly = keys.filter((k) => STAFF_ONLY_UPDATE_FIELDS.has(k));
396
+ const unknown = keys.filter((k) => !STAFF_ONLY_UPDATE_FIELDS.has(k));
397
+ const reasons = [
398
+ ...(staffOnly.length > 0
399
+ ? [`${listFields(staffOnly)} set by Vellum staff`]
400
+ : []),
401
+ ...(unknown.length > 0
402
+ ? [`${listFields(unknown)} not a roadmap update field`]
403
+ : []),
404
+ ];
405
+ return `An assistant can change only an item's title and description; ${reasons.join("; ")}.`;
406
+ }
407
+
408
+ /**
409
+ * Only the fields the roadmap service lets this assistant change. An
410
+ * assistant is always the author tier there, never staff, and an author may
411
+ * edit only an open item's title and description; status and tags are staff
412
+ * triage and answer 403. Strict, so a caller that sends anything else learns
413
+ * why here instead of from the upstream refusal.
414
+ */
382
415
  const updateRequestSchema = z
383
- .object({
384
- title: z.string().optional(),
385
- description: z.string().optional(),
386
- status: z.string().optional(),
387
- tags: z.array(z.string()).optional().describe("Tag slugs"),
388
- })
416
+ .strictObject(
417
+ {
418
+ title: z.string().optional(),
419
+ description: z.string().optional(),
420
+ },
421
+ {
422
+ error: (issue) =>
423
+ issue.code === "unrecognized_keys"
424
+ ? unsupportedUpdateFieldsMessage(issue.keys)
425
+ : undefined,
426
+ },
427
+ )
389
428
  .refine(
390
429
  (patch) => Object.values(patch).some((v) => v !== undefined),
391
- "At least one of title, description, status or tags is required.",
430
+ "At least one of title or description is required.",
392
431
  );
393
432
 
394
433
  type RoadmapItem = z.infer<typeof itemSchema>;
@@ -684,7 +723,7 @@ export const ROUTES: RouteDefinition[] = [
684
723
  },
685
724
  summary: "Update a roadmap item",
686
725
  description:
687
- "Updates a roadmap item. At least one field is required; the roadmap service decides which items this assistant may edit.",
726
+ "Updates the title or description of a roadmap item this assistant filed, while the item is still open. Status and tags are set by Vellum staff.",
688
727
  tags: ["roadmap"],
689
728
  pathParams: SLUG_PARAM,
690
729
  requestBody: updateRequestSchema,
@@ -303,7 +303,7 @@ async function handleAddSecret({ body }: RouteHandlerArgs) {
303
303
  );
304
304
  return { success: false, error: validation.reason };
305
305
  }
306
- } else if (name === "jev") {
306
+ } else if (name === "typesafe") {
307
307
  const validation = await validateJevApiKey(value);
308
308
  if (!validation.valid) {
309
309
  log.warn(
@@ -662,10 +662,16 @@ async function handleToolPermissionSimulate({ body = {} }: RouteHandlerArgs) {
662
662
  const manifestOverride = resolveManifestOverride(toolName);
663
663
  // Permission Simulator path: registered tool wins, then explicit
664
664
  // manifest override, then the standard inference rules.
665
- const executionTarget =
666
- getTool(toolName)?.executionTarget ??
667
- manifestOverride?.execution_target ??
668
- resolveExecutionTarget({ name: toolName });
665
+ const tool = getTool(toolName);
666
+ const executionTarget = resolveExecutionTarget(
667
+ {
668
+ name: toolName,
669
+ executionTarget:
670
+ tool?.executionTarget ?? manifestOverride?.execution_target,
671
+ getExecutionTarget: tool?.getExecutionTarget,
672
+ },
673
+ input,
674
+ );
669
675
  const executionContext =
670
676
  isInteractive === false ? "headless" : "conversation";
671
677
  const policyContext = { executionTarget, executionContext } as const;
@@ -86,7 +86,7 @@ function handleWatcherCreate({ body = {} }: RouteHandlerArgs) {
86
86
  const credentialService =
87
87
  credentialServiceOverride ?? provider.requiredCredentialService;
88
88
 
89
- const watcher = createWatcher({
89
+ return createWatcher({
90
90
  name,
91
91
  providerId,
92
92
  actionPrompt,
@@ -94,8 +94,6 @@ function handleWatcherCreate({ body = {} }: RouteHandlerArgs) {
94
94
  pollIntervalMs,
95
95
  configJson: config ? JSON.stringify(config) : null,
96
96
  });
97
-
98
- return watcher;
99
97
  }
100
98
 
101
99
  function handleWatcherList({ body = {} }: RouteHandlerArgs) {
@@ -1,11 +1,12 @@
1
1
  import { afterEach, describe, expect, test } from "bun:test";
2
2
 
3
+ import { TRUST_CLASS_VALUES } from "@vellumai/gateway-client";
4
+
3
5
  import { resolveCapabilities } from "./capabilities.js";
4
6
  import {
5
7
  derivePersonaTrustFlags,
6
8
  isContactTrustClass,
7
9
  type PersonaTrustFlags,
8
- trustClassSchema,
9
10
  } from "./trust-class.js";
10
11
 
11
12
  describe("isContactTrustClass", () => {
@@ -27,7 +28,7 @@ describe("isContactTrustClass", () => {
27
28
  test("agrees with derivePersonaTrustFlags for every trust class", () => {
28
29
  // The predicate and the persona flags encode the same grouping; pin them
29
30
  // together so neither can drift without failing here.
30
- for (const trustClass of trustClassSchema.options) {
31
+ for (const trustClass of TRUST_CLASS_VALUES) {
31
32
  expect(isContactTrustClass(trustClass)).toBe(
32
33
  derivePersonaTrustFlags(trustClass).isTrustedContact,
33
34
  );
@@ -46,7 +47,7 @@ describe("derivePersonaTrustFlags", () => {
46
47
  });
47
48
 
48
49
  test("trusted_contact and unverified_contact derive identical contact flags", () => {
49
- // The admission-only equivalence documented on trustClassSchema: the two
50
+ // The admission-only equivalence documented in trust-class.ts: the two
50
51
  // classes must never drift apart at the persona layer.
51
52
  const expected: PersonaTrustFlags = {
52
53
  trustClass: "trusted_contact",
@@ -82,9 +83,9 @@ describe("derivePersonaTrustFlags", () => {
82
83
  });
83
84
 
84
85
  test("exactly one flag is true for every trust class", () => {
85
- // Iterates the Zod enum so a newly added class is covered automatically
86
+ // Iterates the canonical class list so a newly added class is covered
86
87
  // (the helper itself won't compile until the new class gets a case).
87
- for (const trustClass of trustClassSchema.options) {
88
+ for (const trustClass of TRUST_CLASS_VALUES) {
88
89
  const flags = derivePersonaTrustFlags(trustClass);
89
90
  const trueCount = [
90
91
  flags.isGuardian,
@@ -128,7 +129,7 @@ describe("derivePersonaTrustFlags", () => {
128
129
  isTrustedContact: "social-engineering-defense",
129
130
  isStranger: "stranger-warning",
130
131
  };
131
- for (const trustClass of trustClassSchema.options) {
132
+ for (const trustClass of TRUST_CLASS_VALUES) {
132
133
  const flags = derivePersonaTrustFlags(trustClass);
133
134
  const guidance = resolveCapabilities(trustClass).promptTrustGuidance;
134
135
  for (const [flag, expected] of Object.entries(guidanceByFlag)) {
@@ -1,10 +1,9 @@
1
1
  /**
2
- * Trust classification for an inbound actor — the single source of truth for
3
- * both the {@link TrustClass} type and the Zod enum ({@link trustClassSchema})
4
- * that validates it in persisted message metadata.
5
- *
6
- * Kept as a leaf module (imports only `zod`) so the runtime trust layer and the
7
- * persistence schema can share one definition without a circular import.
2
+ * The daemon's reading of an inbound actor's trust class. The vocabulary
3
+ * itself ({@link TrustClass}, `TrustClassSchema`) belongs to the gateway,
4
+ * which classifies every actor; it lives in `@vellumai/gateway-client`
5
+ * (`trust-verdict-contract.ts`) and is re-exported here, never redeclared.
6
+ * This module holds what the daemon derives from a class:
8
7
  *
9
8
  * - `'guardian'`: The sender matches the active guardian binding for this
10
9
  * (assistant, channel). Guardians have full control-plane access and
@@ -21,21 +20,14 @@
21
20
  * actors are fail-closed with no escalation path.
22
21
  */
23
22
 
24
- import { z } from "zod";
25
-
26
- export const trustClassSchema = z.enum([
27
- "guardian",
28
- "trusted_contact",
29
- "unverified_contact",
30
- "unknown",
31
- ]);
23
+ import type { TrustClass } from "@vellumai/gateway-client";
32
24
 
33
- export type TrustClass = z.infer<typeof trustClassSchema>;
25
+ export type { TrustClass };
34
26
 
35
27
  /**
36
28
  * Whether a trust class names a known non-guardian contact — the
37
29
  * `trusted_contact` / `unverified_contact` pair whose admission-only
38
- * equivalence is documented on {@link trustClassSchema}.
30
+ * equivalence is documented in this module's header.
39
31
  *
40
32
  * Accepts a raw string (not just `TrustClass`) because several call sites
41
33
  * classify trust classes read back from persisted turn metadata, which may
@@ -75,7 +67,7 @@ export interface PersonaTrustFlags {
75
67
  * needs the opposite default — fail closed, so a turn that never resolved an
76
68
  * actor still renders the guardrail rather than a guardian exemption.
77
69
  * - `unverified_contact` derives identically to `trusted_contact`, making the
78
- * admission-only equivalence documented on {@link trustClassSchema}
70
+ * admission-only equivalence documented in this module's header
79
71
  * executable in one place.
80
72
  * - The switch is exhaustive with no default: adding a `TrustClass` member is a
81
73
  * compile error here, forcing a deliberate persona decision for the new