@vellumai/assistant 0.10.12 → 0.11.0-staging.1

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 (776) hide show
  1. package/AGENTS.md +1 -1
  2. package/ARCHITECTURE.md +4 -5
  3. package/README.md +1 -1
  4. package/docs/architecture/memory.md +60 -23
  5. package/docs/error-handling.md +3 -3
  6. package/docs/guardian-request-flow.md +112 -0
  7. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +1 -0
  8. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +9 -1
  9. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
  10. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
  11. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
  12. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/app.d.ts +28 -0
  13. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/app.d.ts.map +1 -1
  14. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.d.ts +2 -2
  15. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.d.ts.map +1 -1
  16. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.js.map +1 -1
  17. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/message.d.ts +2 -0
  18. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/message.d.ts.map +1 -1
  19. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/package.json +1 -1
  20. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +1 -0
  21. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +9 -1
  22. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
  23. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
  24. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
  25. package/node_modules/@vellumai/gateway-client/package.json +1 -1
  26. package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +6 -0
  27. package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +34 -0
  28. package/node_modules/@vellumai/service-contracts/package.json +1 -0
  29. package/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +9 -1
  30. package/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
  31. package/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
  32. package/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
  33. package/openapi.yaml +246 -10
  34. package/package.json +2 -2
  35. package/src/__tests__/acp-session.test.ts +3 -3
  36. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +3 -0
  37. package/src/__tests__/anthropic-provider.test.ts +40 -0
  38. package/src/__tests__/approval-cascade.test.ts +5 -5
  39. package/src/__tests__/approval-routes-http.test.ts +3 -3
  40. package/src/__tests__/ask-question-resolver.test.ts +207 -0
  41. package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +16 -16
  42. package/src/__tests__/assistant-event-hub-targeted.test.ts +13 -11
  43. package/src/__tests__/assistant-event-hub.test.ts +13 -11
  44. package/src/__tests__/assistant-event.test.ts +12 -9
  45. package/src/__tests__/assistant-feature-flag-guard.test.ts +3 -3
  46. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +1 -1
  47. package/src/__tests__/assistant-id-boundary-guard.test.ts +0 -58
  48. package/src/__tests__/assistant-stream-state.test.ts +17 -7
  49. package/src/__tests__/avatar-identity-sync.test.ts +3 -3
  50. package/src/__tests__/background-workers-disk-pressure.test.ts +1 -0
  51. package/src/__tests__/call-conversation-messages.test.ts +134 -18
  52. package/src/__tests__/call-start-guardian-guard.test.ts +27 -0
  53. package/src/__tests__/channel-approvals.test.ts +0 -27
  54. package/src/__tests__/channel-guardian.test.ts +85 -512
  55. package/src/__tests__/channel-readiness-slack-remote.test.ts +151 -3
  56. package/src/__tests__/channel-retry-sweep.test.ts +88 -1
  57. package/src/__tests__/channel-setup-panel-ack.test.ts +12 -9
  58. package/src/__tests__/chat-reveal-guard-priming.test.ts +31 -34
  59. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +2 -2
  60. package/src/__tests__/compaction-events.test.ts +8 -8
  61. package/src/__tests__/config-loader-platform-defaults.test.ts +54 -28
  62. package/src/__tests__/config-model-image-provider.test.ts +20 -0
  63. package/src/__tests__/config-schema-memory-substrate.test.ts +306 -0
  64. package/src/__tests__/config-schema.test.ts +14 -2
  65. package/src/__tests__/config-set-platform-guard.test.ts +11 -12
  66. package/src/__tests__/config-sounds-sync.test.ts +4 -4
  67. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +5 -0
  68. package/src/__tests__/context-search-memory-source.test.ts +1 -1
  69. package/src/__tests__/context-search-memory-v2-source.test.ts +6 -6
  70. package/src/__tests__/context-token-estimator.test.ts +54 -1
  71. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +12 -3
  72. package/src/__tests__/conversation-agent-loop-fatal-cleanup.test.ts +13 -4
  73. package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +4 -4
  74. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +10 -1
  75. package/src/__tests__/conversation-agent-loop-overflow.test.ts +22 -13
  76. package/src/__tests__/conversation-agent-loop.test.ts +39 -30
  77. package/src/__tests__/conversation-confirmation-signals.test.ts +14 -14
  78. package/src/__tests__/conversation-evictor.test.ts +49 -0
  79. package/src/__tests__/conversation-fork-crud.test.ts +1 -1
  80. package/src/__tests__/conversation-history-web-search.test.ts +1 -1
  81. package/src/__tests__/conversation-key-store-disk-view.test.ts +5 -5
  82. package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +5 -5
  83. package/src/__tests__/conversation-message-sync-tags.test.ts +4 -4
  84. package/src/__tests__/conversation-queue.test.ts +81 -81
  85. package/src/__tests__/conversation-routes-enabled-plugins.test.ts +8 -1
  86. package/src/__tests__/conversation-routes-hidden-queue.test.ts +8 -1
  87. package/src/__tests__/conversation-routes-slash-commands.test.ts +10 -1
  88. package/src/__tests__/conversation-runtime-assembly.test.ts +29 -2
  89. package/src/__tests__/conversation-slash-queue.test.ts +11 -11
  90. package/src/__tests__/conversation-slash-unknown.test.ts +2 -2
  91. package/src/__tests__/conversation-speed-override.test.ts +2 -2
  92. package/src/__tests__/conversation-summarize-route.test.ts +9 -0
  93. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +18 -16
  94. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +17 -17
  95. package/src/__tests__/conversation-surfaces-app-open.test.ts +7 -4
  96. package/src/__tests__/conversation-surfaces-data-persist.test.ts +7 -7
  97. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +9 -9
  98. package/src/__tests__/conversation-surfaces-standalone.test.ts +12 -12
  99. package/src/__tests__/conversation-surfaces-state-update.test.ts +8 -5
  100. package/src/__tests__/conversation-surfaces-table-action.test.ts +6 -3
  101. package/src/__tests__/conversation-surfaces-task-progress.test.ts +46 -46
  102. package/src/__tests__/conversation-sync-tags.test.ts +5 -5
  103. package/src/__tests__/conversation-wait-for-idle.test.ts +2 -2
  104. package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -4
  105. package/src/__tests__/conversation-workspace-injection.test.ts +0 -3
  106. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -3
  107. package/src/__tests__/copy-composer-tc-templates.test.ts +3 -131
  108. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  109. package/src/__tests__/daemon-assistant-events.test.ts +14 -15
  110. package/src/__tests__/db-test-helpers.ts +13 -27
  111. package/src/__tests__/disk-pressure-routes.test.ts +12 -3
  112. package/src/__tests__/document-tool-security.test.ts +95 -0
  113. package/src/__tests__/drain-kick-guard.test.ts +232 -0
  114. package/src/__tests__/dynamic-skill-background-guard.test.ts +19 -6
  115. package/src/__tests__/emit-event-signal.test.ts +5 -6
  116. package/src/__tests__/encrypted-store-test-helpers.ts +10 -20
  117. package/src/__tests__/events-tail-route.test.ts +6 -4
  118. package/src/__tests__/feature-flag-test-helpers.ts +10 -20
  119. package/src/__tests__/file-edit-tool.test.ts +24 -4
  120. package/src/__tests__/file-list-tool.test.ts +2 -1
  121. package/src/__tests__/file-read-tool.test.ts +62 -10
  122. package/src/__tests__/file-write-tool.test.ts +24 -5
  123. package/src/__tests__/followup-tools.test.ts +58 -0
  124. package/src/__tests__/gateway-threshold-reader-mock.ts +99 -0
  125. package/src/__tests__/graph-extraction-event-date.test.ts +1 -1
  126. package/src/__tests__/guardian-question-mode.test.ts +42 -3
  127. package/src/__tests__/guardian-reply-router-answer-mode.test.ts +283 -0
  128. package/src/__tests__/guardian-vellum-destination-pinning.test.ts +221 -0
  129. package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
  130. package/src/__tests__/heartbeat-service.test.ts +1 -0
  131. package/src/__tests__/helpers/native-web-search-harness.ts +10 -10
  132. package/src/__tests__/host-browser-proxy.test.ts +1 -1
  133. package/src/__tests__/host-file-edit-tool.test.ts +3 -3
  134. package/src/__tests__/host-file-read-tool.test.ts +2 -2
  135. package/src/__tests__/host-file-write-tool.test.ts +7 -3
  136. package/src/__tests__/host-shell-tool.test.ts +17 -5
  137. package/src/__tests__/host-transfer-pending-interactions.test.ts +8 -8
  138. package/src/__tests__/image-credentials.test.ts +65 -8
  139. package/src/__tests__/injection-block.test.ts +4 -4
  140. package/src/__tests__/injector-chain.test.ts +1 -1
  141. package/src/__tests__/injector-pkb-v2-silenced.test.ts +2 -2
  142. package/src/__tests__/injector-registry-order-guard.test.ts +4 -9
  143. package/src/__tests__/injector-v3-suppression.test.ts +6 -4
  144. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +27 -28
  145. package/src/__tests__/list-messages-page-latest.test.ts +2 -2
  146. package/src/__tests__/llm-usage-store.test.ts +67 -4
  147. package/src/__tests__/log-redact.test.ts +18 -0
  148. package/src/__tests__/managed-profile-guard.test.ts +27 -0
  149. package/src/__tests__/managed-skill-lifecycle.test.ts +2 -2
  150. package/src/__tests__/media-generate-image.test.ts +62 -11
  151. package/src/__tests__/memory-identity-context-parity.test.ts +1 -1
  152. package/src/__tests__/memory-jobs-worker-lanes.test.ts +9 -1
  153. package/src/__tests__/memory-retrieval-hook.test.ts +4 -4
  154. package/src/__tests__/notification-decision-strategy.test.ts +115 -11
  155. package/src/__tests__/notification-deep-link.test.ts +12 -12
  156. package/src/__tests__/notification-vellum-adapter.test.ts +8 -8
  157. package/src/__tests__/outbound-slack-persistence.test.ts +8 -8
  158. package/src/__tests__/path-policy.test.ts +315 -0
  159. package/src/__tests__/pending-interactions-resolved-event.test.ts +6 -6
  160. package/src/__tests__/persistence-layering-guard.test.ts +2 -2
  161. package/src/__tests__/pkb-autoinject.test.ts +1 -1
  162. package/src/__tests__/platform-bash-auto-approve.test.ts +1 -0
  163. package/src/__tests__/plugin-event-hub-facade.test.ts +22 -15
  164. package/src/__tests__/plugin-import-boundary-guard.test.ts +15 -15
  165. package/src/__tests__/processing-flag-persist-failure.test.ts +0 -4
  166. package/src/__tests__/provider-platform-proxy-integration.test.ts +0 -1
  167. package/src/__tests__/rebuild-index-graph-nodes.test.ts +1 -1
  168. package/src/__tests__/request-secret-standalone-channel-gate.test.ts +5 -5
  169. package/src/__tests__/require-fresh-approval.test.ts +38 -38
  170. package/src/__tests__/run-due-schedules.test.ts +72 -1
  171. package/src/__tests__/runtime-events-sse-parity.test.ts +11 -10
  172. package/src/__tests__/runtime-events-sse.test.ts +1 -1
  173. package/src/__tests__/schedule-routes.test.ts +44 -5
  174. package/src/__tests__/schedule-store.test.ts +3 -3
  175. package/src/__tests__/schedule-tools.test.ts +176 -0
  176. package/src/__tests__/secret-prompt-log-hygiene.test.ts +3 -3
  177. package/src/__tests__/secret-prompter-channel-fallback.test.ts +3 -3
  178. package/src/__tests__/secret-response-routing.test.ts +3 -3
  179. package/src/__tests__/secret-routes-platform-proxy.test.ts +4 -7
  180. package/src/__tests__/secret-scanner.test.ts +36 -0
  181. package/src/__tests__/send-endpoint-busy.test.ts +7 -7
  182. package/src/__tests__/slack-required-scopes-mirror.test.ts +81 -0
  183. package/src/__tests__/starter-task-flow.test.ts +6 -3
  184. package/src/__tests__/subagent-call-site-routing.test.ts +2 -2
  185. package/src/__tests__/subagent-disposal.test.ts +40 -11
  186. package/src/__tests__/subagent-fork-notifications.test.ts +4 -4
  187. package/src/__tests__/subagent-fork-prompt-role.test.ts +3 -3
  188. package/src/__tests__/subagent-fork-spawn.test.ts +4 -4
  189. package/src/__tests__/subagent-manager-notify.test.ts +73 -14
  190. package/src/__tests__/subagent-notify-parent.test.ts +48 -4
  191. package/src/__tests__/subagent-spawn-and-await.test.ts +62 -14
  192. package/src/__tests__/subagent-tools.test.ts +64 -0
  193. package/src/__tests__/sync-message-contract.test.ts +3 -3
  194. package/src/__tests__/terminal-tools.test.ts +12 -3
  195. package/src/__tests__/test-preload.ts +9 -0
  196. package/src/__tests__/tool-approval-handler.test.ts +583 -43
  197. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +7 -4
  198. package/src/__tests__/tool-executor.test.ts +116 -0
  199. package/src/__tests__/tool-grant-request-escalation.test.ts +5 -0
  200. package/src/__tests__/tool-preview-lifecycle.test.ts +32 -29
  201. package/src/__tests__/tool-result-metadata-plumbing.test.ts +5 -5
  202. package/src/__tests__/tool-start-timestamp.test.ts +4 -4
  203. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +9 -22
  204. package/src/__tests__/ui-choice-copy-surfaces.test.ts +13 -13
  205. package/src/__tests__/ui-work-result-surface.test.ts +3 -3
  206. package/src/__tests__/voice-scoped-grant-consumer.test.ts +6 -6
  207. package/src/__tests__/voice-session-bridge.test.ts +44 -44
  208. package/src/__tests__/workspace-migration-134-image-generation-mode-to-provider.test.ts +284 -0
  209. package/src/__tests__/workspace-policy.test.ts +399 -0
  210. package/src/acp/__tests__/client-handler.test.ts +3 -3
  211. package/src/acp/__tests__/session-manager-persistence.test.ts +10 -10
  212. package/src/acp/__tests__/session-manager-resume.test.ts +7 -7
  213. package/src/acp/client-handler.ts +3 -3
  214. package/src/acp/session-manager.ts +8 -8
  215. package/src/api/events/subagent-event.ts +2 -2
  216. package/src/api/responses/memory-v2-activation-log.ts +2 -2
  217. package/src/approvals/AGENTS.md +2 -0
  218. package/src/approvals/guardian-request-resolvers.ts +118 -24
  219. package/src/calls/__tests__/voice-control-protocol.test.ts +57 -0
  220. package/src/calls/__tests__/voice-session-bridge.test.ts +158 -4
  221. package/src/calls/__tests__/voice-triage-escalate.test.ts +3 -4
  222. package/src/calls/call-controller.ts +27 -27
  223. package/src/calls/call-conversation-messages.ts +58 -18
  224. package/src/calls/voice-control-protocol.ts +56 -0
  225. package/src/calls/voice-session-bridge.ts +156 -58
  226. package/src/calls/voice-triage-escalate.ts +2 -3
  227. package/src/channels/config.ts +8 -0
  228. package/src/channels/types.ts +1 -0
  229. package/src/cli/commands/config.ts +49 -13
  230. package/src/cli/commands/memory/index.help.ts +4 -2
  231. package/src/cli/commands/memory/memory-retrospective.ts +5 -0
  232. package/src/cli/lib/bundled-marketplace.json +12 -0
  233. package/src/cli.ts +2 -109
  234. package/src/config/__tests__/deployment-context-defaults.test.ts +9 -0
  235. package/src/config/__tests__/substrate-twin-shadowing.test.ts +191 -0
  236. package/src/config/assistant-feature-flags.ts +1 -1
  237. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +13 -7
  238. package/src/config/feature-flag-cache.ts +6 -16
  239. package/src/config/feature-flag-registry.json +14 -30
  240. package/src/config/loader.ts +7 -1
  241. package/src/config/memory-tier.ts +15 -10
  242. package/src/config/memory-v3-gate.test.ts +278 -1
  243. package/src/config/memory-v3-gate.ts +88 -26
  244. package/src/config/raw-config-utils.ts +1 -1
  245. package/src/config/schemas/__tests__/live-voice.test.ts +27 -16
  246. package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
  247. package/src/config/schemas/live-voice.ts +33 -7
  248. package/src/config/schemas/llm.ts +1 -0
  249. package/src/config/schemas/memory-retrospective.ts +13 -0
  250. package/src/config/schemas/memory-substrate.ts +183 -0
  251. package/src/config/schemas/memory-v2.ts +3 -2
  252. package/src/config/schemas/memory-v3.ts +11 -4
  253. package/src/config/schemas/memory.ts +35 -1
  254. package/src/config/schemas/services.ts +10 -2
  255. package/src/config/substrate-twin-shadowing.ts +195 -0
  256. package/src/config/webhook-routing.ts +67 -0
  257. package/src/context/compactor.ts +10 -3
  258. package/src/context/token-estimator.ts +21 -0
  259. package/src/daemon/__tests__/channel-ui-capability.test.ts +85 -0
  260. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +3 -3
  261. package/src/daemon/__tests__/embedding-reconcile.test.ts +3 -3
  262. package/src/daemon/__tests__/inference-profile-notification.test.ts +3 -6
  263. package/src/daemon/__tests__/native-web-search-metadata.test.ts +5 -5
  264. package/src/daemon/__tests__/web-search-status-text.test.ts +2 -2
  265. package/src/daemon/channel-ui-capability.ts +70 -1
  266. package/src/daemon/conversation-agent-loop-handlers.ts +4 -4
  267. package/src/daemon/conversation-agent-loop.ts +12 -5
  268. package/src/daemon/conversation-evictor.ts +26 -4
  269. package/src/daemon/conversation-launch.ts +11 -14
  270. package/src/daemon/conversation-messaging.ts +14 -14
  271. package/src/daemon/conversation-notifiers.ts +2 -2
  272. package/src/daemon/conversation-process.ts +133 -21
  273. package/src/daemon/conversation-queue-manager.ts +7 -7
  274. package/src/daemon/conversation-runtime-assembly.ts +16 -0
  275. package/src/daemon/conversation-store.ts +11 -3
  276. package/src/daemon/conversation-surfaces.ts +4 -4
  277. package/src/daemon/conversation-tool-setup.ts +13 -7
  278. package/src/daemon/conversation-usage.ts +12 -11
  279. package/src/daemon/conversation.ts +38 -15
  280. package/src/daemon/disk-pressure-guard.ts +5 -12
  281. package/src/daemon/embedding-reconcile.ts +14 -9
  282. package/src/daemon/handlers/config-channels.ts +40 -134
  283. package/src/daemon/handlers/config-model.ts +15 -7
  284. package/src/daemon/handlers/conversations.ts +4 -2
  285. package/src/daemon/handlers/shared.ts +29 -0
  286. package/src/daemon/host-proxy-base.ts +4 -4
  287. package/src/daemon/lifecycle.ts +13 -0
  288. package/src/daemon/message-protocol.ts +8 -144
  289. package/src/daemon/message-types/computer-use.ts +0 -12
  290. package/src/daemon/message-types/conversations.ts +9 -345
  291. package/src/daemon/message-types/host-app-control.ts +0 -9
  292. package/src/daemon/message-types/host-browser.ts +0 -7
  293. package/src/daemon/message-types/host-ui-snapshot.ts +0 -7
  294. package/src/daemon/message-types/messages.ts +0 -48
  295. package/src/daemon/message-types/notifications.ts +0 -7
  296. package/src/daemon/message-types/skills.ts +0 -5
  297. package/src/daemon/message-types/surfaces.ts +0 -9
  298. package/src/daemon/message-types/sync.ts +0 -2
  299. package/src/daemon/process-message.ts +5 -5
  300. package/src/daemon/skill-memory-refresh.ts +5 -5
  301. package/src/daemon/tool-side-effects.ts +13 -13
  302. package/src/daemon/trust-context.ts +1 -1
  303. package/src/daemon/wake-conversation-ops.ts +4 -4
  304. package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +100 -7
  305. package/src/heartbeat/__tests__/heartbeat-service.test.ts +67 -0
  306. package/src/heartbeat/heartbeat-run-store.ts +81 -4
  307. package/src/heartbeat/heartbeat-service.ts +32 -1
  308. package/src/home/__tests__/feed-writer.test.ts +7 -7
  309. package/src/home/__tests__/home-content-refresh.test.ts +3 -0
  310. package/src/home/__tests__/suggested-prompts.test.ts +1 -0
  311. package/src/home/feed-writer.ts +6 -13
  312. package/src/home/home-content-refresh.ts +6 -9
  313. package/src/home/relationship-state-writer.ts +5 -12
  314. package/src/home/suggested-prompts-cache.ts +6 -19
  315. package/src/ipc/__tests__/events-publish-client.test.ts +67 -0
  316. package/src/ipc/events-publish-client.ts +44 -0
  317. package/src/ipc/routes/__tests__/conversation-sync-ipc-routes.test.ts +2 -2
  318. package/src/ipc/routes/__tests__/events-ipc-routes.test.ts +38 -9
  319. package/src/ipc/routes/events-ipc-routes.ts +11 -31
  320. package/src/live-voice/__tests__/front-decision.test.ts +4 -176
  321. package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +276 -68
  322. package/src/live-voice/__tests__/live-voice-events.test.ts +6 -3
  323. package/src/live-voice/__tests__/live-voice-progress.test.ts +185 -46
  324. package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +24 -59
  325. package/src/live-voice/__tests__/live-voice-tts-session.test.ts +38 -54
  326. package/src/live-voice/__tests__/live-voice-vad.test.ts +218 -422
  327. package/src/live-voice/front-decision.ts +5 -155
  328. package/src/live-voice/live-voice-metrics.ts +4 -1
  329. package/src/live-voice/live-voice-session.ts +650 -333
  330. package/src/live-voice/progress-phrases.ts +17 -0
  331. package/src/live-voice/protocol.ts +15 -0
  332. package/src/media/app-icon-generator.ts +15 -8
  333. package/src/media/avatar-router.ts +9 -5
  334. package/src/media/image-credentials.ts +42 -10
  335. package/src/media/image-service.ts +1 -13
  336. package/src/media/types.ts +26 -3
  337. package/src/notifications/AGENTS.md +2 -0
  338. package/src/notifications/__tests__/broadcaster.test.ts +95 -0
  339. package/src/notifications/adapters/macos.ts +3 -3
  340. package/src/notifications/broadcaster.ts +57 -0
  341. package/src/notifications/copy-composer.ts +0 -15
  342. package/src/notifications/decision-engine.ts +21 -22
  343. package/src/notifications/guardian-question-mode.ts +57 -2
  344. package/src/notifications/home-feed-side-effect.ts +4 -0
  345. package/src/notifications/signal.ts +6 -4
  346. package/src/notifications/trusted-contact-payloads.ts +3 -4
  347. package/src/notifications/vellum-card-affinity.ts +39 -0
  348. package/src/oauth/AGENTS.md +1 -1
  349. package/src/permissions/channel-permission-query.test.ts +69 -0
  350. package/src/permissions/channel-permission-query.ts +73 -1
  351. package/src/permissions/checker.test.ts +85 -9
  352. package/src/permissions/checker.ts +17 -22
  353. package/src/permissions/confirmation-guardian-request.test.ts +2 -2
  354. package/src/permissions/confirmation-guardian-request.ts +2 -2
  355. package/src/permissions/gateway-threshold-reader.test.ts +224 -17
  356. package/src/permissions/gateway-threshold-reader.ts +82 -10
  357. package/src/permissions/ipc-risk-types.ts +8 -0
  358. package/src/permissions/prompter.ts +5 -5
  359. package/src/permissions/question-guardian-request.test.ts +222 -0
  360. package/src/permissions/question-guardian-request.ts +179 -0
  361. package/src/permissions/question-prompter.test.ts +8 -8
  362. package/src/permissions/question-prompter.ts +18 -0
  363. package/src/permissions/secret-prompter.ts +2 -4
  364. package/src/permissions/workspace-policy.ts +236 -34
  365. package/src/persistence/__tests__/lifecycle-quiesce.test.ts +82 -0
  366. package/src/persistence/__tests__/message-content-file.test.ts +58 -3
  367. package/src/persistence/conversation-crud.ts +93 -0
  368. package/src/persistence/conversation-key-store.ts +63 -0
  369. package/src/persistence/db-async-query.ts +1 -1
  370. package/src/persistence/db-singleton.ts +14 -27
  371. package/src/persistence/delivery-crud.ts +45 -0
  372. package/src/persistence/embeddings/embedding-backend.ts +2 -1
  373. package/src/persistence/embeddings/embedding-identity.ts +7 -3
  374. package/src/persistence/job-utils.ts +32 -27
  375. package/src/persistence/jobs-store.ts +92 -3
  376. package/src/persistence/lifecycle-quiesce.ts +80 -0
  377. package/src/persistence/llm-usage-store.ts +45 -8
  378. package/src/persistence/message-content-file.ts +4 -4
  379. package/src/persistence/migrations/336-move-memory-v2-activation-logs-to-memory-db.ts +1 -1
  380. package/src/persistence/migrations/351-schedule-skill-script-handoff.ts +39 -0
  381. package/src/persistence/migrations/352-drop-schedule-skill-script-handoff.test.ts +83 -0
  382. package/src/persistence/migrations/352-drop-schedule-skill-script-handoff.ts +36 -0
  383. package/src/persistence/migrations/353-add-llm-usage-conversation-type.test.ts +110 -0
  384. package/src/persistence/migrations/353-add-llm-usage-conversation-type.ts +49 -0
  385. package/src/persistence/schema/infrastructure.ts +11 -0
  386. package/src/persistence/steps.ts +7 -1
  387. package/src/plugin-api/__tests__/publish-event-forwarding.test.ts +113 -0
  388. package/src/plugin-api/__tests__/publish-event.test.ts +57 -0
  389. package/src/plugin-api/conversation-turn.ts +4 -4
  390. package/src/plugin-api/event-hub-facade.ts +15 -6
  391. package/src/plugin-api/index.ts +10 -4
  392. package/src/plugin-api/publish-event.ts +36 -0
  393. package/src/plugins/AGENTS.md +2 -0
  394. package/src/plugins/defaults/compaction/window-manager.ts +9 -0
  395. package/src/plugins/defaults/index.ts +9 -13
  396. package/src/plugins/defaults/memory/AGENTS.md +775 -0
  397. package/src/plugins/defaults/memory/__tests__/capability-seed-embed-gate.test.ts +186 -0
  398. package/src/plugins/defaults/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +1 -1
  399. package/src/plugins/defaults/memory/__tests__/indexer-tier-dispatch.test.ts +129 -0
  400. package/src/plugins/defaults/memory/__tests__/jobs-worker-quiesce-gate.test.ts +91 -0
  401. package/src/plugins/defaults/memory/__tests__/jobs-worker-v1-graph-substrate-noop.test.ts +342 -0
  402. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +9 -1
  403. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-schedule.test.ts +36 -1
  404. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-sweep-defer.test.ts +9 -1
  405. package/src/plugins/defaults/memory/__tests__/memory-log-stores-degraded.test.ts +2 -2
  406. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +44 -10
  407. package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +151 -10
  408. package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +1155 -0
  409. package/src/plugins/defaults/memory/__tests__/memory-v2-activation-log-store.test.ts +1 -1
  410. package/src/plugins/defaults/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -3
  411. package/src/plugins/defaults/memory/__tests__/tools-delete-memory-page.test.ts +1 -1
  412. package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +71 -35
  413. package/src/plugins/defaults/memory/context-search/sources/memory.ts +5 -1
  414. package/src/plugins/defaults/memory/fork-conversation-memory.ts +4 -4
  415. package/src/plugins/defaults/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +80 -10
  416. package/src/plugins/defaults/memory/graph/__tests__/handle-remember-v2.test.ts +1 -1
  417. package/src/plugins/defaults/memory/graph/capability-seed.ts +24 -10
  418. package/src/plugins/defaults/memory/graph/conversation-graph-memory.ts +123 -49
  419. package/src/plugins/defaults/memory/graph/graph-search.ts +6 -118
  420. package/src/plugins/defaults/memory/graph/in-context-tracker.test.ts +173 -0
  421. package/src/plugins/defaults/memory/graph/in-context-tracker.ts +109 -0
  422. package/src/plugins/defaults/memory/graph/store.ts +1 -0
  423. package/src/plugins/defaults/memory/graph/tool-handlers.test.ts +1 -1
  424. package/src/plugins/defaults/memory/graph/tool-handlers.ts +5 -2
  425. package/src/plugins/defaults/memory/graph-topology/__tests__/build-memory-graph.test.ts +1 -1
  426. package/src/plugins/defaults/memory/graph-topology/build-memory-graph.ts +6 -9
  427. package/src/plugins/defaults/memory/hooks/__tests__/user-prompt-submit.test.ts +30 -16
  428. package/src/plugins/defaults/memory/hooks/user-prompt-submit.ts +18 -14
  429. package/src/plugins/defaults/memory/indexer.ts +146 -89
  430. package/src/plugins/defaults/memory/injectors.ts +86 -41
  431. package/src/plugins/defaults/memory/job-handlers.ts +130 -39
  432. package/src/plugins/defaults/memory/jobs/__tests__/embed-concept-page.test.ts +2 -2
  433. package/src/plugins/defaults/memory/jobs/embed-concept-page.ts +22 -10
  434. package/src/plugins/defaults/memory/jobs-worker.ts +279 -208
  435. package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +4 -2
  436. package/src/plugins/defaults/memory/memory-retrospective-job.ts +40 -3
  437. package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +99 -11
  438. package/src/plugins/defaults/memory/src/__tests__/memory-v2-routes.test.ts +5 -3
  439. package/src/plugins/defaults/memory/src/__tests__/memory-v2-simulate-route.test.ts +3 -4
  440. package/src/plugins/defaults/memory/src/memory-graph-routes.ts +2 -1
  441. package/src/plugins/defaults/memory/src/memory-item-routes.test.ts +7 -5
  442. package/src/plugins/defaults/memory/src/memory-item-routes.ts +51 -19
  443. package/src/plugins/defaults/memory/src/memory-v2-routes.ts +31 -20
  444. package/src/plugins/defaults/memory/startup.ts +58 -21
  445. package/src/plugins/defaults/memory/substrate/__tests__/boot-maintenance.test.ts +335 -0
  446. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/cli-command-store.test.ts +14 -8
  447. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/consolidation-job.test.ts +51 -21
  448. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/edge-index.test.ts +1 -1
  449. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/frontmatter-sweep.test.ts +3 -3
  450. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/page-index.test.ts +1 -1
  451. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/page-store.test.ts +1 -1
  452. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/prompts-consolidation.test.ts +2 -2
  453. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/qdrant.test.ts +23 -14
  454. package/src/plugins/defaults/memory/substrate/__tests__/reembed-job.test.ts +262 -0
  455. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sim.test.ts +9 -12
  456. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/skill-content.test.ts +2 -2
  457. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/skill-store.test.ts +9 -9
  458. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sparse-bm25.test.ts +12 -5
  459. package/src/plugins/defaults/memory/substrate/__tests__/spread.test.ts +276 -0
  460. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/static-context.test.ts +17 -8
  461. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sweep-job.test.ts +9 -9
  462. package/src/plugins/defaults/memory/{v3/substrate/memory-v2-startup.ts → substrate/boot-maintenance.ts} +43 -24
  463. package/src/plugins/defaults/memory/{v3/substrate → substrate}/cli-command-store.ts +13 -8
  464. package/src/plugins/defaults/memory/{v3/substrate → substrate}/consolidation-job.ts +51 -27
  465. package/src/plugins/defaults/memory/{v3/substrate → substrate}/constants.ts +1 -0
  466. package/src/plugins/defaults/memory/{v3/substrate → substrate}/edge-index.ts +28 -9
  467. package/src/plugins/defaults/memory/{v3/substrate → substrate}/frontmatter-sweep.ts +14 -7
  468. package/src/plugins/defaults/memory/{v3/substrate → substrate}/injected-block-slugs.ts +9 -3
  469. package/src/plugins/defaults/memory/{v3/substrate → substrate}/page-index.ts +29 -10
  470. package/src/plugins/defaults/memory/{v3/substrate → substrate}/page-store.ts +35 -12
  471. package/src/plugins/defaults/memory/{v3/substrate → substrate}/prompts/consolidation.ts +14 -8
  472. package/src/plugins/defaults/memory/{v3/substrate → substrate}/prompts/sweep.ts +4 -1
  473. package/src/plugins/defaults/memory/{v3/substrate → substrate}/qdrant.ts +96 -36
  474. package/src/plugins/defaults/memory/substrate/reembed-job.ts +54 -0
  475. package/src/plugins/defaults/memory/{v3/substrate → substrate}/sim.ts +26 -15
  476. package/src/plugins/defaults/memory/{v3/substrate → substrate}/skill-content.ts +1 -1
  477. package/src/plugins/defaults/memory/{v3/substrate → substrate}/skill-store.ts +13 -8
  478. package/src/plugins/defaults/memory/{v3/substrate → substrate}/sparse-bm25.ts +27 -10
  479. package/src/plugins/defaults/memory/substrate/spread.ts +165 -0
  480. package/src/plugins/defaults/memory/{v3/substrate → substrate}/static-context.ts +12 -7
  481. package/src/plugins/defaults/memory/{v3/substrate → substrate}/sweep-job.ts +20 -15
  482. package/src/plugins/defaults/memory/substrate/tuning.ts +93 -0
  483. package/src/plugins/defaults/memory/{v3/substrate → substrate}/types.ts +7 -4
  484. package/src/plugins/defaults/memory/tools.test.ts +1 -1
  485. package/src/plugins/defaults/memory/tools.ts +1 -1
  486. package/src/plugins/defaults/memory/v1/README.md +5 -0
  487. package/src/plugins/defaults/memory/{__tests__ → v1/__tests__}/filing-jobs.test.ts +4 -4
  488. package/src/plugins/defaults/memory/{filing-jobs.ts → v1/filing-jobs.ts} +3 -3
  489. package/src/plugins/defaults/memory/{graph → v1/graph}/bootstrap.test.ts +68 -6
  490. package/src/plugins/defaults/memory/{graph → v1/graph}/bootstrap.ts +40 -21
  491. package/src/plugins/defaults/memory/{graph → v1/graph}/consolidation.ts +14 -14
  492. package/src/plugins/defaults/memory/{graph → v1/graph}/decay.test.ts +1 -1
  493. package/src/plugins/defaults/memory/{graph → v1/graph}/decay.ts +3 -3
  494. package/src/plugins/defaults/memory/{graph → v1/graph}/extraction-job.ts +5 -5
  495. package/src/plugins/defaults/memory/{graph → v1/graph}/extraction.test.ts +1 -1
  496. package/src/plugins/defaults/memory/{graph → v1/graph}/extraction.ts +20 -14
  497. package/src/plugins/defaults/memory/{graph → v1/graph}/graph-search.test.ts +3 -3
  498. package/src/plugins/defaults/memory/v1/graph/graph-search.ts +123 -0
  499. package/src/plugins/defaults/memory/{graph → v1/graph}/injection.test.ts +1 -118
  500. package/src/plugins/defaults/memory/{graph → v1/graph}/injection.ts +9 -111
  501. package/src/plugins/defaults/memory/{graph → v1/graph}/narrative.ts +6 -6
  502. package/src/plugins/defaults/memory/{graph → v1/graph}/pattern-scan.ts +5 -5
  503. package/src/plugins/defaults/memory/{graph → v1/graph}/retriever.test.ts +135 -42
  504. package/src/plugins/defaults/memory/{graph → v1/graph}/retriever.ts +40 -22
  505. package/src/plugins/defaults/memory/{graph → v1/graph}/scoring.test.ts +1 -1
  506. package/src/plugins/defaults/memory/{graph → v1/graph}/scoring.ts +1 -1
  507. package/src/plugins/defaults/memory/{graph → v1/graph}/serendipity.ts +1 -1
  508. package/src/plugins/defaults/memory/{graph → v1/graph}/triggers.test.ts +1 -1
  509. package/src/plugins/defaults/memory/{graph → v1/graph}/triggers.ts +1 -1
  510. package/src/plugins/defaults/memory/{identity-context.ts → v1/identity-context.ts} +4 -4
  511. package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/backfill.ts +6 -6
  512. package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/embedding.test.ts +6 -6
  513. package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/embedding.ts +6 -6
  514. package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/index-maintenance.ts +8 -8
  515. package/src/plugins/defaults/memory/{jobs → v1/jobs}/embed-pkb-file.test.ts +7 -7
  516. package/src/plugins/defaults/memory/{jobs → v1/jobs}/embed-pkb-file.ts +5 -5
  517. package/src/plugins/defaults/memory/{pkb → v1/pkb}/autoinject.ts +1 -1
  518. package/src/plugins/defaults/memory/{pkb → v1/pkb}/context.ts +2 -2
  519. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-index.test.ts +3 -3
  520. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-index.ts +2 -2
  521. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-reconcile.test.ts +3 -3
  522. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-reconcile.ts +2 -2
  523. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-search.test.ts +3 -3
  524. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-search.ts +6 -6
  525. package/src/plugins/defaults/memory/{pkb → v1/pkb}/types.ts +3 -5
  526. package/src/plugins/defaults/memory/{pkb-schedule.ts → v1/pkb-schedule.ts} +2 -2
  527. package/src/plugins/defaults/memory/{search/semantic.ts → v1/semantic-search.ts} +1 -1
  528. package/src/plugins/defaults/memory/v2/__tests__/activation-store.test.ts +1 -1
  529. package/src/plugins/defaults/memory/v2/__tests__/activation.test.ts +11 -274
  530. package/src/plugins/defaults/memory/v2/__tests__/backfill-jobs.test.ts +9 -131
  531. package/src/plugins/defaults/memory/v2/__tests__/harness-compare.test.ts +1 -1
  532. package/src/plugins/defaults/memory/v2/__tests__/harness-oracle.test.ts +1 -1
  533. package/src/plugins/defaults/memory/v2/__tests__/harness-replay-input.test.ts +1 -1
  534. package/src/plugins/defaults/memory/v2/__tests__/injection.test.ts +14 -10
  535. package/src/plugins/defaults/memory/v2/__tests__/reranker.test.ts +7 -5
  536. package/src/plugins/defaults/memory/v2/__tests__/router.test.ts +12 -6
  537. package/src/plugins/defaults/memory/{memory-v2-activation-log-store.ts → v2/activation-log-store.ts} +2 -2
  538. package/src/plugins/defaults/memory/v2/activation-store.ts +22 -8
  539. package/src/plugins/defaults/memory/v2/activation.ts +30 -163
  540. package/src/plugins/defaults/memory/v2/backfill-jobs.ts +7 -54
  541. package/src/plugins/defaults/memory/{memory-v2-concept-frequency.ts → v2/concept-frequency.ts} +3 -3
  542. package/src/plugins/defaults/memory/v2/harness/oracle.ts +1 -1
  543. package/src/plugins/defaults/memory/v2/harness/replay-input.ts +2 -2
  544. package/src/plugins/defaults/memory/v2/harness/retriever.ts +1 -1
  545. package/src/plugins/defaults/memory/v2/injection.ts +36 -26
  546. package/src/plugins/defaults/memory/v2/migration.ts +2 -2
  547. package/src/plugins/defaults/memory/{rerank-local.ts → v2/rerank-local.ts} +44 -18
  548. package/src/plugins/defaults/memory/v2/reranker.ts +29 -11
  549. package/src/plugins/defaults/memory/v2/router.ts +38 -15
  550. package/src/plugins/defaults/memory/v3/__tests__/candidate-match.test.ts +5 -3
  551. package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +21 -8
  552. package/src/plugins/defaults/memory/v3/__tests__/edge.test.ts +1 -1
  553. package/src/plugins/defaults/memory/v3/__tests__/live-integration.test.ts +1 -1
  554. package/src/plugins/defaults/memory/v3/__tests__/maintain-job.test.ts +4 -1
  555. package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +181 -3
  556. package/src/plugins/defaults/memory/v3/__tests__/selection-log-store.test.ts +3 -0
  557. package/src/plugins/defaults/memory/v3/__tests__/shadow-integration.test.ts +14 -5
  558. package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +40 -50
  559. package/src/plugins/defaults/memory/v3/__tests__/tuning-profile.test.ts +1 -0
  560. package/src/plugins/defaults/memory/v3/candidate-match.ts +2 -2
  561. package/src/plugins/defaults/memory/v3/capabilities.ts +6 -4
  562. package/src/plugins/defaults/memory/v3/card.ts +25 -9
  563. package/src/plugins/defaults/memory/v3/edge.ts +52 -18
  564. package/src/plugins/defaults/memory/v3/gate.ts +4 -4
  565. package/src/plugins/defaults/memory/v3/injector.ts +10 -3
  566. package/src/plugins/defaults/memory/v3/maintain-job.ts +3 -3
  567. package/src/plugins/defaults/memory/v3/orchestrate.ts +100 -18
  568. package/src/plugins/defaults/memory/v3/page-content.ts +26 -10
  569. package/src/plugins/defaults/memory/v3/prune.ts +40 -16
  570. package/src/plugins/defaults/memory/v3/selection-log-store.ts +34 -12
  571. package/src/plugins/defaults/memory/v3/shadow-plugin.ts +9 -13
  572. package/src/plugins/defaults/memory/v3/span-query.test.ts +86 -0
  573. package/src/plugins/defaults/memory/v3/span-query.ts +71 -0
  574. package/src/plugins/defaults/memory/v3/tuning-profile.ts +3 -0
  575. package/src/plugins/defaults/memory/v3/types.ts +4 -1
  576. package/src/plugins/defaults/memory/v3-eval/eval-packets.ts +2 -2
  577. package/src/plugins/defaults/memory/validation.ts +1 -1
  578. package/src/plugins/defaults/memory/worker.ts +2 -1
  579. package/src/plugins/defaults/platform-hosted/__tests__/reengage.test.ts +104 -12
  580. package/src/plugins/defaults/platform-hosted/routes/reengage.ts +104 -12
  581. package/src/plugins/types.ts +2 -2
  582. package/src/providers/__tests__/registry-native-web-search.test.ts +47 -2
  583. package/src/providers/anthropic/client.ts +15 -6
  584. package/src/providers/content-block-schema.ts +26 -0
  585. package/src/providers/inference/__tests__/connections-credential-normalize.test.ts +87 -0
  586. package/src/providers/inference/adapter-factory.ts +6 -0
  587. package/src/providers/inference/connections.ts +30 -14
  588. package/src/providers/model-catalog.ts +77 -0
  589. package/src/providers/openai/__tests__/chat-completions-input-audio.test.ts +260 -0
  590. package/src/providers/openai/chat-completions-provider.ts +65 -17
  591. package/src/providers/openai/input-audio.ts +76 -0
  592. package/src/providers/openrouter/client.ts +0 -2
  593. package/src/providers/platform-proxy/constants.ts +4 -0
  594. package/src/providers/poolside/client.ts +42 -0
  595. package/src/providers/registry.ts +40 -8
  596. package/src/providers/retry.ts +2 -0
  597. package/src/providers/types.ts +39 -1
  598. package/src/providers/vercel-ai-gateway/client.ts +0 -2
  599. package/src/runtime/AGENTS.md +7 -5
  600. package/src/runtime/__tests__/question-request-guardian-bridge.test.ts +173 -0
  601. package/src/runtime/__tests__/question-resolution.test.ts +111 -0
  602. package/src/runtime/access-request-helper.ts +7 -15
  603. package/src/runtime/assistant-event-hub.ts +43 -31
  604. package/src/runtime/assistant-event-publish-options.ts +31 -0
  605. package/src/runtime/assistant-event.ts +19 -30
  606. package/src/runtime/assistant-stream-state.ts +4 -4
  607. package/src/runtime/channel-approvals.ts +0 -25
  608. package/src/runtime/channel-readiness-service.ts +99 -40
  609. package/src/runtime/channel-retry-sweep.ts +38 -15
  610. package/src/runtime/confirmation-request-guardian-bridge.ts +4 -0
  611. package/src/runtime/guardian-reply-router.ts +108 -0
  612. package/src/runtime/http-server.ts +8 -0
  613. package/src/runtime/http-types.ts +2 -2
  614. package/src/runtime/process-role.ts +42 -0
  615. package/src/runtime/question-request-guardian-bridge.ts +184 -0
  616. package/src/runtime/question-resolution.ts +153 -0
  617. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +6 -2
  618. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +1 -1
  619. package/src/runtime/routes/acp-routes.ts +2 -2
  620. package/src/runtime/routes/bookmark-routes.ts +3 -15
  621. package/src/runtime/routes/canned-message-complete.ts +2 -2
  622. package/src/runtime/routes/consolidation-routes.ts +8 -2
  623. package/src/runtime/routes/conversation-list-routes.ts +3 -19
  624. package/src/runtime/routes/conversation-management-routes.ts +1 -5
  625. package/src/runtime/routes/conversation-query-routes.ts +52 -8
  626. package/src/runtime/routes/conversation-routes.ts +36 -22
  627. package/src/runtime/routes/credential-request-routes.ts +0 -1
  628. package/src/runtime/routes/filing-routes.ts +7 -7
  629. package/src/runtime/routes/global-search-routes.ts +1 -1
  630. package/src/runtime/routes/guardian-approval-prompt.ts +2 -2
  631. package/src/runtime/routes/image-generation-routes.ts +12 -9
  632. package/src/runtime/routes/inbound-message-handler.ts +17 -0
  633. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +50 -0
  634. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +19 -0
  635. package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -4
  636. package/src/runtime/routes/inbound-stages/inbound-content-prep.test.ts +129 -0
  637. package/src/runtime/routes/inbound-stages/inbound-content-prep.ts +141 -9
  638. package/src/runtime/routes/index.ts +2 -0
  639. package/src/runtime/routes/lifecycle-routes.ts +199 -0
  640. package/src/runtime/routes/platform-routes.ts +3 -8
  641. package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +7 -7
  642. package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +5 -5
  643. package/src/runtime/routes/question-routes.ts +34 -87
  644. package/src/runtime/routes/secret-routes.ts +11 -1
  645. package/src/runtime/routes/settings-routes.ts +8 -18
  646. package/src/runtime/routes/upgrade-broadcast-routes.ts +4 -5
  647. package/src/runtime/routes/workspace-routes.test.ts +7 -4
  648. package/src/runtime/slack-reply-session.test.ts +12 -12
  649. package/src/runtime/slack-reply-session.ts +17 -17
  650. package/src/runtime/sync/sync-publisher.test.ts +7 -5
  651. package/src/runtime/tool-grant-request-helper.ts +4 -0
  652. package/src/schedule/schedule-store.ts +70 -0
  653. package/src/schedule/scheduler.ts +27 -0
  654. package/src/security/AGENTS.md +1 -1
  655. package/src/security/credential-key.ts +17 -0
  656. package/src/security/secret-ingress.ts +14 -105
  657. package/src/security/secret-patterns.ts +8 -139
  658. package/src/security/secret-scanner.ts +8 -3
  659. package/src/security/store-path-override.ts +6 -16
  660. package/src/sequence/store.ts +8 -0
  661. package/src/signals/emit-event.ts +5 -10
  662. package/src/signals/event-stream.ts +20 -10
  663. package/src/subagent/manager.ts +76 -25
  664. package/src/subagent/notify.ts +8 -0
  665. package/src/subagent/types.ts +13 -3
  666. package/src/telegram/__tests__/webhook-health.test.ts +442 -0
  667. package/src/telegram/webhook-health.ts +478 -0
  668. package/src/telemetry/AGENTS.md +6 -0
  669. package/src/telemetry/memory-corpus-size.test.ts +129 -0
  670. package/src/telemetry/memory-corpus-size.ts +184 -0
  671. package/src/telemetry/memory-tier-reporter.test.ts +67 -2
  672. package/src/telemetry/memory-tier-reporter.ts +30 -3
  673. package/src/tools/__tests__/document-tool-input-schemas.test.ts +103 -0
  674. package/src/tools/__tests__/followup-call-acp-tool-input-schemas.test.ts +125 -0
  675. package/src/tools/__tests__/schedule-tool-input-schemas.test.ts +83 -0
  676. package/src/tools/__tests__/subagent-workflow-tool-input-schemas.test.ts +116 -0
  677. package/src/tools/__tests__/tool-input-schemas.test.ts +192 -0
  678. package/src/tools/__tests__/tool-schema-drift-harness.ts +142 -0
  679. package/src/tools/acp/abort.ts +21 -1
  680. package/src/tools/acp/context.ts +5 -5
  681. package/src/tools/acp/spawn.test.ts +15 -5
  682. package/src/tools/acp/spawn.ts +26 -3
  683. package/src/tools/acp/status.ts +20 -1
  684. package/src/tools/acp/steer.test.ts +20 -0
  685. package/src/tools/acp/steer.ts +23 -2
  686. package/src/tools/ask-question/ask-question-tool.test.ts +65 -0
  687. package/src/tools/ask-question/ask-question-tool.ts +68 -92
  688. package/src/tools/browser/browser-screencast.ts +6 -6
  689. package/src/tools/calls/call-end.ts +24 -3
  690. package/src/tools/calls/call-start.ts +35 -11
  691. package/src/tools/calls/call-status.ts +20 -1
  692. package/src/tools/document/document-comment-tool.test.ts +49 -0
  693. package/src/tools/document/document-comment-tool.ts +45 -6
  694. package/src/tools/document/document-tool.ts +142 -24
  695. package/src/tools/executor.ts +27 -13
  696. package/src/tools/filesystem/edit.ts +62 -60
  697. package/src/tools/filesystem/list.ts +36 -29
  698. package/src/tools/filesystem/read.ts +56 -39
  699. package/src/tools/filesystem/write.ts +44 -38
  700. package/src/tools/followups/followup_create.ts +41 -12
  701. package/src/tools/followups/followup_list.ts +34 -6
  702. package/src/tools/followups/followup_resolve.ts +26 -4
  703. package/src/tools/host-filesystem/edit.ts +50 -60
  704. package/src/tools/host-filesystem/read.ts +45 -39
  705. package/src/tools/host-filesystem/write.ts +31 -36
  706. package/src/tools/host-terminal/host-shell.ts +76 -62
  707. package/src/tools/policy-context.ts +27 -10
  708. package/src/tools/schedule/create.ts +76 -33
  709. package/src/tools/schedule/delete.ts +21 -2
  710. package/src/tools/schedule/list.ts +25 -3
  711. package/src/tools/schedule/update.ts +105 -48
  712. package/src/tools/shared/filesystem/path-policy.ts +246 -40
  713. package/src/tools/shared/zod-tool-schema.ts +117 -0
  714. package/src/tools/subagent/abort.ts +12 -4
  715. package/src/tools/subagent/consult-deadline.ts +9 -3
  716. package/src/tools/subagent/message.ts +21 -5
  717. package/src/tools/subagent/notify-parent.ts +44 -23
  718. package/src/tools/subagent/read.ts +15 -4
  719. package/src/tools/subagent/resolve.ts +26 -4
  720. package/src/tools/subagent/spawn.ts +37 -13
  721. package/src/tools/subagent/status.ts +12 -4
  722. package/src/tools/system/request-permission.ts +35 -26
  723. package/src/tools/terminal/shell.ts +68 -55
  724. package/src/tools/tool-approval-handler.ts +327 -53
  725. package/src/tools/tool-input-schemas.ts +85 -0
  726. package/src/tools/tool-types.ts +7 -0
  727. package/src/tools/types.ts +8 -0
  728. package/src/tools/workflows/manage-workflows.ts +30 -2
  729. package/src/tools/workflows/run-workflow.test.ts +54 -2
  730. package/src/tools/workflows/run-workflow.ts +32 -4
  731. package/src/util/fs-symlinks.ts +30 -0
  732. package/src/util/log-redact.ts +7 -3
  733. package/src/vellum-assistant-namespace.d.ts +80 -0
  734. package/src/watcher/watcher-store.ts +8 -0
  735. package/src/workflows/leaf-runner.test.ts +104 -2
  736. package/src/workflows/leaf-runner.ts +31 -6
  737. package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +2 -2
  738. package/src/workspace/migrations/134-image-generation-mode-to-provider.ts +128 -0
  739. package/src/workspace/migrations/135-copy-substrate-tunables.ts +248 -0
  740. package/src/workspace/migrations/__tests__/135-copy-substrate-tunables.test.ts +446 -0
  741. package/src/workspace/migrations/__tests__/backfill-v3-leaves.test.ts +2 -2
  742. package/src/workspace/migrations/registry.ts +4 -0
  743. package/src/__tests__/memory-retrieval-budget.test.ts +0 -49
  744. package/src/__tests__/secret-patterns.test.ts +0 -27
  745. package/src/config/__tests__/proc-to-skills.test.ts +0 -21
  746. package/src/config/memory-tier.test.ts +0 -44
  747. package/src/daemon/message-types/acp.ts +0 -20
  748. package/src/daemon/message-types/apps.ts +0 -11
  749. package/src/daemon/message-types/background-tools.ts +0 -14
  750. package/src/daemon/message-types/bookmarks.ts +0 -13
  751. package/src/daemon/message-types/contacts.ts +0 -13
  752. package/src/daemon/message-types/document-comments.ts +0 -14
  753. package/src/daemon/message-types/documents.ts +0 -13
  754. package/src/daemon/message-types/home.ts +0 -15
  755. package/src/daemon/message-types/host-bash.ts +0 -12
  756. package/src/daemon/message-types/host-cu.ts +0 -10
  757. package/src/daemon/message-types/host-file.ts +0 -12
  758. package/src/daemon/message-types/host-transfer.ts +0 -12
  759. package/src/daemon/message-types/integrations.ts +0 -90
  760. package/src/daemon/message-types/memory.ts +0 -10
  761. package/src/daemon/message-types/schedules.ts +0 -14
  762. package/src/daemon/message-types/settings.ts +0 -17
  763. package/src/daemon/message-types/subagents.ts +0 -63
  764. package/src/daemon/message-types/upgrades.ts +0 -14
  765. package/src/daemon/message-types/workflows.ts +0 -25
  766. package/src/daemon/message-types/workspace.ts +0 -137
  767. package/src/live-voice/ack-phrases.ts +0 -58
  768. package/src/plugins/defaults/memory/retrieval-budget.ts +0 -29
  769. package/src/plugins/defaults/memory/v3/__tests__/gate-flag.test.ts +0 -69
  770. package/src/plugins/defaults/memory/v3/gate-flag.ts +0 -20
  771. package/src/plugins/defaults/memory/v3/substrate/__tests__/memory-v2-startup.test.ts +0 -86
  772. package/src/plugins/defaults/memory/v3/substrate/memory-v2-startup.test.ts +0 -205
  773. /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/concept-page-frontmatter-schema.test.ts +0 -0
  774. /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/consolidation-prompt-flag-gating-guard.test.ts +0 -0
  775. /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/injected-block-slugs.test.ts +0 -0
  776. /package/src/plugins/defaults/memory/{v3/substrate → substrate}/cli-command-content.ts +0 -0
@@ -27,7 +27,9 @@ mock.module("../../daemon/conversation-registry.js", () => ({
27
27
  let lastStartArgs: Record<string, unknown> | null = null;
28
28
  let startThrows: Error | null = null;
29
29
  const startMock = mock((opts: Record<string, unknown>) => {
30
- if (startThrows) throw startThrows;
30
+ if (startThrows) {
31
+ throw startThrows;
32
+ }
31
33
  lastStartArgs = opts;
32
34
  return { runId: "run-123" };
33
35
  });
@@ -36,7 +38,9 @@ const abortMock = mock(() => {});
36
38
  const listMock = mock(() => [] as unknown[]);
37
39
  let resumeThrows: Error | null = null;
38
40
  const resumeMock = mock((runId: string) => {
39
- if (resumeThrows) throw resumeThrows;
41
+ if (resumeThrows) {
42
+ throw resumeThrows;
43
+ }
40
44
  return { runId };
41
45
  });
42
46
 
@@ -421,3 +425,51 @@ describe("manage_workflows", () => {
421
425
  expect(abortMock).toHaveBeenCalledWith("mine");
422
426
  });
423
427
  });
428
+
429
+ // ── model-input schema validation (LUM-2855) ────────────────────────
430
+
431
+ describe("workflow tools — model-input schema validation", () => {
432
+ test("run_workflow rejects a non-string script", async () => {
433
+ const result = await executeRunWorkflow({ script: 42 }, makeContext());
434
+ expect(result.isError).toBe(true);
435
+ expect(result.content).toContain('Invalid input for tool "run_workflow"');
436
+ expect(result.content).toContain("script");
437
+ expect(startMock).not.toHaveBeenCalled();
438
+ });
439
+
440
+ test("run_workflow treats explicit null script/name as omitted (bespoke exactly-one error)", async () => {
441
+ const result = await executeRunWorkflow(
442
+ { script: null, name: null },
443
+ makeContext(),
444
+ );
445
+ expect(result.isError).toBe(true);
446
+ expect(result.content).toContain("exactly one");
447
+ });
448
+
449
+ test("run_workflow passes args through unvalidated (workflow runtime accepts any JSON)", async () => {
450
+ const result = await executeRunWorkflow(
451
+ { script: "export const meta = {}", args: ["positional"] },
452
+ makeContext(),
453
+ );
454
+ expect(result.isError).toBe(false);
455
+ expect(lastStartArgs?.args).toEqual(["positional"]);
456
+ });
457
+
458
+ test("manage_workflows rejects a non-string run_id", async () => {
459
+ const result = await executeManageWorkflows(
460
+ { action: "status", run_id: 42 },
461
+ makeContext(),
462
+ );
463
+ expect(result.isError).toBe(true);
464
+ expect(result.content).toContain(
465
+ 'Invalid input for tool "manage_workflows"',
466
+ );
467
+ expect(result.content).toContain("run_id");
468
+ });
469
+
470
+ test("manage_workflows keeps the bespoke unknown-action error", async () => {
471
+ const result = await executeManageWorkflows({ action: 42 }, makeContext());
472
+ expect(result.isError).toBe(true);
473
+ expect(result.content).toContain("Unknown action");
474
+ });
475
+ });
@@ -15,13 +15,37 @@
15
15
  * of truth the model reads when generating the `script`.
16
16
  */
17
17
 
18
+ import { z } from "zod";
19
+
18
20
  import { findConversation } from "../../daemon/conversation-registry.js";
19
21
  import { FALLBACK_TURN_TRUST } from "../../daemon/trust-context.js";
20
22
  import type { TrustContext } from "../../daemon/trust-context-types.js";
21
23
  import { CapabilityManifestSchema } from "../../workflows/capabilities.js";
22
24
  import { getWorkflowRunManager } from "../../workflows/run-manager.js";
25
+ import {
26
+ invalidToolInputResult,
27
+ nullAsOmitted,
28
+ } from "../shared/zod-tool-schema.js";
23
29
  import type { ToolContext, ToolExecutionResult } from "../types.js";
24
30
 
31
+ /**
32
+ * Model-input schema, `safeParse`d at the top of {@link executeRunWorkflow}.
33
+ * Same in-tool pattern and TOOLS.json drift guard as the other bundled-skill
34
+ * tools — see the schema block in `tools/document/document-tool.ts` for the
35
+ * framework.
36
+ *
37
+ * `args` (the workflow runtime accepts any JSON value) and `capabilities`
38
+ * (`CapabilityManifestSchema` is the single validation authority, and
39
+ * `executor.ts` reads it pre-execution for the requireFreshApproval
40
+ * promotion) are deliberately UNDECLARED — loose passthrough. The
41
+ * exactly-one-of script/name rule stays a bespoke check below.
42
+ */
43
+ export const runWorkflowInputSchema = z.looseObject({
44
+ script: nullAsOmitted(z.string()),
45
+ name: nullAsOmitted(z.string()),
46
+ label: nullAsOmitted(z.string()),
47
+ });
48
+
25
49
  /**
26
50
  * Resolve the {@link TrustContext} to forward to the run's leaves. Prefer the
27
51
  * originating conversation's per-turn snapshot (the same context the live turn
@@ -33,7 +57,9 @@ function resolveTrustContext(context: ToolContext): TrustContext {
33
57
  const conversation = findConversation(context.conversationId);
34
58
  const fromConversation =
35
59
  conversation?.currentTurnTrustContext ?? conversation?.trustContext;
36
- if (fromConversation) return fromConversation;
60
+ if (fromConversation) {
61
+ return fromConversation;
62
+ }
37
63
  return { ...FALLBACK_TURN_TRUST, trustClass: context.trustClass };
38
64
  }
39
65
 
@@ -41,8 +67,11 @@ export async function executeRunWorkflow(
41
67
  input: Record<string, unknown>,
42
68
  context: ToolContext,
43
69
  ): Promise<ToolExecutionResult> {
44
- const script = input.script as string | undefined;
45
- const name = input.name as string | undefined;
70
+ const parsedInput = runWorkflowInputSchema.safeParse(input);
71
+ if (!parsedInput.success) {
72
+ return invalidToolInputResult("run_workflow", parsedInput.error);
73
+ }
74
+ const { script, name, label } = parsedInput.data;
46
75
 
47
76
  // Exactly one of script/name is required.
48
77
  if ((script == null) === (name == null)) {
@@ -54,7 +83,6 @@ export async function executeRunWorkflow(
54
83
  }
55
84
 
56
85
  const args = (input.args as Record<string, unknown> | undefined) ?? {};
57
- const label = input.label as string | undefined;
58
86
  const trustContext = resolveTrustContext(context);
59
87
 
60
88
  try {
@@ -0,0 +1,30 @@
1
+ import { lstatSync, readlinkSync } from "node:fs";
2
+ import { dirname, resolve } from "node:path";
3
+
4
+ /**
5
+ * Follow a trailing symlink chain manually so a DANGLING link reports its
6
+ * destination. `realpathSync` throws on a link whose destination does not
7
+ * exist, which makes canonicalization fall back to the benign link path —
8
+ * but a write through the link creates the destination, so containment and
9
+ * security checks must see it. The bound sits above every supported
10
+ * platform's own traversal limit (Linux follows at most 40 links per
11
+ * resolution, macOS 32), so any chain this loop cannot exhaust is one the
12
+ * filesystem itself refuses to follow (ELOOP) — the eventual operation
13
+ * fails rather than writing through an unchecked destination.
14
+ */
15
+ export function resolveTrailingLinkTarget(path: string): string {
16
+ let current = path;
17
+ for (let depth = 0; depth < 64; depth++) {
18
+ let linkTarget: string;
19
+ try {
20
+ if (!lstatSync(current).isSymbolicLink()) {
21
+ return current;
22
+ }
23
+ linkTarget = readlinkSync(current);
24
+ } catch {
25
+ return current;
26
+ }
27
+ current = resolve(dirname(current), linkTarget);
28
+ }
29
+ return current;
30
+ }
@@ -11,15 +11,19 @@
11
11
  */
12
12
 
13
13
  import { memoizePluginPatternDerivation } from "../security/plugin-secret-patterns.js";
14
- import { PREFIX_PATTERNS } from "../security/secret-patterns.js";
14
+ import { REDACTION_PREFIX_PATTERNS } from "../security/secret-patterns.js";
15
15
 
16
16
  // ---------------------------------------------------------------------------
17
- // Sensitive-value patterns (derived from shared PREFIX_PATTERNS)
17
+ // Sensitive-value patterns (derived from shared REDACTION_PREFIX_PATTERNS)
18
18
  // ---------------------------------------------------------------------------
19
19
 
20
20
  const BEARER_RE = /Bearer [A-Za-z0-9._\-]+/g;
21
21
 
22
- const STATIC_API_KEY_PATTERNS: RegExp[] = PREFIX_PATTERNS.map(
22
+ // This serializer redacts by replacing the matched span in place, so it uses
23
+ // the bounded whole-block private-key matcher (via REDACTION_PREFIX_PATTERNS):
24
+ // the match must cover header → body → footer or the key body would survive
25
+ // redaction. The body bound keeps it O(n) on large serialized strings.
26
+ const STATIC_API_KEY_PATTERNS: RegExp[] = REDACTION_PREFIX_PATTERNS.map(
23
27
  (p) => new RegExp(p.regex.source, "g"),
24
28
  );
25
29
 
@@ -0,0 +1,80 @@
1
+ /**
2
+ * The single shape of `globalThis.vellumAssistant` — the per-process namespace
3
+ * that holds the assistant's process-global singletons.
4
+ *
5
+ * Several modules keep process-global state on `globalThis.vellumAssistant.*`
6
+ * (see the slots below). Each such slot is read/written by a production module
7
+ * AND, independently, by a test helper in `src/__tests__/` that must NOT import
8
+ * that production module (importing it would run its load-time side effects
9
+ * before the test preload establishes the per-process workspace override — the
10
+ * coupling behind the May 2026 DB-ghost incidents). This file is how both sides
11
+ * agree on the shape without a runtime import between them.
12
+ *
13
+ * It is an **ambient** declaration (no top-level `import`/`export`), so
14
+ * `VellumAssistantNamespace`, the slot types, and the `vellumAssistant` binding
15
+ * are global — every module and test helper refers to them by name with zero
16
+ * imports, and nothing here reaches into a `src/` module even at the type
17
+ * level. Referring to these types therefore never adds anything to any file's
18
+ * runtime import graph, so the test-machinery isolation invariant holds.
19
+ *
20
+ * Adding a slot: declare its value type here, add the optional property to
21
+ * `VellumAssistantNamespace`, and have the owning module + its test helper
22
+ * reference these globals instead of declaring their own copies.
23
+ */
24
+
25
+ /** Slot value: the encrypted credential store path override. Managed by `security/store-path-override.ts`. */
26
+ interface VellumStorePathOverride {
27
+ storePath: string | null;
28
+ storeKeyPath: string | null;
29
+ }
30
+
31
+ /** Which assistant DB connection a singleton slot holds. */
32
+ type VellumDbSlotKey =
33
+ | "main"
34
+ | "main-readonly"
35
+ | "logs"
36
+ | "memory"
37
+ | "telemetry";
38
+
39
+ /**
40
+ * Slot value: one lazily-opened DB connection and the closer that drops it.
41
+ * `db` is `unknown` so this shape never has to name a Drizzle type; callers in
42
+ * `persistence/db-connection.ts` narrow it via `getStoredDb<T>()`.
43
+ */
44
+ interface VellumDbSlot {
45
+ db: unknown;
46
+ closer: (() => void) | null;
47
+ }
48
+
49
+ /** Slot value: the assistant DB connection singletons, keyed by connection. Managed by `persistence/db-singleton.ts`. */
50
+ type VellumDbSlots = Record<VellumDbSlotKey, VellumDbSlot>;
51
+
52
+ /** Slot value: the resolved feature-flag override cache. Managed by `config/feature-flag-cache.ts`. */
53
+ interface VellumFeatureFlagCache {
54
+ overrides: Record<string, boolean | string> | null;
55
+ fromGateway: boolean;
56
+ }
57
+
58
+ /** The per-process `globalThis.vellumAssistant` namespace. */
59
+ interface VellumAssistantNamespace {
60
+ /**
61
+ * Whether this OS process is the main assistant daemon. Set once by the
62
+ * daemon entrypoint; absent elsewhere. See `runtime/process-role.ts`.
63
+ */
64
+ mainDaemonProcess?: boolean;
65
+ /** See `security/store-path-override.ts`. */
66
+ storePathOverride?: VellumStorePathOverride;
67
+ /** See `persistence/db-singleton.ts`. */
68
+ dbSingletons?: VellumDbSlots;
69
+ /** See `config/feature-flag-cache.ts`. */
70
+ featureFlagCache?: VellumFeatureFlagCache;
71
+ }
72
+
73
+ /**
74
+ * Types `globalThis.vellumAssistant`. Undefined until the first slot accessor
75
+ * seeds it (`globalThis.vellumAssistant ??= {}`). Must be `var`: only `var`
76
+ * declarations at global scope become typed properties of `globalThis`
77
+ * (`let`/`const` do not), so this is the one idiomatic way to type the binding.
78
+ */
79
+ // eslint-disable-next-line no-var
80
+ declare var vellumAssistant: VellumAssistantNamespace | undefined;
@@ -2,6 +2,7 @@ import { and, asc, desc, eq, gte, lte } from "drizzle-orm";
2
2
  import { v4 as uuid } from "uuid";
3
3
 
4
4
  import { getDb } from "../persistence/db-connection.js";
5
+ import { isLifecycleQuiesced } from "../persistence/lifecycle-quiesce.js";
5
6
  import { rawChanges } from "../persistence/raw-query.js";
6
7
  import { watcherEvents, watchers } from "../persistence/schema/index.js";
7
8
  import { truncate } from "../util/truncate.js";
@@ -158,6 +159,13 @@ export function deleteWatcher(id: string): boolean {
158
159
  * to 'polling' using optimistic locking on the current nextPollAt.
159
160
  */
160
161
  export function claimDueWatchers(now: number): Watcher[] {
162
+ // Drain gate: while a quiesce lease is active, claim nothing — a watcher
163
+ // poll runs provider requests that create no row the drain snapshot can
164
+ // see, so it must not start at all. Fail-open via the lease read.
165
+ if (isLifecycleQuiesced()) {
166
+ return [];
167
+ }
168
+
161
169
  const db = getDb();
162
170
  const candidates = db
163
171
  .select()
@@ -472,6 +472,105 @@ describe("runLeaf — tool path", () => {
472
472
  expect(countConversations()).toBe(before);
473
473
  });
474
474
 
475
+ test("rejects out-of-workspace paths for sandbox file tools", async () => {
476
+ // Leaf tool calls bypass the ToolExecutor permission lane, so the file
477
+ // tools' out-of-workspace host fallback must be unreachable from a leaf.
478
+ const calls: Array<Record<string, unknown>> = [];
479
+ const fileRead: Tool = {
480
+ name: "file_read",
481
+ description: "Tool file_read",
482
+ category: "filesystem",
483
+ defaultRiskLevel: "low" as never,
484
+ executionTarget: "sandbox",
485
+ input_schema: { type: "object", properties: {}, required: [] },
486
+ async execute(
487
+ input: Record<string, unknown>,
488
+ ): Promise<ToolExecutionResult> {
489
+ calls.push(input);
490
+ return { content: "read ok", isError: false };
491
+ },
492
+ };
493
+
494
+ responseQueue = [
495
+ {
496
+ content: [
497
+ {
498
+ type: "tool_use",
499
+ name: "file_read",
500
+ id: "tu-1",
501
+ input: { path: "/etc/hosts" },
502
+ },
503
+ ],
504
+ model: "test",
505
+ usage: { inputTokens: 5, outputTokens: 2 },
506
+ stopReason: "tool_use",
507
+ },
508
+ {
509
+ content: [{ type: "text", text: "done" }],
510
+ model: "test",
511
+ usage: { inputTokens: 2, outputTokens: 1 },
512
+ stopReason: "end_turn",
513
+ },
514
+ ];
515
+
516
+ const result = await runLeaf({
517
+ prompt: "read the file",
518
+ tools: [fileRead],
519
+ trustContext,
520
+ });
521
+ expect(result.output).toBe("done");
522
+ // The workspace-bound guard fired before execute — the tool never ran.
523
+ expect(calls).toEqual([]);
524
+ });
525
+
526
+ test("in-workspace file tool paths still execute from a leaf", async () => {
527
+ const calls: Array<Record<string, unknown>> = [];
528
+ const fileRead: Tool = {
529
+ name: "file_read",
530
+ description: "Tool file_read",
531
+ category: "filesystem",
532
+ defaultRiskLevel: "low" as never,
533
+ executionTarget: "sandbox",
534
+ input_schema: { type: "object", properties: {}, required: [] },
535
+ async execute(
536
+ input: Record<string, unknown>,
537
+ ): Promise<ToolExecutionResult> {
538
+ calls.push(input);
539
+ return { content: "read ok", isError: false };
540
+ },
541
+ };
542
+
543
+ responseQueue = [
544
+ {
545
+ content: [
546
+ {
547
+ type: "tool_use",
548
+ name: "file_read",
549
+ id: "tu-1",
550
+ input: { path: "notes.txt" },
551
+ },
552
+ ],
553
+ model: "test",
554
+ usage: { inputTokens: 5, outputTokens: 2 },
555
+ stopReason: "tool_use",
556
+ },
557
+ {
558
+ content: [{ type: "text", text: "done" }],
559
+ model: "test",
560
+ usage: { inputTokens: 2, outputTokens: 1 },
561
+ stopReason: "end_turn",
562
+ },
563
+ ];
564
+
565
+ const result = await runLeaf({
566
+ prompt: "read the file",
567
+ tools: [fileRead],
568
+ trustContext,
569
+ });
570
+ expect(result.output).toBe("done");
571
+ expect(calls).toEqual([{ path: "notes.txt" }]);
572
+ });
573
+
475
574
  test("a leaf with no schema and an empty tool set runs the tool path (no throw)", async () => {
476
575
  // An empty resolved tool set with no schema must NOT fall through to the
477
576
  // schema path (where schemaToInputSchema(undefined) throws) — it runs the
@@ -702,8 +801,11 @@ describe("runLeaf — persona path", () => {
702
801
  }>;
703
802
  expect(messages[0]?.content[0]?.text).not.toBe(MEMORY_BLOCK_TEXT);
704
803
  } finally {
705
- if (savedAuth === undefined) delete process.env.DISABLE_HTTP_AUTH;
706
- else process.env.DISABLE_HTTP_AUTH = savedAuth;
804
+ if (savedAuth === undefined) {
805
+ delete process.env.DISABLE_HTTP_AUTH;
806
+ } else {
807
+ process.env.DISABLE_HTTP_AUTH = savedAuth;
808
+ }
707
809
  }
708
810
  });
709
811
  });
@@ -24,7 +24,7 @@
24
24
  * `tool_choice` provider call whose synthetic tool's input schema is the
25
25
  * caller's Zod schema. The returned tool input is Zod-validated and returned
26
26
  * as `output`. Copies the proven pattern from `memory/v2/router.ts` and
27
- * `memory/graph/extraction.ts`.
27
+ * `memory/v1/graph/extraction.ts`.
28
28
  * - **Tool path** (`tools` provided, no `schema`): a real {@link AgentLoop} with
29
29
  * a minimal task-scoped system prompt and a tool-executor restricted to the
30
30
  * supplied registry tools. No conversation is bootstrapped — the loop runs
@@ -42,11 +42,13 @@ import { randomUUID } from "node:crypto";
42
42
  import { z } from "zod";
43
43
 
44
44
  import { type AgentEvent, AgentLoop } from "../agent/loop.js";
45
+ import type { AssistantEvent } from "../api/index.js";
45
46
  import { getEffectiveProfile } from "../config/default-profile-catalog.js";
46
47
  import { getConfig } from "../config/loader.js";
47
- import type { ServerMessage } from "../daemon/message-protocol.js";
48
+ import { isMemoryEnabled } from "../config/memory-v3-gate.js";
48
49
  import { isPersonalMemoryAllowed } from "../daemon/trust-context.js";
49
50
  import type { TrustContext } from "../daemon/trust-context-types.js";
51
+ import { isOutOfWorkspaceFileInvocation } from "../permissions/workspace-policy.js";
50
52
  import { ConversationGraphMemory } from "../plugins/defaults/memory/graph/conversation-graph-memory.js";
51
53
  import { buildSystemPrompt } from "../prompts/system-prompt.js";
52
54
  import {
@@ -128,21 +130,31 @@ async function resolveLeafContext(
128
130
  * persona leaf still gets the assistant's identity system prompt but NO personal
129
131
  * memory. Without this, a workflow launched by an untrusted actor whose manifest
130
132
  * grants `persona` could exfiltrate private memory in its output.
133
+ *
134
+ * On a v3-live assistant a persona leaf receives no injected memory at all:
135
+ * `prepareMemory`'s v2 route is gated on `isV2InjectionEngineActive` (v3 live
136
+ * suppresses it), the v1 retriever short-circuits to empty under the
137
+ * concept-page substrate, and v3 orchestration is conversation-turn-scoped so
138
+ * it does not run for workflow leaves.
131
139
  */
132
140
  async function injectPersonaMemory(
133
141
  opts: RunLeafOptions,
134
142
  messages: Message[],
135
143
  ): Promise<Message[]> {
136
- if (!isPersonalMemoryAllowed(opts.trustContext)) return messages;
144
+ if (!isPersonalMemoryAllowed(opts.trustContext)) {
145
+ return messages;
146
+ }
137
147
 
138
148
  const config = getConfig();
139
- if (config.memory?.enabled === false) return messages;
149
+ if (!isMemoryEnabled(config)) {
150
+ return messages;
151
+ }
140
152
 
141
153
  const ephemeralConversationId = `workflow-leaf:${randomUUID()}`;
142
154
  const graphMemory = new ConversationGraphMemory(ephemeralConversationId);
143
155
  // The memory pipeline broadcasts retrieval progress to the shared event hub
144
156
  // (matching the main-agent hook); a leaf has no per-turn event callback.
145
- const onEvent = (msg: ServerMessage): void => {
157
+ const onEvent = (msg: AssistantEvent): void => {
146
158
  broadcastMessage(msg);
147
159
  };
148
160
  // `prepareMemory` requires a non-aborting signal; reuse the caller's when
@@ -525,6 +537,17 @@ async function executeLeafTool(
525
537
  };
526
538
  }
527
539
 
540
+ // Leaf tool calls bypass the ToolExecutor's permission lane, so the file
541
+ // tools' out-of-workspace host fallback must not be reachable from here:
542
+ // the manifest consent covers workspace-scoped operation only, and leaves
543
+ // reject host tools outright. Keep the leaf workspace-bound.
544
+ if (isOutOfWorkspaceFileInvocation(name, input, ctx.workingDir)) {
545
+ return {
546
+ content: `Tool "${name}" may only access paths inside the workspace when invoked from a workflow leaf.`,
547
+ isError: true,
548
+ };
549
+ }
550
+
528
551
  const toolContext: ToolContext = {
529
552
  conversationId: ctx.ephemeralConversationId,
530
553
  workingDir: ctx.workingDir,
@@ -552,7 +575,9 @@ async function executeLeafTool(
552
575
  function finalAssistantText(history: Message[]): string {
553
576
  for (let i = history.length - 1; i >= 0; i--) {
554
577
  const msg = history[i];
555
- if (msg.role !== "assistant") continue;
578
+ if (msg.role !== "assistant") {
579
+ continue;
580
+ }
556
581
  const text = msg.content
557
582
  .filter(
558
583
  (b): b is Extract<typeof b, { type: "text" }> => b.type === "text",
@@ -4,8 +4,8 @@ import type { WorkspaceMigration } from "./types.js";
4
4
  * Audit-only entry for the v2 concept-page schema upgrade introduced in PR
5
5
  * #29823 (summary_dense / summary_sparse named vectors). The destructive
6
6
  * collection rebuild and reembed enqueue both run inside the daemon at
7
- * Qdrant init time — see `maybeRebuildMemoryV2Concepts` in
8
- * `assistant/src/plugins/defaults/memory/v2/memory-v2-startup.ts`. The "exactly-once" fence is
7
+ * Qdrant init time — see `maybeRebuildConceptCollection` in
8
+ * `assistant/src/plugins/defaults/memory/substrate/boot-maintenance.ts`. The "exactly-once" fence is
9
9
  * per-collection schema introspection, not per-workspace checkpoint, so
10
10
  * users who wipe Qdrant separately still get re-rebuilt without resetting
11
11
  * any workspace flag.
@@ -0,0 +1,128 @@
1
+ import { existsSync, readFileSync, renameSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
4
+ import type { WorkspaceMigration } from "./types.js";
5
+
6
+ /**
7
+ * Fold `services["image-generation"].mode` into the provider field.
8
+ *
9
+ * Configs written by older versions carry two axes: `mode: "managed"` routes
10
+ * generation through the Vellum platform runtime proxy while `provider`
11
+ * names the backend the proxy fronts (gemini or openai). The schema treats
12
+ * `provider` as the only axis, with `"vellum"` meaning managed and the
13
+ * backend derived from the selected model's prefix at request time, so this
14
+ * migration rewrites every managed service to `provider: "vellum"`. There is
15
+ * no per-provider exemption: the stored backend value under managed mode is
16
+ * itself derived from the model on every model write, so replacing it loses
17
+ * nothing — `model` is preserved verbatim and keeps routing the managed
18
+ * request to the same backend.
19
+ *
20
+ * Idempotent: a config with no `mode` key is left untouched.
21
+ */
22
+ export const imageGenerationModeToProviderMigration: WorkspaceMigration = {
23
+ id: "134-image-generation-mode-to-provider",
24
+ description:
25
+ "Fold services.image-generation mode into provider (managed -> provider: vellum)",
26
+ run(workspaceDir: string): void {
27
+ const configPath = join(workspaceDir, "config.json");
28
+ if (!existsSync(configPath)) {
29
+ return;
30
+ }
31
+
32
+ let config: Record<string, unknown>;
33
+ try {
34
+ const raw = JSON.parse(readFileSync(configPath, "utf-8"));
35
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
36
+ return;
37
+ }
38
+ config = raw as Record<string, unknown>;
39
+ } catch {
40
+ return; // Malformed JSON — skip
41
+ }
42
+
43
+ const services = readObj(config, "services");
44
+ if (!services) {
45
+ return;
46
+ }
47
+
48
+ const service = readObj(services, "image-generation");
49
+ if (!service || !("mode" in service)) {
50
+ return;
51
+ }
52
+
53
+ if (service.mode === "managed") {
54
+ service.provider = "vellum";
55
+ } else if (!("provider" in service)) {
56
+ // An explicit non-managed mode with no persisted provider resolves to
57
+ // the gemini schema default. Pin that choice: with `mode` gone, an
58
+ // absent provider leaf would otherwise be context-filled to "vellum"
59
+ // on platform deployments, silently flipping a your-own config to
60
+ // managed billing.
61
+ service.provider = "gemini";
62
+ }
63
+ delete service.mode;
64
+
65
+ // Write-then-rename keeps the migration rerunnable: a crash mid-write
66
+ // must not leave a truncated config.json that a retry reads as malformed
67
+ // and "completes" past, quarantining the user's unrelated settings.
68
+ const tmpPath = `${configPath}.tmp`;
69
+ writeFileSync(tmpPath, JSON.stringify(config, null, 2) + "\n");
70
+ renameSync(tmpPath, configPath);
71
+ },
72
+ down(workspaceDir: string): void {
73
+ const configPath = join(workspaceDir, "config.json");
74
+ if (!existsSync(configPath)) {
75
+ return;
76
+ }
77
+
78
+ let config: Record<string, unknown>;
79
+ try {
80
+ const raw = JSON.parse(readFileSync(configPath, "utf-8"));
81
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
82
+ return;
83
+ }
84
+ config = raw as Record<string, unknown>;
85
+ } catch {
86
+ return;
87
+ }
88
+
89
+ const services = readObj(config, "services");
90
+ if (!services) {
91
+ return;
92
+ }
93
+
94
+ const service = readObj(services, "image-generation");
95
+ if (!service || "mode" in service) {
96
+ return;
97
+ }
98
+
99
+ // Schemas that predate this migration accept provider "vellum" alongside
100
+ // mode "managed", so the managed pair round-trips exactly. The backend
101
+ // provider a managed service holds before `run()` is not recoverable —
102
+ // `run()` overwrites it with "vellum". That value is derived from the
103
+ // model prefix, so it re-derives on the next model write.
104
+ service.mode = service.provider === "vellum" ? "managed" : "your-own";
105
+
106
+ // Write-then-rename keeps the migration rerunnable: a crash mid-write
107
+ // must not leave a truncated config.json that a retry reads as malformed
108
+ // and "completes" past, quarantining the user's unrelated settings.
109
+ const tmpPath = `${configPath}.tmp`;
110
+ writeFileSync(tmpPath, JSON.stringify(config, null, 2) + "\n");
111
+ renameSync(tmpPath, configPath);
112
+ },
113
+ };
114
+
115
+ // ---------------------------------------------------------------------------
116
+ // Helpers (self-contained per migration AGENTS.md)
117
+ // ---------------------------------------------------------------------------
118
+
119
+ function readObj(
120
+ parent: Record<string, unknown>,
121
+ key: string,
122
+ ): Record<string, unknown> | undefined {
123
+ const value = parent[key];
124
+ if (value == null || typeof value !== "object" || Array.isArray(value)) {
125
+ return undefined;
126
+ }
127
+ return value as Record<string, unknown>;
128
+ }