@vellumai/assistant 0.5.16 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (592) hide show
  1. package/AGENTS.md +4 -0
  2. package/ARCHITECTURE.md +69 -16
  3. package/Dockerfile +2 -5
  4. package/bun.lock +6 -2
  5. package/docker-entrypoint.sh +32 -1
  6. package/docs/architecture/integrations.md +1 -1
  7. package/docs/architecture/memory.md +21 -24
  8. package/knip.json +2 -1
  9. package/openapi.yaml +1198 -83
  10. package/package.json +5 -1
  11. package/src/__tests__/actor-token-service.test.ts +68 -0
  12. package/src/__tests__/agent-loop.test.ts +0 -32
  13. package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
  14. package/src/__tests__/anthropic-provider.test.ts +217 -98
  15. package/src/__tests__/app-compiler.test.ts +120 -0
  16. package/src/__tests__/app-dir-path-guard.test.ts +1 -0
  17. package/src/__tests__/app-executors.test.ts +47 -1
  18. package/src/__tests__/app-source-watcher.test.ts +159 -0
  19. package/src/__tests__/assistant-feature-flags-integration.test.ts +2 -2
  20. package/src/__tests__/call-conversation-messages.test.ts +2 -6
  21. package/src/__tests__/call-domain.test.ts +2 -6
  22. package/src/__tests__/call-pointer-messages.test.ts +2 -14
  23. package/src/__tests__/call-recovery.test.ts +2 -6
  24. package/src/__tests__/call-routes-http.test.ts +2 -6
  25. package/src/__tests__/call-store.test.ts +2 -6
  26. package/src/__tests__/cancel-resolves-conversation-key.test.ts +2 -6
  27. package/src/__tests__/canonical-guardian-store.test.ts +2 -6
  28. package/src/__tests__/channel-delivery-store.test.ts +2 -6
  29. package/src/__tests__/channel-retry-sweep.test.ts +2 -6
  30. package/src/__tests__/checker.test.ts +63 -9
  31. package/src/__tests__/clawhub.test.ts +54 -24
  32. package/src/__tests__/cli-command-risk-guard.test.ts +14 -0
  33. package/src/__tests__/config-schema.test.ts +6 -1
  34. package/src/__tests__/config-set-platform-guard.test.ts +302 -0
  35. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +2 -6
  36. package/src/__tests__/contacts-tools.test.ts +31 -0
  37. package/src/__tests__/context-overflow-reducer.test.ts +86 -0
  38. package/src/__tests__/context-token-estimator.test.ts +175 -10
  39. package/src/__tests__/conversation-agent-loop-overflow.test.ts +13 -6
  40. package/src/__tests__/conversation-agent-loop.test.ts +13 -51
  41. package/src/__tests__/conversation-attachments.test.ts +2 -6
  42. package/src/__tests__/conversation-attention-store.test.ts +2 -6
  43. package/src/__tests__/conversation-clear-safety.test.ts +2 -6
  44. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +4 -10
  45. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -6
  46. package/src/__tests__/conversation-disk-view.test.ts +2 -6
  47. package/src/__tests__/conversation-error.test.ts +33 -2
  48. package/src/__tests__/conversation-fork-crud.test.ts +2 -6
  49. package/src/__tests__/conversation-history-web-search.test.ts +6 -1
  50. package/src/__tests__/conversation-load-history-repair.test.ts +5 -1
  51. package/src/__tests__/conversation-media-retry.test.ts +91 -0
  52. package/src/__tests__/conversation-runtime-assembly.test.ts +653 -832
  53. package/src/__tests__/conversation-runtime-workspace.test.ts +1 -93
  54. package/src/__tests__/conversation-starter-routes.test.ts +20 -11
  55. package/src/__tests__/conversation-store.test.ts +2 -6
  56. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +17 -4
  57. package/src/__tests__/conversation-usage.test.ts +2 -6
  58. package/src/__tests__/conversation-wipe.test.ts +13 -414
  59. package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -12
  60. package/src/__tests__/conversation-workspace-injection.test.ts +25 -26
  61. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -1
  62. package/src/__tests__/copy-composer-tc-templates.test.ts +335 -0
  63. package/src/__tests__/credential-execution-feature-gates.test.ts +3 -3
  64. package/src/__tests__/credential-execution-shell-lockdown.test.ts +2 -2
  65. package/src/__tests__/credential-security-e2e.test.ts +2 -0
  66. package/src/__tests__/date-context.test.ts +76 -210
  67. package/src/__tests__/db-schedule-syntax-migration.test.ts +16 -1
  68. package/src/__tests__/file-list-tool.test.ts +219 -0
  69. package/src/__tests__/first-greeting.test.ts +1 -1
  70. package/src/__tests__/followup-tools.test.ts +2 -6
  71. package/src/__tests__/graph-extraction-event-date.test.ts +186 -0
  72. package/src/__tests__/guardian-action-conversation-turn.test.ts +2 -6
  73. package/src/__tests__/guardian-action-followup-executor.test.ts +2 -6
  74. package/src/__tests__/guardian-action-followup-store.test.ts +2 -6
  75. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +2 -6
  76. package/src/__tests__/guardian-action-late-reply.test.ts +2 -6
  77. package/src/__tests__/guardian-action-store.test.ts +2 -6
  78. package/src/__tests__/guardian-binding-drift-heal.test.ts +2 -6
  79. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +8 -8
  80. package/src/__tests__/guardian-dispatch.test.ts +2 -6
  81. package/src/__tests__/guardian-grant-minting.test.ts +2 -14
  82. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +2 -6
  83. package/src/__tests__/guardian-routing-invariants.test.ts +192 -6
  84. package/src/__tests__/guardian-routing-state.test.ts +2 -6
  85. package/src/__tests__/guardian-verification-voice-binding.test.ts +2 -6
  86. package/src/__tests__/heartbeat-service.test.ts +180 -3
  87. package/src/__tests__/identity-routes.test.ts +328 -0
  88. package/src/__tests__/inbound-invite-redemption.test.ts +2 -6
  89. package/src/__tests__/injection-block.test.ts +178 -0
  90. package/src/__tests__/install-meta.test.ts +506 -0
  91. package/src/__tests__/install-skill-routing.test.ts +293 -0
  92. package/src/__tests__/invite-redemption-service.test.ts +2 -6
  93. package/src/__tests__/invite-routes-http.test.ts +2 -6
  94. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +17 -28
  95. package/src/__tests__/list-messages-attachments.test.ts +2 -6
  96. package/src/__tests__/list-messages-tool-merge.test.ts +300 -0
  97. package/src/__tests__/llm-context-normalization.test.ts +18 -18
  98. package/src/__tests__/llm-context-route-provider.test.ts +103 -6
  99. package/src/__tests__/llm-request-log-turn-query.test.ts +164 -6
  100. package/src/__tests__/llm-usage-store.test.ts +2 -6
  101. package/src/__tests__/log-export-workspace.test.ts +74 -111
  102. package/src/__tests__/managed-store.test.ts +38 -11
  103. package/src/__tests__/mcp-abort-signal.test.ts +5 -0
  104. package/src/__tests__/mcp-client-auth.test.ts +5 -0
  105. package/src/__tests__/memory-jobs-worker-backoff.test.ts +2 -8
  106. package/src/__tests__/memory-recall-log-store.test.ts +134 -6
  107. package/src/__tests__/memory-upsert-concurrency.test.ts +4 -112
  108. package/src/__tests__/migration-export-streaming.test.ts +304 -0
  109. package/src/__tests__/migration-import-commit-http.test.ts +11 -10
  110. package/src/__tests__/mock-fetch.ts +87 -0
  111. package/src/__tests__/non-member-access-request.test.ts +2 -6
  112. package/src/__tests__/notification-decision-recipient-context.test.ts +282 -0
  113. package/src/__tests__/notification-guardian-path.test.ts +2 -6
  114. package/src/__tests__/oauth-cli.test.ts +364 -2
  115. package/src/__tests__/oauth2-gateway-transport.test.ts +18 -3
  116. package/src/__tests__/onboarding-template-contract.test.ts +62 -14
  117. package/src/__tests__/outlook-attachments.test.ts +301 -0
  118. package/src/__tests__/outlook-automation-tools.test.ts +425 -0
  119. package/src/__tests__/outlook-categories.test.ts +212 -0
  120. package/src/__tests__/outlook-client-automation.test.ts +246 -0
  121. package/src/__tests__/outlook-compose-tools.test.ts +325 -0
  122. package/src/__tests__/outlook-declutter-tools.test.ts +585 -0
  123. package/src/__tests__/outlook-email-watcher.test.ts +322 -0
  124. package/src/__tests__/outlook-follow-up.test.ts +196 -0
  125. package/src/__tests__/outlook-messaging-provider.test.ts +498 -3
  126. package/src/__tests__/outlook-trash.test.ts +77 -0
  127. package/src/__tests__/outlook-unsubscribe.test.ts +250 -0
  128. package/src/__tests__/parser.test.ts +32 -0
  129. package/src/__tests__/permission-checker-host-gate.test.ts +452 -0
  130. package/src/__tests__/permission-controls-v2-flag.test.ts +55 -0
  131. package/src/__tests__/permission-mode-sse.test.ts +418 -0
  132. package/src/__tests__/permission-mode-store.test.ts +277 -0
  133. package/src/__tests__/permission-mode.test.ts +101 -0
  134. package/src/__tests__/platform-bash-auto-approve.test.ts +359 -0
  135. package/src/__tests__/platform-callback-registration.test.ts +4 -4
  136. package/src/__tests__/playbook-execution.test.ts +76 -80
  137. package/src/__tests__/playbook-tools.test.ts +5 -7
  138. package/src/__tests__/profiler-routes.test.ts +502 -0
  139. package/src/__tests__/profiler-run-store.test.ts +441 -0
  140. package/src/__tests__/provider-error-scenarios.test.ts +21 -0
  141. package/src/__tests__/proxy-approval-callback.test.ts +4 -75
  142. package/src/__tests__/rebuild-index-graph-nodes.test.ts +273 -0
  143. package/src/__tests__/registry.test.ts +3 -3
  144. package/src/__tests__/require-fresh-approval.test.ts +64 -2
  145. package/src/__tests__/runtime-events-sse-parity.test.ts +2 -6
  146. package/src/__tests__/runtime-events-sse.test.ts +2 -6
  147. package/src/__tests__/sandbox-host-parity.test.ts +5 -4
  148. package/src/__tests__/schedule-store.test.ts +2 -6
  149. package/src/__tests__/schedule-tools.test.ts +2 -6
  150. package/src/__tests__/scheduler-recurrence.test.ts +1 -5
  151. package/src/__tests__/scheduler-reuse-conversation.test.ts +368 -0
  152. package/src/__tests__/scoped-approval-grants.test.ts +2 -6
  153. package/src/__tests__/scoped-grant-security-matrix.test.ts +2 -6
  154. package/src/__tests__/scrub-corrupted-image-attachments.test.ts +278 -0
  155. package/src/__tests__/search-skills-unified.test.ts +422 -0
  156. package/src/__tests__/secret-onetime-send.test.ts +2 -0
  157. package/src/__tests__/send-endpoint-busy.test.ts +44 -9
  158. package/src/__tests__/sequence-store.test.ts +2 -6
  159. package/src/__tests__/server-history-render.test.ts +2 -6
  160. package/src/__tests__/set-permission-mode.test.ts +274 -0
  161. package/src/__tests__/skill-feature-flags-integration.test.ts +38 -31
  162. package/src/__tests__/skill-feature-flags.test.ts +6 -6
  163. package/src/__tests__/skill-load-feature-flag.test.ts +23 -11
  164. package/src/__tests__/skill-memory.test.ts +2 -741
  165. package/src/__tests__/skills-uninstall.test.ts +2 -2
  166. package/src/__tests__/skills.test.ts +1 -1
  167. package/src/__tests__/slack-inbound-verification.test.ts +2 -6
  168. package/src/__tests__/strip-memory-injections.test.ts +187 -0
  169. package/src/__tests__/subagent-detail.test.ts +84 -0
  170. package/src/__tests__/subagent-disposal.test.ts +308 -0
  171. package/src/__tests__/subagent-manager-notify.test.ts +19 -10
  172. package/src/__tests__/subagent-notify-parent.test.ts +390 -0
  173. package/src/__tests__/subagent-role-registry.test.ts +108 -0
  174. package/src/__tests__/subagent-tool-filtering.test.ts +71 -0
  175. package/src/__tests__/subagent-tools.test.ts +464 -4
  176. package/src/__tests__/system-prompt-ask-mode.test.ts +139 -0
  177. package/src/__tests__/task-compiler.test.ts +2 -6
  178. package/src/__tests__/task-management-tools.test.ts +2 -6
  179. package/src/__tests__/task-memory-cleanup.test.ts +185 -241
  180. package/src/__tests__/task-runner.test.ts +2 -6
  181. package/src/__tests__/task-scheduler.test.ts +2 -6
  182. package/src/__tests__/terminal-tools.test.ts +17 -27
  183. package/src/__tests__/test-preload.ts +7 -0
  184. package/src/__tests__/tool-approval-handler.test.ts +2 -6
  185. package/src/__tests__/tool-executor.test.ts +4 -26
  186. package/src/__tests__/tool-grant-request-escalation.test.ts +2 -6
  187. package/src/__tests__/tool-side-effects-slack-dm.test.ts +277 -0
  188. package/src/__tests__/top-level-renderer.test.ts +10 -13
  189. package/src/__tests__/trust-store.test.ts +1 -1
  190. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +2 -6
  191. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +118 -8
  192. package/src/__tests__/trusted-contact-multichannel.test.ts +2 -6
  193. package/src/__tests__/trusted-contact-verification.test.ts +2 -6
  194. package/src/__tests__/turn-boundary-resolution.test.ts +2 -6
  195. package/src/__tests__/usage-cache-backfill-migration.test.ts +1 -6
  196. package/src/__tests__/usage-routes.test.ts +2 -6
  197. package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
  198. package/src/__tests__/voice-invite-redemption.test.ts +2 -6
  199. package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -6
  200. package/src/__tests__/voice-session-bridge.test.ts +2 -6
  201. package/src/__tests__/volume-security-guard.test.ts +2 -0
  202. package/src/__tests__/workspace-lifecycle.test.ts +29 -1
  203. package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +2 -6
  204. package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +2 -6
  205. package/src/__tests__/workspace-migration-026-backfill-install-meta.test.ts +558 -0
  206. package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +387 -0
  207. package/src/__tests__/workspace-policy.test.ts +1 -1
  208. package/src/agent/attachments.ts +7 -2
  209. package/src/agent/image-optimize.ts +165 -0
  210. package/src/agent/loop.ts +7 -15
  211. package/src/approvals/guardian-request-resolvers.ts +24 -0
  212. package/src/avatar/traits-png-sync.ts +3 -3
  213. package/src/bundler/app-compiler.ts +179 -2
  214. package/src/bundler/package-resolver.ts +3 -5
  215. package/src/cli/__tests__/notifications.test.ts +1 -2
  216. package/src/cli/__tests__/run-assistant-command.ts +29 -0
  217. package/src/cli/commands/__tests__/email-download.test.ts +245 -0
  218. package/src/cli/commands/__tests__/email-list.test.ts +192 -0
  219. package/src/cli/commands/__tests__/email-register.test.ts +186 -0
  220. package/src/cli/commands/__tests__/email-send.test.ts +291 -0
  221. package/src/cli/commands/__tests__/email-status.test.ts +181 -0
  222. package/src/cli/commands/__tests__/email-unregister.test.ts +139 -0
  223. package/src/cli/commands/__tests__/routes.test.ts +562 -0
  224. package/src/cli/commands/avatar.ts +3 -3
  225. package/src/cli/commands/config.ts +26 -13
  226. package/src/cli/commands/conversations.ts +1 -8
  227. package/src/cli/commands/doctor.ts +2 -2
  228. package/src/cli/commands/email.ts +584 -835
  229. package/src/cli/commands/memory.ts +37 -84
  230. package/src/cli/commands/notifications.ts +7 -2
  231. package/src/cli/commands/oauth/__tests__/connect.test.ts +2 -2
  232. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +2 -2
  233. package/src/cli/commands/oauth/__tests__/mode.test.ts +8 -1
  234. package/src/cli/commands/oauth/__tests__/status.test.ts +2 -2
  235. package/src/cli/commands/oauth/connect.ts +25 -11
  236. package/src/cli/commands/oauth/mode.ts +7 -0
  237. package/src/cli/commands/oauth/shared.ts +39 -3
  238. package/src/cli/commands/platform/__tests__/connect.test.ts +1 -1
  239. package/src/cli/commands/platform/__tests__/disconnect.test.ts +1 -1
  240. package/src/cli/commands/platform/__tests__/status.test.ts +5 -5
  241. package/src/cli/commands/platform/index.ts +16 -16
  242. package/src/cli/commands/routes.ts +396 -0
  243. package/src/cli/commands/skills.ts +218 -36
  244. package/src/cli/commands/trust.ts +2 -2
  245. package/src/cli/lib/daemon-credential-client.ts +2 -3
  246. package/src/cli/program.ts +2 -0
  247. package/src/cli.ts +1 -120
  248. package/src/config/bundled-skills/acp/TOOLS.json +1 -1
  249. package/src/config/bundled-skills/app-builder/SKILL.md +4 -1
  250. package/src/config/bundled-skills/contacts/SKILL.md +0 -1
  251. package/src/config/bundled-skills/contacts/TOOLS.json +0 -8
  252. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -4
  253. package/src/config/bundled-skills/gmail/SKILL.md +4 -12
  254. package/src/config/bundled-skills/google-calendar/SKILL.md +1 -9
  255. package/src/config/bundled-skills/messaging/SKILL.md +17 -18
  256. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +40 -33
  257. package/src/config/bundled-skills/outlook/SKILL.md +189 -0
  258. package/src/config/bundled-skills/outlook/TOOLS.json +530 -0
  259. package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +85 -0
  260. package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +77 -0
  261. package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +84 -0
  262. package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +94 -0
  263. package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +49 -0
  264. package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +237 -0
  265. package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +161 -0
  266. package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +32 -0
  267. package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +272 -0
  268. package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +29 -0
  269. package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +129 -0
  270. package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +87 -0
  271. package/src/config/bundled-skills/outlook/tools/shared.ts +20 -0
  272. package/src/config/bundled-skills/outlook-calendar/SKILL.md +51 -0
  273. package/src/config/bundled-skills/outlook-calendar/TOOLS.json +221 -0
  274. package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +252 -0
  275. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +53 -0
  276. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +74 -0
  277. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +18 -0
  278. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +46 -0
  279. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +36 -0
  280. package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +17 -0
  281. package/src/config/bundled-skills/outlook-calendar/types.ts +120 -0
  282. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +47 -40
  283. package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +16 -29
  284. package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +16 -18
  285. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +39 -47
  286. package/src/config/bundled-skills/schedule/SKILL.md +22 -2
  287. package/src/config/bundled-skills/schedule/TOOLS.json +8 -0
  288. package/src/config/bundled-skills/settings/tools/avatar-get.ts +3 -13
  289. package/src/config/bundled-skills/settings/tools/avatar-remove.ts +2 -4
  290. package/src/config/bundled-skills/settings/tools/avatar-update.ts +5 -2
  291. package/src/config/bundled-skills/slack/SKILL.md +3 -7
  292. package/src/config/bundled-skills/subagent/SKILL.md +43 -3
  293. package/src/config/bundled-skills/subagent/TOOLS.json +29 -4
  294. package/src/config/bundled-tool-registry.ts +56 -4
  295. package/src/config/env-registry.ts +78 -8
  296. package/src/config/feature-flag-registry.json +38 -125
  297. package/src/config/schema.ts +8 -0
  298. package/src/config/schemas/filing.ts +51 -0
  299. package/src/config/schemas/heartbeat.ts +15 -12
  300. package/src/config/schemas/memory-lifecycle.ts +12 -0
  301. package/src/config/schemas/platform.ts +8 -0
  302. package/src/config/schemas/security.ts +14 -0
  303. package/src/config/schemas/timeouts.ts +1 -1
  304. package/src/config/skills.ts +18 -7
  305. package/src/context/token-estimator.ts +25 -18
  306. package/src/context/window-manager.ts +6 -2
  307. package/src/credential-execution/process-manager.ts +3 -1
  308. package/src/daemon/app-source-watcher.ts +93 -0
  309. package/src/daemon/config-watcher.ts +79 -1
  310. package/src/daemon/context-overflow-reducer.ts +46 -2
  311. package/src/daemon/conversation-agent-loop-handlers.ts +143 -82
  312. package/src/daemon/conversation-agent-loop.ts +236 -108
  313. package/src/daemon/conversation-error.ts +31 -8
  314. package/src/daemon/conversation-history.ts +4 -19
  315. package/src/daemon/conversation-lifecycle.ts +36 -9
  316. package/src/daemon/conversation-media-retry.ts +85 -7
  317. package/src/daemon/conversation-notifiers.ts +4 -1
  318. package/src/daemon/conversation-process.ts +13 -7
  319. package/src/daemon/conversation-runtime-assembly.ts +305 -306
  320. package/src/daemon/conversation-tool-setup.ts +44 -14
  321. package/src/daemon/conversation-workspace.ts +1 -2
  322. package/src/daemon/conversation.ts +59 -2
  323. package/src/daemon/daemon-control.ts +8 -2
  324. package/src/daemon/date-context.ts +26 -53
  325. package/src/daemon/first-greeting.ts +1 -1
  326. package/src/daemon/handlers/conversations.ts +4 -7
  327. package/src/daemon/handlers/shared.test.ts +143 -0
  328. package/src/daemon/handlers/shared.ts +85 -17
  329. package/src/daemon/handlers/skills.ts +416 -209
  330. package/src/daemon/lifecycle.ts +212 -131
  331. package/src/daemon/main.ts +5 -1
  332. package/src/daemon/message-types/conversations.ts +29 -7
  333. package/src/daemon/message-types/messages.ts +12 -2
  334. package/src/daemon/message-types/schedules.ts +1 -0
  335. package/src/daemon/message-types/settings.ts +6 -0
  336. package/src/daemon/message-types/skills.ts +97 -36
  337. package/src/daemon/profiler-run-store.ts +557 -0
  338. package/src/daemon/providers-setup.ts +5 -0
  339. package/src/daemon/server.ts +100 -11
  340. package/src/daemon/shutdown-handlers.ts +5 -0
  341. package/src/daemon/tool-side-effects.ts +50 -8
  342. package/src/export/transcript-formatter.ts +148 -0
  343. package/src/filing/filing-service.ts +228 -0
  344. package/src/heartbeat/heartbeat-service.ts +97 -7
  345. package/src/hooks/cli.ts +2 -2
  346. package/src/hooks/runner.ts +15 -38
  347. package/src/inbound/platform-callback-registration.ts +14 -14
  348. package/src/mcp/client.ts +6 -0
  349. package/src/mcp/mcp-oauth-provider.ts +149 -27
  350. package/src/memory/admin.ts +42 -75
  351. package/src/memory/app-store.ts +69 -0
  352. package/src/memory/conversation-bootstrap.ts +3 -1
  353. package/src/memory/conversation-crud.ts +211 -288
  354. package/src/memory/conversation-group-migration.ts +157 -0
  355. package/src/memory/conversation-queries.ts +61 -13
  356. package/src/memory/conversation-title-service.ts +1 -0
  357. package/src/memory/db-init.ts +194 -361
  358. package/src/memory/embed.ts +73 -0
  359. package/src/memory/embedding-backend.ts +8 -14
  360. package/src/memory/embedding-runtime-manager.ts +12 -114
  361. package/src/memory/fingerprint.ts +2 -2
  362. package/src/memory/graph/bootstrap.ts +521 -0
  363. package/src/memory/graph/capability-seed.ts +449 -0
  364. package/src/memory/graph/consolidation.ts +725 -0
  365. package/src/memory/graph/conversation-graph-memory.ts +659 -0
  366. package/src/memory/graph/decay.test.ts +208 -0
  367. package/src/memory/graph/decay.ts +195 -0
  368. package/src/memory/graph/extraction-job.ts +74 -0
  369. package/src/memory/graph/extraction.test.ts +936 -0
  370. package/src/memory/graph/extraction.ts +1297 -0
  371. package/src/memory/graph/graph-memory-state-store.ts +37 -0
  372. package/src/memory/graph/graph-search.ts +280 -0
  373. package/src/memory/graph/image-ref-utils.ts +29 -0
  374. package/src/memory/graph/injection.test.ts +513 -0
  375. package/src/memory/graph/injection.ts +469 -0
  376. package/src/memory/graph/inspect.ts +543 -0
  377. package/src/memory/graph/narrative.ts +267 -0
  378. package/src/memory/graph/pattern-scan.ts +269 -0
  379. package/src/memory/graph/retriever.ts +1111 -0
  380. package/src/memory/graph/scoring.test.ts +548 -0
  381. package/src/memory/graph/scoring.ts +232 -0
  382. package/src/memory/graph/serendipity.ts +65 -0
  383. package/src/memory/graph/store.test.ts +1098 -0
  384. package/src/memory/graph/store.ts +838 -0
  385. package/src/memory/graph/tool-handlers.ts +301 -0
  386. package/src/memory/graph/tools.ts +97 -0
  387. package/src/memory/graph/triggers.test.ts +487 -0
  388. package/src/memory/graph/triggers.ts +223 -0
  389. package/src/memory/graph/types.ts +295 -0
  390. package/src/memory/group-crud.ts +191 -0
  391. package/src/memory/indexer.ts +37 -19
  392. package/src/memory/job-handlers/cleanup.ts +32 -42
  393. package/src/memory/job-handlers/conversation-starters.ts +91 -53
  394. package/src/memory/job-handlers/embedding.ts +5 -31
  395. package/src/memory/job-handlers/index-maintenance.ts +23 -11
  396. package/src/memory/job-handlers/summarization.ts +32 -17
  397. package/src/memory/job-utils.ts +1 -1
  398. package/src/memory/jobs-store.ts +21 -31
  399. package/src/memory/jobs-worker.ts +180 -129
  400. package/src/memory/llm-request-log-store.ts +96 -12
  401. package/src/memory/memory-recall-log-store.ts +49 -5
  402. package/src/memory/message-content.ts +1 -0
  403. package/src/memory/migrations/202-memory-graph-tables.ts +130 -0
  404. package/src/memory/migrations/203-drop-memory-items-tables.ts +55 -0
  405. package/src/memory/migrations/204-rename-memory-graph-type-values.ts +46 -0
  406. package/src/memory/migrations/205-memory-graph-image-refs.ts +11 -0
  407. package/src/memory/migrations/206-memory-graph-node-edits.ts +19 -0
  408. package/src/memory/migrations/206-scrub-corrupted-image-attachments.ts +131 -0
  409. package/src/memory/migrations/207-conversation-graph-memory-state.ts +20 -0
  410. package/src/memory/migrations/208-conversations-last-message-at.ts +35 -0
  411. package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +85 -0
  412. package/src/memory/migrations/210-schedule-reuse-conversation.ts +13 -0
  413. package/src/memory/migrations/211-memory-recall-logs-query-context.ts +21 -0
  414. package/src/memory/migrations/212-llm-request-logs-created-at-index.ts +19 -0
  415. package/src/memory/migrations/index.ts +12 -0
  416. package/src/memory/migrations/registry.ts +16 -0
  417. package/src/memory/qdrant-client.ts +44 -17
  418. package/src/memory/schema/conversations.ts +14 -0
  419. package/src/memory/schema/index.ts +1 -0
  420. package/src/memory/schema/infrastructure.ts +8 -1
  421. package/src/memory/schema/memory-core.ts +0 -51
  422. package/src/memory/schema/memory-graph.ts +154 -0
  423. package/src/memory/search/semantic.ts +47 -91
  424. package/src/memory/task-memory-cleanup.ts +58 -61
  425. package/src/messaging/providers/outlook/adapter.ts +8 -1
  426. package/src/messaging/providers/outlook/client.ts +299 -0
  427. package/src/messaging/providers/outlook/types.ts +118 -0
  428. package/src/notifications/adapters/macos.ts +1 -0
  429. package/src/notifications/copy-composer.ts +95 -0
  430. package/src/notifications/decision-engine.ts +35 -0
  431. package/src/notifications/signal.ts +16 -0
  432. package/src/oauth/seed-providers.ts +2 -1
  433. package/src/permissions/checker.ts +36 -4
  434. package/src/permissions/defaults.ts +4 -4
  435. package/src/permissions/permission-mode-store.ts +180 -0
  436. package/src/permissions/permission-mode.ts +31 -0
  437. package/src/permissions/workspace-policy.ts +10 -1
  438. package/src/playbooks/playbook-compiler.ts +19 -18
  439. package/src/playbooks/types.ts +4 -3
  440. package/src/prompts/system-prompt.ts +62 -36
  441. package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +100 -0
  442. package/src/prompts/templates/BOOTSTRAP.md +70 -165
  443. package/src/prompts/templates/HEARTBEAT.md +3 -1
  444. package/src/prompts/templates/SOUL.md +25 -4
  445. package/src/prompts/templates/UPDATES.md +8 -0
  446. package/src/providers/anthropic/client.ts +136 -220
  447. package/src/providers/gemini/client.ts +1 -1
  448. package/src/providers/openai/client.ts +1 -1
  449. package/src/providers/registry.ts +1 -1
  450. package/src/providers/retry.ts +19 -3
  451. package/src/runtime/actor-trust-resolver.ts +5 -1
  452. package/src/runtime/auth/route-policy.ts +30 -0
  453. package/src/runtime/guardian-reply-router.ts +5 -1
  454. package/src/runtime/http-server.ts +55 -5
  455. package/src/runtime/http-types.ts +12 -1
  456. package/src/runtime/middleware/auth.ts +20 -0
  457. package/src/runtime/migrations/vbundle-builder.ts +389 -3
  458. package/src/runtime/migrations/vbundle-importer.ts +8 -6
  459. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +378 -0
  460. package/src/runtime/routes/app-management-routes.ts +1 -11
  461. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +26 -0
  462. package/src/runtime/routes/archive-utils.ts +29 -0
  463. package/src/runtime/routes/attachment-routes.test.ts +106 -0
  464. package/src/runtime/routes/attachment-routes.ts +106 -16
  465. package/src/runtime/routes/avatar-routes.ts +2 -9
  466. package/src/runtime/routes/brain-graph-routes.ts +21 -22
  467. package/src/runtime/routes/btw-routes.ts +22 -1
  468. package/src/runtime/routes/conversation-analysis-routes.ts +173 -0
  469. package/src/runtime/routes/conversation-management-routes.ts +3 -14
  470. package/src/runtime/routes/conversation-query-routes.ts +49 -3
  471. package/src/runtime/routes/conversation-routes.ts +264 -44
  472. package/src/runtime/routes/conversation-starter-routes.ts +2 -2
  473. package/src/runtime/routes/debug-routes.ts +1 -1
  474. package/src/runtime/routes/global-search-routes.ts +21 -19
  475. package/src/runtime/routes/group-routes.ts +207 -0
  476. package/src/runtime/routes/guardian-action-routes.ts +21 -10
  477. package/src/runtime/routes/guardian-bootstrap-routes.ts +23 -19
  478. package/src/runtime/routes/heartbeat-routes.ts +4 -10
  479. package/src/runtime/routes/identity-routes.ts +53 -18
  480. package/src/runtime/routes/inbound-message-handler.ts +19 -0
  481. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +292 -0
  482. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +207 -0
  483. package/src/runtime/routes/llm-context-normalization.ts +14 -10
  484. package/src/runtime/routes/log-export-routes.ts +23 -275
  485. package/src/runtime/routes/memory-item-routes.test.ts +170 -247
  486. package/src/runtime/routes/memory-item-routes.ts +341 -388
  487. package/src/runtime/routes/migration-routes.ts +18 -7
  488. package/src/runtime/routes/profiler-routes.ts +350 -0
  489. package/src/runtime/routes/schedule-routes.ts +28 -11
  490. package/src/runtime/routes/settings-routes.ts +95 -8
  491. package/src/runtime/routes/skills-routes.ts +103 -37
  492. package/src/runtime/routes/subagents-routes.ts +28 -7
  493. package/src/runtime/routes/user-route-dispatcher.ts +223 -0
  494. package/src/runtime/routes/user-routes.ts +41 -0
  495. package/src/runtime/routes/work-items-routes.test.ts +2 -6
  496. package/src/runtime/routes/workspace-routes.ts +0 -1
  497. package/src/schedule/schedule-store.ts +30 -0
  498. package/src/schedule/scheduler.ts +52 -18
  499. package/src/security/oauth2.ts +1 -1
  500. package/src/security/secure-keys.ts +4 -8
  501. package/src/shared/provider-env-vars.ts +19 -0
  502. package/src/skills/catalog-cache.ts +5 -0
  503. package/src/skills/catalog-install.ts +25 -16
  504. package/src/skills/clawhub.ts +134 -154
  505. package/src/skills/install-meta.ts +208 -0
  506. package/src/skills/managed-store.ts +29 -18
  507. package/src/skills/skill-memory.ts +12 -229
  508. package/src/skills/skillssh-registry.ts +19 -17
  509. package/src/subagent/index.ts +13 -3
  510. package/src/subagent/manager.ts +308 -29
  511. package/src/subagent/types.ts +68 -0
  512. package/src/tasks/task-runner.ts +7 -5
  513. package/src/telemetry/usage-telemetry-reporter.test.ts +3 -5
  514. package/src/tools/apps/executors.ts +29 -4
  515. package/src/tools/browser/runtime-check.ts +3 -1
  516. package/src/tools/filesystem/list.ts +93 -0
  517. package/src/tools/memory/register.ts +63 -46
  518. package/src/tools/permission-checker.ts +85 -1
  519. package/src/tools/registry.ts +4 -0
  520. package/src/tools/schedule/create.ts +3 -0
  521. package/src/tools/schedule/list.ts +1 -0
  522. package/src/tools/schedule/update.ts +6 -0
  523. package/src/tools/shared/filesystem/errors.ts +5 -0
  524. package/src/tools/shared/filesystem/file-ops-service.ts +90 -2
  525. package/src/tools/shared/filesystem/image-read.ts +22 -85
  526. package/src/tools/shared/filesystem/types.ts +17 -0
  527. package/src/tools/shared/shell-output.ts +31 -2
  528. package/src/tools/subagent/abort.ts +12 -2
  529. package/src/tools/subagent/message.ts +9 -2
  530. package/src/tools/subagent/notify-parent.ts +79 -0
  531. package/src/tools/subagent/read.ts +29 -8
  532. package/src/tools/subagent/resolve.ts +21 -0
  533. package/src/tools/subagent/spawn.ts +2 -0
  534. package/src/tools/subagent/status.ts +11 -1
  535. package/src/tools/system/avatar-generator.ts +3 -3
  536. package/src/tools/system/register.ts +23 -0
  537. package/src/tools/system/set-permission-mode.ts +103 -0
  538. package/src/tools/terminal/parser.ts +30 -5
  539. package/src/tools/terminal/safe-env.ts +17 -1
  540. package/src/tools/tool-manifest.ts +9 -3
  541. package/src/tools/types.ts +2 -0
  542. package/src/util/browser.ts +25 -10
  543. package/src/util/bun-runtime.ts +172 -0
  544. package/src/util/logger.ts +1 -1
  545. package/src/util/platform.ts +50 -17
  546. package/src/watcher/providers/outlook-calendar.ts +343 -0
  547. package/src/watcher/providers/outlook.ts +198 -0
  548. package/src/workspace/migrations/023-move-config-files-to-workspace.ts +2 -2
  549. package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +2 -2
  550. package/src/workspace/migrations/025-remove-oauth-app-setup-skills.ts +76 -0
  551. package/src/workspace/migrations/026-backfill-install-meta.ts +325 -0
  552. package/src/workspace/migrations/027-remove-orphaned-optimized-images-cache.ts +42 -0
  553. package/src/workspace/migrations/028-recover-conversations-from-disk-view.ts +270 -0
  554. package/src/workspace/migrations/029-seed-pkb.ts +84 -0
  555. package/src/workspace/migrations/registry.ts +10 -0
  556. package/src/workspace/top-level-renderer.ts +5 -9
  557. package/src/__tests__/cli-memory.test.ts +0 -372
  558. package/src/__tests__/clipboard.test.ts +0 -88
  559. package/src/__tests__/context-memory-e2e.test.ts +0 -415
  560. package/src/__tests__/journal-context.test.ts +0 -268
  561. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +0 -297
  562. package/src/__tests__/memory-lifecycle-e2e.test.ts +0 -459
  563. package/src/__tests__/memory-query-builder.test.ts +0 -59
  564. package/src/__tests__/memory-recall-quality.test.ts +0 -1046
  565. package/src/__tests__/memory-regressions.experimental.test.ts +0 -629
  566. package/src/__tests__/memory-regressions.test.ts +0 -3696
  567. package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -295
  568. package/src/cli/cli-memory.ts +0 -176
  569. package/src/daemon/conversation-memory.ts +0 -207
  570. package/src/memory/conversation-starters-cadence.ts +0 -74
  571. package/src/memory/items-extractor.ts +0 -860
  572. package/src/memory/job-handlers/batch-extraction.ts +0 -753
  573. package/src/memory/job-handlers/extraction.ts +0 -40
  574. package/src/memory/job-handlers/journal-carry-forward.test.ts +0 -355
  575. package/src/memory/job-handlers/journal-carry-forward.ts +0 -255
  576. package/src/memory/journal-memory.ts +0 -224
  577. package/src/memory/query-builder.ts +0 -47
  578. package/src/memory/query-expansion.ts +0 -83
  579. package/src/memory/retriever.test.ts +0 -1592
  580. package/src/memory/retriever.ts +0 -1331
  581. package/src/memory/search/formatting.test.ts +0 -140
  582. package/src/memory/search/formatting.ts +0 -262
  583. package/src/memory/search/mmr.ts +0 -139
  584. package/src/memory/search/ranking.ts +0 -15
  585. package/src/memory/search/staleness.ts +0 -40
  586. package/src/memory/search/tier-classifier.ts +0 -18
  587. package/src/memory/search/types.ts +0 -121
  588. package/src/prompts/journal-context.ts +0 -154
  589. package/src/tools/memory/definitions.ts +0 -69
  590. package/src/tools/memory/handlers.test.ts +0 -562
  591. package/src/tools/memory/handlers.ts +0 -434
  592. package/src/util/clipboard.ts +0 -34
@@ -1,562 +0,0 @@
1
- /**
2
- * Tests for the handleMemoryRecall() tool handler.
3
- *
4
- * Covers happy path (multi-source results), empty results, degraded mode
5
- * (embeddings/Qdrant unavailable), scope filtering, and error handling.
6
- */
7
- import { beforeAll, beforeEach, describe, expect, mock, test } from "bun:test";
8
-
9
- // ── Module mocks (must precede production imports) ───────────────────
10
-
11
- mock.module("../../util/logger.js", () => ({
12
- getLogger: () =>
13
- new Proxy({} as Record<string, unknown>, {
14
- get: () => () => {},
15
- }),
16
- }));
17
-
18
- mock.module("../../memory/embedding-local.js", () => ({
19
- LocalEmbeddingBackend: class {
20
- readonly provider = "local" as const;
21
- readonly model: string;
22
- constructor(model: string) {
23
- this.model = model;
24
- }
25
- async embed(texts: string[]): Promise<number[][]> {
26
- return texts.map(() => new Array(384).fill(0));
27
- }
28
- },
29
- }));
30
-
31
- mock.module("../../memory/qdrant-client.js", () => ({
32
- getQdrantClient: () => ({
33
- searchWithFilter: async () => [],
34
- hybridSearch: async () => [],
35
- upsertPoints: async () => {},
36
- deletePoints: async () => {},
37
- }),
38
- initQdrantClient: () => {},
39
- }));
40
-
41
- import { DEFAULT_CONFIG } from "../../config/defaults.js";
42
- import type { AssistantConfig } from "../../config/types.js";
43
-
44
- const TEST_CONFIG: AssistantConfig = {
45
- ...DEFAULT_CONFIG,
46
- memory: {
47
- ...DEFAULT_CONFIG.memory,
48
- extraction: {
49
- ...DEFAULT_CONFIG.memory.extraction,
50
- useLLM: false,
51
- },
52
- embeddings: {
53
- ...DEFAULT_CONFIG.memory.embeddings,
54
- required: false,
55
- },
56
- },
57
- };
58
-
59
- mock.module("../../config/loader.js", () => ({
60
- loadConfig: () => TEST_CONFIG,
61
- getConfig: () => TEST_CONFIG,
62
- invalidateConfigCache: () => {},
63
- }));
64
-
65
- import { getDb, initializeDb } from "../../memory/db.js";
66
- import { clearEmbeddingBackendCache } from "../../memory/embedding-backend.js";
67
- import {
68
- conversations,
69
- memoryItems,
70
- memoryItemSources,
71
- messages,
72
- } from "../../memory/schema.js";
73
- import type { MemoryRecallToolResult } from "./handlers.js";
74
- import { handleMemoryRecall } from "./handlers.js";
75
-
76
- function clearTables() {
77
- const db = getDb();
78
- db.run("DELETE FROM memory_item_sources");
79
- db.run("DELETE FROM memory_items");
80
- db.run("DELETE FROM memory_segments");
81
- db.run("DELETE FROM messages");
82
- db.run("DELETE FROM conversations");
83
- }
84
-
85
- // ── Helpers ──────────────────────────────────────────────────────────
86
-
87
- function insertConversation(
88
- db: ReturnType<typeof getDb>,
89
- id: string,
90
- createdAt: number,
91
- ) {
92
- db.insert(conversations)
93
- .values({
94
- id,
95
- title: null,
96
- createdAt,
97
- updatedAt: createdAt,
98
- totalInputTokens: 0,
99
- totalOutputTokens: 0,
100
- totalEstimatedCost: 0,
101
- contextSummary: null,
102
- contextCompactedMessageCount: 0,
103
- contextCompactedAt: null,
104
- })
105
- .run();
106
- }
107
-
108
- function insertMessage(
109
- db: ReturnType<typeof getDb>,
110
- id: string,
111
- conversationId: string,
112
- role: string,
113
- text: string,
114
- createdAt: number,
115
- ) {
116
- db.insert(messages)
117
- .values({
118
- id,
119
- conversationId,
120
- role,
121
- content: JSON.stringify([{ type: "text", text }]),
122
- createdAt,
123
- })
124
- .run();
125
- }
126
-
127
- function insertItem(
128
- db: ReturnType<typeof getDb>,
129
- opts: {
130
- id: string;
131
- kind: string;
132
- subject: string;
133
- statement: string;
134
- status?: string;
135
- confidence?: number;
136
- importance?: number;
137
- firstSeenAt: number;
138
- lastSeenAt?: number;
139
- scopeId?: string;
140
- },
141
- ) {
142
- db.insert(memoryItems)
143
- .values({
144
- id: opts.id,
145
- kind: opts.kind,
146
- subject: opts.subject,
147
- statement: opts.statement,
148
- status: opts.status ?? "active",
149
- confidence: opts.confidence ?? 0.8,
150
- importance: opts.importance ?? 0.6,
151
- accessCount: 0,
152
- fingerprint: `fp-${opts.id}`,
153
- scopeId: opts.scopeId ?? "default",
154
- firstSeenAt: opts.firstSeenAt,
155
- lastSeenAt: opts.lastSeenAt ?? opts.firstSeenAt,
156
- lastUsedAt: null,
157
- })
158
- .run();
159
- }
160
-
161
- function insertItemSource(
162
- db: ReturnType<typeof getDb>,
163
- itemId: string,
164
- messageId: string,
165
- createdAt: number,
166
- ) {
167
- db.insert(memoryItemSources)
168
- .values({
169
- memoryItemId: itemId,
170
- messageId,
171
- evidence: `evidence for ${itemId}`,
172
- createdAt,
173
- })
174
- .run();
175
- }
176
-
177
- function parseResult(content: string): MemoryRecallToolResult {
178
- return JSON.parse(content) as MemoryRecallToolResult;
179
- }
180
-
181
- /** Seed with searchable memory items from multiple sources. */
182
- function seedMemory() {
183
- const db = getDb();
184
- const now = Date.now();
185
- const convId = "conv-recall-test";
186
-
187
- insertConversation(db, convId, now - 60_000);
188
- insertMessage(
189
- db,
190
- "msg-1",
191
- convId,
192
- "user",
193
- "discuss API design",
194
- now - 50_000,
195
- );
196
- insertMessage(
197
- db,
198
- "msg-2",
199
- convId,
200
- "assistant",
201
- "The API design uses REST endpoints",
202
- now - 40_000,
203
- );
204
-
205
- insertItem(db, {
206
- id: "item-api",
207
- kind: "preference",
208
- subject: "API design",
209
- statement: "User prefers REST over GraphQL for API design",
210
- firstSeenAt: now - 30_000,
211
- importance: 0.9,
212
- });
213
- insertItemSource(db, "item-api", "msg-1", now - 30_000);
214
-
215
- insertItem(db, {
216
- id: "item-testing",
217
- kind: "identity",
218
- subject: "testing",
219
- statement: "The project uses bun test for unit testing",
220
- firstSeenAt: now - 20_000,
221
- importance: 0.7,
222
- });
223
- insertItemSource(db, "item-testing", "msg-2", now - 20_000);
224
- }
225
-
226
- // ── Suite ────────────────────────────────────────────────────────────
227
-
228
- describe("handleMemoryRecall", () => {
229
- beforeAll(() => {
230
- initializeDb();
231
- });
232
-
233
- beforeEach(() => {
234
- clearTables();
235
- clearEmbeddingBackendCache();
236
- });
237
-
238
- // ── Input validation ──────────────────────────────────────────────
239
-
240
- test("returns error when query is missing", async () => {
241
- const result = await handleMemoryRecall({}, TEST_CONFIG);
242
- expect(result.isError).toBe(true);
243
- expect(result.content).toContain("query is required");
244
- });
245
-
246
- test("returns error when query is empty string", async () => {
247
- const result = await handleMemoryRecall({ query: " " }, TEST_CONFIG);
248
- expect(result.isError).toBe(true);
249
- expect(result.content).toContain("query is required");
250
- });
251
-
252
- test("returns error when query is not a string", async () => {
253
- const result = await handleMemoryRecall({ query: 42 }, TEST_CONFIG);
254
- expect(result.isError).toBe(true);
255
- expect(result.content).toContain("query is required");
256
- });
257
-
258
- // ── Happy path ────────────────────────────────────────────────────
259
-
260
- test("returns valid result shape with Qdrant mocked empty", async () => {
261
- seedMemory();
262
-
263
- const result = await handleMemoryRecall(
264
- { query: "API design" },
265
- TEST_CONFIG,
266
- );
267
-
268
- // With Qdrant mocked empty, hybrid search returns nothing.
269
- // The handler should return a valid result shape with zero results.
270
- expect(result.isError).toBe(false);
271
- const parsed = parseResult(result.content);
272
- expect(typeof parsed.resultCount).toBe("number");
273
- expect(typeof parsed.text).toBe("string");
274
- });
275
-
276
- // ── Empty results ─────────────────────────────────────────────────
277
-
278
- test("returns empty result when no memories match", async () => {
279
- // No items seeded - tables cleared in beforeEach
280
- const result = await handleMemoryRecall(
281
- { query: "quantum physics" },
282
- TEST_CONFIG,
283
- );
284
-
285
- expect(result.isError).toBe(false);
286
- const parsed = parseResult(result.content);
287
- expect(parsed.resultCount).toBe(0);
288
- expect(parsed.text).toBe("No matching memories found.");
289
- expect(parsed.sources.semantic).toBe(0);
290
- expect(parsed.sources.recency).toBe(0);
291
- });
292
-
293
- // ── Degraded mode ─────────────────────────────────────────────────
294
-
295
- test("returns results with degraded=true when embeddings required but unavailable", async () => {
296
- seedMemory();
297
-
298
- // When embeddings are required but no provider is available,
299
- // the handler reports degraded=true
300
- const degradedConfig: AssistantConfig = {
301
- ...TEST_CONFIG,
302
- memory: {
303
- ...TEST_CONFIG.memory,
304
- embeddings: {
305
- ...TEST_CONFIG.memory.embeddings,
306
- provider: "none" as never,
307
- required: true,
308
- },
309
- },
310
- };
311
-
312
- const result = await handleMemoryRecall(
313
- { query: "API design" },
314
- degradedConfig,
315
- );
316
-
317
- expect(result.isError).toBe(false);
318
- const parsed = parseResult(result.content);
319
- expect(parsed.degraded).toBe(true);
320
- expect(parsed.sources.semantic).toBe(0);
321
- });
322
-
323
- test("returns results with degraded=false when embeddings optional and unavailable", async () => {
324
- seedMemory();
325
-
326
- // When embeddings are not required and no provider is available,
327
- // the handler gracefully continues without degradation
328
- const optionalEmbeddingsConfig: AssistantConfig = {
329
- ...TEST_CONFIG,
330
- memory: {
331
- ...TEST_CONFIG.memory,
332
- embeddings: {
333
- ...TEST_CONFIG.memory.embeddings,
334
- provider: "none" as never,
335
- required: false,
336
- },
337
- },
338
- };
339
-
340
- const result = await handleMemoryRecall(
341
- { query: "API design" },
342
- optionalEmbeddingsConfig,
343
- );
344
-
345
- expect(result.isError).toBe(false);
346
- const parsed = parseResult(result.content);
347
- // Not degraded because embeddings are optional
348
- expect(parsed.degraded).toBe(false);
349
- expect(parsed.sources.semantic).toBe(0);
350
- // Qdrant is mocked empty so hybrid search returns no candidates, but
351
- // serendipity sampling may pick up seeded items from the DB directly.
352
- expect(typeof parsed.resultCount).toBe("number");
353
- });
354
-
355
- test("gracefully returns empty in degraded mode without embeddings", async () => {
356
- seedMemory();
357
-
358
- const degradedConfig: AssistantConfig = {
359
- ...TEST_CONFIG,
360
- memory: {
361
- ...TEST_CONFIG.memory,
362
- embeddings: {
363
- ...TEST_CONFIG.memory.embeddings,
364
- provider: "none" as never,
365
- required: false,
366
- },
367
- },
368
- };
369
-
370
- const result = await handleMemoryRecall(
371
- { query: "API design" },
372
- degradedConfig,
373
- );
374
-
375
- expect(result.isError).toBe(false);
376
- const parsed = parseResult(result.content);
377
- // With FTS removed and Qdrant mocked, no retrieval path finds items.
378
- // The handler returns a valid empty result without throwing.
379
- expect(typeof parsed.resultCount).toBe("number");
380
- });
381
-
382
- // ── Scope filtering ───────────────────────────────────────────────
383
-
384
- test("scope 'conversation' passes scope policy override to retriever", async () => {
385
- // Seed a conversation with segments in the target scope and in a different
386
- // scope. With scope="conversation", only the target scope's segments should
387
- // be returned (fallbackToDefault=false).
388
- const db = getDb();
389
- const now = Date.now();
390
- const convId = "conv-scope-a";
391
-
392
- insertConversation(db, convId, now - 10_000);
393
- insertMessage(
394
- db,
395
- "msg-scope-a",
396
- convId,
397
- "user",
398
- "scoped data for conversation A",
399
- now - 5_000,
400
- );
401
-
402
- // Insert a segment scoped to this conversation's scope
403
- db.run(`
404
- INSERT INTO memory_segments (id, message_id, conversation_id, role, segment_index, text, token_estimate, scope_id, created_at, updated_at)
405
- VALUES ('seg-scope-a', 'msg-scope-a', '${convId}', 'user', 0, 'Conversation-scoped data for conversation A', 8, '${convId}', ${
406
- now - 5_000
407
- }, ${now - 5_000})
408
- `);
409
-
410
- // Insert an out-of-scope segment that should NOT be returned
411
- db.run(`
412
- INSERT INTO memory_segments (id, message_id, conversation_id, role, segment_index, text, token_estimate, scope_id, created_at, updated_at)
413
- VALUES ('seg-scope-other', 'msg-scope-a', '${convId}', 'user', 1, 'Out-of-scope data from a different scope', 8, 'other-scope', ${
414
- now - 5_000
415
- }, ${now - 5_000})
416
- `);
417
-
418
- const result = await handleMemoryRecall(
419
- { query: "data", scope: "conversation" },
420
- TEST_CONFIG,
421
- convId,
422
- convId,
423
- );
424
-
425
- expect(result.isError).toBe(false);
426
- const parsed = parseResult(result.content);
427
- // With Qdrant mocked empty, segments inserted directly into the DB are
428
- // not found via hybrid search. Verify the handler returns a valid result
429
- // shape without erroring — the scope policy is still passed through.
430
- expect(typeof parsed.resultCount).toBe("number");
431
- expect(typeof parsed.sources.recency).toBe("number");
432
- });
433
-
434
- test("default scope handler invocation does not error", async () => {
435
- const db = getDb();
436
- const now = Date.now();
437
-
438
- insertItem(db, {
439
- id: "item-fallback",
440
- kind: "identity",
441
- subject: "global knowledge",
442
- statement: "This global knowledge should be accessible from any scope",
443
- firstSeenAt: now - 10_000,
444
- scopeId: "default",
445
- });
446
-
447
- const result = await handleMemoryRecall(
448
- { query: "global knowledge" },
449
- TEST_CONFIG,
450
- "some-thread-id",
451
- );
452
-
453
- expect(result.isError).toBe(false);
454
- const parsed = parseResult(result.content);
455
- // With Qdrant mocked and no conversation segments, the retriever returns
456
- // empty. Handler should still return a valid result shape.
457
- expect(typeof parsed.resultCount).toBe("number");
458
- });
459
-
460
- // ── Result shape ─────────────────────────────────────────────────
461
-
462
- test("result shape matches MemoryRecallToolResult when successful", async () => {
463
- seedMemory();
464
-
465
- const result = await handleMemoryRecall(
466
- { query: "API design" },
467
- TEST_CONFIG,
468
- );
469
-
470
- expect(result.isError).toBe(false);
471
- const parsed = parseResult(result.content);
472
-
473
- // Verify the result shape has all expected fields
474
- expect(typeof parsed.text).toBe("string");
475
- expect(typeof parsed.resultCount).toBe("number");
476
- expect(typeof parsed.degraded).toBe("boolean");
477
- expect(typeof parsed.sources).toBe("object");
478
- expect(typeof parsed.sources.semantic).toBe("number");
479
- expect(typeof parsed.sources.recency).toBe("number");
480
- });
481
-
482
- test("empty result shape matches MemoryRecallToolResult", async () => {
483
- const result = await handleMemoryRecall(
484
- { query: "nonexistent topic xyz123" },
485
- TEST_CONFIG,
486
- );
487
-
488
- expect(result.isError).toBe(false);
489
- const parsed = parseResult(result.content);
490
-
491
- expect(parsed.text).toBe("No matching memories found.");
492
- expect(parsed.resultCount).toBe(0);
493
- expect(typeof parsed.degraded).toBe("boolean");
494
- expect(parsed.sources.semantic).toBe(0);
495
- expect(parsed.sources.recency).toBe(0);
496
- });
497
-
498
- // ── Source conversation info ───────────────────────────────────────
499
- // These tests must come after normal tests and before the error test,
500
- // because mock.module replaces the retriever for all subsequent imports.
501
-
502
- test("items include sourceConversationTitle when sourceLabel is present", async () => {
503
- mock.module("../../memory/retriever.js", () => ({
504
- buildMemoryRecall: async () => ({
505
- injectedText: "<memory>test memory</memory>",
506
- selectedCount: 2,
507
- semanticHits: 2,
508
- degraded: false,
509
- topCandidates: [
510
- {
511
- key: "item:abc-1",
512
- type: "item",
513
- kind: "preference",
514
- id: "abc-1",
515
- sourceLabel: "API Design Discussion",
516
- },
517
- { key: "item:abc-2", type: "item", kind: "identity", id: "abc-2" },
518
- ],
519
- }),
520
- }));
521
-
522
- const { handleMemoryRecall: recallWithLabels } =
523
- await import("./handlers.js");
524
-
525
- const result = await recallWithLabels({ query: "test" }, TEST_CONFIG);
526
- expect(result.isError).toBe(false);
527
-
528
- const parsed = parseResult(result.content);
529
- expect(parsed.items).toHaveLength(2);
530
-
531
- // First item has a sourceLabel -> should have sourceConversationTitle
532
- expect(parsed.items[0].sourceConversationTitle).toBe(
533
- "API Design Discussion",
534
- );
535
-
536
- // Second item has no sourceLabel -> should not have sourceConversationTitle
537
- expect(parsed.items[1].sourceConversationTitle).toBeUndefined();
538
- });
539
-
540
- // ── Error handling ────────────────────────────────────────────────
541
- // This test must be last: mock.module replaces the retriever for all
542
- // subsequent imports and cannot be cleanly reverted within the same
543
- // test file.
544
-
545
- test("retrieval failure returns error message, does not throw", async () => {
546
- mock.module("../../memory/retriever.js", () => ({
547
- buildMemoryRecall: async () => {
548
- throw new Error("Simulated retrieval failure");
549
- },
550
- }));
551
-
552
- const { handleMemoryRecall: recallWithMock } =
553
- await import("./handlers.js");
554
-
555
- const result = await recallWithMock({ query: "test query" }, TEST_CONFIG);
556
-
557
- // The handler should catch the error and return an error result,
558
- // never throw
559
- expect(result.isError).toBe(true);
560
- expect(result.content).toContain("Simulated retrieval failure");
561
- });
562
- });