@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
@@ -4,8 +4,13 @@ import type {
4
4
  ProviderResponse,
5
5
  ToolUseContent,
6
6
  } from "@vellumai/plugin-api";
7
- import { getConfiguredProvider, safeStringSlice } from "@vellumai/plugin-api";
7
+ import { getConfiguredProvider } from "@vellumai/plugin-api";
8
8
 
9
+ import type {
10
+ RecallMetadata,
11
+ RecallSearchedSource,
12
+ RecallSource,
13
+ } from "../../../../api/events/tool-result.js";
9
14
  import { redactSecrets } from "../../../../security/secret-scanner.js";
10
15
  import {
11
16
  buildRecallAgentPromptBundle,
@@ -15,6 +20,8 @@ import {
15
20
  validateFinishRecallPayload,
16
21
  } from "./agent-protocol.js";
17
22
  import {
23
+ buildRecallActivity,
24
+ compactText,
18
25
  formatDeterministicRecallAnswer,
19
26
  formatRecallFooter,
20
27
  } from "./format.js";
@@ -25,6 +32,7 @@ import {
25
32
  normalizeRecallMaxResults,
26
33
  normalizeRecallSources,
27
34
  } from "./limits.js";
35
+ import type { RecallInput } from "./recall-input.js";
28
36
  import {
29
37
  type DeterministicRecallSearchOptions,
30
38
  type DeterministicRecallSearchResult,
@@ -39,9 +47,7 @@ import {
39
47
  import type {
40
48
  RecallAnswer,
41
49
  RecallEvidence,
42
- RecallInput,
43
50
  RecallSearchContext,
44
- RecallSource,
45
51
  } from "./types.js";
46
52
 
47
53
  type AgenticRecallFallbackReason =
@@ -90,6 +96,7 @@ interface AgenticRecallDebug {
90
96
 
91
97
  interface AgenticRecallAnswer extends RecallAnswer {
92
98
  content: string;
99
+ activity: RecallMetadata;
93
100
  debug: AgenticRecallDebug;
94
101
  }
95
102
 
@@ -266,6 +273,12 @@ export async function runAgenticRecall(
266
273
  options.searchOptions,
267
274
  );
268
275
  let evidence = [...seedResult.evidence];
276
+ // How each source fared across every search this recall runs, the latest
277
+ // search of a source standing: the seed alone would hide a follow-up that
278
+ // degraded, or keep a degradation a later search recovered from.
279
+ let searchedSources = seedResult.searchedSources;
280
+ const currentResult = (): DeterministicRecallSearchResult =>
281
+ withFallbackEvidence({ ...seedResult, searchedSources }, evidence);
269
282
  const autoInspect = await runAutomaticWorkspaceInspection(
270
283
  normalizedInput,
271
284
  context,
@@ -323,7 +336,7 @@ export async function runAgenticRecall(
323
336
  evidence,
324
337
  debug,
325
338
  normalizedInput,
326
- withFallbackEvidence(seedResult, evidence),
339
+ currentResult(),
327
340
  );
328
341
  if (finishResult.ok) {
329
342
  return finishResult.answer;
@@ -380,6 +393,10 @@ export async function runAgenticRecall(
380
393
  );
381
394
  debug.searchCalls.push(searchResult.debug);
382
395
  evidence = mergeEvidence(evidence, searchResult.evidence);
396
+ searchedSources = mergeSearchedSources(
397
+ searchedSources,
398
+ searchResult.searchedSources,
399
+ );
383
400
  }
384
401
  }
385
402
 
@@ -396,7 +413,7 @@ export async function runAgenticRecall(
396
413
  evidence,
397
414
  debug,
398
415
  context,
399
- searchResult: withFallbackEvidence(seedResult, evidence),
416
+ searchResult: currentResult(),
400
417
  });
401
418
  if (finalFinish.ok) {
402
419
  return finalFinish.answer;
@@ -406,7 +423,7 @@ export async function runAgenticRecall(
406
423
  }
407
424
 
408
425
  return deterministicFallback(
409
- withFallbackEvidence(seedResult, evidence),
426
+ currentResult(),
410
427
  debug,
411
428
  fallbackReason,
412
429
  fallbackDetail,
@@ -480,6 +497,7 @@ async function runSeedRecallSearch(
480
497
  }
481
498
 
482
499
  let evidence = [...baseResult.evidence];
500
+ let searchedSources = baseResult.searchedSources;
483
501
  for (const query of expansionQueries) {
484
502
  const expansionResult = await runDeterministicRecallSearch(
485
503
  {
@@ -492,9 +510,33 @@ async function runSeedRecallSearch(
492
510
  searchOptions,
493
511
  );
494
512
  evidence = mergeEvidence(evidence, expansionResult.evidence);
513
+ searchedSources = mergeSearchedSources(
514
+ searchedSources,
515
+ expansionResult.searchedSources,
516
+ );
495
517
  }
496
518
 
497
- return withFallbackEvidence(baseResult, evidence);
519
+ return withFallbackEvidence({ ...baseResult, searchedSources }, evidence);
520
+ }
521
+
522
+ /**
523
+ * Fold a later search's per-source notes into the running record: a source
524
+ * the later search covered takes its newer note, in its existing place; a
525
+ * source it adds goes at the end. Evidence counts are recomputed from the
526
+ * merged evidence by {@link withFallbackEvidence}.
527
+ */
528
+ function mergeSearchedSources(
529
+ current: readonly RecallSearchedSource[],
530
+ later: readonly RecallSearchedSource[],
531
+ ): RecallSearchedSource[] {
532
+ const laterBySource = new Map(later.map((note) => [note.source, note]));
533
+ const merged = current.map((note) => laterBySource.get(note.source) ?? note);
534
+ for (const note of later) {
535
+ if (!current.some((existing) => existing.source === note.source)) {
536
+ merged.push(note);
537
+ }
538
+ }
539
+ return merged;
498
540
  }
499
541
 
500
542
  function buildReferentExpansionQueries(query: string): string[] {
@@ -698,11 +740,12 @@ function finishRecallFromToolUse(
698
740
  citationIds: finish.citationIds,
699
741
  ...(finish.unresolved ? { unresolved: finish.unresolved } : {}),
700
742
  };
743
+ const availableEvidence = shouldAppendAvailableEvidence(finish)
744
+ ? selectAvailableEvidence(input.query, allEvidence, citedEvidence)
745
+ : [];
701
746
  const content = formatAgenticRecallContent({
702
747
  answer: finish.answer,
703
- availableEvidence: shouldAppendAvailableEvidence(finish)
704
- ? selectAvailableEvidence(input.query, allEvidence, citedEvidence)
705
- : [],
748
+ availableEvidence,
706
749
  footer: formatRecallFooter({
707
750
  searchedSources: searchResult.searchedSources,
708
751
  inspectCalls: debug.inspectCalls,
@@ -715,6 +758,15 @@ function finishRecallFromToolUse(
715
758
  content,
716
759
  answer: content,
717
760
  evidence: citedEvidence,
761
+ // Available evidence opens with the cited items, so it is the fuller
762
+ // list whenever the text carries it.
763
+ activity: buildRecallActivity({
764
+ input,
765
+ searchedSources: searchResult.searchedSources,
766
+ evidence:
767
+ availableEvidence.length > 0 ? availableEvidence : citedEvidence,
768
+ answer: finish.answer,
769
+ }),
718
770
  debug,
719
771
  },
720
772
  };
@@ -856,17 +908,6 @@ function formatAvailableEvidence(evidence: readonly RecallEvidence[]): string {
856
908
  ].join("\n");
857
909
  }
858
910
 
859
- function compactText(text: string, maxChars: number): string {
860
- const compacted = text.trim().replace(/\s+/g, " ");
861
- if (compacted.length <= maxChars) {
862
- return compacted;
863
- }
864
- if (maxChars <= 3) {
865
- return safeStringSlice(compacted, 0, maxChars);
866
- }
867
- return `${safeStringSlice(compacted, 0, maxChars - 3).trimEnd()}...`;
868
- }
869
-
870
911
  function dedupeEvidenceById(
871
912
  evidence: readonly RecallEvidence[],
872
913
  ): RecallEvidence[] {
@@ -892,6 +933,7 @@ async function executeSearchSources(
892
933
  searchOptions: DeterministicRecallSearchOptions | undefined,
893
934
  ): Promise<{
894
935
  evidence: RecallEvidence[];
936
+ searchedSources: RecallSearchedSource[];
895
937
  debug: AgenticRecallSearchDebug;
896
938
  }> {
897
939
  const query = readSearchQuery(payload.query);
@@ -915,6 +957,7 @@ async function executeSearchSources(
915
957
  if (!query || sources.length === 0) {
916
958
  return {
917
959
  evidence: [],
960
+ searchedSources: [],
918
961
  debug: {
919
962
  ...debug,
920
963
  error: !query
@@ -937,12 +980,20 @@ async function executeSearchSources(
937
980
  );
938
981
  return {
939
982
  evidence: result.evidence,
983
+ searchedSources: result.searchedSources,
940
984
  debug: { ...debug, evidenceCount: result.evidence.length },
941
985
  };
942
986
  } catch (err) {
987
+ const error = errorToMessage(err);
943
988
  return {
944
989
  evidence: [],
945
- debug: { ...debug, error: errorToMessage(err) },
990
+ searchedSources: sources.map((source) => ({
991
+ source,
992
+ status: "degraded",
993
+ evidenceCount: 0,
994
+ error,
995
+ })),
996
+ debug: { ...debug, error },
946
997
  };
947
998
  }
948
999
  }
@@ -1296,6 +1347,11 @@ function deterministicFallback(
1296
1347
  content: fallback.answer,
1297
1348
  answer: fallback.answer,
1298
1349
  evidence: fallback.evidence,
1350
+ activity: buildRecallActivity({
1351
+ input: result.input,
1352
+ searchedSources: result.searchedSources,
1353
+ evidence: fallback.evidence,
1354
+ }),
1299
1355
  debug: {
1300
1356
  ...debug,
1301
1357
  mode: "deterministic_fallback",
@@ -1,9 +1,11 @@
1
1
  import { safeStringSlice } from "@vellumai/plugin-api";
2
2
 
3
3
  import type {
4
- DeterministicRecallSearchResult,
5
- DeterministicRecallSourceNote,
6
- } from "./search.js";
4
+ RecallMetadata,
5
+ RecallSearchedSource,
6
+ } from "../../../../api/events/tool-result.js";
7
+ import type { NormalizedRecallInput } from "./limits.js";
8
+ import type { DeterministicRecallSearchResult } from "./search.js";
7
9
  import type { RecallAnswer, RecallEvidence } from "./types.js";
8
10
 
9
11
  const CITATION_EXCERPT_MAX_CHARS = 280;
@@ -14,7 +16,7 @@ export interface RecallFooterInspectCall {
14
16
  }
15
17
 
16
18
  export interface RecallFooterOptions {
17
- searchedSources: readonly DeterministicRecallSourceNote[];
19
+ searchedSources: readonly RecallSearchedSource[];
18
20
  inspectCalls?: readonly RecallFooterInspectCall[];
19
21
  }
20
22
 
@@ -56,6 +58,48 @@ export function formatDeterministicRecallAnswer(
56
58
  };
57
59
  }
58
60
 
61
+ /**
62
+ * The recall result as structured data, from the same pieces its text is
63
+ * built from. `answer` is only the answer written from the evidence, never the
64
+ * evidence list or footer the text appends to it.
65
+ */
66
+ export function buildRecallActivity(options: {
67
+ input: NormalizedRecallInput;
68
+ searchedSources: readonly RecallSearchedSource[];
69
+ evidence: readonly RecallEvidence[];
70
+ answer?: string;
71
+ }): RecallMetadata {
72
+ const answer = options.answer?.trim();
73
+ return {
74
+ query: options.input.query,
75
+ depth: options.input.depth,
76
+ sources: [...options.input.sources],
77
+ ...(answer ? { answer } : {}),
78
+ evidence: options.evidence.map((item) => {
79
+ // A path recall could not read is not one a client can open.
80
+ const path =
81
+ item.metadata?.inspectError === true ? undefined : item.metadata?.path;
82
+ const conversationId = item.metadata?.conversationId;
83
+ const messageId = item.metadata?.messageId;
84
+ return {
85
+ source: item.source,
86
+ title: item.title,
87
+ locator: item.locator,
88
+ excerpt: compactText(item.excerpt, CITATION_EXCERPT_MAX_CHARS),
89
+ ...(item.timestampMs !== undefined
90
+ ? { timestampMs: item.timestampMs }
91
+ : {}),
92
+ ...(typeof path === "string" ? { path } : {}),
93
+ ...(typeof conversationId === "string" ? { conversationId } : {}),
94
+ ...(typeof conversationId === "string" && typeof messageId === "string"
95
+ ? { messageId }
96
+ : {}),
97
+ };
98
+ }),
99
+ searchedSources: [...options.searchedSources],
100
+ };
101
+ }
102
+
59
103
  export function formatRecallFooter(options: RecallFooterOptions): string {
60
104
  return [
61
105
  formatSearchedSources(options.searchedSources),
@@ -73,7 +117,7 @@ function formatCitation(evidence: RecallEvidence, index: number): string {
73
117
  }
74
118
 
75
119
  function formatSearchedSources(
76
- searchedSources: readonly DeterministicRecallSourceNote[],
120
+ searchedSources: readonly RecallSearchedSource[],
77
121
  ): string {
78
122
  if (searchedSources.length === 0) {
79
123
  return "";
@@ -84,7 +128,7 @@ function formatSearchedSources(
84
128
  }
85
129
 
86
130
  function formatDegradedSources(
87
- searchedSources: readonly DeterministicRecallSourceNote[],
131
+ searchedSources: readonly RecallSearchedSource[],
88
132
  ): string {
89
133
  const degraded = searchedSources.filter((note) => note.status === "degraded");
90
134
  if (degraded.length === 0) {
@@ -135,7 +179,7 @@ function formatWorkspaceInspectionIssues(
135
179
  return `Workspace inspection issues: ${errors.join(", ")}.`;
136
180
  }
137
181
 
138
- function compactText(text: string, maxChars: number): string {
182
+ export function compactText(text: string, maxChars: number): string {
139
183
  const compacted = text.trim().replace(/\s+/g, " ");
140
184
  if (compacted.length <= maxChars) {
141
185
  return compacted;
@@ -1,12 +1,10 @@
1
- import type { RecallDepth, RecallInput, RecallSource } from "./types.js";
2
-
3
- export const ALL_RECALL_SOURCES: readonly RecallSource[] = [
4
- "memory",
5
- "conversations",
6
- "workspace",
7
- ] as const;
8
-
9
- const RECALL_SOURCE_SET: ReadonlySet<unknown> = new Set(ALL_RECALL_SOURCES);
1
+ import {
2
+ type RecallDepth,
3
+ RecallDepthSchema,
4
+ type RecallSource,
5
+ RecallSourceSchema,
6
+ } from "../../../../api/events/tool-result.js";
7
+ import type { RecallInput } from "./recall-input.js";
10
8
 
11
9
  export const DEFAULT_RECALL_MAX_RESULTS = 8;
12
10
  export const MIN_RECALL_MAX_RESULTS = 1;
@@ -49,7 +47,7 @@ export function normalizeRecallSources(
49
47
  sources: readonly RecallSource[] | undefined,
50
48
  ): RecallSource[] {
51
49
  if (!sources || sources.length === 0) {
52
- return [...ALL_RECALL_SOURCES];
50
+ return [...RecallSourceSchema.options];
53
51
  }
54
52
 
55
53
  const normalized: RecallSource[] = [];
@@ -85,7 +83,7 @@ function normalizeRecallDepth(depth: RecallDepth | undefined): RecallDepth {
85
83
  return DEFAULT_RECALL_DEPTH;
86
84
  }
87
85
 
88
- if (depth !== "fast" && depth !== "standard" && depth !== "deep") {
86
+ if (!RecallDepthSchema.safeParse(depth).success) {
89
87
  throw new Error(`Unknown recall depth: ${String(depth)}`);
90
88
  }
91
89
 
@@ -93,7 +91,7 @@ function normalizeRecallDepth(depth: RecallDepth | undefined): RecallDepth {
93
91
  }
94
92
 
95
93
  export function isRecallSource(source: unknown): source is RecallSource {
96
- return RECALL_SOURCE_SET.has(source);
94
+ return RecallSourceSchema.safeParse(source).success;
97
95
  }
98
96
 
99
97
  function clamp(value: number, min: number, max: number): number {
@@ -0,0 +1,38 @@
1
+ import { nullAsOmitted } from "@vellumai/plugin-api";
2
+ import { z } from "zod";
3
+
4
+ import {
5
+ RecallDepthSchema,
6
+ RecallSourceSchema,
7
+ } from "../../../../api/events/tool-result.js";
8
+ import { MAX_RECALL_MAX_RESULTS, MIN_RECALL_MAX_RESULTS } from "./limits.js";
9
+
10
+ /**
11
+ * The `recall` tool's input: parsed at the top of its `execute`, and the
12
+ * source of the `input_schema` the model is shown, so the two cannot drift.
13
+ *
14
+ * `max_results` accepts any number, which `normalizeRecallInput` clamps, and
15
+ * reads anything else as absent; an explicit `null` on an optional field means
16
+ * omitted. An unknown source or depth is rejected.
17
+ */
18
+ export const RecallInputSchema = z.looseObject({
19
+ query: z
20
+ .string()
21
+ .describe(
22
+ "What you're looking for. Be specific and descriptive: include the topic, person, project, decision, time period, or file clues when known.",
23
+ ),
24
+ sources: nullAsOmitted(z.array(RecallSourceSchema)).describe(
25
+ "Optional local sources to search. Omit to search memory, conversations, and workspace files.",
26
+ ),
27
+ max_results: z.number().optional().catch(undefined).meta({
28
+ type: "integer",
29
+ minimum: MIN_RECALL_MAX_RESULTS,
30
+ maximum: MAX_RECALL_MAX_RESULTS,
31
+ description: "Maximum number of evidence items to return.",
32
+ }),
33
+ depth: nullAsOmitted(RecallDepthSchema).describe(
34
+ "Search effort. Use fast for quick lookups, standard by default, and deep when the answer may require multiple local searches.",
35
+ ),
36
+ });
37
+
38
+ export type RecallInput = z.infer<typeof RecallInputSchema>;
@@ -1,32 +1,26 @@
1
+ import {
2
+ type RecallSearchedSource,
3
+ type RecallSource,
4
+ RecallSourceSchema,
5
+ } from "../../../../api/events/tool-result.js";
1
6
  import { isAbortReason } from "../host-utils.js";
2
7
  import {
3
- ALL_RECALL_SOURCES,
4
8
  type NormalizedRecallInput,
5
9
  normalizeRecallInput,
6
10
  RECALL_EVIDENCE_TEXT_CAP_PER_SOURCE,
7
11
  RECALL_TOTAL_EVIDENCE_TEXT_CAP,
8
12
  } from "./limits.js";
13
+ import type { RecallInput } from "./recall-input.js";
9
14
  import type {
10
15
  RecallEvidence,
11
- RecallInput,
12
16
  RecallSearchContext,
13
17
  RecallSearchResult,
14
- RecallSource,
15
18
  RecallSourceAdapter,
16
19
  } from "./types.js";
17
20
 
18
- export type DeterministicRecallSourceStatus = "searched" | "degraded";
19
-
20
- export interface DeterministicRecallSourceNote {
21
- source: RecallSource;
22
- status: DeterministicRecallSourceStatus;
23
- evidenceCount: number;
24
- error?: string;
25
- }
26
-
27
21
  export interface DeterministicRecallSearchResult extends RecallSearchResult {
28
22
  input: NormalizedRecallInput;
29
- searchedSources: DeterministicRecallSourceNote[];
23
+ searchedSources: RecallSearchedSource[];
30
24
  }
31
25
 
32
26
  export interface DeterministicRecallSearchOptions {
@@ -34,7 +28,7 @@ export interface DeterministicRecallSearchOptions {
34
28
  }
35
29
 
36
30
  const SOURCE_PRIORITY = new Map<RecallSource, number>(
37
- ALL_RECALL_SOURCES.map((source, index) => [source, index]),
31
+ RecallSourceSchema.options.map((source, index) => [source, index]),
38
32
  );
39
33
 
40
34
  export async function runDeterministicRecallSearch(
@@ -181,6 +181,7 @@ export async function searchConversationSource(
181
181
  metadata: {
182
182
  role: row.role,
183
183
  conversationId: row.conversation_id,
184
+ messageId: row.message_id,
184
185
  },
185
186
  })),
186
187
  ),
@@ -1,16 +1,6 @@
1
+ import type { RecallSource } from "../../../../api/events/tool-result.js";
1
2
  import type { AssistantConfig } from "../../../../config/schema.js";
2
3
 
3
- export type RecallSource = "memory" | "conversations" | "workspace";
4
-
5
- export type RecallDepth = "fast" | "standard" | "deep";
6
-
7
- export interface RecallInput {
8
- query: string;
9
- sources?: RecallSource[];
10
- max_results?: number;
11
- depth?: RecallDepth;
12
- }
13
-
14
4
  export interface RecallEvidence {
15
5
  id: string;
16
6
  source: RecallSource;
@@ -203,8 +203,11 @@ describe("handleRemember — batch (array) content", () => {
203
203
  CONFIG,
204
204
  );
205
205
 
206
- expect(result.success).toBe(true);
207
- expect(result.message).toContain("3");
206
+ expect(result).toEqual({
207
+ success: true,
208
+ message: "Saved 3 facts to knowledge base.",
209
+ facts: ["fact one", "fact two", "fact three"],
210
+ });
208
211
 
209
212
  const memoryDir = join(tmpWorkspace, "memory");
210
213
  const buffer = readFileSync(join(memoryDir, "buffer.md"), "utf-8");
@@ -245,11 +248,15 @@ describe("handleRemember — batch (array) content", () => {
245
248
 
246
249
  test("drops blank entries and rejects an all-empty array", () => {
247
250
  const ok = handleRemember(
248
- { content: [" ", "kept fact", ""] },
251
+ { content: [" ", " kept fact ", ""] },
249
252
  "conv-batch-3",
250
253
  CONFIG,
251
254
  );
252
- expect(ok.success).toBe(true);
255
+ expect(ok).toEqual({
256
+ success: true,
257
+ message: "Saved to knowledge base.",
258
+ facts: ["kept fact"],
259
+ });
253
260
  const buffer = readFileSync(
254
261
  join(tmpWorkspace, "memory", "buffer.md"),
255
262
  "utf-8",
@@ -8,6 +8,7 @@
8
8
 
9
9
  import { join } from "node:path";
10
10
 
11
+ import type { RememberInput } from "../../../../api/remember-tool.js";
11
12
  import {
12
13
  isMemoryEnabled,
13
14
  usesConceptPageMemory,
@@ -31,33 +32,23 @@ import { type CapabilityKind, capabilityKind } from "./types.js";
31
32
  // remember handler — appends to the memory/ buffer + daily archive
32
33
  // ---------------------------------------------------------------------------
33
34
 
34
- export interface RememberInput {
35
- /**
36
- * The fact(s) to remember. A single string records one fact; an array
37
- * records several independent facts in one call (each becomes its own
38
- * timestamped entry), so a single turn can batch unrelated facts instead of
39
- * calling `remember` once per fact.
40
- */
41
- content: string | string[];
42
- finish_turn?: boolean;
43
- }
44
-
45
- export interface RememberResult {
46
- success: boolean;
47
- message: string;
48
- }
35
+ export type RememberResult =
36
+ | {
37
+ success: true;
38
+ message: string;
39
+ /** The facts saved, trimmed, in the order they were given. */
40
+ facts: string[];
41
+ }
42
+ | { success: false; message: string };
49
43
 
50
44
  /**
51
45
  * Normalize the `remember` content input to a list of non-empty facts.
52
46
  * Accepts the single-string form or the batch array form, trims each fact, and
53
47
  * drops blanks so an empty or whitespace-only input yields no facts.
54
48
  */
55
- function normalizeFacts(content: string | string[]): string[] {
49
+ function normalizeFacts(content: RememberInput["content"]): string[] {
56
50
  const raw = Array.isArray(content) ? content : [content];
57
- return raw
58
- .filter((fact): fact is string => typeof fact === "string")
59
- .map((fact) => fact.trim())
60
- .filter((fact) => fact.length > 0);
51
+ return raw.map((fact) => fact.trim()).filter((fact) => fact.length > 0);
61
52
  }
62
53
 
63
54
  function rememberSuccessMessage(count: number): string {
@@ -96,7 +87,7 @@ export function handleRemember(
96
87
  now,
97
88
  });
98
89
 
99
- return { success: true, message };
90
+ return { success: true, message, facts };
100
91
  }
101
92
 
102
93
  // ---------------------------------------------------------------------------