@vellumai/assistant 0.4.49 → 0.4.51

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 (353) hide show
  1. package/ARCHITECTURE.md +24 -33
  2. package/README.md +3 -3
  3. package/docs/architecture/integrations.md +2 -2
  4. package/docs/architecture/keychain-broker.md +6 -6
  5. package/docs/architecture/memory.md +180 -119
  6. package/knip.json +32 -0
  7. package/package.json +3 -2
  8. package/src/__tests__/agent-loop.test.ts +3 -1
  9. package/src/__tests__/anthropic-provider.test.ts +114 -23
  10. package/src/__tests__/approval-cascade.test.ts +1 -15
  11. package/src/__tests__/approval-routes-http.test.ts +2 -0
  12. package/src/__tests__/assistant-feature-flag-guard.test.ts +0 -23
  13. package/src/__tests__/btw-routes.test.ts +61 -5
  14. package/src/__tests__/canonical-guardian-store.test.ts +95 -0
  15. package/src/__tests__/checker.test.ts +13 -0
  16. package/src/__tests__/config-schema.test.ts +1 -68
  17. package/src/__tests__/config-watcher.test.ts +8 -0
  18. package/src/__tests__/context-memory-e2e.test.ts +11 -100
  19. package/src/__tests__/conversation-routes-guardian-reply.test.ts +8 -0
  20. package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
  21. package/src/__tests__/credential-security-e2e.test.ts +1 -0
  22. package/src/__tests__/credential-security-invariants.test.ts +8 -7
  23. package/src/__tests__/credential-vault-unit.test.ts +23 -18
  24. package/src/__tests__/credential-vault.test.ts +30 -18
  25. package/src/__tests__/credentials-cli.test.ts +257 -82
  26. package/src/__tests__/cu-unified-flow.test.ts +532 -0
  27. package/src/__tests__/date-context.test.ts +93 -77
  28. package/src/__tests__/deterministic-verification-control-plane.test.ts +64 -0
  29. package/src/__tests__/guardian-routing-invariants.test.ts +93 -0
  30. package/src/__tests__/history-repair.test.ts +245 -0
  31. package/src/__tests__/host-cu-proxy.test.ts +165 -3
  32. package/src/__tests__/http-user-message-parity.test.ts +1 -0
  33. package/src/__tests__/inbound-invite-redemption.test.ts +36 -7
  34. package/src/__tests__/integration-status.test.ts +31 -30
  35. package/src/__tests__/invite-redemption-service.test.ts +166 -13
  36. package/src/__tests__/invite-routes-http.test.ts +166 -5
  37. package/src/__tests__/keychain-broker-client.test.ts +4 -4
  38. package/src/__tests__/list-messages-attachments.test.ts +193 -0
  39. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +56 -18
  40. package/src/__tests__/memory-lifecycle-e2e.test.ts +244 -387
  41. package/src/__tests__/memory-recall-quality.test.ts +244 -407
  42. package/src/__tests__/memory-regressions.experimental.test.ts +126 -101
  43. package/src/__tests__/memory-regressions.test.ts +477 -2841
  44. package/src/__tests__/memory-retrieval.benchmark.test.ts +33 -150
  45. package/src/__tests__/memory-upsert-concurrency.test.ts +5 -244
  46. package/src/__tests__/mime-builder.test.ts +28 -0
  47. package/src/__tests__/native-web-search.test.ts +1 -0
  48. package/src/__tests__/oauth-cli.test.ts +824 -31
  49. package/src/__tests__/oauth-provider-profiles.test.ts +1 -1
  50. package/src/__tests__/oauth-store.test.ts +363 -17
  51. package/src/__tests__/qdrant-collection-migration.test.ts +53 -8
  52. package/src/__tests__/registry.test.ts +0 -1
  53. package/src/__tests__/relay-server.test.ts +55 -1
  54. package/src/__tests__/schedule-tools.test.ts +32 -0
  55. package/src/__tests__/script-proxy-certs.test.ts +1 -1
  56. package/src/__tests__/secret-onetime-send.test.ts +1 -0
  57. package/src/__tests__/secret-routes-managed-proxy.test.ts +183 -0
  58. package/src/__tests__/secure-keys.test.ts +78 -18
  59. package/src/__tests__/send-endpoint-busy.test.ts +3 -0
  60. package/src/__tests__/server-history-render.test.ts +2 -2
  61. package/src/__tests__/session-abort-tool-results.test.ts +1 -14
  62. package/src/__tests__/session-agent-loop-overflow.test.ts +1583 -0
  63. package/src/__tests__/session-agent-loop.test.ts +19 -15
  64. package/src/__tests__/session-confirmation-signals.test.ts +1 -15
  65. package/src/__tests__/session-error.test.ts +124 -2
  66. package/src/__tests__/session-history-web-search.test.ts +918 -0
  67. package/src/__tests__/session-pre-run-repair.test.ts +1 -14
  68. package/src/__tests__/session-provider-retry-repair.test.ts +25 -28
  69. package/src/__tests__/session-queue.test.ts +37 -27
  70. package/src/__tests__/session-runtime-assembly.test.ts +54 -0
  71. package/src/__tests__/session-slash-known.test.ts +1 -15
  72. package/src/__tests__/session-slash-queue.test.ts +1 -15
  73. package/src/__tests__/session-slash-unknown.test.ts +1 -15
  74. package/src/__tests__/session-workspace-cache-state.test.ts +3 -33
  75. package/src/__tests__/session-workspace-injection.test.ts +3 -37
  76. package/src/__tests__/session-workspace-tool-tracking.test.ts +3 -37
  77. package/src/__tests__/skills-install-extract.test.ts +93 -0
  78. package/src/__tests__/skills.test.ts +2 -2
  79. package/src/__tests__/skillssh-registry.test.ts +451 -0
  80. package/src/__tests__/slack-channel-config.test.ts +10 -8
  81. package/src/__tests__/trust-store.test.ts +15 -0
  82. package/src/__tests__/twilio-config.test.ts +11 -10
  83. package/src/__tests__/twilio-provider.test.ts +9 -4
  84. package/src/__tests__/voice-invite-redemption.test.ts +85 -5
  85. package/src/agent/ax-tree-compaction.test.ts +51 -0
  86. package/src/agent/loop.ts +39 -12
  87. package/src/approvals/AGENTS.md +1 -1
  88. package/src/approvals/guardian-request-resolvers.ts +14 -2
  89. package/src/bundler/compiler-tools.ts +66 -2
  90. package/src/calls/call-domain.ts +134 -3
  91. package/src/calls/call-store.ts +6 -0
  92. package/src/calls/relay-server.ts +44 -6
  93. package/src/calls/relay-setup-router.ts +17 -1
  94. package/src/calls/twilio-config.ts +5 -4
  95. package/src/calls/twilio-provider.ts +14 -9
  96. package/src/calls/twilio-rest.ts +10 -7
  97. package/src/calls/types.ts +3 -1
  98. package/src/cli/commands/config.ts +14 -9
  99. package/src/cli/commands/contacts.ts +3 -0
  100. package/src/cli/commands/credentials.ts +170 -174
  101. package/src/cli/commands/doctor.ts +11 -8
  102. package/src/cli/commands/keys.ts +9 -9
  103. package/src/cli/commands/mcp.ts +46 -59
  104. package/src/cli/commands/memory.ts +16 -165
  105. package/src/cli/commands/oauth/apps.ts +68 -10
  106. package/src/cli/commands/oauth/connections.ts +475 -105
  107. package/src/cli/commands/oauth/index.ts +3 -3
  108. package/src/cli/commands/oauth/providers.ts +18 -4
  109. package/src/cli/commands/sessions.ts +5 -2
  110. package/src/cli/commands/skills.ts +173 -1
  111. package/src/cli/http-client.ts +0 -20
  112. package/src/cli/main-screen.tsx +2 -2
  113. package/src/cli/program.ts +5 -6
  114. package/src/cli.ts +20 -22
  115. package/src/config/__tests__/feature-flag-registry-bundled.test.ts +39 -0
  116. package/src/config/bundled-skills/computer-use/TOOLS.json +1 -1
  117. package/src/config/bundled-skills/computer-use/tools/computer-use-observe.ts +12 -0
  118. package/src/config/bundled-skills/contacts/SKILL.md +35 -11
  119. package/src/config/bundled-skills/contacts/tools/google-contacts.ts +1 -1
  120. package/src/config/bundled-skills/gmail/SKILL.md +1 -1
  121. package/src/config/bundled-skills/gmail/TOOLS.json +52 -0
  122. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +13 -3
  123. package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +9 -2
  124. package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +5 -1
  125. package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +5 -1
  126. package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +5 -1
  127. package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +5 -1
  128. package/src/config/bundled-skills/gmail/tools/gmail-label.ts +9 -2
  129. package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +5 -1
  130. package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +5 -1
  131. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +5 -1
  132. package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +5 -1
  133. package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +5 -1
  134. package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +5 -1
  135. package/src/config/bundled-skills/google-calendar/TOOLS.json +20 -0
  136. package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +2 -1
  137. package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +2 -1
  138. package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +2 -1
  139. package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +2 -1
  140. package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +2 -1
  141. package/src/config/bundled-skills/google-calendar/tools/shared.ts +8 -2
  142. package/src/config/bundled-skills/messaging/SKILL.md +1 -1
  143. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +2 -2
  144. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +2 -2
  145. package/src/config/bundled-skills/messaging/tools/messaging-auth-test.ts +2 -2
  146. package/src/config/bundled-skills/messaging/tools/messaging-list-conversations.ts +2 -2
  147. package/src/config/bundled-skills/messaging/tools/messaging-mark-read.ts +2 -2
  148. package/src/config/bundled-skills/messaging/tools/messaging-read.ts +2 -2
  149. package/src/config/bundled-skills/messaging/tools/messaging-search.ts +2 -2
  150. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +2 -2
  151. package/src/config/bundled-skills/messaging/tools/messaging-sender-digest.ts +2 -2
  152. package/src/config/bundled-skills/messaging/tools/shared.ts +7 -5
  153. package/src/config/bundled-skills/slack/tools/shared.ts +1 -1
  154. package/src/config/bundled-skills/slack/tools/slack-add-reaction.ts +1 -1
  155. package/src/config/bundled-skills/slack/tools/slack-channel-details.ts +1 -1
  156. package/src/config/bundled-skills/slack/tools/slack-delete-message.ts +1 -1
  157. package/src/config/bundled-skills/slack/tools/slack-edit-message.ts +1 -1
  158. package/src/config/bundled-skills/slack/tools/slack-leave-channel.ts +1 -1
  159. package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +1 -1
  160. package/src/config/bundled-tool-registry.ts +2 -5
  161. package/src/config/loader.ts +6 -42
  162. package/src/config/schema.ts +1 -12
  163. package/src/config/schemas/memory-lifecycle.ts +0 -9
  164. package/src/config/schemas/memory-processing.ts +0 -180
  165. package/src/config/schemas/memory-retrieval.ts +32 -104
  166. package/src/config/schemas/memory.ts +0 -10
  167. package/src/config/types.ts +0 -4
  168. package/src/contacts/contact-store.ts +39 -2
  169. package/src/contacts/contacts-write.ts +9 -0
  170. package/src/context/window-manager.ts +4 -1
  171. package/src/daemon/config-watcher.ts +55 -2
  172. package/src/daemon/daemon-control.ts +1 -1
  173. package/src/daemon/date-context.ts +114 -31
  174. package/src/daemon/handlers/config-ingress.ts +2 -2
  175. package/src/daemon/handlers/config-slack-channel.ts +59 -39
  176. package/src/daemon/handlers/config-telegram.ts +23 -14
  177. package/src/daemon/handlers/session-history.ts +1 -358
  178. package/src/daemon/handlers/sessions.ts +18 -13
  179. package/src/daemon/handlers/shared.ts +3 -17
  180. package/src/daemon/handlers/skills.ts +20 -1
  181. package/src/daemon/history-repair.ts +72 -8
  182. package/src/daemon/host-cu-proxy.ts +55 -26
  183. package/src/daemon/lifecycle.ts +39 -4
  184. package/src/daemon/mcp-reload-service.ts +2 -2
  185. package/src/daemon/message-types/computer-use.ts +1 -12
  186. package/src/daemon/message-types/memory.ts +4 -16
  187. package/src/daemon/message-types/messages.ts +1 -0
  188. package/src/daemon/message-types/sessions.ts +4 -42
  189. package/src/daemon/server.ts +6 -1
  190. package/src/daemon/session-agent-loop-handlers.ts +38 -0
  191. package/src/daemon/session-agent-loop.ts +334 -48
  192. package/src/daemon/session-error.ts +89 -6
  193. package/src/daemon/session-history.ts +17 -7
  194. package/src/daemon/session-media-retry.ts +6 -2
  195. package/src/daemon/session-memory.ts +69 -149
  196. package/src/daemon/session-process.ts +10 -1
  197. package/src/daemon/session-runtime-assembly.ts +49 -19
  198. package/src/daemon/session-slash.ts +3 -5
  199. package/src/daemon/session-surfaces.ts +4 -1
  200. package/src/daemon/session-tool-setup.ts +7 -1
  201. package/src/daemon/session.ts +12 -2
  202. package/src/email/providers/index.ts +2 -2
  203. package/src/instrument.ts +61 -1
  204. package/src/media/avatar-router.ts +1 -1
  205. package/src/memory/admin.ts +2 -191
  206. package/src/memory/canonical-guardian-store.ts +38 -2
  207. package/src/memory/conversation-crud.ts +0 -33
  208. package/src/memory/conversation-queries.ts +25 -83
  209. package/src/memory/db-init.ts +32 -0
  210. package/src/memory/embedding-backend.ts +84 -8
  211. package/src/memory/embedding-types.ts +9 -1
  212. package/src/memory/indexer.ts +7 -46
  213. package/src/memory/invite-store.ts +19 -0
  214. package/src/memory/items-extractor.ts +274 -76
  215. package/src/memory/job-handlers/backfill.ts +2 -127
  216. package/src/memory/job-handlers/cleanup.ts +2 -16
  217. package/src/memory/job-handlers/extraction.ts +2 -138
  218. package/src/memory/job-handlers/index-maintenance.ts +1 -6
  219. package/src/memory/job-handlers/summarization.ts +3 -148
  220. package/src/memory/job-utils.ts +21 -59
  221. package/src/memory/jobs-store.ts +1 -159
  222. package/src/memory/jobs-worker.ts +9 -52
  223. package/src/memory/migrations/104-core-indexes.ts +3 -3
  224. package/src/memory/migrations/149-oauth-tables.ts +2 -0
  225. package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +98 -0
  226. package/src/memory/migrations/151-oauth-providers-ping-url.ts +11 -0
  227. package/src/memory/migrations/152-memory-item-supersession.ts +44 -0
  228. package/src/memory/migrations/153-drop-entity-tables.ts +15 -0
  229. package/src/memory/migrations/154-drop-fts.ts +20 -0
  230. package/src/memory/migrations/155-drop-conflicts.ts +7 -0
  231. package/src/memory/migrations/156-call-session-invite-metadata.ts +24 -0
  232. package/src/memory/migrations/157-invite-contact-id.ts +104 -0
  233. package/src/memory/migrations/index.ts +8 -0
  234. package/src/memory/migrations/registry.ts +6 -0
  235. package/src/memory/qdrant-client.ts +148 -51
  236. package/src/memory/raw-query.ts +1 -1
  237. package/src/memory/retriever.test.ts +294 -273
  238. package/src/memory/retriever.ts +421 -645
  239. package/src/memory/schema/calls.ts +2 -0
  240. package/src/memory/schema/contacts.ts +1 -0
  241. package/src/memory/schema/memory-core.ts +3 -48
  242. package/src/memory/schema/oauth.ts +2 -0
  243. package/src/memory/search/formatting.ts +263 -176
  244. package/src/memory/search/lexical.ts +1 -254
  245. package/src/memory/search/ranking.ts +0 -455
  246. package/src/memory/search/semantic.ts +100 -14
  247. package/src/memory/search/staleness.ts +47 -0
  248. package/src/memory/search/tier-classifier.ts +21 -0
  249. package/src/memory/search/types.ts +15 -77
  250. package/src/memory/task-memory-cleanup.ts +4 -6
  251. package/src/messaging/provider.ts +1 -1
  252. package/src/messaging/providers/gmail/adapter.ts +1 -1
  253. package/src/messaging/providers/gmail/mime-builder.ts +17 -7
  254. package/src/messaging/providers/telegram-bot/adapter.ts +17 -8
  255. package/src/messaging/providers/whatsapp/adapter.ts +13 -9
  256. package/src/messaging/registry.ts +9 -5
  257. package/src/oauth/byo-connection.test.ts +40 -25
  258. package/src/oauth/connect-orchestrator.ts +4 -10
  259. package/src/oauth/connection-resolver.ts +20 -6
  260. package/src/oauth/manual-token-connection.ts +5 -5
  261. package/src/oauth/oauth-store.ts +183 -31
  262. package/src/oauth/platform-connection.test.ts +1 -1
  263. package/src/oauth/provider-behaviors.ts +503 -4
  264. package/src/oauth/seed-providers.ts +214 -8
  265. package/src/oauth/token-persistence.ts +31 -16
  266. package/src/permissions/defaults.ts +1 -0
  267. package/src/permissions/trust-store.ts +23 -1
  268. package/src/playbooks/playbook-compiler.ts +1 -1
  269. package/src/prompts/system-prompt.ts +18 -2
  270. package/src/providers/anthropic/client.ts +56 -126
  271. package/src/providers/types.ts +7 -1
  272. package/src/runtime/AGENTS.md +9 -0
  273. package/src/runtime/auth/route-policy.ts +6 -3
  274. package/src/runtime/channel-readiness-service.ts +48 -40
  275. package/src/runtime/guardian-reply-router.ts +24 -22
  276. package/src/runtime/http-server.ts +2 -2
  277. package/src/runtime/http-types.ts +2 -0
  278. package/src/runtime/invite-redemption-service.ts +72 -12
  279. package/src/runtime/invite-service.ts +43 -0
  280. package/src/runtime/middleware/twilio-validation.ts +1 -1
  281. package/src/runtime/pending-interactions.ts +2 -2
  282. package/src/runtime/routes/brain-graph-routes.ts +10 -90
  283. package/src/runtime/routes/btw-routes.ts +10 -5
  284. package/src/runtime/routes/conversation-routes.ts +56 -11
  285. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +21 -12
  286. package/src/runtime/routes/integrations/slack/channel.ts +2 -2
  287. package/src/runtime/routes/integrations/telegram.ts +2 -2
  288. package/src/runtime/routes/integrations/twilio.ts +17 -17
  289. package/src/runtime/routes/invite-routes.ts +29 -4
  290. package/src/runtime/routes/memory-item-routes.test.ts +754 -0
  291. package/src/runtime/routes/memory-item-routes.ts +503 -0
  292. package/src/runtime/routes/secret-routes.ts +17 -0
  293. package/src/runtime/routes/session-management-routes.ts +3 -3
  294. package/src/runtime/routes/settings-routes.ts +3 -3
  295. package/src/runtime/routes/trust-rules-routes.ts +14 -0
  296. package/src/runtime/routes/workspace-routes.ts +9 -4
  297. package/src/runtime/routes/workspace-utils.ts +8 -2
  298. package/src/schedule/integration-status.ts +26 -19
  299. package/src/security/keychain-broker-client.ts +17 -4
  300. package/src/security/oauth2.ts +6 -7
  301. package/src/security/secure-keys.ts +44 -19
  302. package/src/security/token-manager.ts +46 -39
  303. package/src/services/vercel-deploy.ts +0 -24
  304. package/src/signals/confirm.ts +78 -0
  305. package/src/signals/mcp-reload.ts +18 -0
  306. package/src/skills/catalog-install.ts +74 -18
  307. package/src/skills/skillssh-registry.ts +503 -0
  308. package/src/tools/assets/search.ts +5 -1
  309. package/src/tools/computer-use/definitions.ts +0 -10
  310. package/src/tools/computer-use/registry.ts +1 -1
  311. package/src/tools/credentials/vault.ts +22 -7
  312. package/src/tools/memory/definitions.ts +4 -13
  313. package/src/tools/memory/handlers.test.ts +83 -103
  314. package/src/tools/memory/handlers.ts +50 -85
  315. package/src/tools/network/script-proxy/session-manager.ts +8 -8
  316. package/src/tools/schedule/create.ts +10 -3
  317. package/src/tools/schedule/update.ts +8 -1
  318. package/src/tools/skills/load.ts +25 -2
  319. package/src/watcher/provider-types.ts +1 -1
  320. package/src/watcher/providers/github.ts +1 -1
  321. package/src/watcher/providers/gmail.ts +3 -3
  322. package/src/watcher/providers/google-calendar.ts +3 -3
  323. package/src/watcher/providers/linear.ts +1 -1
  324. package/src/__tests__/clarification-resolver.test.ts +0 -193
  325. package/src/__tests__/conflict-intent-tokenization.test.ts +0 -160
  326. package/src/__tests__/conflict-policy.test.ts +0 -269
  327. package/src/__tests__/conflict-store.test.ts +0 -372
  328. package/src/__tests__/contradiction-checker.test.ts +0 -361
  329. package/src/__tests__/entity-extractor.test.ts +0 -211
  330. package/src/__tests__/entity-search.test.ts +0 -1117
  331. package/src/__tests__/profile-compiler.test.ts +0 -392
  332. package/src/__tests__/session-conflict-gate.test.ts +0 -1228
  333. package/src/__tests__/session-profile-injection.test.ts +0 -557
  334. package/src/config/bundled-skills/knowledge-graph/SKILL.md +0 -25
  335. package/src/config/bundled-skills/knowledge-graph/TOOLS.json +0 -66
  336. package/src/config/bundled-skills/knowledge-graph/tools/graph-query.ts +0 -211
  337. package/src/daemon/session-conflict-gate.ts +0 -167
  338. package/src/daemon/session-dynamic-profile.ts +0 -77
  339. package/src/memory/clarification-resolver.ts +0 -417
  340. package/src/memory/conflict-intent.ts +0 -205
  341. package/src/memory/conflict-policy.ts +0 -127
  342. package/src/memory/conflict-store.ts +0 -410
  343. package/src/memory/contradiction-checker.ts +0 -508
  344. package/src/memory/entity-extractor.ts +0 -535
  345. package/src/memory/format-recall.ts +0 -47
  346. package/src/memory/fts-reconciler.ts +0 -165
  347. package/src/memory/job-handlers/conflict.ts +0 -200
  348. package/src/memory/profile-compiler.ts +0 -195
  349. package/src/memory/recall-cache.ts +0 -117
  350. package/src/memory/search/entity.ts +0 -535
  351. package/src/memory/search/query-expansion.test.ts +0 -70
  352. package/src/memory/search/query-expansion.ts +0 -118
  353. package/src/runtime/routes/mcp-routes.ts +0 -20
@@ -31,6 +31,23 @@ mock.module("../util/logger.js", () => ({
31
31
  }),
32
32
  }));
33
33
 
34
+ // Dynamic Qdrant mock: tests can push results to be returned by searchWithFilter/hybridSearch
35
+ let mockQdrantResults: Array<{
36
+ id: string;
37
+ score: number;
38
+ payload: Record<string, unknown>;
39
+ }> = [];
40
+
41
+ mock.module("../memory/qdrant-client.js", () => ({
42
+ getQdrantClient: () => ({
43
+ searchWithFilter: async () => mockQdrantResults,
44
+ hybridSearch: async () => mockQdrantResults,
45
+ upsert: async () => {},
46
+ deletePoints: async () => {},
47
+ }),
48
+ initQdrantClient: () => {},
49
+ }));
50
+
34
51
  import { eq } from "drizzle-orm";
35
52
 
36
53
  import { DEFAULT_CONFIG } from "../config/defaults.js";
@@ -55,7 +72,6 @@ mock.module("../config/loader.js", () => ({
55
72
  }));
56
73
  import { getDb, initializeDb, resetDb } from "../memory/db.js";
57
74
  import { indexMessageNow } from "../memory/indexer.js";
58
- import { vectorToBlob } from "../memory/job-utils.js";
59
75
  import { enqueueMemoryJob } from "../memory/jobs-store.js";
60
76
  import {
61
77
  resetCleanupScheduleThrottle,
@@ -65,7 +81,6 @@ import {
65
81
  import { buildMemoryRecall } from "../memory/retriever.js";
66
82
  import {
67
83
  conversations,
68
- memoryEmbeddings,
69
84
  memoryItems,
70
85
  memoryItemSources,
71
86
  memoryJobs,
@@ -80,15 +95,11 @@ describe("Memory regressions (experimental)", () => {
80
95
 
81
96
  beforeEach(() => {
82
97
  const db = getDb();
83
- db.run("DELETE FROM memory_item_conflicts");
84
- db.run("DELETE FROM memory_item_entities");
85
- db.run("DELETE FROM memory_entity_relations");
86
- db.run("DELETE FROM memory_entities");
87
98
  db.run("DELETE FROM memory_item_sources");
88
99
  db.run("DELETE FROM memory_embeddings");
89
- db.run("DELETE FROM memory_summaries");
90
100
  db.run("DELETE FROM memory_items");
91
- db.run("DELETE FROM memory_segment_fts");
101
+
102
+ db.run("DELETE FROM memory_summaries");
92
103
  db.run("DELETE FROM memory_segments");
93
104
  db.run("DELETE FROM messages");
94
105
  db.run("DELETE FROM conversations");
@@ -96,6 +107,7 @@ describe("Memory regressions (experimental)", () => {
96
107
  db.run("DELETE FROM memory_checkpoints");
97
108
  resetCleanupScheduleThrottle();
98
109
  resetStaleSweepThrottle();
110
+ mockQdrantResults = [];
99
111
  });
100
112
 
101
113
  afterAll(() => {
@@ -111,8 +123,11 @@ describe("Memory regressions (experimental)", () => {
111
123
  run: () => Promise<T>,
112
124
  ): Promise<T> {
113
125
  const originalFetch = globalThis.fetch;
126
+ // Return 384-dim vectors to match the Qdrant collection's expected size
127
+ const mockVector = new Array(384).fill(0);
128
+ mockVector[0] = 1;
114
129
  globalThis.fetch = (async () =>
115
- new Response(JSON.stringify({ data: [{ embedding: [1, 0, 0] }] }), {
130
+ new Response(JSON.stringify({ data: [{ embedding: mockVector }] }), {
116
131
  status: 200,
117
132
  headers: { "content-type": "application/json" },
118
133
  })) as unknown as typeof globalThis.fetch;
@@ -135,8 +150,6 @@ describe("Memory regressions (experimental)", () => {
135
150
  },
136
151
  retrieval: {
137
152
  ...DEFAULT_CONFIG.memory.retrieval,
138
- lexicalTopK: 0,
139
- semanticTopK: 10,
140
153
  maxInjectTokens: 2000,
141
154
  },
142
155
  },
@@ -184,7 +197,7 @@ describe("Memory regressions (experimental)", () => {
184
197
  .values([
185
198
  {
186
199
  id: "item-semantic-old",
187
- kind: "fact",
200
+ kind: "identity",
188
201
  subject: "timezone",
189
202
  statement: "User timezone is PST",
190
203
  status: "active",
@@ -196,7 +209,7 @@ describe("Memory regressions (experimental)", () => {
196
209
  },
197
210
  {
198
211
  id: "item-semantic-current",
199
- kind: "fact",
212
+ kind: "identity",
200
213
  subject: "timezone",
201
214
  statement: "User timezone is PST (current turn)",
202
215
  status: "active",
@@ -224,32 +237,35 @@ describe("Memory regressions (experimental)", () => {
224
237
  },
225
238
  ])
226
239
  .run();
227
- db.insert(memoryEmbeddings)
228
- .values([
229
- {
230
- id: "emb-semantic-old",
231
- targetType: "item",
232
- targetId: "item-semantic-old",
233
- provider: "ollama",
234
- model: DEFAULT_CONFIG.memory.embeddings.ollamaModel,
235
- dimensions: 3,
236
- vectorBlob: vectorToBlob([1, 0, 0]),
237
- createdAt: now,
238
- updatedAt: now,
240
+ // Mock Qdrant to return both items as search results
241
+ mockQdrantResults = [
242
+ {
243
+ id: "emb-semantic-old",
244
+ score: 0.95,
245
+ payload: {
246
+ target_type: "item",
247
+ target_id: "item-semantic-old",
248
+ text: "User timezone is PST",
249
+ kind: "identity",
250
+ status: "active",
251
+ created_at: now - 10_000,
252
+ last_seen_at: now - 10_000,
239
253
  },
240
- {
241
- id: "emb-semantic-current",
242
- targetType: "item",
243
- targetId: "item-semantic-current",
244
- provider: "ollama",
245
- model: DEFAULT_CONFIG.memory.embeddings.ollamaModel,
246
- dimensions: 3,
247
- vectorBlob: vectorToBlob([1, 0, 0]),
248
- createdAt: now,
249
- updatedAt: now,
254
+ },
255
+ {
256
+ id: "emb-semantic-current",
257
+ score: 0.93,
258
+ payload: {
259
+ target_type: "item",
260
+ target_id: "item-semantic-current",
261
+ text: "User timezone is PST (current turn)",
262
+ kind: "identity",
263
+ status: "active",
264
+ created_at: now,
265
+ last_seen_at: now,
250
266
  },
251
- ])
252
- .run();
267
+ },
268
+ ];
253
269
 
254
270
  const recall = await withMockOllamaQueryEmbedding(() =>
255
271
  buildMemoryRecall(
@@ -294,7 +310,7 @@ describe("Memory regressions (experimental)", () => {
294
310
  .values([
295
311
  {
296
312
  id: "item-semantic-with-evidence",
297
- kind: "fact",
313
+ kind: "identity",
298
314
  subject: "timezone",
299
315
  statement: "User timezone is PST",
300
316
  status: "active",
@@ -306,7 +322,7 @@ describe("Memory regressions (experimental)", () => {
306
322
  },
307
323
  {
308
324
  id: "item-semantic-orphan",
309
- kind: "fact",
325
+ kind: "identity",
310
326
  subject: "timezone",
311
327
  statement: "Stale orphan fact",
312
328
  status: "active",
@@ -326,32 +342,35 @@ describe("Memory regressions (experimental)", () => {
326
342
  createdAt: now,
327
343
  })
328
344
  .run();
329
- db.insert(memoryEmbeddings)
330
- .values([
331
- {
332
- id: "emb-semantic-with-evidence",
333
- targetType: "item",
334
- targetId: "item-semantic-with-evidence",
335
- provider: "ollama",
336
- model: DEFAULT_CONFIG.memory.embeddings.ollamaModel,
337
- dimensions: 3,
338
- vectorBlob: vectorToBlob([1, 0, 0]),
339
- createdAt: now,
340
- updatedAt: now,
345
+ // Mock Qdrant to return both items as search results
346
+ mockQdrantResults = [
347
+ {
348
+ id: "emb-semantic-with-evidence",
349
+ score: 0.95,
350
+ payload: {
351
+ target_type: "item",
352
+ target_id: "item-semantic-with-evidence",
353
+ text: "User timezone is PST",
354
+ kind: "identity",
355
+ status: "active",
356
+ created_at: now,
357
+ last_seen_at: now,
341
358
  },
342
- {
343
- id: "emb-semantic-orphan",
344
- targetType: "item",
345
- targetId: "item-semantic-orphan",
346
- provider: "ollama",
347
- model: DEFAULT_CONFIG.memory.embeddings.ollamaModel,
348
- dimensions: 3,
349
- vectorBlob: vectorToBlob([1, 0, 0]),
350
- createdAt: now,
351
- updatedAt: now,
359
+ },
360
+ {
361
+ id: "emb-semantic-orphan",
362
+ score: 0.9,
363
+ payload: {
364
+ target_type: "item",
365
+ target_id: "item-semantic-orphan",
366
+ text: "Stale orphan fact",
367
+ kind: "identity",
368
+ status: "active",
369
+ created_at: now,
370
+ last_seen_at: now,
352
371
  },
353
- ])
354
- .run();
372
+ },
373
+ ];
355
374
 
356
375
  const recall = await withMockOllamaQueryEmbedding(() =>
357
376
  buildMemoryRecall(
@@ -420,48 +439,51 @@ describe("Memory regressions (experimental)", () => {
420
439
  },
421
440
  ])
422
441
  .run();
423
- db.insert(memoryEmbeddings)
424
- .values([
425
- {
426
- id: "emb-summary-semantic-conversation",
427
- targetType: "summary",
428
- targetId: "summary-semantic-conversation",
429
- provider: "ollama",
430
- model: DEFAULT_CONFIG.memory.embeddings.ollamaModel,
431
- dimensions: 3,
432
- vectorBlob: vectorToBlob([1, 0, 0]),
433
- createdAt: now,
434
- updatedAt: now,
442
+ // Mock Qdrant to return both summaries as search results.
443
+ // The new pipeline does not exclude conversation summaries based on
444
+ // time overlap with excluded messages — that was old-pipeline behavior.
445
+ // Both summaries pass through; we verify the pipeline runs correctly.
446
+ mockQdrantResults = [
447
+ {
448
+ id: "emb-summary-semantic-conversation",
449
+ score: 0.95,
450
+ payload: {
451
+ target_type: "summary",
452
+ target_id: "summary-semantic-conversation",
453
+ text: "[conversation] Conversation summary containing current turn details",
454
+ kind: "conversation",
455
+ created_at: now,
456
+ last_seen_at: now,
435
457
  },
436
- {
437
- id: "emb-summary-semantic-weekly",
438
- targetType: "summary",
439
- targetId: "summary-semantic-weekly",
440
- provider: "ollama",
441
- model: DEFAULT_CONFIG.memory.embeddings.ollamaModel,
442
- dimensions: 3,
443
- vectorBlob: vectorToBlob([1, 0, 0]),
444
- createdAt: now,
445
- updatedAt: now,
458
+ },
459
+ {
460
+ id: "emb-summary-semantic-weekly",
461
+ score: 0.9,
462
+ payload: {
463
+ target_type: "summary",
464
+ target_id: "summary-semantic-weekly",
465
+ text: "[weekly_global] Weekly summary that should remain eligible",
466
+ kind: "global",
467
+ created_at: now,
468
+ last_seen_at: now,
446
469
  },
447
- ])
448
- .run();
470
+ },
471
+ ];
449
472
 
450
473
  const recall = await withMockOllamaQueryEmbedding(() =>
451
474
  buildMemoryRecall("summary", conversationId, semanticRecallConfig(), {
452
475
  excludeMessageIds: ["msg-semantic-summary-excluded"],
453
476
  }),
454
477
  );
455
- expect(recall.semanticHits).toBe(1);
456
- expect(recall.injectedText).not.toContain(
457
- "Conversation summary containing current turn details",
458
- );
478
+ // Both summaries are returned from Qdrant and both pass post-filtering.
479
+ // Verify the pipeline completes successfully with semantic hits.
480
+ expect(recall.semanticHits).toBe(2);
459
481
  expect(recall.injectedText).toContain(
460
482
  "Weekly summary that should remain eligible",
461
483
  );
462
484
  });
463
485
 
464
- test("indexing no longer enqueues segment embedding jobs", () => {
486
+ test("indexing enqueues embed_segment, extract_items, and build_conversation_summary for user messages", () => {
465
487
  const db = getDb();
466
488
  const createdAt = 2_000;
467
489
  db.insert(conversations)
@@ -502,14 +524,15 @@ describe("Memory regressions (experimental)", () => {
502
524
  },
503
525
  DEFAULT_CONFIG.memory,
504
526
  );
505
- expect(result.enqueuedJobs).toBe(2);
527
+ // embed_segment (1 segment) + extract_items + build_conversation_summary = 3
528
+ expect(result.enqueuedJobs).toBe(3);
506
529
 
507
530
  const embedSegmentJobs = db
508
531
  .select()
509
532
  .from(memoryJobs)
510
533
  .where(eq(memoryJobs.type, "embed_segment"))
511
534
  .all();
512
- expect(embedSegmentJobs).toHaveLength(0);
535
+ expect(embedSegmentJobs).toHaveLength(1);
513
536
  });
514
537
 
515
538
  test("indexing skips durable item extraction for assistant messages when extractFromAssistant is false", () => {
@@ -561,7 +584,9 @@ describe("Memory regressions (experimental)", () => {
561
584
  },
562
585
  memoryConfig,
563
586
  );
564
- expect(result.enqueuedJobs).toBe(1);
587
+ // embed_segment (1 segment) + build_conversation_summary = 2
588
+ // (extract_items is skipped for assistant messages when extractFromAssistant=false)
589
+ expect(result.enqueuedJobs).toBe(2);
565
590
 
566
591
  const extractionJobs = db
567
592
  .select()
@@ -571,24 +596,24 @@ describe("Memory regressions (experimental)", () => {
571
596
  expect(extractionJobs).toHaveLength(0);
572
597
  });
573
598
 
574
- test("embed jobs are skipped (not failed) when no embedding backend is configured", async () => {
599
+ test("embed jobs complete successfully when backend and Qdrant mock are available", async () => {
575
600
  const db = getDb();
576
601
  const now = 3_000;
577
602
  db.insert(memoryItems)
578
603
  .values({
579
- id: "item-no-backend",
580
- kind: "fact",
604
+ id: "item-embed-test",
605
+ kind: "identity",
581
606
  subject: "backend",
582
- statement: "No embedding backend configured in test",
607
+ statement: "Embedding pipeline test item",
583
608
  status: "active",
584
609
  confidence: 0.8,
585
- fingerprint: "item-no-backend-fingerprint",
610
+ fingerprint: "item-embed-test-fingerprint",
586
611
  firstSeenAt: now,
587
612
  lastSeenAt: now,
588
613
  lastUsedAt: null,
589
614
  })
590
615
  .run();
591
- const jobId = enqueueMemoryJob("embed_item", { itemId: "item-no-backend" });
616
+ const jobId = enqueueMemoryJob("embed_item", { itemId: "item-embed-test" });
592
617
 
593
618
  const processed = await runMemoryJobsOnce();
594
619
  expect(processed).toBe(1);