@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
@@ -0,0 +1,39 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+ import { getSqliteFrom } from "../db-connection.js";
3
+
4
+ /**
5
+ * Add the script-handoff and skill-binding columns to `cron_jobs`.
6
+ *
7
+ * - `then_execute` — when set on a script-mode schedule, the firing hands the
8
+ * script's stdout to an agent turn instead of only recording it on the run
9
+ * row. Defaults to 0 so every pre-existing script schedule keeps its
10
+ * no-LLM behaviour.
11
+ * - `skill_id` — the managed skill whose `scripts/` the command invokes. NULL
12
+ * (all pre-existing rows) means the schedule is not bound to a skill.
13
+ * - `skill_version_hash` — the skill's content hash at creation time,
14
+ * re-checked before each firing so a rewritten script cannot keep running
15
+ * under the original approval.
16
+ *
17
+ * Idempotent — the PRAGMA guard makes re-running a no-op once the columns
18
+ * exist.
19
+ */
20
+ export function migrateScheduleSkillScriptHandoff(database: DrizzleDb): void {
21
+ const raw = getSqliteFrom(database);
22
+
23
+ const columns = raw.query(`PRAGMA table_info(cron_jobs)`).all() as Array<{
24
+ name: string;
25
+ }>;
26
+ const columnNames = new Set(columns.map((c) => c.name));
27
+
28
+ if (!columnNames.has("then_execute")) {
29
+ raw.exec(
30
+ `ALTER TABLE cron_jobs ADD COLUMN then_execute INTEGER NOT NULL DEFAULT 0`,
31
+ );
32
+ }
33
+ if (!columnNames.has("skill_id")) {
34
+ raw.exec(`ALTER TABLE cron_jobs ADD COLUMN skill_id TEXT`);
35
+ }
36
+ if (!columnNames.has("skill_version_hash")) {
37
+ raw.exec(`ALTER TABLE cron_jobs ADD COLUMN skill_version_hash TEXT`);
38
+ }
39
+ }
@@ -0,0 +1,83 @@
1
+ import { Database } from "bun:sqlite";
2
+ import { describe, expect, test } from "bun:test";
3
+
4
+ import { drizzle } from "drizzle-orm/bun-sqlite";
5
+
6
+ import * as schema from "../schema.js";
7
+ import { migrateScheduleSkillScriptHandoff } from "./351-schedule-skill-script-handoff.js";
8
+ import { migrateDropScheduleSkillScriptHandoff } from "./352-drop-schedule-skill-script-handoff.js";
9
+
10
+ /** Minimal `cron_jobs`, trimmed to what these two migrations touch. */
11
+ function createTestDb() {
12
+ const sqlite = new Database(":memory:");
13
+ sqlite.exec(/*sql*/ `
14
+ CREATE TABLE cron_jobs (
15
+ id TEXT PRIMARY KEY,
16
+ name TEXT NOT NULL,
17
+ message TEXT NOT NULL,
18
+ next_run_at INTEGER NOT NULL,
19
+ created_by TEXT NOT NULL,
20
+ created_at INTEGER NOT NULL,
21
+ updated_at INTEGER NOT NULL
22
+ )
23
+ `);
24
+ return { sqlite, db: drizzle(sqlite, { schema }) };
25
+ }
26
+
27
+ function columnNames(sqlite: Database): string[] {
28
+ return (
29
+ sqlite.query("PRAGMA table_info(cron_jobs)").all() as Array<{
30
+ name: string;
31
+ }>
32
+ ).map((c) => c.name);
33
+ }
34
+
35
+ const REVERTED = ["then_execute", "skill_id", "skill_version_hash"];
36
+
37
+ describe("migration 352 — drop reverted schedule columns", () => {
38
+ test("removes the columns 351 added", () => {
39
+ const { sqlite, db } = createTestDb();
40
+
41
+ migrateScheduleSkillScriptHandoff(db);
42
+ for (const column of REVERTED) {
43
+ expect(columnNames(sqlite)).toContain(column);
44
+ }
45
+
46
+ migrateDropScheduleSkillScriptHandoff(db);
47
+ for (const column of REVERTED) {
48
+ expect(columnNames(sqlite)).not.toContain(column);
49
+ }
50
+ });
51
+
52
+ test("leaves the surrounding columns intact", () => {
53
+ const { sqlite, db } = createTestDb();
54
+ const before = columnNames(sqlite);
55
+
56
+ migrateScheduleSkillScriptHandoff(db);
57
+ migrateDropScheduleSkillScriptHandoff(db);
58
+
59
+ // 351 + 352 net to nothing: the pair exists only so the already-recorded
60
+ // 351 can stay in the ledger.
61
+ expect(columnNames(sqlite)).toEqual(before);
62
+ });
63
+
64
+ test("is a no-op on a database that never ran 351", () => {
65
+ const { sqlite, db } = createTestDb();
66
+ const before = columnNames(sqlite);
67
+
68
+ expect(() => migrateDropScheduleSkillScriptHandoff(db)).not.toThrow();
69
+ expect(columnNames(sqlite)).toEqual(before);
70
+ });
71
+
72
+ test("is idempotent when re-run after a partial application", () => {
73
+ const { sqlite, db } = createTestDb();
74
+ migrateScheduleSkillScriptHandoff(db);
75
+ // Simulate a crash between column drops.
76
+ sqlite.exec("ALTER TABLE cron_jobs DROP COLUMN skill_id");
77
+
78
+ expect(() => migrateDropScheduleSkillScriptHandoff(db)).not.toThrow();
79
+ for (const column of REVERTED) {
80
+ expect(columnNames(sqlite)).not.toContain(column);
81
+ }
82
+ });
83
+ });
@@ -0,0 +1,36 @@
1
+ import { getLogger } from "../../util/logger.js";
2
+ import { type DrizzleDb, getSqliteFrom } from "../db-connection.js";
3
+
4
+ const log = getLogger("migration-352");
5
+
6
+ /**
7
+ * Drops the script-handoff and skill-binding columns from `cron_jobs`.
8
+ *
9
+ * Migration 351 added `then_execute`, `skill_id`, and `skill_version_hash` for
10
+ * a feature that has since been reverted. 351 is deliberately left in place:
11
+ * it has already run on deployed assistants, and removing a migration the
12
+ * ledger has recorded would break migration-state validation. So the pair
13
+ * nets to nothing — 351 adds the columns, this drops them again.
14
+ *
15
+ * No data is carried over. The feature never shipped to users, so no schedule
16
+ * has meaningful values in these columns.
17
+ *
18
+ * Idempotent: each column is checked before it is dropped, so re-running after
19
+ * a partial application is a no-op.
20
+ */
21
+ export function migrateDropScheduleSkillScriptHandoff(
22
+ database: DrizzleDb,
23
+ ): void {
24
+ const raw = getSqliteFrom(database);
25
+
26
+ const columns = raw.query(`PRAGMA table_info(cron_jobs)`).all() as Array<{
27
+ name: string;
28
+ }>;
29
+ const columnNames = new Set(columns.map((c) => c.name));
30
+
31
+ for (const column of ["then_execute", "skill_id", "skill_version_hash"]) {
32
+ if (!columnNames.has(column)) continue;
33
+ raw.exec(`ALTER TABLE cron_jobs DROP COLUMN ${column}`);
34
+ log.info({ column }, "Dropped reverted schedule column from cron_jobs");
35
+ }
36
+ }
@@ -0,0 +1,110 @@
1
+ import { Database } from "bun:sqlite";
2
+ import { describe, expect, test } from "bun:test";
3
+
4
+ import { drizzle } from "drizzle-orm/bun-sqlite";
5
+
6
+ import * as schema from "../schema.js";
7
+ import { migrateAddLlmUsageConversationType } from "./353-add-llm-usage-conversation-type.js";
8
+
9
+ function createTestDb() {
10
+ const sqlite = new Database(":memory:");
11
+ // Pre-353 shape: only the columns the migration and tests touch.
12
+ sqlite.exec(/*sql*/ `
13
+ CREATE TABLE conversations (
14
+ id TEXT PRIMARY KEY,
15
+ conversation_type TEXT,
16
+ created_at INTEGER NOT NULL,
17
+ updated_at INTEGER NOT NULL
18
+ );
19
+ CREATE TABLE llm_usage_events (
20
+ id TEXT PRIMARY KEY,
21
+ created_at INTEGER NOT NULL,
22
+ conversation_id TEXT,
23
+ provider TEXT NOT NULL,
24
+ model TEXT NOT NULL,
25
+ input_tokens INTEGER NOT NULL,
26
+ output_tokens INTEGER NOT NULL,
27
+ pricing_status TEXT NOT NULL
28
+ );
29
+ `);
30
+ return { sqlite, db: drizzle(sqlite, { schema }) };
31
+ }
32
+
33
+ function insertConversation(
34
+ sqlite: Database,
35
+ id: string,
36
+ conversationType: string,
37
+ ): void {
38
+ sqlite.run(
39
+ `INSERT INTO conversations (id, conversation_type, created_at, updated_at) VALUES (?, ?, 1000, 1000)`,
40
+ [id, conversationType],
41
+ );
42
+ }
43
+
44
+ function insertUsageEvent(
45
+ sqlite: Database,
46
+ id: string,
47
+ conversationId: string | null,
48
+ ): void {
49
+ sqlite.run(
50
+ `INSERT INTO llm_usage_events (id, created_at, conversation_id, provider, model, input_tokens, output_tokens, pricing_status)
51
+ VALUES (?, 1000, ?, 'anthropic', 'test-model', 1, 1, 'priced')`,
52
+ [id, conversationId],
53
+ );
54
+ }
55
+
56
+ function typeOf(sqlite: Database, eventId: string): unknown {
57
+ const row = sqlite
58
+ .query("SELECT conversation_type FROM llm_usage_events WHERE id = ?")
59
+ .get(eventId) as { conversation_type: unknown };
60
+ return row.conversation_type;
61
+ }
62
+
63
+ describe("migration 353: llm_usage_events.conversation_type", () => {
64
+ test("adds the nullable column", () => {
65
+ const { sqlite, db } = createTestDb();
66
+ migrateAddLlmUsageConversationType(db);
67
+
68
+ const columns = (
69
+ sqlite.query("PRAGMA table_info(llm_usage_events)").all() as Array<{
70
+ name: string;
71
+ notnull: number;
72
+ }>
73
+ ).filter((c) => c.name === "conversation_type");
74
+ expect(columns).toHaveLength(1);
75
+ expect(columns[0].notnull).toBe(0);
76
+ });
77
+
78
+ test("backfills existing rows from surviving parent conversations", () => {
79
+ const { sqlite, db } = createTestDb();
80
+ insertConversation(sqlite, "conv-bg", "background");
81
+ insertUsageEvent(sqlite, "evt-live-parent", "conv-bg");
82
+ // Parent already deleted before the upgrade — unrecoverable, stays NULL.
83
+ insertUsageEvent(sqlite, "evt-gone-parent", "conv-gone");
84
+ insertUsageEvent(sqlite, "evt-no-parent", null);
85
+
86
+ migrateAddLlmUsageConversationType(db);
87
+
88
+ expect(typeOf(sqlite, "evt-live-parent")).toBe("background");
89
+ expect(typeOf(sqlite, "evt-gone-parent")).toBeNull();
90
+ expect(typeOf(sqlite, "evt-no-parent")).toBeNull();
91
+ });
92
+
93
+ test("re-run never overwrites existing stamps", () => {
94
+ const { sqlite, db } = createTestDb();
95
+ insertConversation(sqlite, "conv-std", "standard");
96
+ insertUsageEvent(sqlite, "evt-1", "conv-std");
97
+
98
+ migrateAddLlmUsageConversationType(db);
99
+ expect(typeOf(sqlite, "evt-1")).toBe("standard");
100
+
101
+ // Simulate the parent's type having been recorded differently than the
102
+ // row now joined (the stamp is the record-time truth): a re-run must
103
+ // fill only NULLs and leave existing values alone.
104
+ sqlite.run(
105
+ `UPDATE llm_usage_events SET conversation_type = 'background' WHERE id = 'evt-1'`,
106
+ );
107
+ migrateAddLlmUsageConversationType(db);
108
+ expect(typeOf(sqlite, "evt-1")).toBe("background");
109
+ });
110
+ });
@@ -0,0 +1,49 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+ import { tableHasColumn } from "./schema-introspection.js";
3
+
4
+ const COLUMN_NAME = "conversation_type";
5
+ const COLUMN_DEFINITION = "conversation_type TEXT";
6
+
7
+ /**
8
+ * Add `conversation_type` column to the `llm_usage_events` table and
9
+ * backfill it from `conversations` for existing rows.
10
+ *
11
+ * The column captures the parent conversation's `conversation_type`
12
+ * (`"standard"` / `"background"` / `"scheduled"`) at the moment the usage
13
+ * event is RECORDED. The telemetry reporter previously derived the type
14
+ * exclusively via a flush-time LEFT JOIN to `conversations`, but usage rows
15
+ * outlive conversation rows — memory-retrospective forks are GC'd once a
16
+ * newer run supersedes them (or deleted immediately on wake failure), and
17
+ * users can delete conversations — so any row flushed after its parent
18
+ * conversation's deletion reported a null `conversation_type` despite
19
+ * carrying a `conversation_id`.
20
+ *
21
+ * The backfill stamps every existing row whose parent conversation still
22
+ * exists, so usage rows pending flush at upgrade time (delayed or offline
23
+ * telemetry) keep their type even if the parent conversation is deleted
24
+ * before the next successful flush. Rows whose parents are already gone
25
+ * stay NULL — their type is unrecoverable. The telemetry read path
26
+ * (`queryUnreportedUsageEvents`) COALESCEs the stored value with the JOIN
27
+ * as a final fallback.
28
+ *
29
+ * Idempotent: the ALTER is guarded with `tableHasColumn` so a crash between
30
+ * the `ALTER TABLE` and the checkpoint write doesn't cause a
31
+ * duplicate-column error on the next boot, and the backfill only fills NULL
32
+ * values so a re-run never overwrites record-time stamps.
33
+ */
34
+ export function migrateAddLlmUsageConversationType(database: DrizzleDb): void {
35
+ if (!tableHasColumn(database, "llm_usage_events", COLUMN_NAME)) {
36
+ database.run(
37
+ `ALTER TABLE llm_usage_events ADD COLUMN ${COLUMN_DEFINITION}`,
38
+ );
39
+ }
40
+ database.run(
41
+ `UPDATE llm_usage_events
42
+ SET conversation_type = (
43
+ SELECT c.conversation_type FROM conversations AS c
44
+ WHERE c.id = llm_usage_events.conversation_id
45
+ )
46
+ WHERE conversation_id IS NOT NULL
47
+ AND conversation_type IS NULL`,
48
+ );
49
+ }
@@ -275,6 +275,17 @@ export const llmUsageEvents = sqliteTable(
275
275
  * persisted before migration 267 ran.
276
276
  */
277
277
  assistantVersion: text("assistant_version"),
278
+ /**
279
+ * `conversations.conversation_type` of the parent conversation
280
+ * (`"standard"` / `"background"` / `"scheduled"`), captured at RECORD
281
+ * time. The parent conversation can be deleted before the telemetry
282
+ * flush joins against it (memory-retrospective forks are GC'd once
283
+ * superseded; users delete conversations), so a flush-time JOIN alone
284
+ * under-labels usage rows. Null when the call has no parent
285
+ * conversation and for rows persisted before migration 353 ran (the
286
+ * telemetry read path falls back to the JOIN for those).
287
+ */
288
+ conversationType: text("conversation_type"),
278
289
  },
279
290
  (table) => [
280
291
  index("idx_llm_usage_events_conversation_id").on(table.conversationId),
@@ -9,7 +9,7 @@
9
9
 
10
10
  import { backfillAppConversationIds } from "../apps/app-store.js";
11
11
  // Forward migration + down function imports
12
- import { migrateToolCreatedItems } from "../plugins/defaults/memory/graph/bootstrap.js";
12
+ import { migrateToolCreatedItems } from "../plugins/defaults/memory/v1/graph/bootstrap.js";
13
13
  import { migrateCoreTables } from "./migrations/000-core-tables.js";
14
14
  import {
15
15
  downJobDeferrals,
@@ -458,6 +458,9 @@ import { migrateDeleteStrayGreetingConversation } from "./migrations/347-delete-
458
458
  import { migrateMemorySummariesScopeUpdatedIndex } from "./migrations/348-memory-summaries-scope-updated-index.js";
459
459
  import { migrateMoveMemoryGraphTablesToMemoryDb } from "./migrations/349-move-memory-graph-tables-to-memory-db.js";
460
460
  import { migrateConversationsTotalInputTokensNullable } from "./migrations/350-conversations-total-input-tokens-nullable.js";
461
+ import { migrateScheduleSkillScriptHandoff } from "./migrations/351-schedule-skill-script-handoff.js";
462
+ import { migrateDropScheduleSkillScriptHandoff } from "./migrations/352-drop-schedule-skill-script-handoff.js";
463
+ import { migrateAddLlmUsageConversationType } from "./migrations/353-add-llm-usage-conversation-type.js";
461
464
  import type { MigrationStep } from "./migrations/run-migrations.js";
462
465
 
463
466
  export const migrationSteps: MigrationStep[] = [
@@ -1473,4 +1476,7 @@ export const migrationSteps: MigrationStep[] = [
1473
1476
  ],
1474
1477
  },
1475
1478
  migrateConversationsTotalInputTokensNullable,
1479
+ migrateScheduleSkillScriptHandoff,
1480
+ migrateDropScheduleSkillScriptHandoff,
1481
+ migrateAddLlmUsageConversationType,
1476
1482
  ];
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Tests the daemon-vs-side-process routing in the event-hub facade (exercised
3
+ * through {@link publishEvent}).
4
+ *
5
+ * In the daemon the event publishes on the local hub; in a side process (where
6
+ * seq stamping is disabled) the local hub reaches no SSE subscriber, so the
7
+ * event is forwarded to the daemon over IPC instead. The `host_*` guard must
8
+ * run before either path. The process-role signal and the IPC forward are
9
+ * mocked so the test controls the branch without spawning a subprocess.
10
+ */
11
+
12
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
13
+
14
+ import type { AssistantEventEnvelope } from "../../api/index.js";
15
+
16
+ let sideProcess = false;
17
+ const forwardCalls: Array<{
18
+ event: AssistantEventEnvelope;
19
+ options: unknown;
20
+ }> = [];
21
+
22
+ mock.module("../../runtime/process-role.js", () => ({
23
+ isMainDaemonProcess: () => !sideProcess,
24
+ markCurrentProcessAsMainDaemon: () => {},
25
+ }));
26
+
27
+ mock.module("../../ipc/events-publish-client.js", () => ({
28
+ EVENTS_PUBLISH_IPC_METHOD: "/events/publish",
29
+ forwardEventPublishToDaemon: async (
30
+ event: AssistantEventEnvelope,
31
+ options: unknown,
32
+ ) => {
33
+ forwardCalls.push({ event, options });
34
+ },
35
+ }));
36
+
37
+ const { assistantEventHub } =
38
+ await import("../../runtime/assistant-event-hub.js");
39
+ const { publishEvent } = await import("../publish-event.js");
40
+
41
+ function syncEvent(): AssistantEventEnvelope {
42
+ return {
43
+ id: "evt-1",
44
+ conversationId: "conv-1",
45
+ emittedAt: "2026-01-01T00:00:00.000Z",
46
+ message: {
47
+ type: "sync_changed",
48
+ tags: ["my-app:items"],
49
+ } as unknown as AssistantEventEnvelope["message"],
50
+ };
51
+ }
52
+
53
+ function collectLocalDeliveries(): {
54
+ received: AssistantEventEnvelope[];
55
+ dispose: () => void;
56
+ } {
57
+ const received: AssistantEventEnvelope[] = [];
58
+ const sub = assistantEventHub.subscribe({
59
+ type: "process",
60
+ callback: (event) => {
61
+ received.push(event);
62
+ },
63
+ });
64
+ return { received, dispose: () => sub.dispose() };
65
+ }
66
+
67
+ beforeEach(() => {
68
+ sideProcess = false;
69
+ forwardCalls.length = 0;
70
+ });
71
+
72
+ describe("publishEvent — daemon vs side-process routing", () => {
73
+ test("in the daemon, publishes on the local hub (no IPC forward)", async () => {
74
+ sideProcess = false;
75
+ const local = collectLocalDeliveries();
76
+ try {
77
+ await publishEvent(syncEvent());
78
+ } finally {
79
+ local.dispose();
80
+ }
81
+ expect(local.received).toHaveLength(1);
82
+ expect(local.received[0].message.type).toBe("sync_changed");
83
+ expect(forwardCalls).toHaveLength(0);
84
+ });
85
+
86
+ test("in a side process, forwards to the daemon (no local publish)", async () => {
87
+ sideProcess = true;
88
+ const local = collectLocalDeliveries();
89
+ try {
90
+ await publishEvent(syncEvent());
91
+ } finally {
92
+ local.dispose();
93
+ }
94
+ expect(forwardCalls).toHaveLength(1);
95
+ expect(forwardCalls[0].event.message.type).toBe("sync_changed");
96
+ // The local hub reaches no SSE subscriber in a side process, so nothing is
97
+ // delivered locally.
98
+ expect(local.received).toHaveLength(0);
99
+ });
100
+
101
+ test("rejects a host-proxy event before forwarding, even in a side process", async () => {
102
+ sideProcess = true;
103
+ const hostEvent: AssistantEventEnvelope = {
104
+ id: "evt-2",
105
+ emittedAt: "2026-01-01T00:00:00.000Z",
106
+ message: {
107
+ type: "host_bash_request",
108
+ } as unknown as AssistantEventEnvelope["message"],
109
+ };
110
+ await expect(publishEvent(hostEvent)).rejects.toThrow(/host-proxy/);
111
+ expect(forwardCalls).toHaveLength(0);
112
+ });
113
+ });
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Tests for the plugin-facing {@link publishEvent} helper. It is a thin wrapper
3
+ * over the capability-restricted event-hub facade, so these assert the two
4
+ * behaviours a caller relies on: a plain event reaches hub subscribers, and a
5
+ * host-proxy control event is rejected.
6
+ */
7
+
8
+ import { describe, expect, test } from "bun:test";
9
+
10
+ import type { AssistantEventEnvelope } from "../../api/index.js";
11
+ import { assistantEventHub } from "../../runtime/assistant-event-hub.js";
12
+ import { publishEvent } from "../publish-event.js";
13
+
14
+ // A test process defaults to "main daemon" (set by the test preload), so the
15
+ // hub publishes locally here rather than forwarding.
16
+
17
+ function syncEvent(): AssistantEventEnvelope {
18
+ return {
19
+ id: "evt-1",
20
+ conversationId: "conv-1",
21
+ emittedAt: "2026-01-01T00:00:00.000Z",
22
+ message: {
23
+ type: "sync_changed",
24
+ tags: ["my-app:items"],
25
+ } as unknown as AssistantEventEnvelope["message"],
26
+ };
27
+ }
28
+
29
+ describe("publishEvent", () => {
30
+ test("delivers a plain event to hub subscribers", async () => {
31
+ const received: AssistantEventEnvelope[] = [];
32
+ const sub = assistantEventHub.subscribe({
33
+ type: "process",
34
+ callback: (event) => {
35
+ received.push(event);
36
+ },
37
+ });
38
+ try {
39
+ await publishEvent(syncEvent());
40
+ } finally {
41
+ sub.dispose();
42
+ }
43
+ expect(received).toHaveLength(1);
44
+ expect(received[0].message.type).toBe("sync_changed");
45
+ });
46
+
47
+ test("rejects a host-proxy control event", async () => {
48
+ const hostEvent: AssistantEventEnvelope = {
49
+ id: "evt-2",
50
+ emittedAt: "2026-01-01T00:00:00.000Z",
51
+ message: {
52
+ type: "host_bash_request",
53
+ } as unknown as AssistantEventEnvelope["message"],
54
+ };
55
+ await expect(publishEvent(hostEvent)).rejects.toThrow(/host-proxy/);
56
+ });
57
+ });
@@ -13,8 +13,8 @@
13
13
  * context management.
14
14
  */
15
15
 
16
+ import type { AssistantEvent } from "../api/index.js";
16
17
  import type { LLMCallSite } from "../config/schemas/llm.js";
17
- import type { ServerMessage } from "../daemon/message-protocol.js";
18
18
  import type { UserMessageAttachment } from "../daemon/message-types/shared.js";
19
19
  import type { ContentBlock, MediaSource } from "../providers/types.js";
20
20
 
@@ -144,9 +144,9 @@ export async function runConversationTurn(
144
144
  const { resolveMediaSourceData } =
145
145
  await import("../providers/media-resolve.js");
146
146
  const { getConversation, getMessageById, getMessages } =
147
- await import("../persistence/conversation-crud.js");
147
+ await import("../persistence/conversation-crud.js");
148
148
  const { publishConversationListAndMetadataChanged } =
149
- await import("../runtime/sync/resource-sync-events.js");
149
+ await import("../runtime/sync/resource-sync-events.js");
150
150
 
151
151
  // Plugin-driven turns run as the guardian: plugins are installed by the
152
152
  // guardian, so their conversations inherit guardian trust. This lets the
@@ -193,7 +193,7 @@ export async function runConversationTurn(
193
193
  // buildEventEmitter pattern from process-message.ts so plugin-driven
194
194
  // turns reach the same subscribers as HTTP-driven turns.
195
195
  let assistantMessageId: string | undefined;
196
- const onEvent = (msg: ServerMessage): void => {
196
+ const onEvent = (msg: AssistantEvent): void => {
197
197
  broadcastMessage(msg, conversationId);
198
198
  if (msg.type === "message_complete" && msg.messageId) {
199
199
  assistantMessageId = msg.messageId;
@@ -40,7 +40,7 @@
40
40
  * mid-fanout (the hub delivers one object to every subscriber in turn).
41
41
  */
42
42
 
43
- import type { AssistantEvent } from "../runtime/assistant-event.js";
43
+ import type { AssistantEventEnvelope } from "../api/index.js";
44
44
  import {
45
45
  type AssistantEventFilter,
46
46
  type AssistantEventHub,
@@ -86,8 +86,12 @@ function wireSnapshot<T>(value: T): T {
86
86
  * client receives it.
87
87
  */
88
88
  function deepFreeze<T>(value: T, seen: WeakSet<object> = new WeakSet()): T {
89
- if (value === null || typeof value !== "object") return value;
90
- if (seen.has(value)) return value;
89
+ if (value === null || typeof value !== "object") {
90
+ return value;
91
+ }
92
+ if (seen.has(value)) {
93
+ return value;
94
+ }
91
95
  seen.add(value);
92
96
  for (const key of Object.keys(value)) {
93
97
  deepFreeze((value as Record<string, unknown>)[key], seen);
@@ -105,7 +109,9 @@ const startsWith = Function.prototype.call.bind(
105
109
  ) as (str: string, search: string) => boolean;
106
110
 
107
111
  /** The blocked event type if `event` is a host-proxy control event, else `undefined`. */
108
- function hostControlEventType(event: AssistantEvent): string | undefined {
112
+ function hostControlEventType(
113
+ event: AssistantEventEnvelope,
114
+ ): string | undefined {
109
115
  const type: unknown = event.message?.type;
110
116
  return typeof type === "string" &&
111
117
  startsWith(type, HOST_CONTROL_EVENT_TYPE_PREFIX)
@@ -134,7 +140,7 @@ export const pluginAssistantEventHub: PluginEventHub = Object.freeze({
134
140
  type: "process",
135
141
  filter,
136
142
  callback: (event) => {
137
- let isolated: AssistantEvent;
143
+ let isolated: AssistantEventEnvelope;
138
144
  try {
139
145
  isolated = deepFreeze(wireSnapshot(event));
140
146
  } catch {
@@ -146,7 +152,7 @@ export const pluginAssistantEventHub: PluginEventHub = Object.freeze({
146
152
  },
147
153
 
148
154
  publish: async (event, options) => {
149
- let snapshot: AssistantEvent;
155
+ let snapshot: AssistantEventEnvelope;
150
156
  let snapshotOptions: Parameters<AssistantEventHub["publish"]>[1];
151
157
  try {
152
158
  snapshot = deepFreeze(wireSnapshot(event));
@@ -160,6 +166,9 @@ export const pluginAssistantEventHub: PluginEventHub = Object.freeze({
160
166
  `Plugins may not publish daemon-to-client host-proxy control events (type "${blockedType}").`,
161
167
  );
162
168
  }
169
+ // `assistantEventHub.publish` forwards to the daemon when this is not the
170
+ // main process, so the guarded snapshot reaches real subscribers whether
171
+ // published here or from a sidecar worker.
163
172
  return assistantEventHub.publish(snapshot, snapshotOptions);
164
173
  },
165
174
 
@@ -127,7 +127,7 @@ export { RiskLevel } from "./types.js";
127
127
  // Workspace-local plugins resolve these via the boot-time shim, which
128
128
  // re-binds each from the assistant's globalThis-parked namespace so they
129
129
  // share module identity with the assistant's own singletons.
130
- export type { AssistantEvent } from "../runtime/assistant-event.js";
130
+ export type { AssistantEvent, AssistantEventEnvelope } from "../api/index.js";
131
131
  export type {
132
132
  AssistantEventCallback,
133
133
  AssistantEventFilter,
@@ -144,12 +144,18 @@ export type {
144
144
  export type { PluginEventHub } from "./event-hub-facade.js";
145
145
  /**
146
146
  * @deprecated Direct hub access is being replaced by narrower, purpose-built
147
- * importable helpers (e.g. a plugin-driven publish wrapper) so plugins don't
148
- * hold the general publish/subscribe surface. Avoid new usage; prefer the
149
- * scoped helpers as they land.
147
+ * importable helpers so plugins don't hold the general publish/subscribe
148
+ * surface. To emit an event, prefer {@link publishEvent}; avoid new usage of
149
+ * the raw hub.
150
150
  */
151
151
  export { pluginAssistantEventHub as assistantEventHub } from "./event-hub-facade.js";
152
152
  export { getModelProfiles } from "./model-profiles.js";
153
+ // Purpose-built publish wrapper: emit a runtime event to the assistant's event
154
+ // hub without holding the general hub handle. Route/hook authors surfacing a UI
155
+ // invalidation (e.g. `sync_changed`) import this. Delegates to the same
156
+ // capability-restricted facade, so host-proxy control events stay rejected.
157
+ export type { AssistantEventPublishOptions } from "../runtime/assistant-event-publish-options.js";
158
+ export { publishEvent } from "./publish-event.js";
153
159
  // Check whether a model or profile can process image input. Accepts a concrete
154
160
  // model id, a profile key, or a `ModelProfileInfo`; a bare string is resolved
155
161
  // as a model id first and then as a profile key. Profile resolution merges over