@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
@@ -0,0 +1,251 @@
1
+ import { eq } from "drizzle-orm";
2
+
3
+ import type { AssistantConfig } from "../../config/types.js";
4
+ import { getLogger } from "../../util/logger.js";
5
+ import { getDb } from "../db-connection.js";
6
+ import { generateSparseEmbedding } from "../embeddings/embedding-backend.js";
7
+ import {
8
+ getMessagesLexicalIndex,
9
+ initMessagesLexicalIndex,
10
+ MESSAGES_LEXICAL_COLLECTION,
11
+ type MessagesLexicalIndex,
12
+ } from "../embeddings/messages-lexical-index.js";
13
+ import { withQdrantBreaker } from "../embeddings/qdrant-circuit-breaker.js";
14
+ import { resolveQdrantUrl } from "../embeddings/qdrant-client.js";
15
+ import { asString } from "../job-utils.js";
16
+ import { enqueueMemoryJob, type MemoryJob } from "../jobs-store.js";
17
+ import { messages } from "../schema/index.js";
18
+
19
+ const log = getLogger("messages-lexical-enqueue");
20
+
21
+ /**
22
+ * Resolve the messages lexical index singleton, lazily initializing it from
23
+ * `config` when it has not been set up in this process. The eager init in
24
+ * `runMemoryStartup` (startup.ts) only runs in the daemon process; the memory
25
+ * job worker can run as a separate OS process (`jobs/worker.ts`) that never
26
+ * calls `runMemoryStartup`, so without this fallback every lexical job claimed
27
+ * there would throw. `initMessagesLexicalIndex` is idempotent — it just
28
+ * (re)points the singleton at an equivalent client — so re-initializing from
29
+ * the same config is safe.
30
+ */
31
+ export function resolveLexicalIndex(
32
+ config: AssistantConfig,
33
+ ): MessagesLexicalIndex {
34
+ try {
35
+ return getMessagesLexicalIndex();
36
+ } catch {
37
+ return initMessagesLexicalIndex({
38
+ url: resolveQdrantUrl(config),
39
+ collection: MESSAGES_LEXICAL_COLLECTION,
40
+ onDisk: config.memory.qdrant.onDisk,
41
+ });
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Encode `message.content` with the local sparse encoder and upsert it into the
47
+ * messages lexical (Qdrant) index. The single shared indexing primitive — the
48
+ * `index_message_lexical` job and the backfill path both route through here so
49
+ * the encode + upsert sequence lives in one place.
50
+ *
51
+ * The upsert is wrapped in the Qdrant circuit breaker so a transient Qdrant
52
+ * outage trips the breaker and surfaces as a deferrable error rather than an
53
+ * unhandled throw; the job worker's retry/defer logic then drains the backlog
54
+ * once Qdrant recovers.
55
+ */
56
+ export async function indexMessageToLexical(
57
+ message: {
58
+ id: string;
59
+ conversationId: string;
60
+ content: string;
61
+ createdAt: number;
62
+ },
63
+ config: AssistantConfig,
64
+ ): Promise<void> {
65
+ const index = resolveLexicalIndex(config);
66
+ const sparse = generateSparseEmbedding(message.content);
67
+ await withQdrantBreaker(() =>
68
+ index.upsertMessage(message.id, sparse, {
69
+ conversationId: message.conversationId,
70
+ createdAt: message.createdAt,
71
+ }),
72
+ );
73
+ }
74
+
75
+ export async function indexMessageLexicalJob(
76
+ job: MemoryJob,
77
+ config: AssistantConfig,
78
+ ): Promise<void> {
79
+ const messageId = asString(job.payload.messageId);
80
+ if (!messageId) {
81
+ return;
82
+ }
83
+
84
+ const db = getDb();
85
+ const row = db
86
+ .select({
87
+ id: messages.id,
88
+ conversationId: messages.conversationId,
89
+ content: messages.content,
90
+ createdAt: messages.createdAt,
91
+ })
92
+ .from(messages)
93
+ .where(eq(messages.id, messageId))
94
+ .get();
95
+
96
+ // The message may have been deleted between enqueue and dispatch — no-op.
97
+ if (!row) {
98
+ return;
99
+ }
100
+
101
+ await indexMessageToLexical(row, config);
102
+ }
103
+
104
+ /**
105
+ * Delete a conversation's points from the lexical index (the
106
+ * `purge_conversation_lexical` job body).
107
+ */
108
+ async function purgeConversationLexical(
109
+ conversationId: string,
110
+ config: AssistantConfig,
111
+ ): Promise<void> {
112
+ const index = resolveLexicalIndex(config);
113
+ await withQdrantBreaker(() => index.deleteByConversation(conversationId));
114
+ }
115
+
116
+ /**
117
+ * Delete a single message's point from the lexical index (the
118
+ * `delete_message_lexical` job body).
119
+ */
120
+ async function deleteMessageLexical(
121
+ messageId: string,
122
+ config: AssistantConfig,
123
+ ): Promise<void> {
124
+ const index = resolveLexicalIndex(config);
125
+ await withQdrantBreaker(() => index.deleteByMessageId(messageId));
126
+ }
127
+
128
+ export async function purgeConversationLexicalJob(
129
+ job: MemoryJob,
130
+ config: AssistantConfig,
131
+ ): Promise<void> {
132
+ const conversationId = asString(job.payload.conversationId);
133
+ if (!conversationId) {
134
+ return;
135
+ }
136
+ await purgeConversationLexical(conversationId, config);
137
+ }
138
+
139
+ export async function deleteMessageLexicalJob(
140
+ job: MemoryJob,
141
+ config: AssistantConfig,
142
+ ): Promise<void> {
143
+ const messageId = asString(job.payload.messageId);
144
+ if (!messageId) {
145
+ return;
146
+ }
147
+ await deleteMessageLexical(messageId, config);
148
+ }
149
+
150
+ /**
151
+ * Enqueue an `index_message_lexical` job for a single message so its content is
152
+ * (re)indexed into the lexical (Qdrant) index off the SQLite write path. Called
153
+ * wherever a message's content becomes durable — on persist and on the
154
+ * streaming/import finalize seams that mirror the segment indexer
155
+ * (`indexMessageNow`).
156
+ *
157
+ * One job per message (not a debounced per-conversation coalesce): the payload
158
+ * carries a specific `messageId`, so coalescing bursts by conversation would
159
+ * drop every message but the last from the index. The upsert into Qdrant is
160
+ * idempotent, so re-enqueuing the same message id is harmless.
161
+ *
162
+ * Unconditional: message-content search is host infrastructure, so indexing
163
+ * runs regardless of the memory feature's or memory plugin's state (the job
164
+ * worker drains the lexical types even while memory is disabled).
165
+ *
166
+ * Best-effort: the enqueue is a search side effect off the message write path,
167
+ * so a failure (e.g. the jobs database is unavailable) is swallowed and logged
168
+ * rather than propagated — an indexing hiccup must not escalate a successful
169
+ * message persist into a throw, mirroring the `indexMessageNow` call sites
170
+ * this runs beside.
171
+ */
172
+ export function enqueueLexicalIndexForMessage(messageId: string): void {
173
+ if (!messageId) {
174
+ return;
175
+ }
176
+ try {
177
+ enqueueMemoryJob("index_message_lexical", { messageId });
178
+ } catch (err) {
179
+ log.warn(
180
+ { err, messageId },
181
+ "Failed to enqueue lexical index job for message (non-fatal)",
182
+ );
183
+ }
184
+ }
185
+
186
+ /**
187
+ * Purge a deleted/wiped conversation's points from the lexical index, as a
188
+ * `purge_conversation_lexical` job processed off the write path (the worker
189
+ * drains the lexical types regardless of the memory feature's state).
190
+ *
191
+ * The purge targets Qdrant by `conversationId`, so it is correct even after the
192
+ * conversation's message rows have been deleted. Callers on the wipe path must
193
+ * invoke this AFTER `cancelPendingJobsForConversation`, which fails every
194
+ * pending `conversationId`-keyed job — otherwise an enqueued purge is swept by
195
+ * that same cancellation.
196
+ *
197
+ * Best-effort: a failed enqueue is swallowed and logged rather than
198
+ * propagated, so conversation deletion never fails on an indexing hiccup.
199
+ */
200
+ export function enqueuePurgeConversationLexical(conversationId: string): void {
201
+ if (!conversationId) {
202
+ return;
203
+ }
204
+ try {
205
+ enqueueMemoryJob("purge_conversation_lexical", { conversationId });
206
+ } catch (err) {
207
+ log.warn(
208
+ { err, conversationId },
209
+ "Failed to schedule lexical purge for conversation (non-fatal)",
210
+ );
211
+ }
212
+ }
213
+
214
+ /**
215
+ * Remove a deleted message's point from the lexical index, as a
216
+ * `delete_message_lexical` job. Used by single-message delete paths
217
+ * (consolidation, undo) that remove a row without wiping the whole
218
+ * conversation. Best-effort so message deletion never fails on an indexing
219
+ * hiccup.
220
+ */
221
+ export function enqueueDeleteMessageLexical(messageId: string): void {
222
+ if (!messageId) {
223
+ return;
224
+ }
225
+ try {
226
+ enqueueMemoryJob("delete_message_lexical", { messageId });
227
+ } catch (err) {
228
+ log.warn(
229
+ { err, messageId },
230
+ "Failed to schedule lexical delete for message (non-fatal)",
231
+ );
232
+ }
233
+ }
234
+
235
+ /**
236
+ * Drop every point from the messages lexical index. Called inline (not via a
237
+ * job) by "clear all conversations": that path deletes all rows and the
238
+ * `memory_jobs` table itself, so there is nothing left to key a per-conversation
239
+ * purge job on. Best-effort — a Qdrant failure is swallowed, matching the other
240
+ * `clearAll` cleanup steps that tolerate failures.
241
+ */
242
+ export async function clearMessagesLexicalIndex(
243
+ config: AssistantConfig,
244
+ ): Promise<void> {
245
+ try {
246
+ const index = resolveLexicalIndex(config);
247
+ await withQdrantBreaker(() => index.clear());
248
+ } catch (err) {
249
+ log.warn({ err }, "Failed to clear messages lexical index (non-fatal)");
250
+ }
251
+ }
@@ -36,6 +36,7 @@ export type MemoryJobType =
36
36
  | "prune_old_conversations"
37
37
  | "prune_old_llm_request_logs"
38
38
  | "prune_old_trace_events"
39
+ | "prune_old_tool_invocations"
39
40
  | "build_conversation_summary"
40
41
  | "conversation_analyze"
41
42
  | "backfill"
@@ -61,6 +62,10 @@ export type MemoryJobType =
61
62
  | "memory_v2_reembed"
62
63
  | "memory_v2_activation_recompute"
63
64
  | "memory_v3_maintain"
65
+ | "index_message_lexical"
66
+ | "purge_conversation_lexical"
67
+ | "delete_message_lexical"
68
+ | "backfill_lexical_index"
64
69
  // Retired/legacy — no live handler; persisted rows drop via LEGACY_JOB_TYPES.
65
70
  | "memory_v3_consolidate"
66
71
  | "memory_v3_index_maintenance"
@@ -78,6 +83,19 @@ export const EMBED_JOB_TYPES: MemoryJobType[] = [
78
83
  "embed_concept_page",
79
84
  ];
80
85
 
86
+ /**
87
+ * Job types that power message-content lexical search — host infrastructure
88
+ * that shares the background job queue but is not a memory feature. The worker
89
+ * keeps draining exactly these types while memory is disabled, so message
90
+ * search stays indexed regardless of the memory feature's state.
91
+ */
92
+ export const MESSAGE_LEXICAL_JOB_TYPES: MemoryJobType[] = [
93
+ "index_message_lexical",
94
+ "purge_conversation_lexical",
95
+ "delete_message_lexical",
96
+ "backfill_lexical_index",
97
+ ];
98
+
81
99
  export const SLOW_LLM_JOB_TYPES: MemoryJobType[] = [
82
100
  "graph_consolidate",
83
101
  "graph_pattern_scan",
@@ -501,20 +519,84 @@ export function enqueuePruneOldTraceEventsJob(retentionDays?: number): string {
501
519
  return enqueueMemoryJob("prune_old_trace_events", payload);
502
520
  }
503
521
 
522
+ export function enqueuePruneOldToolInvocationsJob(
523
+ retentionDays?: number,
524
+ ): string {
525
+ const db = memoryDb();
526
+ const existing = db
527
+ .select()
528
+ .from(memoryJobs)
529
+ .where(
530
+ and(
531
+ eq(memoryJobs.type, "prune_old_tool_invocations"),
532
+ inArray(memoryJobs.status, ["pending", "running"]),
533
+ ),
534
+ )
535
+ .orderBy(asc(memoryJobs.createdAt))
536
+ .get();
537
+ if (existing) {
538
+ if (
539
+ existing.status === "pending" &&
540
+ typeof retentionDays === "number" &&
541
+ Number.isFinite(retentionDays) &&
542
+ retentionDays >= 0
543
+ ) {
544
+ let payload: Record<string, unknown> = {};
545
+ try {
546
+ payload = JSON.parse(existing.payload) as Record<string, unknown>;
547
+ } catch {
548
+ payload = {};
549
+ }
550
+ if (payload.retentionDays !== retentionDays) {
551
+ db.update(memoryJobs)
552
+ .set({
553
+ payload: JSON.stringify({ ...payload, retentionDays }),
554
+ updatedAt: Date.now(),
555
+ })
556
+ .where(eq(memoryJobs.id, existing.id))
557
+ .run();
558
+ }
559
+ }
560
+ return existing.id;
561
+ }
562
+ const payload =
563
+ typeof retentionDays === "number" &&
564
+ Number.isFinite(retentionDays) &&
565
+ retentionDays >= 0
566
+ ? { retentionDays }
567
+ : {};
568
+ return enqueueMemoryJob("prune_old_tool_invocations", payload);
569
+ }
570
+
504
571
  export interface LaneBudgets {
505
572
  slowLlm: number;
506
573
  fast: number;
507
574
  embed: number;
508
575
  }
509
576
 
510
- export function claimMemoryJobs(limits: LaneBudgets): MemoryJob[] {
511
- if (limits.slowLlm <= 0 && limits.fast <= 0 && limits.embed <= 0) return [];
577
+ /**
578
+ * Claim up to the per-lane budgets of pending jobs. When `restrictToTypes` is
579
+ * provided, only jobs of those types are eligible in every lane — the worker
580
+ * uses this to drain exclusively the message-lexical types while memory is
581
+ * disabled.
582
+ */
583
+ export function claimMemoryJobs(
584
+ limits: LaneBudgets,
585
+ restrictToTypes?: readonly MemoryJobType[],
586
+ ): MemoryJob[] {
587
+ if (limits.slowLlm <= 0 && limits.fast <= 0 && limits.embed <= 0) {
588
+ return [];
589
+ }
512
590
 
513
591
  const db = memoryDb();
514
592
  const now = Date.now();
593
+ const restrictFilter = restrictToTypes
594
+ ? inArray(memoryJobs.type, [...restrictToTypes])
595
+ : undefined;
515
596
  const pendingFilter = and(
516
597
  eq(memoryJobs.status, "pending"),
517
598
  lte(memoryJobs.runAfter, now),
599
+ restrictFilter,
518
600
  );
519
601
 
520
602
  // Slow lane: long-running LLM jobs (graph extract/consolidate, analysis, etc.).
@@ -596,7 +678,9 @@ export function claimMemoryJobs(limits: LaneBudgets): MemoryJob[] {
596
678
  .set({ status: "running", startedAt: now, updatedAt: now })
597
679
  .where(and(eq(memoryJobs.id, row.id), eq(memoryJobs.status, "pending")))
598
680
  .run();
599
- if (rawMemoryChanges() === 0) continue;
681
+ if (rawMemoryChanges() === 0) {
682
+ continue;
683
+ }
600
684
  claimed.push(
601
685
  parseRow({
602
686
  ...row,
@@ -640,7 +724,9 @@ const DEFER_MAX_DELAY_MS = 5 * 60 * 1000;
640
724
  export function deferMemoryJob(id: string): "deferred" | "failed" {
641
725
  const db = memoryDb();
642
726
  const row = db.select().from(memoryJobs).where(eq(memoryJobs.id, id)).get();
643
- if (!row) return "failed";
727
+ if (!row) {
728
+ return "failed";
729
+ }
644
730
 
645
731
  const deferrals = row.deferrals + 1;
646
732
  const now = Date.now();
@@ -697,7 +783,9 @@ export function failMemoryJob(
697
783
  const maxAttempts = options?.maxAttempts ?? 5;
698
784
  const db = memoryDb();
699
785
  const row = db.select().from(memoryJobs).where(eq(memoryJobs.id, id)).get();
700
- if (!row) return;
786
+ if (!row) {
787
+ return;
788
+ }
701
789
  const attempts = row.attempts + 1;
702
790
  const now = Date.now();
703
791
  if (attempts >= maxAttempts) {
@@ -741,6 +829,7 @@ export function failStalledJobs(timeoutMs: number): number {
741
829
  const now = Date.now();
742
830
  const cutoff = now - timeoutMs;
743
831
  const stalled = rawMemoryAll<{ id: string; type: string }>(
832
+ "jobs:failStalledJobs:select",
744
833
  `
745
834
  SELECT id, type
746
835
  FROM memory_jobs
@@ -750,7 +839,9 @@ export function failStalledJobs(timeoutMs: number): number {
750
839
  `,
751
840
  cutoff,
752
841
  );
753
- if (stalled.length === 0) return 0;
842
+ if (stalled.length === 0) {
843
+ return 0;
844
+ }
754
845
 
755
846
  const db = memoryDb();
756
847
  for (const row of stalled) {
@@ -773,11 +864,14 @@ export function failStalledJobs(timeoutMs: number): number {
773
864
  }
774
865
 
775
866
  export function getMemoryJobCounts(): Record<string, number> {
776
- const rows = rawMemoryAll<{ status: string; c: number }>(`
867
+ const rows = rawMemoryAll<{ status: string; c: number }>(
868
+ "jobs:getMemoryJobCounts",
869
+ `
777
870
  SELECT status, COUNT(*) AS c
778
871
  FROM memory_jobs
779
872
  GROUP BY status
780
- `);
873
+ `,
874
+ );
781
875
  const counts: Record<string, number> = {
782
876
  pending: 0,
783
877
  running: 0,
@@ -1,5 +1,3 @@
1
- import { join } from "node:path";
2
-
3
1
  import { getConfig } from "../config/loader.js";
4
2
  import { isMemoryV3Live } from "../config/memory-v3-gate.js";
5
3
  import type { AssistantConfig } from "../config/types.js";
@@ -8,9 +6,7 @@ import {
8
6
  diskPressureBackgroundSkipLogFields,
9
7
  shouldLogDiskPressureBackgroundSkip,
10
8
  } from "../daemon/disk-pressure-background-gate.js";
11
- import { countBufferLines } from "../plugins/defaults/memory/v2/consolidation-job.js";
12
9
  import { getLogger } from "../util/logger.js";
13
- import { getWorkspaceDir } from "../util/platform.js";
14
10
  import { getMemoryCheckpoint, setMemoryCheckpoint } from "./checkpoints.js";
15
11
  import {
16
12
  getLastScheduledCleanupEnqueueMs,
@@ -37,6 +33,7 @@ import {
37
33
  enqueueMemoryJob,
38
34
  enqueuePruneOldConversationsJob,
39
35
  enqueuePruneOldLlmRequestLogsJob,
36
+ enqueuePruneOldToolInvocationsJob,
40
37
  enqueuePruneOldTraceEventsJob,
41
38
  failMemoryJob,
42
39
  failStalledJobs,
@@ -44,6 +41,7 @@ import {
44
41
  MEMORY_V2_CONSOLIDATION_JOB_TRIGGERS,
45
42
  type MemoryJob,
46
43
  type MemoryJobType,
44
+ MESSAGE_LEXICAL_JOB_TYPES,
47
45
  resetRunningJobsToPending,
48
46
  SLOW_LLM_JOB_TYPES,
49
47
  } from "./jobs-store.js";
@@ -206,7 +204,9 @@ export function startMemoryJobsWorker(): MemoryJobsWorker {
206
204
  * stopMemoryWorkerProcess() in worker-control.ts.
207
205
  */
208
206
  export function stopMemoryJobsWorker(): void {
209
- if (!instance) return;
207
+ if (!instance) {
208
+ return;
209
+ }
210
210
  instance.stop();
211
211
  instance = null;
212
212
  }
@@ -251,7 +251,9 @@ export function startInProcessMemoryJobsWorker(
251
251
  let currentIntervalMs = POLL_INTERVAL_MIN_MS;
252
252
 
253
253
  const tick = async () => {
254
- if (stopped || tickRunning) return;
254
+ if (stopped || tickRunning) {
255
+ return;
256
+ }
255
257
  tickRunning = true;
256
258
  try {
257
259
  if (
@@ -296,17 +298,23 @@ export function startInProcessMemoryJobsWorker(
296
298
  };
297
299
 
298
300
  const scheduleTick = () => {
299
- if (stopped) return;
301
+ if (stopped) {
302
+ return;
303
+ }
300
304
  timer = setTimeout(() => {
301
305
  void tick().then(() => {
302
- if (!stopped) scheduleTick();
306
+ if (!stopped) {
307
+ scheduleTick();
308
+ }
303
309
  });
304
310
  }, currentIntervalMs);
305
311
  (timer as NodeJS.Timeout).unref?.();
306
312
  };
307
313
 
308
314
  void tick().then(() => {
309
- if (!stopped) scheduleTick();
315
+ if (!stopped) {
316
+ scheduleTick();
317
+ }
310
318
  });
311
319
 
312
320
  return {
@@ -326,8 +334,13 @@ export async function runMemoryJobsOnce(
326
334
  options: { enableScheduledCleanup?: boolean } = {},
327
335
  ): Promise<number> {
328
336
  const config = getConfig();
329
- if (config.memory.enabled === false) return 0;
330
- const enableScheduledCleanup = options.enableScheduledCleanup === true;
337
+ // While memory is disabled the queue still drains the MESSAGE-LEXICAL job
338
+ // types host-owned message-search indexing that shares this queue but is
339
+ // not a memory feature. Every memory lane and every maintenance enqueue
340
+ // stays idle in that state; only the lexical types are claimable.
341
+ const memoryEnabled = config.memory.enabled !== false;
342
+ const enableScheduledCleanup =
343
+ options.enableScheduledCleanup === true && memoryEnabled;
331
344
 
332
345
  const diskPressureGate = checkDiskPressureBackgroundGate("background-work");
333
346
  if (diskPressureGate.action === "skip") {
@@ -355,19 +368,26 @@ export async function runMemoryJobsOnce(
355
368
 
356
369
  // Claim per-lane budgets so a backlog of slow LLM jobs cannot starve fast
357
370
  // jobs (and vice versa). The Qdrant circuit breaker still gates only the
358
- // embed lane inside `claimMemoryJobs`.
359
- const claimed = claimMemoryJobs({
360
- slowLlm: cfgSlow,
361
- fast: cfgFast,
362
- embed: cfgEmbed,
363
- });
371
+ // embed lane inside `claimMemoryJobs`. With memory disabled, the slow and
372
+ // embed lanes get no budget and the fast lane is restricted to the
373
+ // message-lexical types (they ride the fast lane).
374
+ const claimed = claimMemoryJobs(
375
+ {
376
+ slowLlm: memoryEnabled ? cfgSlow : 0,
377
+ fast: cfgFast,
378
+ embed: memoryEnabled ? cfgEmbed : 0,
379
+ },
380
+ memoryEnabled ? undefined : MESSAGE_LEXICAL_JOB_TYPES,
381
+ );
364
382
 
365
383
  if (claimed.length === 0) {
366
384
  if (enableScheduledCleanup) {
367
385
  maybeEnqueueScheduledCleanupJobs(config);
368
386
  }
369
387
  maybeEnqueueGraphMaintenanceJobs(config);
370
- await maybeRunDbMaintenance();
388
+ if (memoryEnabled) {
389
+ await maybeRunDbMaintenance();
390
+ }
371
391
  return 0;
372
392
  }
373
393
 
@@ -451,7 +471,9 @@ async function runLanePool(
451
471
  concurrency: number,
452
472
  processGroup: ProcessGroup,
453
473
  ): Promise<number> {
454
- if (jobs.length === 0) return 0;
474
+ if (jobs.length === 0) {
475
+ return 0;
476
+ }
455
477
 
456
478
  const groups = new Map<string, MemoryJob[]>();
457
479
  for (const job of jobs) {
@@ -490,7 +512,9 @@ async function runLanePool(
490
512
  // starts the instant any slot frees up.
491
513
  let nextIdx = 0;
492
514
  const startNext = (): Promise<void> | undefined => {
493
- if (nextIdx >= typeGroups.length) return undefined;
515
+ if (nextIdx >= typeGroups.length) {
516
+ return undefined;
517
+ }
494
518
  const group = typeGroups[nextIdx++]!;
495
519
  return processGroup(group)
496
520
  .then(
@@ -634,9 +658,12 @@ function maybeEnqueueScheduledCleanupJobs(
634
658
  nowMs = Date.now(),
635
659
  ): boolean {
636
660
  const cleanup = config.memory.cleanup;
637
- if (!cleanup.enabled) return false;
638
- if (nowMs - getLastScheduledCleanupEnqueueMs() < cleanup.enqueueIntervalMs)
661
+ if (!cleanup.enabled) {
639
662
  return false;
663
+ }
664
+ if (nowMs - getLastScheduledCleanupEnqueueMs() < cleanup.enqueueIntervalMs) {
665
+ return false;
666
+ }
640
667
 
641
668
  const pruneConversationsJobId =
642
669
  cleanup.conversationRetentionDays > 0
@@ -650,16 +677,24 @@ function maybeEnqueueScheduledCleanupJobs(
650
677
  cleanup.traceEventRetentionDays > 0
651
678
  ? enqueuePruneOldTraceEventsJob(cleanup.traceEventRetentionDays)
652
679
  : null;
680
+ // Audit-log (tool_invocations) retention is configured separately under
681
+ // `auditLog.retentionDays`, but rides this same cleanup cadence for now.
682
+ const pruneToolInvocationsJobId =
683
+ config.auditLog.retentionDays > 0
684
+ ? enqueuePruneOldToolInvocationsJob(config.auditLog.retentionDays)
685
+ : null;
653
686
  markScheduledCleanupEnqueued(nowMs);
654
687
  log.debug(
655
688
  {
656
689
  pruneConversationsJobId,
657
690
  pruneLlmRequestLogsJobId,
658
691
  pruneTraceEventsJobId,
692
+ pruneToolInvocationsJobId,
659
693
  enqueueIntervalMs: cleanup.enqueueIntervalMs,
660
694
  conversationRetentionDays: cleanup.conversationRetentionDays,
661
695
  llmRequestLogRetentionMs: cleanup.llmRequestLogRetentionMs,
662
696
  traceEventRetentionDays: cleanup.traceEventRetentionDays,
697
+ auditLogRetentionDays: config.auditLog.retentionDays,
663
698
  },
664
699
  "Enqueued scheduled memory cleanup jobs",
665
700
  );
@@ -721,7 +756,9 @@ export function maybeEnqueueGraphMaintenanceJobs(
721
756
  nowMs = Date.now(),
722
757
  ): void {
723
758
  const memoryEnabled = config.memory.enabled !== false;
724
- if (!memoryEnabled) return;
759
+ if (!memoryEnabled) {
760
+ return;
761
+ }
725
762
 
726
763
  const v2Active = config.memory.v2.enabled;
727
764
 
@@ -787,8 +824,10 @@ export function maybeEnqueueGraphMaintenanceJobs(
787
824
  // The checkpoint advances so the next check fires after the regular
788
825
  // interval. Manual "Run now" is unaffected (routes layer, not schedule).
789
826
  if (jobType === consolidateEntry.jobType) {
790
- const bufferPath = join(getWorkspaceDir(), "memory", "buffer.md");
791
- if (countBufferLines(bufferPath) < MIN_BUFFER_LINES_FOR_CONSOLIDATION) {
827
+ if (
828
+ getMemoryPersistenceHooks().countMemoryBufferLines() <
829
+ MIN_BUFFER_LINES_FOR_CONSOLIDATION
830
+ ) {
792
831
  log.debug(
793
832
  "Scheduled consolidation skipped: buffer under minimum line threshold",
794
833
  );
@@ -802,7 +841,9 @@ export function maybeEnqueueGraphMaintenanceJobs(
802
841
  : {};
803
842
  enqueueMemoryJob(jobType, payload);
804
843
  setMemoryCheckpoint(key, String(nowMs));
805
- if (jobType === consolidateEntry.jobType) enqueuedConsolidate = true;
844
+ if (jobType === consolidateEntry.jobType) {
845
+ enqueuedConsolidate = true;
846
+ }
806
847
  }
807
848
  }
808
849
 
@@ -821,8 +862,7 @@ export function maybeEnqueueGraphMaintenanceJobs(
821
862
  maxLines !== null &&
822
863
  !hasActiveJobOfType(consolidateEntry.jobType)
823
864
  ) {
824
- const bufferPath = join(getWorkspaceDir(), "memory", "buffer.md");
825
- if (countBufferLines(bufferPath) >= maxLines) {
865
+ if (getMemoryPersistenceHooks().countMemoryBufferLines() >= maxLines) {
826
866
  enqueueMemoryJob(
827
867
  consolidateEntry.jobType,
828
868
  AUTOMATIC_CONSOLIDATION_JOB_PAYLOAD,