@vellumai/assistant 0.10.12 → 0.11.0-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 (809) 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 +264 -14
  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__/app-conversation-ids-backfill.test.ts +33 -2
  39. package/src/__tests__/app-conversation-ids.test.ts +204 -0
  40. package/src/__tests__/approval-cascade.test.ts +5 -5
  41. package/src/__tests__/approval-routes-http.test.ts +3 -3
  42. package/src/__tests__/ask-question-resolver.test.ts +207 -0
  43. package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +16 -16
  44. package/src/__tests__/assistant-event-hub-targeted.test.ts +13 -11
  45. package/src/__tests__/assistant-event-hub.test.ts +13 -11
  46. package/src/__tests__/assistant-event.test.ts +12 -9
  47. package/src/__tests__/assistant-feature-flag-guard.test.ts +3 -3
  48. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +1 -1
  49. package/src/__tests__/assistant-id-boundary-guard.test.ts +0 -58
  50. package/src/__tests__/assistant-stream-state.test.ts +17 -7
  51. package/src/__tests__/avatar-identity-sync.test.ts +3 -3
  52. package/src/__tests__/background-workers-disk-pressure.test.ts +1 -0
  53. package/src/__tests__/call-conversation-messages.test.ts +134 -18
  54. package/src/__tests__/call-start-guardian-guard.test.ts +27 -0
  55. package/src/__tests__/channel-approvals.test.ts +0 -27
  56. package/src/__tests__/channel-guardian.test.ts +85 -512
  57. package/src/__tests__/channel-readiness-slack-remote.test.ts +151 -3
  58. package/src/__tests__/channel-retry-sweep.test.ts +88 -1
  59. package/src/__tests__/channel-setup-panel-ack.test.ts +12 -9
  60. package/src/__tests__/chat-reveal-guard-priming.test.ts +31 -34
  61. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +2 -2
  62. package/src/__tests__/compaction-events.test.ts +8 -8
  63. package/src/__tests__/config-loader-platform-defaults.test.ts +54 -28
  64. package/src/__tests__/config-model-image-provider.test.ts +20 -0
  65. package/src/__tests__/config-schema-memory-substrate.test.ts +306 -0
  66. package/src/__tests__/config-schema.test.ts +14 -2
  67. package/src/__tests__/config-set-platform-guard.test.ts +11 -12
  68. package/src/__tests__/config-sounds-sync.test.ts +4 -4
  69. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +5 -0
  70. package/src/__tests__/context-search-memory-source.test.ts +1 -1
  71. package/src/__tests__/context-search-memory-v2-source.test.ts +6 -6
  72. package/src/__tests__/context-token-estimator.test.ts +54 -1
  73. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +12 -3
  74. package/src/__tests__/conversation-agent-loop-fatal-cleanup.test.ts +13 -4
  75. package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +4 -4
  76. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +10 -1
  77. package/src/__tests__/conversation-agent-loop-overflow.test.ts +22 -13
  78. package/src/__tests__/conversation-agent-loop.test.ts +39 -30
  79. package/src/__tests__/conversation-confirmation-signals.test.ts +14 -14
  80. package/src/__tests__/conversation-evictor.test.ts +49 -0
  81. package/src/__tests__/conversation-fork-crud.test.ts +1 -1
  82. package/src/__tests__/conversation-group-tools.test.ts +279 -0
  83. package/src/__tests__/conversation-history-web-search.test.ts +1 -1
  84. package/src/__tests__/conversation-key-store-disk-view.test.ts +5 -5
  85. package/src/__tests__/conversation-lineage.test.ts +235 -0
  86. package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +5 -5
  87. package/src/__tests__/conversation-message-sync-tags.test.ts +4 -4
  88. package/src/__tests__/conversation-queue.test.ts +81 -81
  89. package/src/__tests__/conversation-routes-enabled-plugins.test.ts +8 -1
  90. package/src/__tests__/conversation-routes-hidden-queue.test.ts +8 -1
  91. package/src/__tests__/conversation-routes-slash-commands.test.ts +10 -1
  92. package/src/__tests__/conversation-runtime-assembly.test.ts +29 -2
  93. package/src/__tests__/conversation-slash-queue.test.ts +11 -11
  94. package/src/__tests__/conversation-slash-unknown.test.ts +2 -2
  95. package/src/__tests__/conversation-speed-override.test.ts +2 -2
  96. package/src/__tests__/conversation-summarize-route.test.ts +9 -0
  97. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +18 -16
  98. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +17 -17
  99. package/src/__tests__/conversation-surfaces-app-open.test.ts +7 -4
  100. package/src/__tests__/conversation-surfaces-data-persist.test.ts +7 -7
  101. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +9 -9
  102. package/src/__tests__/conversation-surfaces-standalone.test.ts +12 -12
  103. package/src/__tests__/conversation-surfaces-state-update.test.ts +8 -5
  104. package/src/__tests__/conversation-surfaces-table-action.test.ts +6 -3
  105. package/src/__tests__/conversation-surfaces-task-progress.test.ts +46 -46
  106. package/src/__tests__/conversation-sync-tags.test.ts +5 -5
  107. package/src/__tests__/conversation-wait-for-idle.test.ts +2 -2
  108. package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -4
  109. package/src/__tests__/conversation-workspace-injection.test.ts +0 -3
  110. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -3
  111. package/src/__tests__/copy-composer-tc-templates.test.ts +3 -131
  112. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  113. package/src/__tests__/daemon-assistant-events.test.ts +14 -15
  114. package/src/__tests__/db-test-helpers.ts +13 -27
  115. package/src/__tests__/disk-pressure-routes.test.ts +12 -3
  116. package/src/__tests__/document-tool-security.test.ts +95 -0
  117. package/src/__tests__/drain-kick-guard.test.ts +232 -0
  118. package/src/__tests__/dynamic-skill-background-guard.test.ts +19 -6
  119. package/src/__tests__/emit-event-signal.test.ts +5 -6
  120. package/src/__tests__/encrypted-store-test-helpers.ts +10 -20
  121. package/src/__tests__/events-tail-route.test.ts +6 -4
  122. package/src/__tests__/feature-flag-test-helpers.ts +10 -20
  123. package/src/__tests__/file-edit-tool.test.ts +24 -4
  124. package/src/__tests__/file-list-tool.test.ts +2 -1
  125. package/src/__tests__/file-read-tool.test.ts +62 -10
  126. package/src/__tests__/file-write-tool.test.ts +24 -5
  127. package/src/__tests__/followup-tools.test.ts +58 -0
  128. package/src/__tests__/gateway-threshold-reader-mock.ts +99 -0
  129. package/src/__tests__/graph-extraction-event-date.test.ts +1 -1
  130. package/src/__tests__/guardian-question-mode.test.ts +42 -3
  131. package/src/__tests__/guardian-reply-router-answer-mode.test.ts +283 -0
  132. package/src/__tests__/guardian-vellum-destination-pinning.test.ts +221 -0
  133. package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
  134. package/src/__tests__/heartbeat-service.test.ts +1 -0
  135. package/src/__tests__/helpers/native-web-search-harness.ts +10 -10
  136. package/src/__tests__/host-browser-proxy.test.ts +1 -1
  137. package/src/__tests__/host-file-edit-tool.test.ts +3 -3
  138. package/src/__tests__/host-file-read-tool.test.ts +2 -2
  139. package/src/__tests__/host-file-write-tool.test.ts +7 -3
  140. package/src/__tests__/host-shell-tool.test.ts +17 -5
  141. package/src/__tests__/host-transfer-pending-interactions.test.ts +8 -8
  142. package/src/__tests__/image-credentials.test.ts +65 -8
  143. package/src/__tests__/injection-block.test.ts +4 -4
  144. package/src/__tests__/injector-chain.test.ts +1 -1
  145. package/src/__tests__/injector-pkb-v2-silenced.test.ts +2 -2
  146. package/src/__tests__/injector-registry-order-guard.test.ts +4 -9
  147. package/src/__tests__/injector-v3-suppression.test.ts +6 -4
  148. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +27 -28
  149. package/src/__tests__/list-messages-page-latest.test.ts +2 -2
  150. package/src/__tests__/llm-usage-store.test.ts +67 -4
  151. package/src/__tests__/log-redact.test.ts +18 -0
  152. package/src/__tests__/managed-profile-guard.test.ts +27 -0
  153. package/src/__tests__/managed-skill-lifecycle.test.ts +2 -2
  154. package/src/__tests__/media-generate-image.test.ts +62 -11
  155. package/src/__tests__/memory-identity-context-parity.test.ts +1 -1
  156. package/src/__tests__/memory-jobs-worker-lanes.test.ts +9 -1
  157. package/src/__tests__/memory-retrieval-hook.test.ts +4 -4
  158. package/src/__tests__/notification-decision-strategy.test.ts +115 -11
  159. package/src/__tests__/notification-deep-link.test.ts +12 -12
  160. package/src/__tests__/notification-vellum-adapter.test.ts +8 -8
  161. package/src/__tests__/outbound-slack-persistence.test.ts +8 -8
  162. package/src/__tests__/path-policy.test.ts +315 -0
  163. package/src/__tests__/pending-interactions-resolved-event.test.ts +6 -6
  164. package/src/__tests__/persistence-layering-guard.test.ts +2 -2
  165. package/src/__tests__/pkb-autoinject.test.ts +1 -1
  166. package/src/__tests__/platform-bash-auto-approve.test.ts +1 -0
  167. package/src/__tests__/platform-callback-registration.test.ts +10 -10
  168. package/src/__tests__/plugin-event-hub-facade.test.ts +22 -15
  169. package/src/__tests__/plugin-import-boundary-guard.test.ts +15 -15
  170. package/src/__tests__/processing-flag-persist-failure.test.ts +0 -4
  171. package/src/__tests__/provider-platform-proxy-integration.test.ts +0 -1
  172. package/src/__tests__/rebuild-index-graph-nodes.test.ts +1 -1
  173. package/src/__tests__/request-secret-standalone-channel-gate.test.ts +5 -5
  174. package/src/__tests__/require-fresh-approval.test.ts +38 -38
  175. package/src/__tests__/resolve-app-id.test.ts +32 -0
  176. package/src/__tests__/run-due-schedules.test.ts +72 -1
  177. package/src/__tests__/runtime-events-sse-parity.test.ts +11 -10
  178. package/src/__tests__/runtime-events-sse.test.ts +1 -1
  179. package/src/__tests__/schedule-routes.test.ts +44 -5
  180. package/src/__tests__/schedule-store.test.ts +3 -3
  181. package/src/__tests__/schedule-tools.test.ts +176 -0
  182. package/src/__tests__/secret-prompt-log-hygiene.test.ts +3 -3
  183. package/src/__tests__/secret-prompter-channel-fallback.test.ts +3 -3
  184. package/src/__tests__/secret-response-routing.test.ts +3 -3
  185. package/src/__tests__/secret-routes-platform-proxy.test.ts +4 -7
  186. package/src/__tests__/secret-scanner.test.ts +36 -0
  187. package/src/__tests__/send-endpoint-busy.test.ts +7 -7
  188. package/src/__tests__/slack-required-scopes-mirror.test.ts +81 -0
  189. package/src/__tests__/starter-task-flow.test.ts +26 -3
  190. package/src/__tests__/subagent-call-site-routing.test.ts +2 -2
  191. package/src/__tests__/subagent-disposal.test.ts +40 -11
  192. package/src/__tests__/subagent-fork-notifications.test.ts +4 -4
  193. package/src/__tests__/subagent-fork-prompt-role.test.ts +3 -3
  194. package/src/__tests__/subagent-fork-spawn.test.ts +4 -4
  195. package/src/__tests__/subagent-manager-notify.test.ts +73 -14
  196. package/src/__tests__/subagent-notify-parent.test.ts +48 -4
  197. package/src/__tests__/subagent-spawn-and-await.test.ts +62 -14
  198. package/src/__tests__/subagent-tools.test.ts +64 -0
  199. package/src/__tests__/sync-message-contract.test.ts +3 -3
  200. package/src/__tests__/terminal-tools.test.ts +12 -3
  201. package/src/__tests__/test-preload.ts +9 -0
  202. package/src/__tests__/tool-approval-handler.test.ts +587 -43
  203. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +7 -4
  204. package/src/__tests__/tool-executor.test.ts +116 -0
  205. package/src/__tests__/tool-grant-request-escalation.test.ts +5 -0
  206. package/src/__tests__/tool-preview-lifecycle.test.ts +32 -29
  207. package/src/__tests__/tool-result-metadata-plumbing.test.ts +5 -5
  208. package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
  209. package/src/__tests__/tool-start-timestamp.test.ts +4 -4
  210. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +9 -22
  211. package/src/__tests__/ui-choice-copy-surfaces.test.ts +13 -13
  212. package/src/__tests__/ui-work-result-surface.test.ts +3 -3
  213. package/src/__tests__/voice-scoped-grant-consumer.test.ts +6 -6
  214. package/src/__tests__/voice-session-bridge.test.ts +44 -44
  215. package/src/__tests__/workspace-migration-134-image-generation-mode-to-provider.test.ts +284 -0
  216. package/src/__tests__/workspace-policy.test.ts +482 -2
  217. package/src/acp/__tests__/client-handler.test.ts +3 -3
  218. package/src/acp/__tests__/session-manager-persistence.test.ts +10 -10
  219. package/src/acp/__tests__/session-manager-resume.test.ts +7 -7
  220. package/src/acp/client-handler.ts +3 -3
  221. package/src/acp/session-manager.ts +8 -8
  222. package/src/api/events/subagent-event.ts +2 -2
  223. package/src/api/responses/memory-v2-activation-log.ts +2 -2
  224. package/src/api/responses/subagent-detail.ts +13 -0
  225. package/src/approvals/AGENTS.md +2 -0
  226. package/src/approvals/guardian-request-resolvers.ts +118 -24
  227. package/src/apps/app-store.ts +95 -4
  228. package/src/calls/__tests__/voice-control-protocol.test.ts +57 -0
  229. package/src/calls/__tests__/voice-session-bridge.test.ts +229 -7
  230. package/src/calls/__tests__/voice-triage-escalate.test.ts +3 -4
  231. package/src/calls/call-controller.ts +27 -27
  232. package/src/calls/call-conversation-messages.ts +58 -18
  233. package/src/calls/voice-control-protocol.ts +56 -0
  234. package/src/calls/voice-session-bridge.ts +178 -65
  235. package/src/calls/voice-triage-escalate.ts +2 -3
  236. package/src/channels/config.ts +8 -0
  237. package/src/channels/types.ts +1 -0
  238. package/src/cli/commands/config.ts +49 -13
  239. package/src/cli/commands/memory/index.help.ts +4 -2
  240. package/src/cli/commands/memory/memory-retrospective.ts +5 -0
  241. package/src/cli/commands/webhooks.help.ts +9 -4
  242. package/src/cli/lib/bundled-marketplace.json +12 -0
  243. package/src/cli.ts +2 -109
  244. package/src/config/__tests__/deployment-context-defaults.test.ts +9 -0
  245. package/src/config/__tests__/substrate-twin-shadowing.test.ts +191 -0
  246. package/src/config/assistant-feature-flags.ts +1 -1
  247. package/src/config/bundled-skills/conversation-groups/SKILL.md +29 -0
  248. package/src/config/bundled-skills/conversation-groups/TOOLS.json +58 -0
  249. package/src/config/bundled-skills/conversation-groups/tools/group-create.ts +12 -0
  250. package/src/config/bundled-skills/conversation-groups/tools/group-list.ts +12 -0
  251. package/src/config/bundled-skills/conversation-groups/tools/move-to-group.ts +12 -0
  252. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +13 -7
  253. package/src/config/bundled-skills/schedule/SKILL.md +2 -0
  254. package/src/config/feature-flag-cache.ts +6 -16
  255. package/src/config/feature-flag-registry.json +14 -38
  256. package/src/config/loader.ts +7 -1
  257. package/src/config/memory-tier.ts +15 -10
  258. package/src/config/memory-v3-gate.test.ts +278 -1
  259. package/src/config/memory-v3-gate.ts +88 -26
  260. package/src/config/raw-config-utils.ts +1 -1
  261. package/src/config/schemas/__tests__/live-voice.test.ts +27 -16
  262. package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
  263. package/src/config/schemas/live-voice.ts +33 -7
  264. package/src/config/schemas/llm.ts +1 -0
  265. package/src/config/schemas/memory-retrospective.ts +13 -0
  266. package/src/config/schemas/memory-substrate.ts +183 -0
  267. package/src/config/schemas/memory-v2.ts +3 -2
  268. package/src/config/schemas/memory-v3.ts +11 -4
  269. package/src/config/schemas/memory.ts +35 -1
  270. package/src/config/schemas/services.ts +10 -2
  271. package/src/config/substrate-twin-shadowing.ts +195 -0
  272. package/src/config/webhook-routing.ts +67 -0
  273. package/src/context/compactor.ts +10 -3
  274. package/src/context/token-estimator.ts +21 -0
  275. package/src/daemon/__tests__/channel-ui-capability.test.ts +85 -0
  276. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +3 -3
  277. package/src/daemon/__tests__/embedding-reconcile.test.ts +3 -3
  278. package/src/daemon/__tests__/inference-profile-notification.test.ts +3 -6
  279. package/src/daemon/__tests__/native-web-search-metadata.test.ts +5 -5
  280. package/src/daemon/__tests__/web-search-status-text.test.ts +2 -2
  281. package/src/daemon/channel-ui-capability.ts +70 -1
  282. package/src/daemon/conversation-agent-loop-handlers.ts +4 -4
  283. package/src/daemon/conversation-agent-loop.ts +12 -5
  284. package/src/daemon/conversation-evictor.ts +26 -4
  285. package/src/daemon/conversation-launch.ts +11 -14
  286. package/src/daemon/conversation-lineage.ts +76 -0
  287. package/src/daemon/conversation-messaging.ts +14 -14
  288. package/src/daemon/conversation-notifiers.ts +2 -2
  289. package/src/daemon/conversation-process.ts +133 -21
  290. package/src/daemon/conversation-queue-manager.ts +7 -7
  291. package/src/daemon/conversation-runtime-assembly.ts +16 -0
  292. package/src/daemon/conversation-store.ts +11 -3
  293. package/src/daemon/conversation-surfaces.ts +8 -14
  294. package/src/daemon/conversation-tool-setup.ts +13 -7
  295. package/src/daemon/conversation-usage.ts +12 -11
  296. package/src/daemon/conversation.ts +38 -15
  297. package/src/daemon/disk-pressure-guard.ts +5 -12
  298. package/src/daemon/embedding-reconcile.ts +14 -9
  299. package/src/daemon/handlers/config-channels.ts +40 -134
  300. package/src/daemon/handlers/config-model.ts +15 -7
  301. package/src/daemon/handlers/conversations.ts +4 -2
  302. package/src/daemon/handlers/shared.ts +29 -0
  303. package/src/daemon/host-proxy-base.ts +4 -4
  304. package/src/daemon/lifecycle.ts +13 -0
  305. package/src/daemon/message-protocol.ts +8 -144
  306. package/src/daemon/message-types/computer-use.ts +0 -12
  307. package/src/daemon/message-types/conversations.ts +9 -345
  308. package/src/daemon/message-types/host-app-control.ts +0 -9
  309. package/src/daemon/message-types/host-browser.ts +0 -7
  310. package/src/daemon/message-types/host-ui-snapshot.ts +0 -7
  311. package/src/daemon/message-types/messages.ts +0 -48
  312. package/src/daemon/message-types/notifications.ts +0 -7
  313. package/src/daemon/message-types/skills.ts +0 -5
  314. package/src/daemon/message-types/surfaces.ts +0 -9
  315. package/src/daemon/message-types/sync.ts +0 -2
  316. package/src/daemon/process-message.ts +5 -5
  317. package/src/daemon/skill-memory-refresh.ts +5 -5
  318. package/src/daemon/tool-side-effects.ts +32 -16
  319. package/src/daemon/trust-context.ts +1 -1
  320. package/src/daemon/wake-conversation-ops.ts +4 -4
  321. package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +100 -7
  322. package/src/heartbeat/__tests__/heartbeat-service.test.ts +67 -0
  323. package/src/heartbeat/heartbeat-run-store.ts +81 -4
  324. package/src/heartbeat/heartbeat-service.ts +32 -1
  325. package/src/home/__tests__/feed-writer.test.ts +7 -7
  326. package/src/home/__tests__/home-content-refresh.test.ts +3 -0
  327. package/src/home/__tests__/suggested-prompts.test.ts +1 -0
  328. package/src/home/feed-writer.ts +6 -13
  329. package/src/home/home-content-refresh.ts +6 -9
  330. package/src/home/relationship-state-writer.ts +5 -12
  331. package/src/home/suggested-prompts-cache.ts +6 -19
  332. package/src/ipc/__tests__/events-publish-client.test.ts +67 -0
  333. package/src/ipc/events-publish-client.ts +44 -0
  334. package/src/ipc/routes/__tests__/conversation-sync-ipc-routes.test.ts +2 -2
  335. package/src/ipc/routes/__tests__/events-ipc-routes.test.ts +38 -9
  336. package/src/ipc/routes/events-ipc-routes.ts +11 -31
  337. package/src/live-voice/__tests__/front-decision.test.ts +4 -176
  338. package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +276 -68
  339. package/src/live-voice/__tests__/live-voice-continuation-fork-hydration.test.ts +286 -0
  340. package/src/live-voice/__tests__/live-voice-events.test.ts +6 -3
  341. package/src/live-voice/__tests__/live-voice-progress.test.ts +185 -46
  342. package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +24 -59
  343. package/src/live-voice/__tests__/live-voice-tts-session.test.ts +38 -54
  344. package/src/live-voice/__tests__/live-voice-vad.test.ts +1154 -636
  345. package/src/live-voice/front-decision.ts +5 -155
  346. package/src/live-voice/live-voice-metrics.ts +4 -1
  347. package/src/live-voice/live-voice-session.ts +1288 -439
  348. package/src/live-voice/progress-phrases.ts +17 -0
  349. package/src/live-voice/protocol.ts +15 -0
  350. package/src/media/app-icon-generator.ts +15 -8
  351. package/src/media/avatar-router.ts +9 -5
  352. package/src/media/image-credentials.ts +42 -10
  353. package/src/media/image-service.ts +1 -13
  354. package/src/media/types.ts +26 -3
  355. package/src/notifications/AGENTS.md +2 -0
  356. package/src/notifications/__tests__/broadcaster.test.ts +95 -0
  357. package/src/notifications/adapters/macos.ts +3 -3
  358. package/src/notifications/broadcaster.ts +57 -0
  359. package/src/notifications/copy-composer.ts +0 -15
  360. package/src/notifications/decision-engine.ts +21 -22
  361. package/src/notifications/guardian-question-mode.ts +57 -2
  362. package/src/notifications/home-feed-side-effect.ts +4 -0
  363. package/src/notifications/signal.ts +6 -4
  364. package/src/notifications/trusted-contact-payloads.ts +3 -4
  365. package/src/notifications/vellum-card-affinity.ts +39 -0
  366. package/src/oauth/AGENTS.md +1 -1
  367. package/src/permissions/channel-permission-query.test.ts +69 -0
  368. package/src/permissions/channel-permission-query.ts +73 -1
  369. package/src/permissions/checker.test.ts +298 -15
  370. package/src/permissions/checker.ts +102 -36
  371. package/src/permissions/confirmation-guardian-request.test.ts +2 -2
  372. package/src/permissions/confirmation-guardian-request.ts +2 -2
  373. package/src/permissions/gateway-threshold-reader.test.ts +224 -17
  374. package/src/permissions/gateway-threshold-reader.ts +82 -10
  375. package/src/permissions/ipc-risk-types.ts +8 -0
  376. package/src/permissions/prompter.ts +5 -5
  377. package/src/permissions/question-guardian-request.test.ts +222 -0
  378. package/src/permissions/question-guardian-request.ts +179 -0
  379. package/src/permissions/question-prompter.test.ts +8 -8
  380. package/src/permissions/question-prompter.ts +18 -0
  381. package/src/permissions/secret-prompter.ts +2 -4
  382. package/src/permissions/workspace-policy.ts +269 -34
  383. package/src/persistence/__tests__/lifecycle-quiesce.test.ts +82 -0
  384. package/src/persistence/__tests__/message-content-file.test.ts +58 -3
  385. package/src/persistence/conversation-crud.ts +93 -0
  386. package/src/persistence/conversation-key-store.ts +63 -0
  387. package/src/persistence/conversation-parent.ts +27 -0
  388. package/src/persistence/db-async-query.ts +1 -1
  389. package/src/persistence/db-singleton.ts +14 -27
  390. package/src/persistence/delivery-crud.ts +45 -0
  391. package/src/persistence/embeddings/embedding-backend.ts +2 -1
  392. package/src/persistence/embeddings/embedding-identity.ts +7 -3
  393. package/src/persistence/job-utils.ts +32 -27
  394. package/src/persistence/jobs-store.ts +92 -3
  395. package/src/persistence/lifecycle-quiesce.ts +80 -0
  396. package/src/persistence/llm-usage-store.ts +45 -8
  397. package/src/persistence/message-content-file.ts +4 -4
  398. package/src/persistence/migrations/336-move-memory-v2-activation-logs-to-memory-db.ts +1 -1
  399. package/src/persistence/migrations/351-schedule-skill-script-handoff.ts +39 -0
  400. package/src/persistence/migrations/352-drop-schedule-skill-script-handoff.test.ts +83 -0
  401. package/src/persistence/migrations/352-drop-schedule-skill-script-handoff.ts +36 -0
  402. package/src/persistence/migrations/353-add-llm-usage-conversation-type.test.ts +110 -0
  403. package/src/persistence/migrations/353-add-llm-usage-conversation-type.ts +49 -0
  404. package/src/persistence/migrations/354-backfill-app-conversation-lineage.ts +41 -0
  405. package/src/persistence/schema/infrastructure.ts +11 -0
  406. package/src/persistence/steps.ts +9 -1
  407. package/src/plugin-api/__tests__/publish-event-forwarding.test.ts +113 -0
  408. package/src/plugin-api/__tests__/publish-event.test.ts +57 -0
  409. package/src/plugin-api/conversation-turn.ts +4 -4
  410. package/src/plugin-api/event-hub-facade.ts +15 -6
  411. package/src/plugin-api/index.ts +10 -4
  412. package/src/plugin-api/publish-event.ts +36 -0
  413. package/src/plugins/AGENTS.md +2 -0
  414. package/src/plugins/defaults/compaction/window-manager.ts +9 -0
  415. package/src/plugins/defaults/index.ts +9 -13
  416. package/src/plugins/defaults/memory/AGENTS.md +775 -0
  417. package/src/plugins/defaults/memory/__tests__/capability-seed-embed-gate.test.ts +186 -0
  418. package/src/plugins/defaults/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +1 -1
  419. package/src/plugins/defaults/memory/__tests__/indexer-tier-dispatch.test.ts +129 -0
  420. package/src/plugins/defaults/memory/__tests__/jobs-worker-quiesce-gate.test.ts +91 -0
  421. package/src/plugins/defaults/memory/__tests__/jobs-worker-v1-graph-substrate-noop.test.ts +342 -0
  422. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +9 -1
  423. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-schedule.test.ts +36 -1
  424. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-sweep-defer.test.ts +9 -1
  425. package/src/plugins/defaults/memory/__tests__/memory-log-stores-degraded.test.ts +2 -2
  426. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +44 -10
  427. package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +151 -10
  428. package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +1155 -0
  429. package/src/plugins/defaults/memory/__tests__/memory-v2-activation-log-store.test.ts +1 -1
  430. package/src/plugins/defaults/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -3
  431. package/src/plugins/defaults/memory/__tests__/tools-delete-memory-page.test.ts +1 -1
  432. package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +71 -35
  433. package/src/plugins/defaults/memory/context-search/sources/memory.ts +5 -1
  434. package/src/plugins/defaults/memory/fork-conversation-memory.ts +4 -4
  435. package/src/plugins/defaults/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +80 -10
  436. package/src/plugins/defaults/memory/graph/__tests__/handle-remember-v2.test.ts +1 -1
  437. package/src/plugins/defaults/memory/graph/capability-seed.ts +24 -10
  438. package/src/plugins/defaults/memory/graph/conversation-graph-memory.ts +123 -49
  439. package/src/plugins/defaults/memory/graph/graph-search.ts +6 -118
  440. package/src/plugins/defaults/memory/graph/in-context-tracker.test.ts +173 -0
  441. package/src/plugins/defaults/memory/graph/in-context-tracker.ts +109 -0
  442. package/src/plugins/defaults/memory/graph/store.ts +1 -0
  443. package/src/plugins/defaults/memory/graph/tool-handlers.test.ts +1 -1
  444. package/src/plugins/defaults/memory/graph/tool-handlers.ts +5 -2
  445. package/src/plugins/defaults/memory/graph-topology/__tests__/build-memory-graph.test.ts +1 -1
  446. package/src/plugins/defaults/memory/graph-topology/build-memory-graph.ts +6 -9
  447. package/src/plugins/defaults/memory/hooks/__tests__/user-prompt-submit.test.ts +30 -16
  448. package/src/plugins/defaults/memory/hooks/user-prompt-submit.ts +18 -14
  449. package/src/plugins/defaults/memory/indexer.ts +146 -89
  450. package/src/plugins/defaults/memory/injectors.ts +86 -41
  451. package/src/plugins/defaults/memory/job-handlers.ts +130 -39
  452. package/src/plugins/defaults/memory/jobs/__tests__/embed-concept-page.test.ts +2 -2
  453. package/src/plugins/defaults/memory/jobs/embed-concept-page.ts +22 -10
  454. package/src/plugins/defaults/memory/jobs-worker.ts +279 -208
  455. package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +4 -2
  456. package/src/plugins/defaults/memory/memory-retrospective-job.ts +40 -3
  457. package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +99 -11
  458. package/src/plugins/defaults/memory/src/__tests__/memory-v2-routes.test.ts +5 -3
  459. package/src/plugins/defaults/memory/src/__tests__/memory-v2-simulate-route.test.ts +3 -4
  460. package/src/plugins/defaults/memory/src/memory-graph-routes.ts +2 -1
  461. package/src/plugins/defaults/memory/src/memory-item-routes.test.ts +7 -5
  462. package/src/plugins/defaults/memory/src/memory-item-routes.ts +51 -19
  463. package/src/plugins/defaults/memory/src/memory-v2-routes.ts +31 -20
  464. package/src/plugins/defaults/memory/startup.ts +58 -21
  465. package/src/plugins/defaults/memory/substrate/__tests__/boot-maintenance.test.ts +335 -0
  466. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/cli-command-store.test.ts +14 -8
  467. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/consolidation-job.test.ts +51 -21
  468. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/edge-index.test.ts +1 -1
  469. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/frontmatter-sweep.test.ts +3 -3
  470. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/page-index.test.ts +1 -1
  471. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/page-store.test.ts +1 -1
  472. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/prompts-consolidation.test.ts +2 -2
  473. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/qdrant.test.ts +23 -14
  474. package/src/plugins/defaults/memory/substrate/__tests__/reembed-job.test.ts +262 -0
  475. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sim.test.ts +9 -12
  476. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/skill-content.test.ts +2 -2
  477. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/skill-store.test.ts +9 -9
  478. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sparse-bm25.test.ts +12 -5
  479. package/src/plugins/defaults/memory/substrate/__tests__/spread.test.ts +276 -0
  480. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/static-context.test.ts +17 -8
  481. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sweep-job.test.ts +9 -9
  482. package/src/plugins/defaults/memory/{v3/substrate/memory-v2-startup.ts → substrate/boot-maintenance.ts} +43 -24
  483. package/src/plugins/defaults/memory/{v3/substrate → substrate}/cli-command-store.ts +13 -8
  484. package/src/plugins/defaults/memory/{v3/substrate → substrate}/consolidation-job.ts +51 -27
  485. package/src/plugins/defaults/memory/{v3/substrate → substrate}/constants.ts +1 -0
  486. package/src/plugins/defaults/memory/{v3/substrate → substrate}/edge-index.ts +28 -9
  487. package/src/plugins/defaults/memory/{v3/substrate → substrate}/frontmatter-sweep.ts +14 -7
  488. package/src/plugins/defaults/memory/{v3/substrate → substrate}/injected-block-slugs.ts +9 -3
  489. package/src/plugins/defaults/memory/{v3/substrate → substrate}/page-index.ts +29 -10
  490. package/src/plugins/defaults/memory/{v3/substrate → substrate}/page-store.ts +35 -12
  491. package/src/plugins/defaults/memory/{v3/substrate → substrate}/prompts/consolidation.ts +14 -8
  492. package/src/plugins/defaults/memory/{v3/substrate → substrate}/prompts/sweep.ts +4 -1
  493. package/src/plugins/defaults/memory/{v3/substrate → substrate}/qdrant.ts +96 -36
  494. package/src/plugins/defaults/memory/substrate/reembed-job.ts +54 -0
  495. package/src/plugins/defaults/memory/{v3/substrate → substrate}/sim.ts +26 -15
  496. package/src/plugins/defaults/memory/{v3/substrate → substrate}/skill-content.ts +1 -1
  497. package/src/plugins/defaults/memory/{v3/substrate → substrate}/skill-store.ts +13 -8
  498. package/src/plugins/defaults/memory/{v3/substrate → substrate}/sparse-bm25.ts +27 -10
  499. package/src/plugins/defaults/memory/substrate/spread.ts +165 -0
  500. package/src/plugins/defaults/memory/{v3/substrate → substrate}/static-context.ts +12 -7
  501. package/src/plugins/defaults/memory/{v3/substrate → substrate}/sweep-job.ts +20 -15
  502. package/src/plugins/defaults/memory/substrate/tuning.ts +93 -0
  503. package/src/plugins/defaults/memory/{v3/substrate → substrate}/types.ts +7 -4
  504. package/src/plugins/defaults/memory/tools.test.ts +1 -1
  505. package/src/plugins/defaults/memory/tools.ts +1 -1
  506. package/src/plugins/defaults/memory/v1/README.md +5 -0
  507. package/src/plugins/defaults/memory/{__tests__ → v1/__tests__}/filing-jobs.test.ts +4 -4
  508. package/src/plugins/defaults/memory/{filing-jobs.ts → v1/filing-jobs.ts} +3 -3
  509. package/src/plugins/defaults/memory/{graph → v1/graph}/bootstrap.test.ts +68 -6
  510. package/src/plugins/defaults/memory/{graph → v1/graph}/bootstrap.ts +40 -21
  511. package/src/plugins/defaults/memory/{graph → v1/graph}/consolidation.ts +14 -14
  512. package/src/plugins/defaults/memory/{graph → v1/graph}/decay.test.ts +1 -1
  513. package/src/plugins/defaults/memory/{graph → v1/graph}/decay.ts +3 -3
  514. package/src/plugins/defaults/memory/{graph → v1/graph}/extraction-job.ts +5 -5
  515. package/src/plugins/defaults/memory/{graph → v1/graph}/extraction.test.ts +1 -1
  516. package/src/plugins/defaults/memory/{graph → v1/graph}/extraction.ts +20 -14
  517. package/src/plugins/defaults/memory/{graph → v1/graph}/graph-search.test.ts +3 -3
  518. package/src/plugins/defaults/memory/v1/graph/graph-search.ts +123 -0
  519. package/src/plugins/defaults/memory/{graph → v1/graph}/injection.test.ts +1 -118
  520. package/src/plugins/defaults/memory/{graph → v1/graph}/injection.ts +9 -111
  521. package/src/plugins/defaults/memory/{graph → v1/graph}/narrative.ts +6 -6
  522. package/src/plugins/defaults/memory/{graph → v1/graph}/pattern-scan.ts +5 -5
  523. package/src/plugins/defaults/memory/{graph → v1/graph}/retriever.test.ts +135 -42
  524. package/src/plugins/defaults/memory/{graph → v1/graph}/retriever.ts +40 -22
  525. package/src/plugins/defaults/memory/{graph → v1/graph}/scoring.test.ts +1 -1
  526. package/src/plugins/defaults/memory/{graph → v1/graph}/scoring.ts +1 -1
  527. package/src/plugins/defaults/memory/{graph → v1/graph}/serendipity.ts +1 -1
  528. package/src/plugins/defaults/memory/{graph → v1/graph}/triggers.test.ts +1 -1
  529. package/src/plugins/defaults/memory/{graph → v1/graph}/triggers.ts +1 -1
  530. package/src/plugins/defaults/memory/{identity-context.ts → v1/identity-context.ts} +4 -4
  531. package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/backfill.ts +6 -6
  532. package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/embedding.test.ts +6 -6
  533. package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/embedding.ts +6 -6
  534. package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/index-maintenance.ts +8 -8
  535. package/src/plugins/defaults/memory/{jobs → v1/jobs}/embed-pkb-file.test.ts +7 -7
  536. package/src/plugins/defaults/memory/{jobs → v1/jobs}/embed-pkb-file.ts +5 -5
  537. package/src/plugins/defaults/memory/{pkb → v1/pkb}/autoinject.ts +1 -1
  538. package/src/plugins/defaults/memory/{pkb → v1/pkb}/context.ts +2 -2
  539. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-index.test.ts +3 -3
  540. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-index.ts +2 -2
  541. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-reconcile.test.ts +3 -3
  542. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-reconcile.ts +2 -2
  543. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-search.test.ts +3 -3
  544. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-search.ts +6 -6
  545. package/src/plugins/defaults/memory/{pkb → v1/pkb}/types.ts +3 -5
  546. package/src/plugins/defaults/memory/{pkb-schedule.ts → v1/pkb-schedule.ts} +2 -2
  547. package/src/plugins/defaults/memory/{search/semantic.ts → v1/semantic-search.ts} +1 -1
  548. package/src/plugins/defaults/memory/v2/__tests__/activation-store.test.ts +1 -1
  549. package/src/plugins/defaults/memory/v2/__tests__/activation.test.ts +11 -274
  550. package/src/plugins/defaults/memory/v2/__tests__/backfill-jobs.test.ts +9 -131
  551. package/src/plugins/defaults/memory/v2/__tests__/harness-compare.test.ts +1 -1
  552. package/src/plugins/defaults/memory/v2/__tests__/harness-oracle.test.ts +1 -1
  553. package/src/plugins/defaults/memory/v2/__tests__/harness-replay-input.test.ts +1 -1
  554. package/src/plugins/defaults/memory/v2/__tests__/injection.test.ts +14 -10
  555. package/src/plugins/defaults/memory/v2/__tests__/reranker.test.ts +7 -5
  556. package/src/plugins/defaults/memory/v2/__tests__/router.test.ts +12 -6
  557. package/src/plugins/defaults/memory/{memory-v2-activation-log-store.ts → v2/activation-log-store.ts} +2 -2
  558. package/src/plugins/defaults/memory/v2/activation-store.ts +22 -8
  559. package/src/plugins/defaults/memory/v2/activation.ts +30 -163
  560. package/src/plugins/defaults/memory/v2/backfill-jobs.ts +7 -54
  561. package/src/plugins/defaults/memory/{memory-v2-concept-frequency.ts → v2/concept-frequency.ts} +3 -3
  562. package/src/plugins/defaults/memory/v2/harness/oracle.ts +1 -1
  563. package/src/plugins/defaults/memory/v2/harness/replay-input.ts +2 -2
  564. package/src/plugins/defaults/memory/v2/harness/retriever.ts +1 -1
  565. package/src/plugins/defaults/memory/v2/injection.ts +36 -26
  566. package/src/plugins/defaults/memory/v2/migration.ts +2 -2
  567. package/src/plugins/defaults/memory/{rerank-local.ts → v2/rerank-local.ts} +44 -18
  568. package/src/plugins/defaults/memory/v2/reranker.ts +29 -11
  569. package/src/plugins/defaults/memory/v2/router.ts +38 -15
  570. package/src/plugins/defaults/memory/v3/__tests__/candidate-match.test.ts +5 -3
  571. package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +21 -8
  572. package/src/plugins/defaults/memory/v3/__tests__/edge.test.ts +1 -1
  573. package/src/plugins/defaults/memory/v3/__tests__/live-integration.test.ts +1 -1
  574. package/src/plugins/defaults/memory/v3/__tests__/maintain-job.test.ts +4 -1
  575. package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +181 -3
  576. package/src/plugins/defaults/memory/v3/__tests__/selection-log-store.test.ts +3 -0
  577. package/src/plugins/defaults/memory/v3/__tests__/shadow-integration.test.ts +14 -5
  578. package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +40 -50
  579. package/src/plugins/defaults/memory/v3/__tests__/tuning-profile.test.ts +1 -0
  580. package/src/plugins/defaults/memory/v3/candidate-match.ts +2 -2
  581. package/src/plugins/defaults/memory/v3/capabilities.ts +6 -4
  582. package/src/plugins/defaults/memory/v3/card.ts +25 -9
  583. package/src/plugins/defaults/memory/v3/edge.ts +52 -18
  584. package/src/plugins/defaults/memory/v3/gate.ts +4 -4
  585. package/src/plugins/defaults/memory/v3/injector.ts +10 -3
  586. package/src/plugins/defaults/memory/v3/maintain-job.ts +3 -3
  587. package/src/plugins/defaults/memory/v3/orchestrate.ts +100 -18
  588. package/src/plugins/defaults/memory/v3/page-content.ts +26 -10
  589. package/src/plugins/defaults/memory/v3/prune.ts +40 -16
  590. package/src/plugins/defaults/memory/v3/selection-log-store.ts +34 -12
  591. package/src/plugins/defaults/memory/v3/shadow-plugin.ts +9 -13
  592. package/src/plugins/defaults/memory/v3/span-query.test.ts +86 -0
  593. package/src/plugins/defaults/memory/v3/span-query.ts +71 -0
  594. package/src/plugins/defaults/memory/v3/tuning-profile.ts +3 -0
  595. package/src/plugins/defaults/memory/v3/types.ts +4 -1
  596. package/src/plugins/defaults/memory/v3-eval/eval-packets.ts +2 -2
  597. package/src/plugins/defaults/memory/validation.ts +1 -1
  598. package/src/plugins/defaults/memory/worker.ts +2 -1
  599. package/src/plugins/defaults/platform-hosted/__tests__/reengage.test.ts +104 -12
  600. package/src/plugins/defaults/platform-hosted/routes/reengage.ts +104 -12
  601. package/src/plugins/types.ts +2 -2
  602. package/src/prompts/sections.ts +4 -16
  603. package/src/providers/__tests__/registry-native-web-search.test.ts +47 -2
  604. package/src/providers/anthropic/client.ts +15 -6
  605. package/src/providers/content-block-schema.ts +26 -0
  606. package/src/providers/inference/__tests__/connections-credential-normalize.test.ts +87 -0
  607. package/src/providers/inference/adapter-factory.ts +6 -0
  608. package/src/providers/inference/connections.ts +30 -14
  609. package/src/providers/model-catalog.ts +77 -0
  610. package/src/providers/openai/__tests__/chat-completions-input-audio.test.ts +260 -0
  611. package/src/providers/openai/chat-completions-provider.ts +65 -17
  612. package/src/providers/openai/input-audio.ts +76 -0
  613. package/src/providers/openrouter/client.ts +0 -2
  614. package/src/providers/platform-proxy/constants.ts +4 -0
  615. package/src/providers/poolside/client.ts +42 -0
  616. package/src/providers/registry.ts +40 -8
  617. package/src/providers/retry.ts +2 -0
  618. package/src/providers/types.ts +39 -1
  619. package/src/providers/vercel-ai-gateway/client.ts +0 -2
  620. package/src/runtime/AGENTS.md +7 -5
  621. package/src/runtime/__tests__/question-request-guardian-bridge.test.ts +173 -0
  622. package/src/runtime/__tests__/question-resolution.test.ts +111 -0
  623. package/src/runtime/access-request-helper.ts +7 -15
  624. package/src/runtime/assistant-event-hub.ts +43 -31
  625. package/src/runtime/assistant-event-publish-options.ts +31 -0
  626. package/src/runtime/assistant-event.ts +19 -30
  627. package/src/runtime/assistant-stream-state.ts +4 -4
  628. package/src/runtime/channel-approvals.ts +0 -25
  629. package/src/runtime/channel-readiness-service.ts +99 -40
  630. package/src/runtime/channel-retry-sweep.ts +38 -15
  631. package/src/runtime/confirmation-request-guardian-bridge.ts +4 -0
  632. package/src/runtime/guardian-reply-router.ts +108 -0
  633. package/src/runtime/http-server.ts +8 -0
  634. package/src/runtime/http-types.ts +2 -2
  635. package/src/runtime/process-role.ts +42 -0
  636. package/src/runtime/question-request-guardian-bridge.ts +184 -0
  637. package/src/runtime/question-resolution.ts +153 -0
  638. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +6 -2
  639. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +1 -1
  640. package/src/runtime/routes/__tests__/subagents-routes.test.ts +250 -0
  641. package/src/runtime/routes/__tests__/webhook-routes.test.ts +201 -0
  642. package/src/runtime/routes/acp-routes.ts +2 -2
  643. package/src/runtime/routes/bookmark-routes.ts +3 -15
  644. package/src/runtime/routes/canned-message-complete.ts +2 -2
  645. package/src/runtime/routes/consolidation-routes.ts +8 -2
  646. package/src/runtime/routes/conversation-list-routes.ts +3 -19
  647. package/src/runtime/routes/conversation-management-routes.ts +1 -5
  648. package/src/runtime/routes/conversation-query-routes.ts +52 -8
  649. package/src/runtime/routes/conversation-routes.ts +36 -22
  650. package/src/runtime/routes/credential-request-routes.ts +0 -1
  651. package/src/runtime/routes/filing-routes.ts +7 -7
  652. package/src/runtime/routes/global-search-routes.ts +1 -1
  653. package/src/runtime/routes/guardian-approval-prompt.ts +2 -2
  654. package/src/runtime/routes/image-generation-routes.ts +12 -9
  655. package/src/runtime/routes/inbound-message-handler.ts +17 -0
  656. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +50 -0
  657. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +19 -0
  658. package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -4
  659. package/src/runtime/routes/inbound-stages/inbound-content-prep.test.ts +129 -0
  660. package/src/runtime/routes/inbound-stages/inbound-content-prep.ts +141 -9
  661. package/src/runtime/routes/index.ts +2 -0
  662. package/src/runtime/routes/lifecycle-routes.ts +199 -0
  663. package/src/runtime/routes/platform-routes.ts +3 -8
  664. package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +7 -7
  665. package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +5 -5
  666. package/src/runtime/routes/question-routes.ts +34 -87
  667. package/src/runtime/routes/secret-routes.ts +11 -1
  668. package/src/runtime/routes/settings-routes.ts +8 -18
  669. package/src/runtime/routes/subagents-routes.ts +35 -8
  670. package/src/runtime/routes/upgrade-broadcast-routes.ts +4 -5
  671. package/src/runtime/routes/webhook-routes.ts +89 -30
  672. package/src/runtime/routes/workspace-routes.test.ts +7 -4
  673. package/src/runtime/slack-reply-session.test.ts +12 -12
  674. package/src/runtime/slack-reply-session.ts +17 -17
  675. package/src/runtime/sync/sync-publisher.test.ts +7 -5
  676. package/src/runtime/tool-grant-request-helper.ts +4 -0
  677. package/src/schedule/schedule-store.ts +70 -0
  678. package/src/schedule/scheduler.ts +27 -0
  679. package/src/security/AGENTS.md +1 -1
  680. package/src/security/credential-key.ts +17 -0
  681. package/src/security/secret-ingress.ts +14 -105
  682. package/src/security/secret-patterns.ts +8 -139
  683. package/src/security/secret-scanner.ts +8 -3
  684. package/src/security/store-path-override.ts +6 -16
  685. package/src/sequence/store.ts +8 -0
  686. package/src/signals/emit-event.ts +5 -10
  687. package/src/signals/event-stream.ts +20 -10
  688. package/src/subagent/manager.ts +76 -25
  689. package/src/subagent/notify.ts +8 -0
  690. package/src/subagent/types.ts +13 -3
  691. package/src/telegram/__tests__/webhook-health.test.ts +442 -0
  692. package/src/telegram/webhook-health.ts +478 -0
  693. package/src/telemetry/AGENTS.md +6 -0
  694. package/src/telemetry/memory-corpus-size.test.ts +129 -0
  695. package/src/telemetry/memory-corpus-size.ts +184 -0
  696. package/src/telemetry/memory-tier-reporter.test.ts +67 -2
  697. package/src/telemetry/memory-tier-reporter.ts +30 -3
  698. package/src/tools/__tests__/conversation-group-tool-input-schemas.test.ts +61 -0
  699. package/src/tools/__tests__/document-tool-input-schemas.test.ts +103 -0
  700. package/src/tools/__tests__/followup-call-acp-tool-input-schemas.test.ts +125 -0
  701. package/src/tools/__tests__/schedule-tool-input-schemas.test.ts +83 -0
  702. package/src/tools/__tests__/subagent-workflow-tool-input-schemas.test.ts +116 -0
  703. package/src/tools/__tests__/tool-input-schemas.test.ts +192 -0
  704. package/src/tools/__tests__/tool-schema-drift-harness.ts +142 -0
  705. package/src/tools/acp/abort.ts +21 -1
  706. package/src/tools/acp/context.ts +5 -5
  707. package/src/tools/acp/spawn.test.ts +15 -5
  708. package/src/tools/acp/spawn.ts +26 -3
  709. package/src/tools/acp/status.ts +20 -1
  710. package/src/tools/acp/steer.test.ts +20 -0
  711. package/src/tools/acp/steer.ts +23 -2
  712. package/src/tools/apps/resolve-app-id.ts +15 -3
  713. package/src/tools/ask-question/ask-question-tool.test.ts +65 -0
  714. package/src/tools/ask-question/ask-question-tool.ts +68 -92
  715. package/src/tools/browser/browser-screencast.ts +6 -6
  716. package/src/tools/calls/call-end.ts +24 -3
  717. package/src/tools/calls/call-start.ts +35 -11
  718. package/src/tools/calls/call-status.ts +20 -1
  719. package/src/tools/conversation-groups/group_create.ts +63 -0
  720. package/src/tools/conversation-groups/group_list.ts +20 -0
  721. package/src/tools/conversation-groups/group_shared.ts +52 -0
  722. package/src/tools/conversation-groups/move_to_group.ts +106 -0
  723. package/src/tools/document/document-comment-tool.test.ts +49 -0
  724. package/src/tools/document/document-comment-tool.ts +45 -6
  725. package/src/tools/document/document-tool.ts +142 -24
  726. package/src/tools/executor.ts +27 -13
  727. package/src/tools/filesystem/edit.ts +62 -60
  728. package/src/tools/filesystem/list.ts +36 -29
  729. package/src/tools/filesystem/read.ts +56 -39
  730. package/src/tools/filesystem/write.ts +44 -38
  731. package/src/tools/followups/followup_create.ts +41 -12
  732. package/src/tools/followups/followup_list.ts +34 -6
  733. package/src/tools/followups/followup_resolve.ts +26 -4
  734. package/src/tools/host-filesystem/edit.ts +50 -60
  735. package/src/tools/host-filesystem/read.ts +45 -39
  736. package/src/tools/host-filesystem/write.ts +31 -36
  737. package/src/tools/host-terminal/host-shell.ts +76 -62
  738. package/src/tools/policy-context.ts +27 -10
  739. package/src/tools/schedule/create.ts +76 -33
  740. package/src/tools/schedule/delete.ts +21 -2
  741. package/src/tools/schedule/list.ts +25 -3
  742. package/src/tools/schedule/update.ts +105 -48
  743. package/src/tools/shared/filesystem/path-policy.ts +246 -40
  744. package/src/tools/shared/zod-tool-schema.ts +117 -0
  745. package/src/tools/subagent/abort.ts +12 -4
  746. package/src/tools/subagent/consult-deadline.ts +9 -3
  747. package/src/tools/subagent/message.ts +21 -5
  748. package/src/tools/subagent/notify-parent.ts +44 -23
  749. package/src/tools/subagent/read.ts +15 -4
  750. package/src/tools/subagent/resolve.ts +26 -4
  751. package/src/tools/subagent/spawn.ts +37 -13
  752. package/src/tools/subagent/status.ts +12 -4
  753. package/src/tools/system/request-permission.ts +35 -26
  754. package/src/tools/terminal/shell.ts +68 -55
  755. package/src/tools/tool-approval-handler.ts +327 -53
  756. package/src/tools/tool-input-schemas.ts +85 -0
  757. package/src/tools/tool-types.ts +7 -0
  758. package/src/tools/types.ts +8 -0
  759. package/src/tools/workflows/manage-workflows.ts +30 -2
  760. package/src/tools/workflows/run-workflow.test.ts +54 -2
  761. package/src/tools/workflows/run-workflow.ts +32 -4
  762. package/src/util/fs-symlinks.ts +30 -0
  763. package/src/util/log-redact.ts +7 -3
  764. package/src/util/platform.ts +15 -0
  765. package/src/vellum-assistant-namespace.d.ts +80 -0
  766. package/src/watcher/watcher-store.ts +8 -0
  767. package/src/workflows/leaf-runner.test.ts +104 -2
  768. package/src/workflows/leaf-runner.ts +31 -6
  769. package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +2 -2
  770. package/src/workspace/migrations/134-image-generation-mode-to-provider.ts +128 -0
  771. package/src/workspace/migrations/135-copy-substrate-tunables.ts +248 -0
  772. package/src/workspace/migrations/__tests__/135-copy-substrate-tunables.test.ts +446 -0
  773. package/src/workspace/migrations/__tests__/backfill-v3-leaves.test.ts +2 -2
  774. package/src/workspace/migrations/registry.ts +4 -0
  775. package/tsconfig.plugin-api.json +1 -1
  776. package/src/__tests__/memory-retrieval-budget.test.ts +0 -49
  777. package/src/__tests__/secret-patterns.test.ts +0 -27
  778. package/src/config/__tests__/proc-to-skills.test.ts +0 -21
  779. package/src/config/memory-tier.test.ts +0 -44
  780. package/src/daemon/message-types/acp.ts +0 -20
  781. package/src/daemon/message-types/apps.ts +0 -11
  782. package/src/daemon/message-types/background-tools.ts +0 -14
  783. package/src/daemon/message-types/bookmarks.ts +0 -13
  784. package/src/daemon/message-types/contacts.ts +0 -13
  785. package/src/daemon/message-types/document-comments.ts +0 -14
  786. package/src/daemon/message-types/documents.ts +0 -13
  787. package/src/daemon/message-types/home.ts +0 -15
  788. package/src/daemon/message-types/host-bash.ts +0 -12
  789. package/src/daemon/message-types/host-cu.ts +0 -10
  790. package/src/daemon/message-types/host-file.ts +0 -12
  791. package/src/daemon/message-types/host-transfer.ts +0 -12
  792. package/src/daemon/message-types/integrations.ts +0 -90
  793. package/src/daemon/message-types/memory.ts +0 -10
  794. package/src/daemon/message-types/schedules.ts +0 -14
  795. package/src/daemon/message-types/settings.ts +0 -17
  796. package/src/daemon/message-types/subagents.ts +0 -63
  797. package/src/daemon/message-types/upgrades.ts +0 -14
  798. package/src/daemon/message-types/workflows.ts +0 -25
  799. package/src/daemon/message-types/workspace.ts +0 -137
  800. package/src/live-voice/ack-phrases.ts +0 -58
  801. package/src/plugins/defaults/memory/retrieval-budget.ts +0 -29
  802. package/src/plugins/defaults/memory/v3/__tests__/gate-flag.test.ts +0 -69
  803. package/src/plugins/defaults/memory/v3/gate-flag.ts +0 -20
  804. package/src/plugins/defaults/memory/v3/substrate/__tests__/memory-v2-startup.test.ts +0 -86
  805. package/src/plugins/defaults/memory/v3/substrate/memory-v2-startup.test.ts +0 -205
  806. /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/concept-page-frontmatter-schema.test.ts +0 -0
  807. /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/consolidation-prompt-flag-gating-guard.test.ts +0 -0
  808. /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/injected-block-slugs.test.ts +0 -0
  809. /package/src/plugins/defaults/memory/{v3/substrate → substrate}/cli-command-content.ts +0 -0
@@ -8,8 +8,7 @@ import { z } from "zod";
8
8
  import type { ServiceGroupUpdateCompleteEvent } from "../../api/events/service-group-update-complete.js";
9
9
  import type { ServiceGroupUpdateProgressEvent } from "../../api/events/service-group-update-progress.js";
10
10
  import type { ServiceGroupUpdateStartingEvent } from "../../api/events/service-group-update-starting.js";
11
- import { buildAssistantEvent } from "../assistant-event.js";
12
- import { assistantEventHub } from "../assistant-event-hub.js";
11
+ import { broadcastMessage } from "../assistant-event-hub.js";
13
12
  import { GATEWAY_PRINCIPALS } from "../auth/route-policy.js";
14
13
  import { BadRequestError } from "./errors.js";
15
14
  import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
@@ -48,7 +47,7 @@ async function handleUpgradeBroadcast({ body }: RouteHandlerArgs) {
48
47
  expectedDowntimeSeconds: downtime,
49
48
  };
50
49
 
51
- await assistantEventHub.publish(buildAssistantEvent(message));
50
+ broadcastMessage(message);
52
51
 
53
52
  return { ok: true };
54
53
  }
@@ -67,7 +66,7 @@ async function handleUpgradeBroadcast({ body }: RouteHandlerArgs) {
67
66
  statusMessage,
68
67
  };
69
68
 
70
- await assistantEventHub.publish(buildAssistantEvent(message));
69
+ broadcastMessage(message);
71
70
 
72
71
  return { ok: true };
73
72
  }
@@ -108,7 +107,7 @@ async function handleUpgradeBroadcast({ body }: RouteHandlerArgs) {
108
107
  : {}),
109
108
  };
110
109
 
111
- await assistantEventHub.publish(buildAssistantEvent(message));
110
+ broadcastMessage(message);
112
111
 
113
112
  return { ok: true };
114
113
  }
@@ -3,9 +3,8 @@
3
3
  *
4
4
  * Serves two operations:
5
5
  * - webhooks_register (POST webhooks/register): Resolve a stable callback URL
6
- * for a webhook type, registering with the platform gateway on
7
- * platform-managed assistants or using the configured ingress.publicBaseUrl
8
- * on self-hosted assistants.
6
+ * for a webhook type. See `handleWebhooksRegister` for the resolution
7
+ * order.
9
8
  * - webhooks_list (GET webhooks): List all webhook callback routes registered
10
9
  * with the platform for this assistant.
11
10
  */
@@ -18,7 +17,10 @@ import {
18
17
  registerCallbackRoute,
19
18
  resolvePlatformCallbackRegistrationContext,
20
19
  } from "../../inbound/platform-callback-registration.js";
21
- import { getPublicBaseUrl } from "../../inbound/public-ingress-urls.js";
20
+ import {
21
+ getPublicBaseUrl,
22
+ type IngressConfig,
23
+ } from "../../inbound/public-ingress-urls.js";
22
24
  import { ACTOR_PRINCIPALS } from "../auth/route-policy.js";
23
25
  import {
24
26
  BadRequestError,
@@ -77,10 +79,66 @@ function deriveWebhookPath(type: string): string {
77
79
  return `webhooks/${type.replace(/_/g, "/")}`;
78
80
  }
79
81
 
82
+ /**
83
+ * Register `webhookPath` with the platform gateway, mapping failures onto the
84
+ * route error vocabulary.
85
+ */
86
+ async function registerWithPlatform(
87
+ webhookPath: string,
88
+ type: string,
89
+ source: string | undefined,
90
+ ): Promise<WebhooksRegisterResponse> {
91
+ let callbackUrl: string;
92
+ try {
93
+ callbackUrl = await registerCallbackRoute(webhookPath, type, source);
94
+ } catch (err) {
95
+ const msg = (err as Error).message;
96
+ if (msg.includes("missing platform registration context")) {
97
+ throw new UnprocessableEntityError(msg);
98
+ }
99
+ throw new InternalError(`Failed to register callback route: ${msg}`);
100
+ }
101
+ return { callbackUrl, type, path: webhookPath, mode: "platform" };
102
+ }
103
+
104
+ /**
105
+ * True when the user has explicitly switched public ingress off.
106
+ *
107
+ * An explicit opt-out is a decision not to accept inbound webhooks at all, so
108
+ * it must not be silently routed around via platform callbacks. An *absent*
109
+ * ingress config is merely "not set up yet" and is eligible for the platform
110
+ * fallback.
111
+ */
112
+ function isPublicIngressDisabled(config: IngressConfig): boolean {
113
+ return config.ingress?.enabled === false;
114
+ }
115
+
80
116
  // ---------------------------------------------------------------------------
81
117
  // Handlers
82
118
  // ---------------------------------------------------------------------------
83
119
 
120
+ /**
121
+ * Resolve a stable callback URL for a webhook type.
122
+ *
123
+ * Resolution order:
124
+ * 1. **Platform pods** (`IS_PLATFORM`) always register with the platform
125
+ * gateway: they have no ingress of their own to advertise.
126
+ * 2. **A configured public ingress wins** for everyone else. That URL is
127
+ * either the user's own tunnel (ngrok, a custom domain) or the Velay
128
+ * tunnel URL the gateway publishes into `ingress.publicBaseUrl`, so a
129
+ * platform-connected local assistant with a live tunnel already resolves
130
+ * to a stable platform-owned URL here.
131
+ * 3. **Platform-connected assistants with no ingress** register with the
132
+ * platform gateway rather than failing. Connectivity is decided by
133
+ * credentials (platform base URL + assistant ID + assistant API key), not
134
+ * by `IS_PLATFORM`, which is only ever true on a platform pod.
135
+ *
136
+ * Ingress deliberately precedes platform registration: any logged-in local
137
+ * assistant holds platform credentials (it needs them for the LLM proxy), so
138
+ * treating credential presence as "managed" would silently reroute an
139
+ * explicitly configured self-hosted webhook through the platform. The gateway's
140
+ * Telegram and email registrars order the same two tiers the same way.
141
+ */
84
142
  async function handleWebhooksRegister(
85
143
  args: RouteHandlerArgs,
86
144
  ): Promise<WebhooksRegisterResponse> {
@@ -92,39 +150,40 @@ async function handleWebhooksRegister(
92
150
 
93
151
  const webhookPath =
94
152
  (pathOverride as string | undefined) ?? deriveWebhookPath(type as string);
153
+ const sourceIdentifier = source as string | undefined;
95
154
 
96
155
  if (getIsPlatform()) {
97
- let callbackUrl: string;
98
- try {
99
- callbackUrl = await registerCallbackRoute(
100
- webhookPath,
101
- type as string,
102
- source as string | undefined,
103
- );
104
- } catch (err) {
105
- const msg = (err as Error).message;
106
- if (msg.includes("missing platform registration context")) {
107
- throw new UnprocessableEntityError(msg);
108
- }
109
- throw new InternalError(`Failed to register callback route: ${msg}`);
110
- }
111
- return { callbackUrl, type, path: webhookPath, mode: "platform" };
156
+ return registerWithPlatform(webhookPath, type, sourceIdentifier);
112
157
  }
113
158
 
114
- // Self-hosted: use ingress.publicBaseUrl
115
159
  const config = getConfig();
116
- let baseUrl: string;
160
+ if (isPublicIngressDisabled(config)) {
161
+ throw new UnprocessableEntityError(
162
+ "Public ingress is disabled. Ask the assistant to enable it, or update it from the Settings page.",
163
+ );
164
+ }
165
+
166
+ let ingressError: Error;
117
167
  try {
118
- baseUrl = getPublicBaseUrl(config);
168
+ const baseUrl = getPublicBaseUrl(config);
169
+ return {
170
+ callbackUrl: `${baseUrl}/${webhookPath}`,
171
+ type,
172
+ path: webhookPath,
173
+ mode: "self-hosted",
174
+ };
119
175
  } catch (err) {
120
- throw new UnprocessableEntityError((err as Error).message);
176
+ ingressError = err as Error;
121
177
  }
122
- return {
123
- callbackUrl: `${baseUrl}/${webhookPath}`,
124
- type,
125
- path: webhookPath,
126
- mode: "self-hosted",
127
- };
178
+
179
+ // No ingress configured. Fall back to the platform gateway when this
180
+ // assistant is connected to the platform.
181
+ const context = await resolvePlatformCallbackRegistrationContext();
182
+ if (context.enabled) {
183
+ return registerWithPlatform(webhookPath, type, sourceIdentifier);
184
+ }
185
+
186
+ throw new UnprocessableEntityError(ingressError.message);
128
187
  }
129
188
 
130
189
  async function handleWebhooksList(
@@ -189,7 +248,7 @@ export const ROUTES: RouteDefinition[] = [
189
248
  },
190
249
  summary: "Register a webhook callback URL",
191
250
  description:
192
- "Resolves a stable callback URL for a webhook type. On platform-managed assistants, registers the route with the platform gateway. On self-hosted assistants, uses the configured ingress.publicBaseUrl.",
251
+ "Resolves a stable callback URL for a webhook type. On platform-managed assistants, registers the route with the platform gateway. Otherwise uses the configured ingress.publicBaseUrl, falling back to the platform gateway when no ingress is configured and the assistant is connected to the platform.",
193
252
  tags: ["webhooks"],
194
253
  requestBody: WebhooksRegisterRequestSchema,
195
254
  responseBody: WebhooksRegisterResponseSchema,
@@ -17,8 +17,8 @@ import {
17
17
  import { join } from "node:path";
18
18
  import { beforeAll, describe, expect, test } from "bun:test";
19
19
 
20
+ import type { AssistantEventEnvelope } from "../../api/index.js";
20
21
  import { SYNC_TAGS } from "../../daemon/message-types/sync.js";
21
- import type { AssistantEvent } from "../assistant-event.js";
22
22
  import { assistantEventHub } from "../assistant-event-hub.js";
23
23
 
24
24
  // ---------------------------------------------------------------------------
@@ -66,15 +66,18 @@ beforeAll(() => {
66
66
 
67
67
  function getRoute(operationId: string): RouteDefinition {
68
68
  const route = ROUTES.find((r) => r.operationId === operationId);
69
- if (!route)
69
+ if (!route) {
70
70
  throw new Error(`No shared route found for operationId: ${operationId}`);
71
+ }
71
72
  return route;
72
73
  }
73
74
 
74
75
  async function waitFor(predicate: () => boolean): Promise<void> {
75
76
  const deadline = Date.now() + 500;
76
77
  while (Date.now() < deadline) {
77
- if (predicate()) return;
78
+ if (predicate()) {
79
+ return;
80
+ }
78
81
  await new Promise((resolve) => setTimeout(resolve, 5));
79
82
  }
80
83
  throw new Error("Timed out waiting for workspace route event");
@@ -557,7 +560,7 @@ describe("POST /v1/workspace/write", () => {
557
560
  });
558
561
 
559
562
  test("publishes sounds sync events when writing sounds config", async () => {
560
- const received: AssistantEvent[] = [];
563
+ const received: AssistantEventEnvelope[] = [];
561
564
  const subscription = assistantEventHub.subscribe({
562
565
  type: "process",
563
566
  callback: (event) => {
@@ -28,7 +28,7 @@ mock.module("./gateway-client.js", () => ({
28
28
  },
29
29
  }));
30
30
 
31
- import type { ServerMessage } from "../daemon/message-protocol.js";
31
+ import type { AssistantEvent } from "../api/index.js";
32
32
  import { SLACK_STREAM_MARKDOWN_LIMIT } from "../messaging/providers/slack/api.js";
33
33
  import {
34
34
  createSlackReplySession,
@@ -39,34 +39,34 @@ const CHANNEL = "D-STREAM";
39
39
  const THREAD_TS = "1700000000.000001";
40
40
  const CALLBACK_URL = `https://example.test/deliver/slack?channel=${CHANNEL}&threadTs=${THREAD_TS}`;
41
41
 
42
- const textDelta = (text: string): ServerMessage =>
42
+ const textDelta = (text: string): AssistantEvent =>
43
43
  ({
44
44
  type: "assistant_text_delta",
45
45
  text,
46
46
  conversationId: "conv-stream",
47
- }) as ServerMessage;
47
+ }) as AssistantEvent;
48
48
 
49
- const toolUseStart = (toolUseId: string): ServerMessage =>
49
+ const toolUseStart = (toolUseId: string): AssistantEvent =>
50
50
  ({
51
51
  type: "tool_use_start",
52
52
  toolName: "web_search",
53
53
  input: { query: "example" },
54
54
  conversationId: "conv-stream",
55
55
  toolUseId,
56
- }) as ServerMessage;
56
+ }) as AssistantEvent;
57
57
 
58
- const messageComplete = (messageId: string): ServerMessage =>
58
+ const messageComplete = (messageId: string): AssistantEvent =>
59
59
  ({
60
60
  type: "message_complete",
61
61
  conversationId: "conv-stream",
62
62
  messageId,
63
- }) as ServerMessage;
63
+ }) as AssistantEvent;
64
64
 
65
65
  const taskProgressShow = (
66
66
  surfaceId: string,
67
67
  steps: Array<{ label: string; status: string; detail?: string }>,
68
68
  templateTitle?: string,
69
- ): ServerMessage =>
69
+ ): AssistantEvent =>
70
70
  ({
71
71
  type: "ui_surface_show",
72
72
  conversationId: "conv-stream",
@@ -80,18 +80,18 @@ const taskProgressShow = (
80
80
  steps,
81
81
  },
82
82
  },
83
- }) as ServerMessage;
83
+ }) as AssistantEvent;
84
84
 
85
85
  const taskProgressUpdate = (
86
86
  surfaceId: string,
87
87
  steps: Array<{ label: string; status: string }>,
88
- ): ServerMessage =>
88
+ ): AssistantEvent =>
89
89
  ({
90
90
  type: "ui_surface_update",
91
91
  conversationId: "conv-stream",
92
92
  surfaceId,
93
93
  data: { templateData: { steps } },
94
- }) as ServerMessage;
94
+ }) as AssistantEvent;
95
95
 
96
96
  const tick = (ms: number): Promise<void> =>
97
97
  new Promise((resolve) => setTimeout(resolve, ms));
@@ -351,7 +351,7 @@ describe("createSlackReplySession", () => {
351
351
  test("falls back when stopStream throws after streaming text", async () => {
352
352
  deliverImpl = async (_url, payload) => {
353
353
  const op = payload.slackStream as { action: string };
354
- if (op.action === "stop") throw new Error("stop failed");
354
+ if (op.action === "stop") {throw new Error("stop failed");}
355
355
  return { ok: true, ts: "stream-ts-1" };
356
356
  };
357
357
  const session = createSlackReplySession({
@@ -1,5 +1,6 @@
1
1
  import type { SlackStreamTask } from "@vellumai/gateway-client";
2
2
 
3
+ import type { AssistantEvent } from "../api/index.js";
3
4
  import {
4
5
  extractThreadTsFromCallbackUrl,
5
6
  isSlackDeliveryCallbackUrl,
@@ -9,7 +10,6 @@ import {
9
10
  incompleteVellumLinkSuffixLength,
10
11
  stripVellumLinks,
11
12
  } from "../daemon/assistant-attachments.js";
12
- import type { ServerMessage } from "../daemon/message-protocol.js";
13
13
  import { SLACK_STREAM_MARKDOWN_LIMIT } from "../messaging/providers/slack/api.js";
14
14
  import { renderSlackBlocks } from "../messaging/providers/slack/render.js";
15
15
  import { getLogger } from "../util/logger.js";
@@ -51,7 +51,7 @@ export type SlackStreamReconciliation =
51
51
  | { mode: "fallback" };
52
52
 
53
53
  export type SlackReplySession = {
54
- observeEvent: (msg: ServerMessage) => void;
54
+ observeEvent: (msg: AssistantEvent) => void;
55
55
  /**
56
56
  * Settle in-flight stream operations, finalize the stream, and report how
57
57
  * durable delivery should reconcile. Call once after processing completes.
@@ -79,12 +79,12 @@ export function shouldStreamSlackReply(params: {
79
79
  recipientUserId?: string;
80
80
  recipientTeamId?: string;
81
81
  }): boolean {
82
- if (params.sourceChannel !== "slack") return false;
83
- if (!isSlackDeliveryCallbackUrl(params.replyCallbackUrl)) return false;
82
+ if (params.sourceChannel !== "slack") {return false;}
83
+ if (!isSlackDeliveryCallbackUrl(params.replyCallbackUrl)) {return false;}
84
84
  if (extractThreadTsFromCallbackUrl(params.replyCallbackUrl) === null) {
85
85
  return false;
86
86
  }
87
- if (params.chatType === "im") return true;
87
+ if (params.chatType === "im") {return true;}
88
88
  return Boolean(params.recipientUserId && params.recipientTeamId);
89
89
  }
90
90
 
@@ -130,7 +130,7 @@ export function createSlackReplySession(params: {
130
130
  const coalesceMs = params.coalesceMs ?? STREAM_COALESCE_MS;
131
131
  const replyCallbackUrl = params.replyCallbackUrl;
132
132
  const threadTs = extractThreadTsFromCallbackUrl(replyCallbackUrl);
133
- if (threadTs === null) return undefined;
133
+ if (threadTs === null) {return undefined;}
134
134
 
135
135
  let state: StreamState = "idle";
136
136
  let started = false;
@@ -172,7 +172,7 @@ export function createSlackReplySession(params: {
172
172
  // (and `stripVellumLinks` can remove it). Once `finished`, no delta can
173
173
  // extend the text, so the full cleaned reply is safe to emit.
174
174
  const streamableText = (): string => {
175
- if (finished) return cleanedText();
175
+ if (finished) {return cleanedText();}
176
176
  const hold = incompleteVellumLinkSuffixLength(rawText);
177
177
  const stable = hold > 0 ? rawText.slice(0, rawText.length - hold) : rawText;
178
178
  return stripVellumLinks(stable).replace(NO_RESPONSE_INLINE_RE, "");
@@ -205,7 +205,7 @@ export function createSlackReplySession(params: {
205
205
  const enqueueStart = (): void => {
206
206
  enqueue(async () => {
207
207
  const clean = streamableText();
208
- if (clean.trim().length === 0) return;
208
+ if (clean.trim().length === 0) {return;}
209
209
  const firstChunk = clean.slice(0, SLACK_STREAM_MARKDOWN_LIMIT);
210
210
  const title = activeProgress?.title;
211
211
  const tasks = planTasks();
@@ -259,7 +259,7 @@ export function createSlackReplySession(params: {
259
259
 
260
260
  const enqueueAppend = (): void => {
261
261
  enqueue(async () => {
262
- if (state !== "streaming" || !streamTs) return;
262
+ if (state !== "streaming" || !streamTs) {return;}
263
263
  const clean = streamableText();
264
264
  const title = activeProgress?.title;
265
265
  const tasks = planTasks();
@@ -329,9 +329,9 @@ export function createSlackReplySession(params: {
329
329
  clearTimeout(coalesceTimer);
330
330
  coalesceTimer = undefined;
331
331
  }
332
- if (finished || state === "fallback") return;
332
+ if (finished || state === "fallback") {return;}
333
333
  if (!started) {
334
- if (!hasDeliverableAssistantText(streamableText())) return;
334
+ if (!hasDeliverableAssistantText(streamableText())) {return;}
335
335
  started = true;
336
336
  enqueueStart();
337
337
  return;
@@ -340,7 +340,7 @@ export function createSlackReplySession(params: {
340
340
  };
341
341
 
342
342
  const scheduleFlush = (): void => {
343
- if (coalesceTimer || finished) return;
343
+ if (coalesceTimer || finished) {return;}
344
344
  coalesceTimer = setTimeout(() => {
345
345
  coalesceTimer = undefined;
346
346
  flush();
@@ -356,15 +356,15 @@ export function createSlackReplySession(params: {
356
356
  }
357
357
  };
358
358
 
359
- const observeTaskProgress = (msg: ServerMessage): void => {
359
+ const observeTaskProgress = (msg: AssistantEvent): void => {
360
360
  if (msg.type === "ui_surface_show") {
361
361
  const progress = getTaskProgressDataFromSurfaceData(msg.data);
362
- if (!progress) return;
362
+ if (!progress) {return;}
363
363
  taskProgressBySurfaceId.set(msg.surfaceId, progress);
364
364
  } else if (msg.type === "ui_surface_update") {
365
365
  const existing = taskProgressBySurfaceId.get(msg.surfaceId);
366
366
  const progress = mergeTaskProgressData(existing, msg.data);
367
- if (!progress) return;
367
+ if (!progress) {return;}
368
368
  taskProgressBySurfaceId.set(msg.surfaceId, progress);
369
369
  } else {
370
370
  return;
@@ -375,7 +375,7 @@ export function createSlackReplySession(params: {
375
375
 
376
376
  return {
377
377
  observeEvent(msg) {
378
- if (finished) return;
378
+ if (finished) {return;}
379
379
 
380
380
  if (msg.type === "ui_surface_show" || msg.type === "ui_surface_update") {
381
381
  observeTaskProgress(msg);
@@ -415,7 +415,7 @@ export function createSlackReplySession(params: {
415
415
 
416
416
  enqueueAppend();
417
417
  enqueue(async () => {
418
- if (state !== "streaming" || !streamTs) return;
418
+ if (state !== "streaming" || !streamTs) {return;}
419
419
  const clean = cleanedText();
420
420
  const remaining = clean.slice(confirmedLength);
421
421
  const blocks = imageBlocks(clean);
@@ -1,7 +1,7 @@
1
1
  import { describe, expect, test } from "bun:test";
2
2
 
3
+ import type { AssistantEventEnvelope } from "../../api/index.js";
3
4
  import { SYNC_TAGS } from "../../daemon/message-types/sync.js";
4
- import type { AssistantEvent } from "../assistant-event.js";
5
5
  import { assistantEventHub, broadcastMessage } from "../assistant-event-hub.js";
6
6
  import { publishSyncInvalidation } from "./sync-publisher.js";
7
7
 
@@ -18,7 +18,7 @@ async function waitFor(predicate: () => boolean): Promise<void> {
18
18
 
19
19
  describe("sync publisher", () => {
20
20
  test("publishes a deduped sync_changed event", async () => {
21
- const received: AssistantEvent[] = [];
21
+ const received: AssistantEventEnvelope[] = [];
22
22
  const subscription = assistantEventHub.subscribe({
23
23
  type: "process",
24
24
  callback: (event) => {
@@ -104,7 +104,7 @@ describe("sync publisher", () => {
104
104
  });
105
105
 
106
106
  test("forwards originClientId when provided", async () => {
107
- const received: AssistantEvent[] = [];
107
+ const received: AssistantEventEnvelope[] = [];
108
108
  const subscription = assistantEventHub.subscribe({
109
109
  type: "process",
110
110
  callback: (event) => {
@@ -132,7 +132,7 @@ describe("sync publisher", () => {
132
132
  });
133
133
 
134
134
  test("omits originClientId when not provided", async () => {
135
- const received: AssistantEvent[] = [];
135
+ const received: AssistantEventEnvelope[] = [];
136
136
  const subscription = assistantEventHub.subscribe({
137
137
  type: "process",
138
138
  callback: (event) => {
@@ -141,7 +141,9 @@ describe("sync publisher", () => {
141
141
  });
142
142
 
143
143
  try {
144
- const message = await publishSyncInvalidation([SYNC_TAGS.assistantAvatar]);
144
+ const message = await publishSyncInvalidation([
145
+ SYNC_TAGS.assistantAvatar,
146
+ ]);
145
147
 
146
148
  await waitFor(() => received.length === 1);
147
149
 
@@ -21,6 +21,7 @@ import {
21
21
  recordApprovalCardDelivery,
22
22
  recordGuardianRequestDeliveries,
23
23
  } from "../notifications/guardian-delivery-recorder.js";
24
+ import { buildVellumCardAffinity } from "../notifications/vellum-card-affinity.js";
24
25
  import { getLogger } from "../util/logger.js";
25
26
  import { resolveApprovalSourceReference } from "./approval-source-link.js";
26
27
  import { getGuardianBinding } from "./channel-verification-service.js";
@@ -177,6 +178,9 @@ export async function createOrReuseToolGrantRequest(
177
178
  sourceChannel,
178
179
  sourceContextId: conversationId,
179
180
  requiresConversation: true,
181
+ // Pin the in-app (vellum) card to the conversation the escalated tool is
182
+ // running in, so the guardian decides it in context.
183
+ ...(buildVellumCardAffinity(conversationId) ?? {}),
180
184
  attentionHints: {
181
185
  requiresAction: true,
182
186
  urgency: "high",
@@ -3,6 +3,7 @@ import { and, asc, desc, eq, isNull, lt, lte, sql } from "drizzle-orm";
3
3
  import { v4 as uuid } from "uuid";
4
4
 
5
5
  import { getDb } from "../persistence/db-connection.js";
6
+ import { isLifecycleQuiesced } from "../persistence/lifecycle-quiesce.js";
6
7
  import { rawChanges } from "../persistence/raw-query.js";
7
8
  import { scheduleJobs, scheduleRuns } from "../persistence/schema/index.js";
8
9
  import { publishSchedulesChanged } from "../runtime/sync/resource-sync-events.js";
@@ -465,6 +466,15 @@ export async function deleteSchedule(id: string): Promise<boolean> {
465
466
  * next_run_at <= now and enabled = true and cron_expression IS NULL.
466
467
  */
467
468
  export async function claimDueSchedules(now: number): Promise<ScheduleJob[]> {
469
+ // Drain gate: while a quiesce lease is active, claim nothing so in-flight
470
+ // runs can drain before a stop. The check lives here — immediately before
471
+ // the claim writes — rather than at the tick boundary, to shrink the window
472
+ // in which a lease armed mid-tick could miss a claim that already passed an
473
+ // earlier check. Fail-open via the lease read.
474
+ if (isLifecycleQuiesced()) {
475
+ return [];
476
+ }
477
+
468
478
  const db = getDb();
469
479
  const claimed: ScheduleJob[] = [];
470
480
 
@@ -750,6 +760,27 @@ export async function createScheduleRun(
750
760
  return id;
751
761
  }
752
762
 
763
+ /** Currently-running schedule runs with their job names, oldest first. */
764
+ export function listRunningScheduleRuns(): Array<{
765
+ runId: string;
766
+ scheduleName: string | null;
767
+ startedAt: number;
768
+ }> {
769
+ const db = getDb();
770
+ return db
771
+ .select({
772
+ runId: scheduleRuns.id,
773
+ scheduleName: scheduleJobs.name,
774
+ startedAt: scheduleRuns.startedAt,
775
+ })
776
+ .from(scheduleRuns)
777
+ .leftJoin(scheduleJobs, eq(scheduleRuns.jobId, scheduleJobs.id))
778
+ .where(eq(scheduleRuns.status, "running"))
779
+ .orderBy(asc(scheduleRuns.startedAt))
780
+ .limit(20)
781
+ .all();
782
+ }
783
+
753
784
  export async function setScheduleRunConversationId(
754
785
  runId: string,
755
786
  conversationId: string,
@@ -1082,6 +1113,45 @@ export function describeCronExpression(expr: string | null): string {
1082
1113
  }
1083
1114
  }
1084
1115
 
1116
+ /**
1117
+ * Return a claimed-but-not-started schedule to the queue (drain deferral).
1118
+ *
1119
+ * Restores everything the claim mutated before any execution began:
1120
+ * `nextRunAt` is pulled to `nextRetryAt`, a one-shot's `firing` reverts to
1121
+ * `active`, and `enabled` is restored — a bounded recurring schedule's final
1122
+ * occurrence is claimed by exhausting the job (`enabled = false`,
1123
+ * `nextRunAt = 0`), so without the restore that deferred final occurrence
1124
+ * would never fire.
1125
+ */
1126
+ export async function deferClaimedSchedule(
1127
+ id: string,
1128
+ nextRetryAt: number,
1129
+ ): Promise<void> {
1130
+ const db = getDb();
1131
+ const now = Date.now();
1132
+ await withSqliteRetry(
1133
+ () => {
1134
+ db.update(scheduleJobs)
1135
+ .set({ nextRunAt: nextRetryAt, enabled: true, updatedAt: now })
1136
+ .where(eq(scheduleJobs.id, id))
1137
+ .run();
1138
+ return rawChanges() > 0;
1139
+ },
1140
+ { op: "deferClaimedSchedule.requeue", context: { scheduleId: id } },
1141
+ );
1142
+ await withSqliteRetry(
1143
+ () => {
1144
+ db.update(scheduleJobs)
1145
+ .set({ status: "active", updatedAt: now })
1146
+ .where(and(eq(scheduleJobs.id, id), eq(scheduleJobs.status, "firing")))
1147
+ .run();
1148
+ return rawChanges() > 0;
1149
+ },
1150
+ { op: "deferClaimedSchedule.status", context: { scheduleId: id } },
1151
+ );
1152
+ notifySchedulesChanged();
1153
+ }
1154
+
1085
1155
  /**
1086
1156
  * Set the next retry time for a schedule and revert one-shot status from
1087
1157
  * "firing" to "active" so the scheduler will claim it again when nextRetryAt
@@ -9,6 +9,7 @@ import { processMessage } from "../daemon/process-message.js";
9
9
  import { INTERNAL_GUARDIAN_TRUST_CONTEXT } from "../daemon/trust-context.js";
10
10
  import { emitNotificationSignal } from "../notifications/emit-signal.js";
11
11
  import { getConversation } from "../persistence/conversation-crud.js";
12
+ import { isLifecycleQuiesced } from "../persistence/lifecycle-quiesce.js";
12
13
  import { invalidateAssistantInferredItemsForConversation } from "../plugins/defaults/memory/task-memory-cleanup.js";
13
14
  import { wakeAgentForOpportunity } from "../runtime/agent-wake.js";
14
15
  import { broadcastMessage } from "../runtime/assistant-event-hub.js";
@@ -33,6 +34,7 @@ import {
33
34
  completeOneShot,
34
35
  completeScheduleRun,
35
36
  createScheduleRun,
37
+ deferClaimedSchedule,
36
38
  failOneShotPermanently,
37
39
  getLastScheduleConversationId,
38
40
  resetRetryCount,
@@ -434,6 +436,9 @@ export async function runScheduleDueWorkOnce(
434
436
  return result;
435
437
  }
436
438
 
439
+ // The drain quiesce gates live inside claimDueWatchers and
440
+ // claimDueEnrollments, immediately before their claim writes.
441
+
437
442
  // ── Watchers (event-driven polling) ────────────────────────────────
438
443
  try {
439
444
  const watcherProcessed = await runWatchersOnce(emitWatcherNotifySignal);
@@ -463,6 +468,9 @@ export async function runScheduleDueWorkOnce(
463
468
  * (`worker.ts`). Claims are atomic in the schedule store, so overlapping ticks
464
469
  * cannot double-run a job another claim already took.
465
470
  */
471
+ /** How far a claimed-but-quiesced schedule is pushed back into the queue. */
472
+ const QUIESCE_DEFER_MS = 30_000;
473
+
466
474
  export async function runDueSchedulesOnce(
467
475
  now: number = Date.now(),
468
476
  ): Promise<SchedulerDueWorkResult> {
@@ -490,9 +498,28 @@ export async function runDueSchedulesOnce(
490
498
  return result;
491
499
  }
492
500
 
501
+ // The drain quiesce gate lives inside claimDueSchedules, immediately
502
+ // before the claim writes.
493
503
  const jobs = await claimDueSchedules(now);
494
504
  result.claimed = jobs.length;
495
505
  for (const job of jobs) {
506
+ // Lease re-check per claimed job: a lease armed between the batch claim
507
+ // and this job's start returns the job to the queue untouched instead of
508
+ // starting work the drain snapshot cannot see — notify mode especially,
509
+ // which emits before any run row exists.
510
+ if (isLifecycleQuiesced()) {
511
+ try {
512
+ await deferClaimedSchedule(job.id, Date.now() + QUIESCE_DEFER_MS);
513
+ } catch (err) {
514
+ log.warn(
515
+ { err, jobId: job.id },
516
+ "Failed to defer claimed schedule under quiesce",
517
+ );
518
+ }
519
+ result.skipped += 1;
520
+ continue;
521
+ }
522
+
496
523
  const isOneShot = job.expression == null;
497
524
 
498
525
  // ── Notify mode (one-shot or recurring) ─────────────────────────