@vellumai/assistant 0.10.4 → 0.10.5-dev.202607022329.d89bf2f

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 (866) hide show
  1. package/ARCHITECTURE.md +94 -91
  2. package/Dockerfile +5 -16
  3. package/README.md +7 -10
  4. package/bun.lock +0 -4
  5. package/docs/architecture/security.md +20 -20
  6. package/docs/stt-provider-onboarding.md +4 -5
  7. package/docs/trusted-contact-access.md +7 -7
  8. package/eslint-rules/cli-no-daemon-internals.js +4 -0
  9. package/eslint.config.mjs +7 -1
  10. package/knip.json +0 -1
  11. package/node_modules/@vellumai/gateway-client/src/__tests__/contact-read-contracts.test.ts +36 -0
  12. package/node_modules/@vellumai/gateway-client/src/__tests__/invite-contract.test.ts +233 -0
  13. package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +40 -0
  14. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +20 -8
  15. package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +10 -0
  16. package/node_modules/@vellumai/gateway-client/src/index.ts +33 -0
  17. package/node_modules/@vellumai/gateway-client/src/invite-contract.ts +216 -0
  18. package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +91 -0
  19. package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +39 -3
  20. package/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +0 -8
  21. package/node_modules/@vellumai/service-contracts/src/__tests__/package-boundary.test.ts +1 -5
  22. package/node_modules/@vellumai/service-contracts/src/twilio-ingress.ts +3 -14
  23. package/openapi.yaml +1073 -225
  24. package/package.json +1 -4
  25. package/scripts/test.sh +35 -13
  26. package/src/__tests__/access-request-seed-content-blocks.test.ts +60 -4
  27. package/src/__tests__/acp-session.test.ts +4 -1
  28. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +0 -6
  29. package/src/__tests__/add-message-preassigned-id.test.ts +56 -0
  30. package/src/__tests__/agent-loop-set-system-prompt.test.ts +139 -0
  31. package/src/__tests__/app-conversation-ids-backfill.test.ts +3 -0
  32. package/src/__tests__/app-source-watcher.test.ts +11 -0
  33. package/src/__tests__/approval-interception-trust-gates.test.ts +148 -3
  34. package/src/__tests__/assistant-attachments.test.ts +62 -4
  35. package/src/__tests__/assistant-id-boundary-guard.test.ts +0 -1
  36. package/src/__tests__/attachments-store-heic-normalize.test.ts +230 -0
  37. package/src/__tests__/attachments-store.test.ts +3 -0
  38. package/src/__tests__/background-shell-bash.test.ts +34 -0
  39. package/src/__tests__/background-shell-host-bash.test.ts +12 -0
  40. package/src/__tests__/background-tool-registry.test.ts +97 -0
  41. package/src/__tests__/background-tool-routes.test.ts +72 -1
  42. package/src/__tests__/background-workers-disk-pressure.test.ts +2 -1
  43. package/src/__tests__/btw-routes.test.ts +57 -3
  44. package/src/__tests__/call-controller.test.ts +474 -84
  45. package/src/__tests__/call-domain.test.ts +48 -1
  46. package/src/__tests__/call-pointer-messages.test.ts +57 -19
  47. package/src/__tests__/call-pointer-no-hardcoded-copy.guard.test.ts +2 -6
  48. package/src/__tests__/call-routes-http.test.ts +15 -14
  49. package/src/__tests__/call-setup-flow-invite.test.ts +568 -0
  50. package/src/__tests__/call-setup-flow-midcall-trust.test.ts +231 -0
  51. package/src/__tests__/call-setup-flow-name-capture.test.ts +754 -0
  52. package/src/__tests__/call-setup-flow-verification.test.ts +925 -0
  53. package/src/__tests__/call-setup-flow.test.ts +311 -0
  54. package/src/__tests__/cancel-resolves-conversation-key.test.ts +0 -1
  55. package/src/__tests__/channel-guardian.test.ts +4 -7
  56. package/src/__tests__/channel-readiness-service.test.ts +0 -6
  57. package/src/__tests__/channel-readiness-slack-remote.test.ts +0 -4
  58. package/src/__tests__/channel-retry-sweep.test.ts +76 -64
  59. package/src/__tests__/channel-setup-panel-ack.test.ts +184 -0
  60. package/src/__tests__/clear-all-lexical.test.ts +90 -0
  61. package/src/__tests__/compactor-media-strip.test.ts +177 -0
  62. package/src/__tests__/config-loader-backfill.test.ts +5 -5
  63. package/src/__tests__/config-schema.test.ts +17 -0
  64. package/src/__tests__/contact-store-interaction-info.test.ts +27 -70
  65. package/src/__tests__/contacts-relay-reads.test.ts +188 -23
  66. package/src/__tests__/contacts-tools.test.ts +42 -1
  67. package/src/__tests__/contacts-write.test.ts +181 -0
  68. package/src/__tests__/context-search-conversations-source.test.ts +220 -81
  69. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -0
  70. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
  71. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
  72. package/src/__tests__/conversation-agent-loop.test.ts +39 -0
  73. package/src/__tests__/conversation-analysis-routes.test.ts +1 -1
  74. package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -0
  75. package/src/__tests__/conversation-clear-safety.test.ts +0 -1
  76. package/src/__tests__/conversation-crud-enabled-plugins.test.ts +60 -0
  77. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +0 -1
  78. package/src/__tests__/conversation-disk-view.test.ts +1 -0
  79. package/src/__tests__/conversation-enabledplugins-route.test.ts +184 -0
  80. package/src/__tests__/conversation-error.test.ts +0 -18
  81. package/src/__tests__/conversation-fork-crud.test.ts +67 -0
  82. package/src/__tests__/conversation-history-web-search.test.ts +7 -137
  83. package/src/__tests__/conversation-initial-prompt.test.ts +110 -0
  84. package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +191 -0
  85. package/src/__tests__/conversation-process-callsite.test.ts +37 -0
  86. package/src/__tests__/conversation-queue.test.ts +149 -0
  87. package/src/__tests__/conversation-routes-enabled-plugins.test.ts +392 -0
  88. package/src/__tests__/conversation-routes-guardian-reply.test.ts +84 -0
  89. package/src/__tests__/conversation-routes-hidden-queue.test.ts +407 -0
  90. package/src/__tests__/conversation-runtime-assembly.test.ts +36 -16
  91. package/src/__tests__/conversation-skill-tools.test.ts +73 -0
  92. package/src/__tests__/conversation-wipe.test.ts +20 -5
  93. package/src/__tests__/credential-prompt-route.test.ts +69 -0
  94. package/src/__tests__/credential-security-invariants.test.ts +1 -3
  95. package/src/__tests__/db-drop-messages-fts.test.ts +115 -0
  96. package/src/__tests__/deterministic-verification-control-plane.test.ts +1 -62
  97. package/src/__tests__/edit-propagation.test.ts +56 -2
  98. package/src/__tests__/empty-state-greeting-cache.test.ts +9 -0
  99. package/src/__tests__/gateway-only-enforcement.test.ts +15 -110
  100. package/src/__tests__/guardian-expiry-notifier.test.ts +1 -0
  101. package/src/__tests__/guardian-question-mode.test.ts +57 -0
  102. package/src/__tests__/guardian-verification-voice-binding.test.ts +1 -1
  103. package/src/__tests__/guardian-wait-controller.test.ts +619 -0
  104. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +33 -2
  105. package/src/__tests__/heic-fixture.ts +55 -0
  106. package/src/__tests__/helpers/seed-contact-channel.ts +0 -2
  107. package/src/__tests__/http-conversation-lineage.test.ts +6 -1
  108. package/src/__tests__/image-conversion.test.ts +170 -0
  109. package/src/__tests__/inbound-invite-redemption.test.ts +72 -341
  110. package/src/__tests__/introduction-card-resolver.test.ts +354 -0
  111. package/src/__tests__/invite-redeemed-ipc.test.ts +97 -0
  112. package/src/__tests__/invite-routes-http.test.ts +246 -420
  113. package/src/__tests__/job-handler-registration-guard.test.ts +104 -0
  114. package/src/__tests__/lexical-index-dual-write.test.ts +426 -0
  115. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +2 -2
  116. package/src/__tests__/list-messages-attachments.test.ts +159 -0
  117. package/src/__tests__/list-messages-background-tool-completion.test.ts +141 -0
  118. package/src/__tests__/list-messages-queued.test.ts +25 -0
  119. package/src/__tests__/managed-store.test.ts +129 -1
  120. package/src/__tests__/media-stream-audio-transcode.test.ts +113 -0
  121. package/src/__tests__/media-stream-output.test.ts +350 -19
  122. package/src/__tests__/media-stream-server-integration.test.ts +943 -169
  123. package/src/__tests__/media-stream-stt-session.test.ts +498 -1
  124. package/src/__tests__/memory-jobs-worker-lanes.test.ts +2 -2
  125. package/src/__tests__/model-intents.test.ts +1 -1
  126. package/src/__tests__/mtime-cache.test.ts +19 -0
  127. package/src/__tests__/non-member-access-request.test.ts +349 -3
  128. package/src/__tests__/notification-decision-fallback.test.ts +104 -8
  129. package/src/__tests__/notification-decision-strategy.test.ts +57 -8
  130. package/src/__tests__/onboarding-template-contract.test.ts +27 -43
  131. package/src/__tests__/openai-provider.test.ts +33 -0
  132. package/src/__tests__/openai-responses-provider.test.ts +40 -0
  133. package/src/__tests__/persistence-layering-guard.test.ts +29 -20
  134. package/src/__tests__/persona-resolver.test.ts +56 -2
  135. package/src/__tests__/personal-memory-auth-bypass.test.ts +62 -0
  136. package/src/__tests__/phone.test.ts +1 -15
  137. package/src/__tests__/plugin-bootstrap.test.ts +25 -196
  138. package/src/__tests__/plugin-disabled-state.test.ts +33 -0
  139. package/src/__tests__/plugin-effective-enabled-set.test.ts +227 -0
  140. package/src/__tests__/plugin-event-hub-facade.test.ts +323 -0
  141. package/src/__tests__/plugin-import-boundary-guard.test.ts +156 -42
  142. package/src/__tests__/plugin-injector-contribution.test.ts +4 -20
  143. package/src/__tests__/plugin-pipeline.test.ts +63 -1
  144. package/src/__tests__/plugin-route-contribution.test.ts +62 -115
  145. package/src/__tests__/plugin-tool-contribution.test.ts +0 -22
  146. package/src/__tests__/plugin-types.test.ts +0 -1
  147. package/src/__tests__/pointer-conversation-trust.test.ts +38 -6
  148. package/src/__tests__/pre-model-call-sanitize.test.ts +1 -1
  149. package/src/__tests__/prune-old-tool-invocations-job.test.ts +97 -0
  150. package/src/__tests__/public-ingress-urls.test.ts +0 -48
  151. package/src/__tests__/qdrant-collection-migration.test.ts +145 -2
  152. package/src/__tests__/reaction-intercept-member-verdict-warm.test.ts +0 -1
  153. package/src/__tests__/resolve-trust-class.test.ts +28 -10
  154. package/src/__tests__/scaffold-managed-skill-tool.test.ts +137 -0
  155. package/src/__tests__/schedule-retry.test.ts +38 -14
  156. package/src/__tests__/schedule-routes-workflow-validation.test.ts +3 -3
  157. package/src/__tests__/schedule-routes.test.ts +14 -6
  158. package/src/__tests__/schedule-store.test.ts +3 -1
  159. package/src/__tests__/scheduler-disk-pressure.test.ts +17 -6
  160. package/src/__tests__/scheduler-recurrence.test.ts +57 -107
  161. package/src/__tests__/scheduler-reuse-conversation.test.ts +51 -46
  162. package/src/__tests__/scheduler-wake.test.ts +13 -23
  163. package/src/__tests__/scheduler-worker-standdown.test.ts +220 -0
  164. package/src/__tests__/secret-routes-platform-proxy.test.ts +1 -1
  165. package/src/__tests__/shell-observability.test.ts +1 -0
  166. package/src/__tests__/skill-boundary-guard.test.ts +3 -4
  167. package/src/__tests__/skill-load-plugin-scope.test.ts +238 -0
  168. package/src/__tests__/skill-projection-feature-flag.test.ts +2 -0
  169. package/src/__tests__/skill-script-runner-host.test.ts +53 -0
  170. package/src/__tests__/skill-script-runner-sandbox.test.ts +5 -2
  171. package/src/__tests__/skill-tool-factory.test.ts +73 -1
  172. package/src/__tests__/slack-app-setup-skill-regression.test.ts +37 -14
  173. package/src/__tests__/slack-inbound-verification.test.ts +36 -0
  174. package/src/__tests__/slack-notification-approval-card.test.ts +89 -2
  175. package/src/__tests__/slack-reaction-canonical-approval.test.ts +51 -1
  176. package/src/__tests__/stt-hints.test.ts +2 -256
  177. package/src/__tests__/subagent-allowlist-validation.test.ts +47 -0
  178. package/src/__tests__/subagent-call-site-routing.test.ts +72 -0
  179. package/src/__tests__/subagent-fork-notifications.test.ts +14 -2
  180. package/src/__tests__/subagent-persistence.test.ts +122 -0
  181. package/src/__tests__/subagent-spawn-and-await.test.ts +1 -0
  182. package/src/__tests__/subagent-terminal-message.test.ts +99 -0
  183. package/src/__tests__/subagent-tool-gate-mode.test.ts +78 -1
  184. package/src/__tests__/system-prompt.test.ts +17 -118
  185. package/src/__tests__/task-scheduler.test.ts +68 -89
  186. package/src/__tests__/telephony-credential-preflight.test.ts +312 -0
  187. package/src/__tests__/telephony-tts-guard.test.ts +538 -0
  188. package/src/__tests__/title-generate-hook.test.ts +16 -0
  189. package/src/__tests__/tool-approval-handler.test.ts +87 -1
  190. package/src/__tests__/tool-approval-seed-content-blocks.test.ts +45 -20
  191. package/src/__tests__/tool-grant-request-escalation.test.ts +39 -0
  192. package/src/__tests__/trust-context-guards.test.ts +21 -10
  193. package/src/__tests__/trusted-contact-multichannel.test.ts +4 -0
  194. package/src/__tests__/twilio-provider.test.ts +17 -17
  195. package/src/__tests__/twilio-routes-twiml.test.ts +6 -543
  196. package/src/__tests__/twilio-routes.test.ts +257 -387
  197. package/src/__tests__/twilio-validation.test.ts +1 -1
  198. package/src/__tests__/unified-turn-context-client-os.test.ts +45 -0
  199. package/src/__tests__/usage-cache-backfill-migration.test.ts +5 -0
  200. package/src/__tests__/voice-approval-resolver-relay.test.ts +150 -0
  201. package/src/__tests__/voice-ingress-preflight.test.ts +61 -0
  202. package/src/__tests__/voice-quality.test.ts +2 -2
  203. package/src/__tests__/voice-scoped-grant-consumer.test.ts +1 -7
  204. package/src/__tests__/voice-session-bridge-processing-wait.test.ts +27 -0
  205. package/src/__tests__/voice-session-bridge.test.ts +1 -10
  206. package/src/__tests__/workspace-git-service.test.ts +1 -1
  207. package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -0
  208. package/src/__tests__/workspace-migration-118-seed-now-md.test.ts +120 -0
  209. package/src/__tests__/workspace-migration-120-revise-onboarding-threads.test.ts +175 -0
  210. package/src/__tests__/workspace-migration-121-seed-default-user-guardrails.test.ts +118 -0
  211. package/src/__tests__/workspace-migration-122-relocate-default-user-boundary.test.ts +119 -0
  212. package/src/__tests__/workspace-migration-123-swap-quality-profile-to-fable.test.ts +191 -0
  213. package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +235 -241
  214. package/src/acp/__tests__/prepare-agent-env.test.ts +0 -97
  215. package/src/acp/__tests__/session-manager-persistence.test.ts +2 -0
  216. package/src/acp/__tests__/session-manager-resume.test.ts +8 -0
  217. package/src/acp/__tests__/session-manager-usage.test.ts +6 -0
  218. package/src/acp/__tests__/session-manager.test.ts +6 -0
  219. package/src/acp/agent-process.test.ts +116 -0
  220. package/src/acp/agent-process.ts +71 -0
  221. package/src/acp/auto-install.ts +12 -8
  222. package/src/acp/failure-error.test.ts +109 -0
  223. package/src/acp/failure-error.ts +111 -0
  224. package/src/acp/prepare-agent-env.ts +0 -12
  225. package/src/acp/resolve-agent.test.ts +6 -45
  226. package/src/acp/resolve-agent.ts +2 -4
  227. package/src/acp/session-manager.test.ts +312 -0
  228. package/src/acp/session-manager.ts +102 -46
  229. package/src/agent/ax-tree-compaction.test.ts +4 -1
  230. package/src/agent/image-optimize.ts +17 -127
  231. package/src/agent/loop.ts +45 -192
  232. package/src/api/events/background-tool-completed.test.ts +51 -0
  233. package/src/api/events/background-tool-completed.ts +29 -0
  234. package/src/api/events/background-tool-started.test.ts +36 -0
  235. package/src/api/events/background-tool-started.ts +28 -0
  236. package/src/api/events/conversation-error.ts +0 -1
  237. package/src/api/events/open-panel.ts +33 -0
  238. package/src/api/events/subagent-status-changed.ts +4 -1
  239. package/src/api/index.ts +19 -0
  240. package/src/api/responses/conversation-message.ts +34 -0
  241. package/src/approvals/guardian-decision-primitive.ts +74 -24
  242. package/src/approvals/guardian-request-resolvers.ts +450 -122
  243. package/src/apps/app-store.ts +1 -0
  244. package/src/apps/shared-app-links-store.ts +1 -0
  245. package/src/avatar/identity-avatar.ts +3 -7
  246. package/src/background-wake/wake-intent-hooks.test.ts +1 -1
  247. package/src/calls/__tests__/fish-audio-client.test.ts +73 -0
  248. package/src/calls/__tests__/gateway-invite-reader.test.ts +170 -0
  249. package/src/calls/__tests__/relay-setup-router.test.ts +126 -102
  250. package/src/calls/call-controller.ts +134 -48
  251. package/src/calls/call-domain.ts +18 -42
  252. package/src/calls/call-pointer-messages.ts +51 -67
  253. package/src/calls/call-setup-flow-types.ts +76 -0
  254. package/src/calls/call-setup-flow.ts +1743 -0
  255. package/src/calls/call-speech-output.ts +87 -23
  256. package/src/calls/call-store.ts +4 -0
  257. package/src/calls/call-transport.ts +22 -36
  258. package/src/calls/fish-audio-client.ts +3 -0
  259. package/src/calls/gateway-invite-reader.ts +98 -0
  260. package/src/calls/guardian-wait-controller.ts +451 -0
  261. package/src/calls/media-stream-audio-transcode.ts +82 -2
  262. package/src/calls/media-stream-output.ts +142 -36
  263. package/src/calls/media-stream-server.ts +297 -178
  264. package/src/calls/media-stream-stt-session.ts +393 -50
  265. package/src/calls/media-turn-detector.ts +4 -6
  266. package/src/calls/relay-access-wait.ts +3 -4
  267. package/src/calls/relay-setup-router.ts +22 -43
  268. package/src/calls/relay-verification.ts +17 -24
  269. package/src/calls/resolve-call-tts-provider.ts +96 -29
  270. package/src/calls/stt-hints.ts +24 -87
  271. package/src/calls/telephony-credential-preflight.ts +159 -0
  272. package/src/calls/telephony-tts-capability.ts +183 -0
  273. package/src/calls/tts-call-strategy.ts +18 -20
  274. package/src/calls/twilio-provider.ts +3 -2
  275. package/src/calls/twilio-routes.ts +47 -351
  276. package/src/calls/types.ts +5 -3
  277. package/src/calls/voice-ingress-preflight.ts +9 -0
  278. package/src/calls/voice-quality.ts +13 -18
  279. package/src/calls/voice-session-bridge.ts +25 -35
  280. package/src/channels/__tests__/types.test.ts +28 -0
  281. package/src/channels/channel-verification-sessions.ts +7 -2
  282. package/src/channels/config.ts +0 -42
  283. package/src/channels/slack-thread-store.ts +12 -0
  284. package/src/channels/types.ts +23 -0
  285. package/src/cli/commands/__tests__/conversations-slack.test.ts +1 -1
  286. package/src/cli/commands/__tests__/schedules.test.ts +83 -34
  287. package/src/cli/commands/__tests__/status.test.ts +42 -2
  288. package/src/cli/commands/contacts.ts +2 -2
  289. package/src/cli/commands/credentials.ts +17 -0
  290. package/src/cli/commands/monitoring.ts +191 -0
  291. package/src/cli/commands/schedules-worker.ts +175 -0
  292. package/src/cli/commands/schedules.ts +169 -43
  293. package/src/cli/commands/status.ts +12 -1
  294. package/src/cli/commands/tools.ts +5 -1
  295. package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +1 -0
  296. package/src/cli/lib/__tests__/search-plugins.test.ts +29 -1
  297. package/src/cli/lib/__tests__/toggle-plugin.test.ts +7 -0
  298. package/src/cli/lib/search-plugins.ts +6 -0
  299. package/src/cli/lib/toggle-plugin.ts +21 -2
  300. package/src/cli/program.ts +3 -1
  301. package/src/config/__tests__/deployment-context-defaults.test.ts +23 -0
  302. package/src/config/acp-defaults.test.ts +0 -10
  303. package/src/config/acp-defaults.ts +0 -6
  304. package/src/config/bundled-skills/acp/SKILL.md +13 -45
  305. package/src/config/bundled-skills/acp/TOOLS.json +3 -3
  306. package/src/config/bundled-skills/app-builder/SKILL.md +3 -3
  307. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +9 -9
  308. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +1 -1
  309. package/src/config/bundled-skills/contacts/tools/contact-search.ts +1 -1
  310. package/src/config/bundled-skills/phone-calls/SKILL.md +1 -1
  311. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +9 -9
  312. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +10 -7
  313. package/src/config/bundled-skills/skill-management/TOOLS.json +10 -0
  314. package/src/config/call-site-defaults.ts +0 -2
  315. package/src/config/feature-flag-registry.json +16 -8
  316. package/src/config/loader.ts +11 -0
  317. package/src/config/schema.ts +9 -1
  318. package/src/config/schemas/__tests__/memory-v2.test.ts +2 -2
  319. package/src/config/schemas/__tests__/memory-v3.test.ts +64 -0
  320. package/src/config/schemas/call-site-catalog.ts +0 -12
  321. package/src/config/schemas/calls.ts +8 -0
  322. package/src/config/schemas/elevenlabs.ts +1 -1
  323. package/src/config/schemas/llm.ts +0 -2
  324. package/src/config/schemas/memory-v2.ts +1 -1
  325. package/src/config/schemas/memory-v3.ts +82 -0
  326. package/src/config/schemas/monitoring.ts +61 -0
  327. package/src/config/schemas/schedules.ts +35 -0
  328. package/src/config/seed-inference-profiles.ts +2 -2
  329. package/src/config/skills-plugin-filter.test.ts +96 -0
  330. package/src/config/skills.ts +26 -0
  331. package/src/contacts/__tests__/member-write-relay.test.ts +156 -4
  332. package/src/contacts/canonical-guardian-store.ts +5 -0
  333. package/src/contacts/contact-store.ts +81 -35
  334. package/src/contacts/contacts-write.ts +50 -25
  335. package/src/contacts/member-write-relay.ts +115 -31
  336. package/src/contacts/types.ts +0 -8
  337. package/src/context/compactor.ts +29 -15
  338. package/src/context/outbound-sanitize.ts +202 -0
  339. package/src/daemon/__tests__/abort-null-controller.test.ts +167 -0
  340. package/src/daemon/__tests__/conversation-tool-setup-plugin-scope.test.ts +122 -0
  341. package/src/daemon/__tests__/embedding-reconcile.test.ts +99 -16
  342. package/src/daemon/__tests__/wake-conversation-ops-completion.test.ts +107 -0
  343. package/src/daemon/abort-watchdog.ts +7 -0
  344. package/src/daemon/app-source-watcher.ts +9 -0
  345. package/src/daemon/assistant-attachments.ts +42 -0
  346. package/src/daemon/conversation-agent-loop-handlers.ts +256 -147
  347. package/src/daemon/conversation-agent-loop.ts +61 -68
  348. package/src/daemon/conversation-error.ts +1 -15
  349. package/src/daemon/conversation-history.ts +32 -236
  350. package/src/daemon/conversation-initial-prompt.ts +77 -0
  351. package/src/daemon/conversation-lifecycle.ts +25 -1
  352. package/src/daemon/conversation-messaging.ts +2 -2
  353. package/src/daemon/conversation-plugin-scope.ts +38 -0
  354. package/src/daemon/conversation-process.ts +50 -14
  355. package/src/daemon/conversation-runtime-assembly.ts +36 -6
  356. package/src/daemon/conversation-skill-tools.ts +19 -3
  357. package/src/daemon/conversation-store.ts +3 -3
  358. package/src/daemon/conversation-surfaces.ts +171 -0
  359. package/src/daemon/conversation-tool-setup.test.ts +95 -0
  360. package/src/daemon/conversation-tool-setup.ts +116 -1
  361. package/src/daemon/conversation-turn-finalize.ts +211 -0
  362. package/src/daemon/conversation.ts +92 -1
  363. package/src/daemon/disk-pressure-policy.ts +2 -1
  364. package/src/daemon/event-loop-watchdog.ts +22 -6
  365. package/src/daemon/external-plugins-bootstrap.ts +47 -134
  366. package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +1 -1
  367. package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +26 -14
  368. package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +27 -14
  369. package/src/daemon/handlers/__tests__/config-channels.test.ts +0 -5
  370. package/src/daemon/handlers/config-a2a.ts +7 -14
  371. package/src/daemon/handlers/config-channels.ts +2 -10
  372. package/src/daemon/handlers/conversation-history.ts +3 -1
  373. package/src/daemon/handlers/conversations.ts +0 -52
  374. package/src/daemon/handlers/shared.ts +4 -24
  375. package/src/daemon/handlers/skills.ts +4 -1
  376. package/src/daemon/host-cu-proxy.ts +1 -1
  377. package/src/daemon/lifecycle.ts +59 -472
  378. package/src/daemon/message-protocol.ts +3 -3
  379. package/src/daemon/message-provenance.ts +12 -14
  380. package/src/daemon/message-types/background-tools.ts +28 -0
  381. package/src/daemon/message-types/contacts.ts +2 -10
  382. package/src/daemon/message-types/conversations.ts +10 -0
  383. package/src/daemon/message-types/integrations.ts +2 -0
  384. package/src/daemon/message-types/surfaces.ts +1 -0
  385. package/src/daemon/message-types/sync.ts +1 -0
  386. package/src/daemon/pointer-conversation-trust.ts +23 -9
  387. package/src/daemon/pointer-turn-runner.ts +174 -0
  388. package/src/daemon/providers-setup.ts +16 -0
  389. package/src/daemon/shutdown-handlers.ts +139 -47
  390. package/src/daemon/skill-memory-refresh.ts +2 -2
  391. package/src/daemon/sqlite-corruption-watchdog.test.ts +217 -0
  392. package/src/daemon/sqlite-corruption-watchdog.ts +155 -0
  393. package/src/daemon/tool-setup-types.ts +8 -0
  394. package/src/daemon/trust-context.ts +21 -6
  395. package/src/daemon/turn-latency-tracker.test.ts +93 -0
  396. package/src/daemon/turn-latency-tracker.ts +38 -0
  397. package/src/daemon/wake-conversation-ops.ts +10 -8
  398. package/src/documents/document-comments-store.test.ts +7 -1
  399. package/src/documents/document-comments-store.ts +8 -0
  400. package/src/documents/document-store.ts +15 -0
  401. package/src/export/__tests__/transcript-formatter.test.ts +11 -0
  402. package/src/export/transcript-formatter.ts +49 -67
  403. package/src/home/__tests__/feed-writer.test.ts +247 -1
  404. package/src/home/conversation-starter-checkpoints.ts +1 -0
  405. package/src/home/feed-writer.ts +61 -0
  406. package/src/home/job-handlers/conversation-starters.ts +1 -0
  407. package/src/hooks/hook-loader.ts +12 -0
  408. package/src/hooks/registry.ts +32 -4
  409. package/src/inbound/public-ingress-urls.ts +0 -17
  410. package/src/ipc/__tests__/contacts-info-ipc.test.ts +285 -0
  411. package/src/ipc/assistant-server.ts +28 -7
  412. package/src/ipc/routes/__tests__/contacts-mirror-apply-atomicity.test.ts +62 -0
  413. package/src/ipc/routes/__tests__/contacts-mirror-apply.test.ts +272 -0
  414. package/src/ipc/routes/__tests__/contacts-mirror-ipc-routes.test.ts +322 -0
  415. package/src/ipc/routes/__tests__/invite-ipc-routes.test.ts +60 -4
  416. package/src/ipc/routes/contacts-info-ipc-routes.ts +239 -0
  417. package/src/ipc/routes/contacts-mirror-ipc-routes.ts +202 -0
  418. package/src/ipc/routes/db-proxy.ts +5 -2
  419. package/src/ipc/routes/invite-ipc-routes.ts +53 -39
  420. package/src/jobs/worker.ts +9 -2
  421. package/src/live-voice/__tests__/live-voice-archive.test.ts +10 -1
  422. package/src/live-voice/live-voice-archive.ts +5 -0
  423. package/src/messaging/providers/__tests__/transport-dispatch.test.ts +22 -6
  424. package/src/messaging/providers/channel-transport.ts +6 -0
  425. package/src/messaging/providers/index.ts +3 -0
  426. package/src/messaging/providers/slack/api.test.ts +49 -1
  427. package/src/messaging/providers/slack/api.ts +110 -0
  428. package/src/messaging/providers/slack/send.test.ts +85 -0
  429. package/src/messaging/providers/slack/send.ts +100 -28
  430. package/src/messaging/providers/slack/transport.ts +7 -13
  431. package/src/messaging/providers/whatsapp/send.ts +29 -9
  432. package/src/monitoring/__tests__/control.test.ts +235 -0
  433. package/src/monitoring/__tests__/sample-ring-buffer.test.ts +96 -0
  434. package/src/monitoring/control.ts +105 -0
  435. package/src/monitoring/resource-sampler.ts +258 -0
  436. package/src/monitoring/sample-ring-buffer.ts +108 -0
  437. package/src/monitoring/worker.ts +94 -0
  438. package/src/notifications/README.md +1 -1
  439. package/src/notifications/access-request-copy.ts +94 -23
  440. package/src/notifications/adapters/slack.ts +89 -21
  441. package/src/notifications/approval-card-builder.ts +33 -18
  442. package/src/notifications/approval-card-data.ts +48 -15
  443. package/src/notifications/broadcaster.ts +25 -16
  444. package/src/notifications/decision-engine.ts +131 -32
  445. package/src/notifications/guardian-question-mode.ts +58 -10
  446. package/src/permissions/approval-policy.ts +8 -1
  447. package/src/permissions/checker.ts +2 -0
  448. package/src/permissions/gateway-threshold-reader.ts +7 -6
  449. package/src/permissions/ipc-risk-types.ts +1 -0
  450. package/src/permissions/secret-prompter.ts +11 -3
  451. package/src/permissions/types.ts +2 -2
  452. package/src/persistence/__tests__/conversation-queries-search.test.ts +397 -0
  453. package/src/persistence/__tests__/conversation-search-lexical.test.ts +103 -0
  454. package/src/persistence/__tests__/jobs-worker-memory-disabled.test.ts +95 -0
  455. package/src/persistence/__tests__/slow-query-log.test.ts +266 -0
  456. package/src/persistence/__tests__/slow-sync-log.test.ts +155 -0
  457. package/src/persistence/a2a-invite-store.ts +205 -0
  458. package/src/persistence/attachments-store.ts +94 -10
  459. package/src/persistence/checkpoints.ts +45 -0
  460. package/src/persistence/conversation-crud.ts +453 -260
  461. package/src/persistence/conversation-display-order-migration.ts +8 -2
  462. package/src/persistence/conversation-group-migration.test.ts +8 -0
  463. package/src/persistence/conversation-group-migration.ts +9 -0
  464. package/src/persistence/conversation-queries.ts +244 -125
  465. package/src/persistence/conversation-row-batch-delete.ts +9 -5
  466. package/src/persistence/conversation-search-lexical.ts +49 -0
  467. package/src/persistence/db-async-query.ts +42 -0
  468. package/src/persistence/db-connection.ts +13 -0
  469. package/src/persistence/delivery-channels.ts +0 -82
  470. package/src/persistence/delivery-crud.ts +27 -6
  471. package/src/persistence/embeddings/__tests__/embedding-identity.test.ts +18 -5
  472. package/src/persistence/embeddings/__tests__/messages-lexical-index.test.ts +334 -0
  473. package/src/persistence/embeddings/embedding-identity.ts +17 -5
  474. package/src/persistence/embeddings/embedding-runtime-manager.ts +31 -0
  475. package/src/persistence/embeddings/messages-lexical-index.ts +396 -0
  476. package/src/persistence/embeddings/qdrant-client.ts +81 -5
  477. package/src/persistence/group-crud.ts +13 -1
  478. package/src/persistence/job-handlers/__tests__/message-lexical-backfill.test.ts +506 -0
  479. package/src/persistence/job-handlers/__tests__/message-lexical-enqueue.test.ts +164 -0
  480. package/src/persistence/job-handlers/__tests__/message-lexical.test.ts +259 -0
  481. package/src/persistence/job-handlers/cleanup.ts +57 -9
  482. package/src/persistence/job-handlers/message-lexical-backfill.ts +187 -0
  483. package/src/persistence/job-handlers/message-lexical.ts +251 -0
  484. package/src/persistence/jobs-store.ts +102 -8
  485. package/src/persistence/jobs-worker.ts +68 -28
  486. package/src/persistence/llm-request-log-store.ts +35 -19
  487. package/src/persistence/llm-usage-store.ts +11 -0
  488. package/src/persistence/memory-lifecycle-hooks.test.ts +65 -0
  489. package/src/persistence/memory-lifecycle-hooks.ts +55 -1
  490. package/src/persistence/migrations/028-call-session-mode.ts +1 -1
  491. package/src/persistence/migrations/116-messages-fts.ts +8 -1
  492. package/src/persistence/migrations/311-create-subagents-table.ts +50 -0
  493. package/src/persistence/migrations/312-drop-inbox-conversation-state-table.ts +15 -0
  494. package/src/persistence/migrations/313-drop-messages-fts.ts +17 -0
  495. package/src/persistence/migrations/314-add-conversation-enabled-plugins.ts +25 -0
  496. package/src/persistence/migrations/315-create-a2a-invites.ts +58 -0
  497. package/src/persistence/migrations/316-drop-contact-channels-invite-id.ts +28 -0
  498. package/src/persistence/migrations/317-canonical-guardian-requester-signals.ts +24 -0
  499. package/src/persistence/migrations/318-drop-contact-channel-telemetry.ts +32 -0
  500. package/src/persistence/migrations/__tests__/315-create-a2a-invites.test.ts +161 -0
  501. package/src/persistence/migrations/__tests__/316-drop-contact-channels-invite-id.test.ts +156 -0
  502. package/src/persistence/migrations/__tests__/318-drop-contact-channel-telemetry.test.ts +134 -0
  503. package/src/persistence/migrations/__tests__/migration-prefix-guard.test.ts +99 -0
  504. package/src/persistence/raw-query.ts +50 -11
  505. package/src/persistence/schema/a2a.ts +14 -0
  506. package/src/persistence/schema/contacts.ts +0 -62
  507. package/src/persistence/schema/conversation-groups.ts +12 -0
  508. package/src/persistence/schema/conversations.ts +2 -0
  509. package/src/persistence/schema/documents.ts +65 -0
  510. package/src/persistence/schema/guardian.ts +4 -0
  511. package/src/persistence/schema/index.ts +4 -0
  512. package/src/persistence/schema/memory-injection.ts +62 -0
  513. package/src/persistence/schema/workflows.ts +55 -0
  514. package/src/persistence/slow-query-log.ts +437 -0
  515. package/src/persistence/slow-sync-log.ts +204 -0
  516. package/src/persistence/steps.ts +16 -0
  517. package/src/persistence/subagent-store.ts +125 -0
  518. package/src/persistence/worker-control.ts +45 -238
  519. package/src/plugin-api/event-hub-facade.ts +172 -0
  520. package/src/plugin-api/index.ts +9 -1
  521. package/src/plugin-api/types.ts +40 -9
  522. package/src/plugins/defaults/default-plugin-names.ts +60 -0
  523. package/src/plugins/defaults/index.ts +19 -29
  524. package/src/plugins/defaults/memory/__tests__/conversation-queries.test.ts +46 -67
  525. package/src/plugins/defaults/memory/__tests__/db-async-query.test.ts +36 -1
  526. package/src/plugins/defaults/memory/__tests__/find-most-recent-retrospective-for.test.ts +2 -4
  527. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +2 -2
  528. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-schedule.test.ts +9 -0
  529. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +7 -4
  530. package/src/plugins/defaults/memory/config.ts +11 -0
  531. package/src/plugins/defaults/memory/context-search/agent-runner.ts +1 -1
  532. package/src/plugins/defaults/memory/context-search/sources/conversations.ts +124 -113
  533. package/src/plugins/defaults/memory/embeddings.ts +77 -0
  534. package/src/plugins/defaults/memory/find-most-recent-retrospective-for.ts +66 -0
  535. package/src/plugins/defaults/memory/frontmatter.ts +50 -0
  536. package/src/plugins/defaults/memory/graph/bootstrap.test.ts +36 -10
  537. package/src/plugins/defaults/memory/graph/bootstrap.ts +6 -5
  538. package/src/plugins/defaults/memory/graph/consolidation.ts +3 -5
  539. package/src/plugins/defaults/memory/graph/extraction.ts +3 -6
  540. package/src/plugins/defaults/memory/graph/graph-search.ts +12 -23
  541. package/src/plugins/defaults/memory/graph/narrative.ts +3 -5
  542. package/src/plugins/defaults/memory/graph/pattern-scan.ts +3 -5
  543. package/src/plugins/defaults/memory/graph/retriever.test.ts +1 -6
  544. package/src/plugins/defaults/memory/graph/retriever.ts +5 -10
  545. package/src/plugins/defaults/memory/graph/tools.ts +1 -1
  546. package/src/plugins/defaults/memory/hooks/init.ts +31 -5
  547. package/src/plugins/defaults/memory/indexer.ts +2 -3
  548. package/src/plugins/defaults/memory/injectors.ts +2 -2
  549. package/src/plugins/defaults/memory/job-handler-registration.ts +96 -0
  550. package/src/plugins/defaults/memory/job-handlers/backfill.ts +4 -26
  551. package/src/plugins/defaults/memory/job-handlers/embedding.test.ts +6 -19
  552. package/src/plugins/defaults/memory/job-handlers/embedding.ts +9 -22
  553. package/src/plugins/defaults/memory/job-handlers/index-maintenance.ts +2 -3
  554. package/src/plugins/defaults/memory/job-handlers.ts +13 -12
  555. package/src/plugins/defaults/memory/jobs/embed-concept-page.ts +1 -1
  556. package/src/plugins/defaults/memory/llm-helpers.ts +76 -0
  557. package/src/plugins/defaults/memory/memory-retrospective-job.ts +8 -5
  558. package/src/plugins/defaults/memory/memory-retrospective-startup-cleanup.ts +2 -2
  559. package/src/plugins/defaults/memory/memory-v2-concept-frequency.ts +2 -0
  560. package/src/plugins/defaults/memory/persistence-hooks.ts +46 -1
  561. package/src/plugins/defaults/memory/pkb/pkb-index.ts +1 -5
  562. package/src/plugins/defaults/memory/pkb/pkb-search.ts +2 -2
  563. package/src/plugins/defaults/memory/routes/__tests__/memory-v2-simulate-route.test.ts +4 -6
  564. package/src/plugins/defaults/memory/routes/memory-item-routes.ts +1 -1
  565. package/src/plugins/defaults/memory/search/semantic.ts +2 -2
  566. package/src/plugins/defaults/memory/startup.ts +244 -0
  567. package/src/plugins/defaults/memory/task-memory-cleanup.ts +8 -0
  568. package/src/{daemon → plugins/defaults/memory/v2}/__tests__/memory-v2-startup.test.ts +6 -6
  569. package/src/plugins/defaults/memory/v2/__tests__/migration.test.ts +2 -13
  570. package/src/plugins/defaults/memory/v2/__tests__/router.test.ts +4 -5
  571. package/src/plugins/defaults/memory/v2/__tests__/sweep-job.test.ts +1 -8
  572. package/src/plugins/defaults/memory/v2/activation.ts +2 -4
  573. package/src/plugins/defaults/memory/v2/cli-command-store.ts +2 -4
  574. package/src/plugins/defaults/memory/v2/frontmatter-sweep.ts +1 -1
  575. package/src/{daemon → plugins/defaults/memory/v2}/memory-v2-startup.test.ts +8 -8
  576. package/src/{daemon → plugins/defaults/memory/v2}/memory-v2-startup.ts +20 -22
  577. package/src/plugins/defaults/memory/v2/migration.ts +2 -5
  578. package/src/plugins/defaults/memory/v2/page-store.ts +1 -1
  579. package/src/plugins/defaults/memory/v2/qdrant.ts +2 -3
  580. package/src/plugins/defaults/memory/v2/router.ts +5 -5
  581. package/src/plugins/defaults/memory/v2/sim.ts +2 -4
  582. package/src/plugins/defaults/memory/v2/skill-store.ts +2 -4
  583. package/src/plugins/defaults/memory/v2/sweep-job.ts +6 -6
  584. package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +11 -9
  585. package/src/plugins/defaults/memory/v3/__tests__/dense.test.ts +107 -2
  586. package/src/plugins/defaults/memory/v3/__tests__/gate-flag.test.ts +69 -0
  587. package/src/plugins/defaults/memory/v3/__tests__/gate.test.ts +181 -0
  588. package/src/plugins/defaults/memory/v3/__tests__/live-integration.test.ts +7 -3
  589. package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +345 -8
  590. package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +1 -4
  591. package/src/plugins/defaults/memory/v3/__tests__/section-needle.test.ts +64 -0
  592. package/src/plugins/defaults/memory/v3/__tests__/shadow-integration.test.ts +18 -13
  593. package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +62 -1
  594. package/src/plugins/defaults/memory/v3/card.ts +1 -4
  595. package/src/plugins/defaults/memory/v3/dense.ts +60 -25
  596. package/src/plugins/defaults/memory/v3/edge.ts +1 -1
  597. package/src/plugins/defaults/memory/v3/gate-flag.ts +20 -0
  598. package/src/plugins/defaults/memory/v3/gate.ts +158 -0
  599. package/src/plugins/defaults/memory/v3/maintain-job.ts +2 -4
  600. package/src/plugins/defaults/memory/v3/orchestrate.ts +186 -25
  601. package/src/plugins/defaults/memory/v3/pool-select.test.ts +7 -9
  602. package/src/plugins/defaults/memory/v3/pool-select.ts +6 -6
  603. package/src/plugins/defaults/memory/v3/prune.ts +2 -2
  604. package/src/plugins/defaults/memory/v3/section-dense-store.ts +8 -11
  605. package/src/plugins/defaults/memory/v3/section-needle.ts +27 -7
  606. package/src/plugins/defaults/memory/v3/shadow-plugin.ts +10 -0
  607. package/src/plugins/defaults/memory/v3-eval/eval-packets.ts +1 -4
  608. package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +5 -0
  609. package/src/plugins/defaults/turn-context/injectors.ts +1 -0
  610. package/src/plugins/defaults/turn-context/unified-turn-context.ts +12 -0
  611. package/src/plugins/injector-registry.ts +13 -2
  612. package/src/plugins/mtime-cache.ts +36 -47
  613. package/src/plugins/pipeline.ts +15 -1
  614. package/src/plugins/types.ts +14 -23
  615. package/src/prompts/__tests__/system-prompt.test.ts +170 -32
  616. package/src/prompts/persona-resolver.ts +13 -9
  617. package/src/prompts/system-prompt.ts +30 -9
  618. package/src/prompts/templates/BOOTSTRAP.md +16 -119
  619. package/src/prompts/templates/SOUL.md +43 -13
  620. package/src/prompts/templates/system-sections.ts +32 -27
  621. package/src/prompts/templates/users/default.md +19 -0
  622. package/src/providers/__tests__/placeholder-sentinels.test.ts +56 -0
  623. package/src/providers/inference/__tests__/base-url-route-validation.test.ts +96 -1
  624. package/src/providers/model-intents.ts +2 -2
  625. package/src/providers/openai/chat-completions-provider.ts +14 -1
  626. package/src/providers/openai/responses-provider.ts +18 -0
  627. package/src/providers/placeholder-sentinels.ts +18 -8
  628. package/src/providers/retry.ts +1 -0
  629. package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +0 -64
  630. package/src/providers/speech-to-text/__tests__/resolve.test.ts +92 -79
  631. package/src/providers/speech-to-text/deepgram-realtime.test.ts +98 -0
  632. package/src/providers/speech-to-text/deepgram-realtime.ts +62 -3
  633. package/src/providers/speech-to-text/provider-catalog.ts +0 -89
  634. package/src/providers/speech-to-text/resolve.ts +55 -0
  635. package/src/providers/tool-progress-events.test.ts +50 -0
  636. package/src/providers/tool-progress-events.ts +99 -0
  637. package/src/providers/types.ts +1 -1
  638. package/src/providers/vellum-model-routing.test.ts +51 -0
  639. package/src/providers/vellum-model-routing.ts +84 -0
  640. package/src/runtime/AGENTS.md +5 -4
  641. package/src/runtime/__tests__/agent-wake.test.ts +158 -1
  642. package/src/runtime/__tests__/channel-verification-service.test.ts +2 -2
  643. package/src/runtime/__tests__/trust-verdict-consumer.test.ts +37 -8
  644. package/src/runtime/access-request-helper.ts +154 -3
  645. package/src/runtime/actor-trust-resolver.ts +7 -21
  646. package/src/runtime/agent-wake.ts +41 -1
  647. package/src/runtime/assistant-event.ts +86 -12
  648. package/src/runtime/auth/__tests__/route-policy.test.ts +31 -0
  649. package/src/runtime/channel-approval-types.ts +52 -2
  650. package/src/runtime/channel-approvals.ts +23 -8
  651. package/src/runtime/channel-invite-transport.ts +2 -2
  652. package/src/runtime/channel-invite-transports/voice.ts +1 -1
  653. package/src/runtime/channel-readiness-service.ts +3 -5
  654. package/src/runtime/channel-retry-sweep.ts +18 -24
  655. package/src/runtime/channel-verification-service.ts +9 -11
  656. package/src/runtime/finalize-event-delivery.ts +30 -16
  657. package/src/runtime/guardian-action-service.ts +10 -11
  658. package/src/runtime/guardian-reply-router.ts +122 -21
  659. package/src/runtime/http-server.ts +44 -101
  660. package/src/runtime/introduction-policy.test.ts +214 -0
  661. package/src/runtime/introduction-policy.ts +284 -0
  662. package/src/runtime/invite-service.ts +104 -361
  663. package/src/runtime/local-actor-identity.test.ts +38 -0
  664. package/src/runtime/local-actor-identity.ts +14 -0
  665. package/src/runtime/middleware/__tests__/rate-limiter.test.ts +22 -0
  666. package/src/runtime/middleware/rate-limiter.ts +30 -0
  667. package/src/runtime/middleware/twilio-validation.ts +5 -7
  668. package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +28 -0
  669. package/src/runtime/migrations/origin-mode.ts +6 -6
  670. package/src/runtime/pre-first-message-gate.ts +1 -0
  671. package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +6 -35
  672. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +24 -3
  673. package/src/runtime/routes/__tests__/contact-routes.test.ts +80 -15
  674. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +7 -1
  675. package/src/runtime/routes/__tests__/global-search-routes.test.ts +0 -3
  676. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +142 -1
  677. package/src/runtime/routes/__tests__/invite-relay-routes.test.ts +119 -30
  678. package/src/runtime/routes/__tests__/migration-import-allowed-hosts-env.test.ts +70 -0
  679. package/src/runtime/routes/__tests__/monitoring-routes.test.ts +194 -0
  680. package/src/runtime/routes/__tests__/plugins-routes.test.ts +755 -29
  681. package/src/runtime/routes/__tests__/retrospective-routes.test.ts +4 -0
  682. package/src/runtime/routes/__tests__/schedule-routes-create.test.ts +70 -0
  683. package/src/runtime/routes/__tests__/schedule-worker-routes.test.ts +161 -0
  684. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +1 -1
  685. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +1 -1
  686. package/src/runtime/routes/acp-routes.ts +15 -3
  687. package/src/runtime/routes/app-management-routes.ts +4 -7
  688. package/src/runtime/routes/approval-routes.ts +4 -0
  689. package/src/runtime/routes/attachment-routes.ts +54 -3
  690. package/src/runtime/routes/avatar-routes.ts +0 -4
  691. package/src/runtime/routes/background-tool-routes.ts +34 -5
  692. package/src/runtime/routes/btw-routes.ts +32 -4
  693. package/src/runtime/routes/channel-route-shared.ts +18 -14
  694. package/src/runtime/routes/channel-verification-routes.ts +0 -3
  695. package/src/runtime/routes/contact-routes.ts +298 -117
  696. package/src/runtime/routes/conversation-list-routes.ts +6 -0
  697. package/src/runtime/routes/conversation-management-routes.ts +74 -37
  698. package/src/runtime/routes/conversation-query-routes.ts +5 -2
  699. package/src/runtime/routes/conversation-routes.ts +222 -82
  700. package/src/runtime/routes/conversations-import-routes.ts +8 -1
  701. package/src/runtime/routes/credential-prompt-routes.ts +20 -5
  702. package/src/runtime/routes/debug-routes.ts +1 -0
  703. package/src/runtime/routes/documents-routes.ts +5 -2
  704. package/src/runtime/routes/empty-state-greeting-cache.ts +37 -10
  705. package/src/runtime/routes/global-search-routes.ts +2 -1
  706. package/src/runtime/routes/guardian-approval-interception.ts +51 -0
  707. package/src/runtime/routes/home-feed-routes.ts +60 -1
  708. package/src/runtime/routes/identity-routes.ts +4 -87
  709. package/src/runtime/routes/inbound-message-handler.ts +82 -41
  710. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +430 -57
  711. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +302 -572
  712. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +76 -270
  713. package/src/runtime/routes/inbound-stages/background-dispatch.ts +21 -116
  714. package/src/runtime/routes/inbound-stages/edit-intercept.ts +9 -1
  715. package/src/runtime/routes/inbound-stages/escalation-intercept.test.ts +158 -0
  716. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +22 -1
  717. package/src/runtime/routes/index.ts +6 -0
  718. package/src/runtime/routes/inference-provider-connection-routes.ts +22 -16
  719. package/src/runtime/routes/internal-twilio-routes.ts +0 -15
  720. package/src/runtime/routes/messages-lexical-routes.ts +75 -0
  721. package/src/runtime/routes/migration-routes.ts +69 -6
  722. package/src/runtime/routes/monitoring-routes.ts +237 -0
  723. package/src/runtime/routes/plugins-routes.ts +329 -8
  724. package/src/runtime/routes/schedule-routes.ts +49 -8
  725. package/src/runtime/routes/schedule-worker-routes.ts +210 -0
  726. package/src/runtime/routes/secret-routes.ts +1 -1
  727. package/src/runtime/routes/surface-conversation-resolver.ts +1 -0
  728. package/src/runtime/services/__tests__/analyze-conversation.test.ts +54 -9
  729. package/src/runtime/services/__tests__/auto-analysis-enqueue.test.ts +30 -6
  730. package/src/runtime/services/__tests__/conversation-analyze-job.test.ts +43 -8
  731. package/src/runtime/services/__tests__/conversation-serializer.test.ts +20 -0
  732. package/src/runtime/services/analyze-conversation.ts +14 -4
  733. package/src/runtime/services/conversation-serializer.ts +5 -0
  734. package/src/runtime/slack-no-response.ts +47 -0
  735. package/src/runtime/slack-reply-session.test.ts +633 -0
  736. package/src/runtime/slack-reply-session.ts +382 -0
  737. package/src/runtime/slack-task-progress.ts +95 -0
  738. package/src/runtime/sync/resource-sync-events.ts +25 -0
  739. package/src/runtime/tool-grant-request-helper.ts +17 -1
  740. package/src/runtime/trust-class.test.ts +141 -0
  741. package/src/runtime/trust-class.ts +121 -0
  742. package/src/runtime/trust-verdict-consumer.ts +7 -6
  743. package/src/schedule/__tests__/run-script.test.ts +21 -0
  744. package/src/schedule/__tests__/worker-control.test.ts +241 -0
  745. package/src/schedule/run-script.ts +13 -6
  746. package/src/schedule/schedule-usage-store.ts +1 -0
  747. package/src/schedule/scheduler.ts +178 -127
  748. package/src/schedule/worker-control.ts +118 -0
  749. package/src/schedule/worker.ts +131 -0
  750. package/src/skills/__tests__/categories-cache.test.ts +38 -0
  751. package/src/skills/categories-cache.ts +40 -5
  752. package/src/skills/managed-store.ts +41 -6
  753. package/src/skills/validate-input.ts +47 -0
  754. package/src/stt/types.ts +5 -9
  755. package/src/subagent/manager.ts +267 -39
  756. package/src/subagent/types.ts +6 -2
  757. package/src/subagent/validate-allowlists.ts +65 -0
  758. package/src/telemetry/watchdog-direct-emit.test.ts +109 -0
  759. package/src/telemetry/watchdog-direct-emit.ts +89 -0
  760. package/src/tools/acp/list-agents.test.ts +0 -6
  761. package/src/tools/background-tool-registry.ts +61 -0
  762. package/src/tools/document/document-comment-tool.test.ts +4 -0
  763. package/src/tools/host-terminal/host-shell.test.ts +397 -0
  764. package/src/tools/host-terminal/host-shell.ts +203 -14
  765. package/src/tools/skills/find-similar-skills.test.ts +152 -1
  766. package/src/tools/skills/find-similar-skills.ts +30 -4
  767. package/src/tools/skills/load.ts +36 -0
  768. package/src/tools/skills/scaffold-managed.ts +66 -34
  769. package/src/tools/skills/skill-script-runner.ts +17 -0
  770. package/src/tools/skills/skill-tool-factory.ts +5 -1
  771. package/src/tools/terminal/safe-env.ts +3 -0
  772. package/src/tools/terminal/shell.test.ts +177 -0
  773. package/src/tools/terminal/shell.ts +98 -4
  774. package/src/tools/tool-approval-handler.ts +106 -29
  775. package/{node_modules/@vellumai/skill-host-contracts/src → src/tools}/tool-types.ts +16 -17
  776. package/src/tools/types.ts +29 -17
  777. package/src/tools/ui-surface/definitions.ts +3 -1
  778. package/src/tts/__tests__/provider-adapters.test.ts +37 -0
  779. package/src/tts/__tests__/provider-catalog.test.ts +21 -0
  780. package/src/tts/provider-catalog.ts +40 -9
  781. package/src/tts/providers/fish-audio-provider.ts +19 -10
  782. package/src/tts/types.ts +3 -4
  783. package/src/util/__tests__/process-tree.test.ts +10 -2
  784. package/src/util/__tests__/text-spacing.test.ts +53 -0
  785. package/src/util/cgroup-memory.ts +142 -0
  786. package/src/util/image-conversion.ts +281 -0
  787. package/src/util/phone.ts +1 -8
  788. package/src/util/platform.ts +33 -0
  789. package/src/util/process-tree.ts +10 -2
  790. package/src/util/text-spacing.ts +53 -0
  791. package/src/util/worker-process.ts +271 -0
  792. package/src/workflows/journal-store.ts +16 -1
  793. package/src/workflows/library.test.ts +35 -20
  794. package/src/workflows/library.ts +105 -66
  795. package/src/workspace/git-service.ts +1 -0
  796. package/src/workspace/migrations/011-backfill-installation-id.ts +83 -31
  797. package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +41 -22
  798. package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +1 -1
  799. package/src/workspace/migrations/118-seed-now-md.ts +64 -0
  800. package/src/workspace/migrations/119-strip-persisted-memory-v3-tuning-defaults.ts +169 -0
  801. package/src/workspace/migrations/120-revise-onboarding-threads.ts +47 -0
  802. package/src/workspace/migrations/121-seed-default-user-guardrails.ts +82 -0
  803. package/src/workspace/migrations/122-relocate-default-user-boundary.ts +111 -0
  804. package/src/workspace/migrations/123-swap-quality-profile-to-fable.ts +85 -0
  805. package/src/workspace/migrations/__tests__/119-strip-persisted-memory-v3-tuning-defaults.test.ts +181 -0
  806. package/src/workspace/migrations/registry.ts +12 -0
  807. package/drizzle/0000_dizzy_maggott.sql +0 -301
  808. package/drizzle/meta/0000_snapshot.json +0 -1933
  809. package/drizzle/meta/_journal.json +0 -13
  810. package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +0 -887
  811. package/node_modules/@vellumai/skill-host-contracts/bun.lock +0 -24
  812. package/node_modules/@vellumai/skill-host-contracts/package.json +0 -18
  813. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -97
  814. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +0 -1349
  815. package/node_modules/@vellumai/skill-host-contracts/src/index.ts +0 -6
  816. package/node_modules/@vellumai/skill-host-contracts/src/runtime-mode.ts +0 -11
  817. package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +0 -32
  818. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +0 -333
  819. package/node_modules/@vellumai/skill-host-contracts/tsconfig.json +0 -20
  820. package/node_modules/@vellumai/skill-host-contracts/tsconfig.test.json +0 -12
  821. package/src/__tests__/invite-redemption-service.test.ts +0 -1180
  822. package/src/__tests__/invite-service-ipc.test.ts +0 -350
  823. package/src/__tests__/job-handler-registry-guard.test.ts +0 -125
  824. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +0 -203
  825. package/src/__tests__/relay-server.test.ts +0 -6153
  826. package/src/__tests__/telephony-stt-routing.test.ts +0 -329
  827. package/src/__tests__/voice-invite-redemption.test.ts +0 -702
  828. package/src/calls/relay-server.ts +0 -2463
  829. package/src/calls/telephony-stt-routing.ts +0 -145
  830. package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +0 -128
  831. package/src/daemon/__tests__/daemon-skill-host.test.ts +0 -273
  832. package/src/daemon/daemon-skill-host.ts +0 -262
  833. package/src/daemon/message-types/meet.ts +0 -143
  834. package/src/daemon/shutdown-registry.ts +0 -40
  835. package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -253
  836. package/src/ipc/__tests__/skill-server.test.ts +0 -182
  837. package/src/ipc/skill-ipc-types.ts +0 -54
  838. package/src/ipc/skill-routes/__tests__/config.test.ts +0 -146
  839. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +0 -448
  840. package/src/ipc/skill-routes/__tests__/identity.test.ts +0 -62
  841. package/src/ipc/skill-routes/__tests__/log.test.ts +0 -133
  842. package/src/ipc/skill-routes/__tests__/memory.test.ts +0 -203
  843. package/src/ipc/skill-routes/__tests__/platform.test.ts +0 -111
  844. package/src/ipc/skill-routes/__tests__/providers.test.ts +0 -265
  845. package/src/ipc/skill-routes/__tests__/registries.test.ts +0 -400
  846. package/src/ipc/skill-routes/config.ts +0 -47
  847. package/src/ipc/skill-routes/events.ts +0 -147
  848. package/src/ipc/skill-routes/identity.ts +0 -21
  849. package/src/ipc/skill-routes/index.ts +0 -37
  850. package/src/ipc/skill-routes/log.ts +0 -40
  851. package/src/ipc/skill-routes/memory.ts +0 -92
  852. package/src/ipc/skill-routes/platform.ts +0 -39
  853. package/src/ipc/skill-routes/providers.ts +0 -162
  854. package/src/ipc/skill-routes/registries.ts +0 -338
  855. package/src/ipc/skill-server.ts +0 -831
  856. package/src/ipc/skill-socket-path.ts +0 -20
  857. package/src/jobs/register-job-handlers.ts +0 -74
  858. package/src/persistence/invite-store.ts +0 -481
  859. package/src/plugins/job-handler-registry.ts +0 -94
  860. package/src/providers/cache-control.ts +0 -26
  861. package/src/runtime/__tests__/runtime-mode.test.ts +0 -62
  862. package/src/runtime/invite-redemption-service.ts +0 -828
  863. package/src/runtime/invite-redemption-templates.ts +0 -46
  864. package/src/runtime/runtime-mode.ts +0 -40
  865. package/src/runtime/slack-dm-text-delivery.ts +0 -177
  866. package/src/util/voice-code.ts +0 -31
@@ -1,9 +1,18 @@
1
+ import { join } from "node:path";
2
+
1
3
  import { getConfig } from "../../../config/loader.js";
4
+ import {
5
+ clearMessagesLexicalIndex,
6
+ enqueueDeleteMessageLexical,
7
+ enqueuePurgeConversationLexical,
8
+ } from "../../../persistence/job-handlers/message-lexical.js";
2
9
  import type {
3
10
  ConversationForkedEvent,
4
11
  MemoryPersistenceHooks,
5
12
  MessagePersistedEvent,
6
13
  } from "../../../persistence/memory-lifecycle-hooks.js";
14
+ import { getWorkspaceDir } from "../../../util/platform.js";
15
+ import { getMemoryConfig } from "./config.js";
7
16
  import { forkGraphMemoryState } from "./graph/graph-memory-state-store.js";
8
17
  import { indexMessageNow } from "./indexer.js";
9
18
  import { sweepOrphanMemoryRetrospectiveConversations } from "./memory-retrospective-startup-cleanup.js";
@@ -13,6 +22,7 @@ import {
13
22
  forkActivationState,
14
23
  seedForkActivationState,
15
24
  } from "./v2/activation-store.js";
25
+ import { countBufferLines } from "./v2/consolidation-job.js";
16
26
  import {
17
27
  extractInjectedConceptSlugs,
18
28
  readInjectedBlock,
@@ -31,7 +41,7 @@ import {
31
41
  */
32
42
  export const memoryPersistenceHooks: MemoryPersistenceHooks = {
33
43
  async onMessagePersisted(event: MessagePersistedEvent): Promise<void> {
34
- await indexMessageNow({ ...event, scopeId: "default" }, getConfig().memory);
44
+ await indexMessageNow({ ...event, scopeId: "default" }, getMemoryConfig());
35
45
  },
36
46
 
37
47
  onConversationForked(event: ConversationForkedEvent): void {
@@ -110,10 +120,45 @@ export const memoryPersistenceHooks: MemoryPersistenceHooks = {
110
120
  },
111
121
 
112
122
  onConversationWiped(conversationId: string): number {
123
+ // Cancel pending memory jobs only. The lexical purge is fired from the
124
+ // shared delete primitive via `onConversationDeleted` (which
125
+ // `wipeConversation` reaches through its internal `deleteConversation`), so
126
+ // the purge lands AFTER this cancellation pass and cannot be swept by it.
113
127
  return cancelPendingJobsForConversation(conversationId);
114
128
  },
115
129
 
130
+ onConversationDeleted(conversationId: string): void {
131
+ // Purge the conversation's points from the lexical (Qdrant) index. Fired
132
+ // from the shared delete primitive, so every delete caller — route, wipe,
133
+ // retrospective cleanup, GC — cleans up. The enqueue helper self-selects:
134
+ // enqueue a job when memory is enabled, run the delete inline (best-effort,
135
+ // breaker-wrapped) when it is disabled.
136
+ enqueuePurgeConversationLexical(conversationId);
137
+ },
138
+
139
+ onMessagesDeleted(messageIds: string[]): void {
140
+ // Remove each deleted message's point from the lexical index. The enqueue
141
+ // helper self-selects: enqueue a job when memory is enabled, run the delete
142
+ // inline (best-effort, breaker-wrapped) when it is disabled.
143
+ for (const messageId of messageIds) {
144
+ enqueueDeleteMessageLexical(messageId);
145
+ }
146
+ },
147
+
148
+ async onAllConversationsCleared(): Promise<void> {
149
+ // Drop the whole lexical (Qdrant) collection — a "delete all" leaves no ids
150
+ // to key per-message cleanup on. Awaited so the drop completes before
151
+ // clear-all returns and writes resume; otherwise a message created right
152
+ // after clear-all could upsert into the not-yet-dropped collection and then
153
+ // be erased when the drop lands.
154
+ await clearMessagesLexicalIndex(getConfig());
155
+ },
156
+
116
157
  onWorkerStartup(): void {
117
158
  sweepOrphanMemoryRetrospectiveConversations();
118
159
  },
160
+
161
+ countMemoryBufferLines(): number {
162
+ return countBufferLines(join(getWorkspaceDir(), "memory", "buffer.md"));
163
+ },
119
164
  };
@@ -15,10 +15,9 @@ import { createHash } from "node:crypto";
15
15
  import { readdir, readFile, stat } from "node:fs/promises";
16
16
  import { join, relative } from "node:path";
17
17
 
18
- import { getConfig } from "../../../../config/loader.js";
19
18
  import { withQdrantBreaker } from "../../../../persistence/embeddings/qdrant-circuit-breaker.js";
20
19
  import { getQdrantClient } from "../../../../persistence/embeddings/qdrant-client.js";
21
- import { embedAndUpsert } from "../../../../persistence/job-utils.js";
20
+ import { embedAndUpsert } from "../embeddings.js";
22
21
  import type { PkbIndexEntry } from "./types.js";
23
22
  import { PKB_TARGET_TYPE } from "./types.js";
24
23
 
@@ -189,8 +188,6 @@ export async function indexPkbFile(
189
188
  const relPath = relative(pkbRoot, absPath);
190
189
  const chunks = chunkPkbFile(content);
191
190
 
192
- const config = getConfig();
193
-
194
191
  const qdrant = getQdrantClient();
195
192
  const existing = await withQdrantBreaker(() =>
196
193
  qdrant.scrollByTargetType(PKB_TARGET_TYPE, {
@@ -209,7 +206,6 @@ export async function indexPkbFile(
209
206
  const targetId = `${memoryScopeId}:${relPath}#${chunkIndex}`;
210
207
  newTargetIds.add(targetId);
211
208
  await embedAndUpsert(
212
- config,
213
209
  PKB_TARGET_TYPE,
214
210
  targetId,
215
211
  { type: "text", text: chunk },
@@ -2,7 +2,6 @@
2
2
  // PKB — Qdrant hybrid search for indexed PKB markdown files
3
3
  // ---------------------------------------------------------------------------
4
4
 
5
- import { getConfig } from "../../../../config/loader.js";
6
5
  import {
7
6
  isQdrantBreakerOpen,
8
7
  withQdrantBreaker,
@@ -13,6 +12,7 @@ import type {
13
12
  } from "../../../../persistence/embeddings/qdrant-client.js";
14
13
  import { getQdrantClient } from "../../../../persistence/embeddings/qdrant-client.js";
15
14
  import { getLogger } from "../../../../util/logger.js";
15
+ import { getMemoryConfig } from "../config.js";
16
16
  import type { PkbSearchResult } from "./types.js";
17
17
  import { PKB_TARGET_TYPE } from "./types.js";
18
18
 
@@ -44,7 +44,7 @@ export async function searchPkbFiles(
44
44
  // v2 owns the read path when enabled; v2 absorbs PKB as a read source,
45
45
  // so PKB hint search short-circuits to keep traffic off the v1 collection
46
46
  // (avoiding OOM-crash risk from a corrupted sparse segment).
47
- if (getConfig().memory.v2.enabled) return [];
47
+ if (getMemoryConfig().v2.enabled) return [];
48
48
 
49
49
  if (isQdrantBreakerOpen()) {
50
50
  log.warn("Qdrant circuit breaker open, skipping PKB search");
@@ -22,12 +22,10 @@ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
22
22
  import type {
23
23
  Message,
24
24
  Provider,
25
- ProviderResponse,
26
25
  SendMessageOptions,
27
- ToolUseContent,
28
26
  } from "@vellumai/plugin-api";
29
27
 
30
- import type { ToolDefinition } from "../../../../../providers/types.js";
28
+ import type { ToolDefinition } from "../../llm-helpers.js";
31
29
 
32
30
  // ---------------------------------------------------------------------------
33
31
  // Mocks (installed before the route module is imported)
@@ -123,10 +121,10 @@ interface ProviderCall {
123
121
  options: SendMessageOptions | undefined;
124
122
  }
125
123
  const providerCalls: ProviderCall[] = [];
126
- mock.module("../../../../../providers/provider-send-message.js", () => ({
124
+ // The route imports `getConfiguredProvider` from `@vellumai/plugin-api`; the
125
+ // pure `extractToolUse` helper runs for real from the plugin's `llm-helpers`.
126
+ mock.module("@vellumai/plugin-api", () => ({
127
127
  getConfiguredProvider: async () => providerStub,
128
- extractToolUse: (response: ProviderResponse) =>
129
- response.content.find((b): b is ToolUseContent => b.type === "tool_use"),
130
128
  }));
131
129
 
132
130
  // Platform helpers. `getWorkspaceDir` must return the per-test tmp dir so
@@ -27,7 +27,6 @@ import { z } from "zod";
27
27
  import { getConfig } from "../../../../config/loader.js";
28
28
  import { getDb } from "../../../../persistence/db-connection.js";
29
29
  import {
30
- embedWithBackend,
31
30
  generateSparseEmbedding,
32
31
  getMemoryBackendStatus,
33
32
  } from "../../../../persistence/embeddings/embedding-backend.js";
@@ -46,6 +45,7 @@ import {
46
45
  } from "../../../../runtime/routes/errors.js";
47
46
  import type { RouteDefinition } from "../../../../runtime/routes/types.js";
48
47
  import { getLogger } from "../../../../util/logger.js";
48
+ import { embedWithBackend } from "../embeddings.js";
49
49
  import { createNode, deleteNode, getNode, updateNode } from "../graph/store.js";
50
50
  import type {
51
51
  Fidelity,
@@ -1,6 +1,5 @@
1
1
  import { inArray } from "drizzle-orm";
2
2
 
3
- import { getConfig } from "../../../../config/loader.js";
4
3
  import { getDb } from "../../../../persistence/db-connection.js";
5
4
  import { withQdrantBreaker } from "../../../../persistence/embeddings/qdrant-circuit-breaker.js";
6
5
  import type {
@@ -12,6 +11,7 @@ import {
12
11
  memorySegments,
13
12
  memorySummaries,
14
13
  } from "../../../../persistence/schema/index.js";
14
+ import { getMemoryConfig } from "../config.js";
15
15
  import { mapCosineToUnit } from "../validation.js";
16
16
  // ── Types (inlined from deleted types.ts) ──────────────────────────
17
17
 
@@ -62,7 +62,7 @@ export async function semanticSearch(
62
62
  // v2 owns the read path when enabled; the v1 `memory` collection is in
63
63
  // active retirement, and routing semantic recall there would re-enter the
64
64
  // same corrupted sparse segments that can OOM-crash Qdrant.
65
- if (getConfig().memory.v2.enabled) return [];
65
+ if (getMemoryConfig().v2.enabled) return [];
66
66
 
67
67
  const qdrant = getQdrantClient();
68
68
 
@@ -0,0 +1,244 @@
1
+ /**
2
+ * Memory plugin — background startup orchestration.
3
+ *
4
+ * Boots the Qdrant vector store, reconciles the embedding-identity and v2
5
+ * concept-page collections, runs the PKB and BM25 reconciles, and seeds the
6
+ * capability graph. Kicked off fire-and-forget from the memory plugin's `init`
7
+ * hook during daemon plugin bootstrap (after the runtime HTTP server is up), so
8
+ * the daemon accepts requests without waiting on Qdrant. Each step contains its
9
+ * own failure so a memory-subsystem problem never blocks boot.
10
+ *
11
+ * Job-handler registration happens in the plugin's `init` hook, synchronously,
12
+ * before this is kicked off — so the memory handlers are guaranteed to be in the
13
+ * dispatch table before the jobs worker started near the end of this function
14
+ * claims its first job.
15
+ */
16
+
17
+ import { join } from "node:path";
18
+
19
+ import type { AssistantConfig } from "../../../config/schema.js";
20
+ import { reconcileEmbeddingIdentity } from "../../../daemon/embedding-reconcile.js";
21
+ import { refreshSkillCapabilityMemories } from "../../../daemon/skill-memory-refresh.js";
22
+ import { selectEmbeddingBackend } from "../../../persistence/embeddings/embedding-backend.js";
23
+ import {
24
+ initMessagesLexicalIndex,
25
+ MESSAGES_LEXICAL_COLLECTION,
26
+ } from "../../../persistence/embeddings/messages-lexical-index.js";
27
+ import {
28
+ clearRebuildSentinel,
29
+ initQdrantClient,
30
+ } from "../../../persistence/embeddings/qdrant-client.js";
31
+ import { createQdrantManager } from "../../../persistence/embeddings/qdrant-manager.js";
32
+ import {
33
+ enqueueMemoryJob,
34
+ isMemoryEnabled,
35
+ } from "../../../persistence/jobs-store.js";
36
+ import { startMemoryJobsWorker } from "../../../persistence/jobs-worker.js";
37
+ import { getLogger } from "../../../util/logger.js";
38
+ import { getWorkspaceDir } from "../../../util/platform.js";
39
+ import { resolveQdrantUrl } from "./embeddings.js";
40
+ import { sweepConceptPageFrontmatter } from "./v2/frontmatter-sweep.js";
41
+ import {
42
+ maybeRebuildMemoryV2Concepts,
43
+ rebuildBm25CorpusStatsAndReseedSkills,
44
+ } from "./v2/memory-v2-startup.js";
45
+
46
+ const log = getLogger("memory-startup");
47
+
48
+ export async function runMemoryStartup(config: AssistantConfig): Promise<void> {
49
+ const qdrantUrl = resolveQdrantUrl();
50
+ log.info({ qdrantUrl }, "Daemon startup: initializing Qdrant");
51
+ const manager = createQdrantManager({ url: qdrantUrl });
52
+ const QDRANT_START_MAX_ATTEMPTS = 3;
53
+ let qdrantStarted = false;
54
+ for (let attempt = 1; attempt <= QDRANT_START_MAX_ATTEMPTS; attempt++) {
55
+ try {
56
+ await manager.start();
57
+ qdrantStarted = true;
58
+ break;
59
+ } catch (err) {
60
+ if (attempt < QDRANT_START_MAX_ATTEMPTS) {
61
+ const backoffMs = attempt * 5_000; // 5s, 10s
62
+ log.warn(
63
+ {
64
+ err,
65
+ attempt,
66
+ maxAttempts: QDRANT_START_MAX_ATTEMPTS,
67
+ backoffMs,
68
+ },
69
+ "Qdrant startup failed, retrying",
70
+ );
71
+ await Bun.sleep(backoffMs);
72
+ } else {
73
+ log.warn(
74
+ { err },
75
+ "Qdrant failed to start after all attempts — memory features will be unavailable",
76
+ );
77
+ }
78
+ }
79
+ }
80
+
81
+ if (qdrantStarted) {
82
+ // Skip the v1 Qdrant collection lifecycle when memory v2 is active —
83
+ // the v1 collection has no writers (handleRemember returns early) or
84
+ // readers (graph search is bypassed) under v2, so ensuring/migrating
85
+ // it just maintains a dead-on-arrival collection. Existing on-disk
86
+ // collections are left intact so flipping v2 off restores v1 cleanly.
87
+ if (!config.memory.v2.enabled) {
88
+ try {
89
+ const embeddingSelection = await selectEmbeddingBackend(config);
90
+ // Sentinel only encodes the dense provider+model identity; sparse
91
+ // encoder changes never require collection recreation, so they
92
+ // intentionally do not contribute to the v1 collection identity.
93
+ const embeddingModel = embeddingSelection.backend
94
+ ? `${embeddingSelection.backend.provider}:${embeddingSelection.backend.model}`
95
+ : undefined;
96
+ const qdrantClient = initQdrantClient({
97
+ url: qdrantUrl,
98
+ collection: config.memory.qdrant.collection,
99
+ vectorSize: config.memory.qdrant.vectorSize,
100
+ onDisk: config.memory.qdrant.onDisk,
101
+ quantization: config.memory.qdrant.quantization,
102
+ embeddingModel,
103
+ });
104
+
105
+ // Eagerly ensure the collection exists so we detect migrations
106
+ // (unnamed→named vectors, dimension/model changes) at startup.
107
+ // If a destructive migration occurred, enqueue a rebuild_index job
108
+ // to re-embed all memory items from the SQLite cache.
109
+ const { migrated } = await qdrantClient.ensureCollection();
110
+ if (migrated && isMemoryEnabled()) {
111
+ enqueueMemoryJob("rebuild_index", {});
112
+ // Clear the on-disk sentinel the ensure-path writes before its
113
+ // destructive delete: now that rebuild_index is queued, the
114
+ // cross-boot signal can retire. No-op if no sentinel was written.
115
+ await clearRebuildSentinel();
116
+ log.info(
117
+ "Qdrant collection was migrated — enqueued rebuild_index job",
118
+ );
119
+ }
120
+
121
+ log.info("Qdrant vector store initialized");
122
+ } catch (err) {
123
+ log.warn(
124
+ { err },
125
+ "Qdrant client initialization failed — memory features will be degraded",
126
+ );
127
+ }
128
+ }
129
+
130
+ // Initialize the messages lexical index — a dedicated sparse-only Qdrant
131
+ // collection that is the lexical (BM25-style) replacement for SQLite FTS5
132
+ // over message content. Independent of the v1 dense collection lifecycle
133
+ // (sparse-only, no embedding model), so it is constructed whenever Qdrant
134
+ // is up regardless of the v2 flag. Lazy collection creation lives in the
135
+ // client, so this only wires the singleton.
136
+ try {
137
+ initMessagesLexicalIndex({
138
+ url: qdrantUrl,
139
+ collection: MESSAGES_LEXICAL_COLLECTION,
140
+ onDisk: config.memory.qdrant.onDisk,
141
+ });
142
+ } catch (err) {
143
+ log.warn(
144
+ { err },
145
+ "Messages lexical index initialization failed — lexical search will be degraded",
146
+ );
147
+ }
148
+
149
+ // Reconcile the committed embedding-collection dimension against a live
150
+ // backend probe (confirm-before-destroy) before the v2 rebuild and the
151
+ // worker drain, so `memory.qdrant.vectorSize` is settled first. Its own
152
+ // try/catch keeps an unreachable backend or reconcile failure from
153
+ // blocking startup.
154
+ try {
155
+ await reconcileEmbeddingIdentity(config);
156
+ } catch (err) {
157
+ log.warn(
158
+ { err },
159
+ "Embedding-identity reconcile threw — continuing startup",
160
+ );
161
+ }
162
+
163
+ // Detect schema drift on the v2 concept-page collection (e.g.
164
+ // pre-#29823 collections lacking summary_dense / summary_sparse) and
165
+ // recreate + enqueue a reembed when needed. Awaited inline so the
166
+ // reembed enqueue happens before the memory worker drains its first
167
+ // batch; the call's own try/catch keeps any v2-side failure from
168
+ // blocking the v1 PKB reconcile or BM25 build below.
169
+ try {
170
+ await maybeRebuildMemoryV2Concepts(config);
171
+ } catch (err) {
172
+ log.warn(
173
+ { err },
174
+ "Memory v2 collection schema check threw — continuing startup",
175
+ );
176
+ }
177
+
178
+ // Reconcile the PKB Qdrant index against the on-disk tree. Gated on
179
+ // !v2 because PKB is the v1 storage layer; under v2 the v1 collection
180
+ // is not initialized, so calling `getQdrantClient()` here would throw.
181
+ // Fire-and-forget so enqueued re-index jobs drain in the background
182
+ // and first-turn latency stays unaffected.
183
+ if (!config.memory.v2.enabled) {
184
+ void (async () => {
185
+ try {
186
+ const { reconcilePkbIndex } = await import("./pkb/pkb-reconcile.js");
187
+ const { PKB_WORKSPACE_SCOPE } = await import("./pkb/types.js");
188
+ const pkbRoot = join(getWorkspaceDir(), "pkb");
189
+ await reconcilePkbIndex(pkbRoot, PKB_WORKSPACE_SCOPE);
190
+ } catch (err) {
191
+ log.warn(
192
+ { err },
193
+ "PKB index reconciliation failed — continuing startup",
194
+ );
195
+ }
196
+ })();
197
+ }
198
+
199
+ void rebuildBm25CorpusStatsAndReseedSkills(config);
200
+
201
+ try {
202
+ await sweepConceptPageFrontmatter(config, getWorkspaceDir());
203
+ } catch (err) {
204
+ log.warn(
205
+ { err },
206
+ "Concept page frontmatter sweep threw — continuing startup",
207
+ );
208
+ }
209
+ }
210
+
211
+ // `startMemoryJobsWorker` starts the in-process supervisor (which owns the
212
+ // synchronous runner and stands down when an out-of-process worker is live)
213
+ // and spawns the out-of-process worker at boot when `memory.worker.enabled`
214
+ // is set. Shutdown stops whichever worker is actually running — see
215
+ // shutdown-handlers.ts. The job handlers were registered synchronously by the
216
+ // plugin's `init` hook before this function was kicked off, so the dispatch
217
+ // table is populated before the worker's first claim.
218
+ log.info("Daemon startup: starting memory worker");
219
+ startMemoryJobsWorker();
220
+
221
+ // Seed capability graph nodes (new memory graph system)
222
+ try {
223
+ const { seedCliGraphNodes } = await import("./graph/capability-seed.js");
224
+ refreshSkillCapabilityMemories(config);
225
+ await seedCliGraphNodes();
226
+ } catch (err) {
227
+ log.warn({ err }, "Graph capability seeding failed — continuing");
228
+ }
229
+
230
+ // Auto-bootstrap: if the graph has no non-procedural nodes but historical
231
+ // segments exist, enqueue a one-time graph_bootstrap job to populate the
232
+ // graph from conversation history and journal files.
233
+ try {
234
+ const { maybeEnqueueGraphBootstrap, cleanupStaleItemVectors } =
235
+ await import("./graph/bootstrap.js");
236
+ maybeEnqueueGraphBootstrap();
237
+ // Fire-and-forget: clean up orphaned Qdrant vectors from dropped memory_items table
238
+ void cleanupStaleItemVectors().catch((err) =>
239
+ log.warn({ err }, "Stale item vector cleanup failed — continuing"),
240
+ );
241
+ } catch (err) {
242
+ log.warn({ err }, "Graph bootstrap check failed — continuing");
243
+ }
244
+ }
@@ -35,6 +35,7 @@ function cancelJobsByPayloadIds(
35
35
  const chunk = ids.slice(i, i + ID_CHUNK_SIZE);
36
36
  const placeholders = chunk.map(() => "?").join(", ");
37
37
  affected += rawMemoryRun(
38
+ "taskMemory:cancelJobsByPayloadIds",
38
39
  `UPDATE memory_jobs
39
40
  SET status = 'failed',
40
41
  last_error = ?,
@@ -62,6 +63,7 @@ export function isConversationFailed(conversationId: string): boolean {
62
63
  // which is a monotonically increasing epoch timestamp) has an error status.
63
64
  // Note: cron_runs.id is a UUID v4 (random), so we cannot use MAX(id).
64
65
  const row = rawGet<{ found: number }>(
66
+ "taskMemory:isConversationFailed",
65
67
  `SELECT 1 AS found
66
68
  FROM (
67
69
  SELECT 1 FROM task_runs WHERE conversation_id = ? AND status = 'failed'
@@ -98,6 +100,7 @@ export function invalidateAssistantInferredItemsForConversation(
98
100
  cancelPendingExtractionJobsForConversation(conversationId);
99
101
 
100
102
  const affected = rawRun(
103
+ "taskMemory:invalidateInferredNodes",
101
104
  `UPDATE memory_graph_nodes
102
105
  SET fidelity = 'gone',
103
106
  last_accessed = ?
@@ -164,6 +167,7 @@ export function cancelPendingJobsForConversation(
164
167
 
165
168
  // Jobs keyed by messageId: embed_attachment
166
169
  const messageIds = rawAll<{ id: string }>(
170
+ "taskMemory:cancelJobs:messageIds",
167
171
  `SELECT id FROM messages WHERE conversation_id = ?`,
168
172
  conversationId,
169
173
  ).map((r) => r.id);
@@ -171,6 +175,7 @@ export function cancelPendingJobsForConversation(
171
175
 
172
176
  // Jobs keyed by conversationId: graph_extract, build_conversation_summary
173
177
  total += rawMemoryRun(
178
+ "taskMemory:cancelJobs:byConversation",
174
179
  `UPDATE memory_jobs
175
180
  SET status = 'failed',
176
181
  last_error = ?,
@@ -184,6 +189,7 @@ export function cancelPendingJobsForConversation(
184
189
 
185
190
  // Jobs keyed by segmentId: embed_segment (segments belong to the conversation)
186
191
  const segmentIds = rawAll<{ id: string }>(
192
+ "taskMemory:cancelJobs:segmentIds",
187
193
  `SELECT id FROM memory_segments WHERE conversation_id = ?`,
188
194
  conversationId,
189
195
  ).map((r) => r.id);
@@ -191,6 +197,7 @@ export function cancelPendingJobsForConversation(
191
197
 
192
198
  // Jobs keyed by nodeId: embed_graph_node (nodes sourced from this conversation)
193
199
  const nodeIds = rawAll<{ id: string }>(
200
+ "taskMemory:cancelJobs:nodeIds",
194
201
  `SELECT mgn.id
195
202
  FROM memory_graph_nodes mgn, json_each(mgn.source_conversations) jc
196
203
  WHERE jc.value = ?`,
@@ -219,6 +226,7 @@ function cancelPendingExtractionJobsForConversation(
219
226
  ): number {
220
227
  const now = Date.now();
221
228
  const cancelled = rawMemoryRun(
229
+ "taskMemory:cancelExtractionJobs",
222
230
  `UPDATE memory_jobs
223
231
  SET status = 'failed',
224
232
  last_error = 'conversation_failed',
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, mock, test } from "bun:test";
2
2
 
3
- import type { AssistantConfig } from "../../config/schema.js";
3
+ import type { AssistantConfig } from "../../../../../config/schema.js";
4
4
 
5
5
  function fakeConfig(): AssistantConfig {
6
6
  return {
@@ -30,20 +30,20 @@ async function withMocks(opts: { reembedInFlight: boolean }) {
30
30
  hasConceptPages: mock(async () => true),
31
31
  };
32
32
 
33
- mock.module("../../persistence/jobs-store.js", () => ({
33
+ mock.module("../../../../../persistence/jobs-store.js", () => ({
34
34
  enqueueMemoryJob: spies.enqueueMemoryJob,
35
35
  hasActiveJobOfType: spies.hasActiveJobOfType,
36
36
  }));
37
- mock.module("../../plugins/defaults/memory/v2/qdrant.js", () => ({
37
+ mock.module("../qdrant.js", () => ({
38
38
  ensureConceptPageCollection: spies.ensureConceptPageCollection,
39
39
  countConceptPagePoints: spies.countConceptPagePoints,
40
40
  clearReembedSentinel: spies.clearReembedSentinel,
41
41
  }));
42
- mock.module("../../plugins/defaults/memory/v2/page-store.js", () => ({
42
+ mock.module("../page-store.js", () => ({
43
43
  hasConceptPages: spies.hasConceptPages,
44
44
  }));
45
- const realPlatform = await import("../../util/platform.js");
46
- mock.module("../../util/platform.js", () => ({
45
+ const realPlatform = await import("../../../../../util/platform.js");
46
+ mock.module("../../../../../util/platform.js", () => ({
47
47
  ...realPlatform,
48
48
  getWorkspaceDir: () => "/tmp/workspace",
49
49
  }));
@@ -28,7 +28,6 @@ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
28
28
  import type {
29
29
  Message,
30
30
  Provider,
31
- ProviderResponse,
32
31
  SendMessageOptions,
33
32
  } from "@vellumai/plugin-api";
34
33
 
@@ -62,18 +61,8 @@ mock.module("../../../../../persistence/jobs-store.js", () => ({
62
61
  // provider, but the safety net mock keeps any accidental real-call from
63
62
  // reaching the network — and lets us add a "no provider configured" test.
64
63
  let providerStub: Provider | null = null;
65
- mock.module("../../../../../providers/provider-send-message.js", () => ({
64
+ mock.module("@vellumai/plugin-api", () => ({
66
65
  getConfiguredProvider: async () => providerStub,
67
- userMessage: (text: string) => ({
68
- role: "user" as const,
69
- content: [{ type: "text" as const, text }],
70
- }),
71
- extractText: (response: ProviderResponse) => {
72
- const block = response.content.find(
73
- (b): b is { type: "text"; text: string } => b.type === "text",
74
- );
75
- return block?.text?.trim() ?? "";
76
- },
77
66
  }));
78
67
 
79
68
  import {
@@ -100,7 +89,7 @@ import * as schema from "../../../../../persistence/schema/index.js";
100
89
  import type { Cluster, V1Edge, V1Item } from "../migration.js";
101
90
 
102
91
  // Dynamic import — runs *after* the mock.module calls above so the migration
103
- // module's transitive references to logger / jobs-store / provider-send-message
92
+ // module's transitive references to logger / jobs-store / @vellumai/plugin-api
104
93
  // resolve to our stubs (matches the pattern used in `qdrant.test.ts`).
105
94
  const {
106
95
  clusterByTopic,
@@ -30,10 +30,9 @@ import type {
30
30
  Provider,
31
31
  ProviderResponse,
32
32
  SendMessageOptions,
33
- ToolUseContent,
34
33
  } from "@vellumai/plugin-api";
35
34
 
36
- import type { ToolDefinition } from "../../../../../providers/types.js";
35
+ import type { ToolDefinition } from "../../llm-helpers.js";
37
36
 
38
37
  // ---------------------------------------------------------------------------
39
38
  // Mocks installed BEFORE the router import so the module observes them at
@@ -106,10 +105,10 @@ interface ProviderCall {
106
105
  }
107
106
  const providerCalls: ProviderCall[] = [];
108
107
 
109
- mock.module("../../../../../providers/provider-send-message.js", () => ({
108
+ // The router imports `getConfiguredProvider` from `@vellumai/plugin-api`; the
109
+ // pure `extractToolUse` helper runs for real from the plugin's `llm-helpers`.
110
+ mock.module("@vellumai/plugin-api", () => ({
110
111
  getConfiguredProvider: async () => providerStub,
111
- extractToolUse: (response: ProviderResponse) =>
112
- response.content.find((b): b is ToolUseContent => b.type === "tool_use"),
113
112
  }));
114
113
 
115
114
  // IDENTITY.md / users/default.md aren't required for these tests — the
@@ -38,7 +38,6 @@ import type {
38
38
  Provider,
39
39
  ProviderResponse,
40
40
  SendMessageOptions,
41
- ToolUseContent,
42
41
  } from "@vellumai/plugin-api";
43
42
 
44
43
  import { makeMockLogger } from "../../../../../__tests__/helpers/mock-logger.js";
@@ -55,14 +54,8 @@ const providerCalls: Array<{
55
54
  userText: string;
56
55
  }> = [];
57
56
 
58
- mock.module("../../../../../providers/provider-send-message.js", () => ({
57
+ mock.module("@vellumai/plugin-api", () => ({
59
58
  getConfiguredProvider: async () => providerStub,
60
- userMessage: (text: string) => ({
61
- role: "user" as const,
62
- content: [{ type: "text" as const, text }],
63
- }),
64
- extractToolUse: (response: ProviderResponse) =>
65
- response.content.find((b): b is ToolUseContent => b.type === "tool_use"),
66
59
  }));
67
60
 
68
61
  // emitNotificationSignal spy — captures every notification the sweep emits
@@ -35,11 +35,9 @@
35
35
  // for the next turn and drop below `epsilon` if no longer relevant.
36
36
 
37
37
  import type { AssistantConfig } from "../../../../config/types.js";
38
- import {
39
- embedWithBackend,
40
- isEmbeddingDimensionAvailable,
41
- } from "../../../../persistence/embeddings/embedding-backend.js";
38
+ import { isEmbeddingDimensionAvailable } from "../../../../persistence/embeddings/embedding-backend.js";
42
39
  import { applyCorrectionIfCalibrated } from "../anisotropy.js";
40
+ import { embedWithBackend } from "../embeddings.js";
43
41
  import { clampUnitInterval } from "../validation.js";
44
42
  import type { EdgeIndex } from "./edge-index.js";
45
43
  import { hybridQueryConceptPages } from "./qdrant.js";
@@ -21,12 +21,10 @@
21
21
  // summary.
22
22
 
23
23
  import { getConfig } from "../../../../config/loader.js";
24
- import {
25
- embedWithBackend,
26
- generateSparseEmbedding,
27
- } from "../../../../persistence/embeddings/embedding-backend.js";
24
+ import { generateSparseEmbedding } from "../../../../persistence/embeddings/embedding-backend.js";
28
25
  import { getLogger } from "../../../../util/logger.js";
29
26
  import { applyCorrectionIfCalibrated } from "../anisotropy.js";
27
+ import { embedWithBackend } from "../embeddings.js";
30
28
  import { buildCliCommandContent } from "./cli-command-content.js";
31
29
  import { invalidatePageIndex } from "./page-index.js";
32
30
  import {