@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
@@ -0,0 +1,295 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Memory Graph — Core type definitions
3
+ // ---------------------------------------------------------------------------
4
+
5
+ /** Classification of what kind of memory a node represents. */
6
+ export type MemoryType =
7
+ | "episodic" // specific moments, conversations, events
8
+ | "semantic" // facts, knowledge, understanding
9
+ | "procedural" // learned skills, how-to knowledge
10
+ | "emotional" // feelings attached to memories
11
+ | "prospective" // future-oriented, things to remember to do
12
+ | "behavioral" // things that change how the assistant acts going forward
13
+ | "narrative" // the story a memory becomes over time
14
+ | "shared"; // memories that belong to a relationship, not either party
15
+
16
+ /** How detailed the memory is — degrades over time via consolidation. */
17
+ export type Fidelity = "vivid" | "clear" | "faded" | "gist" | "gone";
18
+
19
+ /** Shape of emotional intensity decay over time. */
20
+ export type DecayCurve =
21
+ | "linear" // constant rate of decay
22
+ | "logarithmic" // sharp initial drop, long tail (negative events)
23
+ | "transformative" // feeling changes shape, not just intensity (positive milestones)
24
+ | "permanent"; // no decay (core identity markers)
25
+
26
+ /** How the memory was originally acquired. */
27
+ export type SourceType =
28
+ | "direct" // user explicitly stated it
29
+ | "inferred" // assistant derived it from context
30
+ | "observed" // assistant noticed a pattern
31
+ | "told-by-other"; // third party provided it
32
+
33
+ /** Reference to an image stored in a conversation message. */
34
+ export interface ImageRef {
35
+ /** Message ID containing the image. */
36
+ messageId: string;
37
+ /** Index of the image ContentBlock within the message's content array. */
38
+ blockIndex: number;
39
+ /** LLM-generated description of what the image shows. */
40
+ description: string;
41
+ /** MIME type (image/png, image/jpeg, etc). */
42
+ mimeType: string;
43
+ }
44
+
45
+ /** Emotional charge attached to a memory — decays independently from the memory itself. */
46
+ export interface EmotionalCharge {
47
+ /** Positive vs negative sentiment (-1 to 1). */
48
+ valence: number;
49
+ /** Current emotional intensity (0 to 1). Decays per the curve. */
50
+ intensity: number;
51
+ /** Shape of the decay function. */
52
+ decayCurve: DecayCurve;
53
+ /** Rate parameter for decay (higher = faster). */
54
+ decayRate: number;
55
+ /** What the intensity was when the memory was created. */
56
+ originalIntensity: number;
57
+ }
58
+
59
+ // ---------------------------------------------------------------------------
60
+ // Graph primitives
61
+ // ---------------------------------------------------------------------------
62
+
63
+ export interface MemoryNode {
64
+ id: string;
65
+
66
+ /** First-person prose — how the assistant naturally remembers this. */
67
+ content: string;
68
+ type: MemoryType;
69
+
70
+ // -- Temporal --
71
+ /** Epoch ms when the memory was created. Hour/day/month are derived at query time. */
72
+ created: number;
73
+ /** Epoch ms — used ONLY as a decay-rate modifier, NOT a retrieval signal. */
74
+ lastAccessed: number;
75
+ /** Epoch ms of last consolidation pass that touched this node. */
76
+ lastConsolidated: number;
77
+ /** Epoch ms of the event this memory describes (null for non-event memories). */
78
+ eventDate: number | null;
79
+
80
+ // -- Energy --
81
+ emotionalCharge: EmotionalCharge;
82
+ fidelity: Fidelity;
83
+ /** How sure the assistant is this memory is accurate (0–1). */
84
+ confidence: number;
85
+ /** How important this memory is (0–1). Subject to Ebbinghaus decay. */
86
+ significance: number;
87
+
88
+ // -- Reinforcement (Ebbinghaus forgetting curve) --
89
+ /** Resistance to significance decay. Grows with reinforcement (×1.5 per reinforcement). */
90
+ stability: number;
91
+ /** How many times this memory has been confirmed/reinforced. */
92
+ reinforcementCount: number;
93
+ /** Epoch ms of last reinforcement event. */
94
+ lastReinforced: number;
95
+
96
+ // -- Provenance --
97
+ /** Conversation IDs that contributed to this memory. */
98
+ sourceConversations: string[];
99
+ sourceType: SourceType;
100
+
101
+ // -- Narrative --
102
+ /** Role in a larger story arc (e.g. "turning-point", "foreshadowing"). */
103
+ narrativeRole: string | null;
104
+ /** Which story arc this belongs to. */
105
+ partOfStory: string | null;
106
+
107
+ /** Image references attached to this memory (null if text-only). */
108
+ imageRefs: ImageRef[] | null;
109
+
110
+ /** Memory scope for multi-scope isolation. */
111
+ scopeId: string;
112
+ }
113
+
114
+ /**
115
+ * Whether a node is an auto-seeded capability (skill or CLI command) rather
116
+ * than an organically-extracted procedural memory. Capability nodes are
117
+ * created by the seeding systems at startup; organic procedural nodes are
118
+ * extracted from conversations (e.g. "FFmpeg needs -ac 2 for stereo").
119
+ *
120
+ * Only capability nodes should be reserved/excluded from normal retrieval
121
+ * and consolidation — organic procedural nodes participate normally.
122
+ */
123
+ export function isCapabilityNode(node: MemoryNode): boolean {
124
+ if (node.type !== "procedural") return false;
125
+ // Old seeding systems: content starts with "skill:{id}\n" or "cli:{name}\n"
126
+ if (node.content.startsWith("skill:") || node.content.startsWith("cli:"))
127
+ return true;
128
+ // New seeding system (capability-seed.ts): content matches
129
+ // 'The "{name}" skill ({id}) is available.' or
130
+ // 'The "assistant {name}" CLI command is available.'
131
+ if (
132
+ node.content.startsWith('The "') &&
133
+ node.content.includes(" is available.")
134
+ ) {
135
+ return true;
136
+ }
137
+ return false;
138
+ }
139
+
140
+ /** Relationship type between two memory nodes. */
141
+ export type EdgeRelationship =
142
+ | "caused-by"
143
+ | "reminds-of"
144
+ | "contradicts"
145
+ | "depends-on"
146
+ | "part-of"
147
+ | "supersedes"
148
+ | "resolved-by";
149
+
150
+ export interface MemoryEdge {
151
+ id: string;
152
+ sourceNodeId: string;
153
+ targetNodeId: string;
154
+ relationship: EdgeRelationship;
155
+ /** Connection strength (0–1). */
156
+ weight: number;
157
+ /** Epoch ms. */
158
+ created: number;
159
+ }
160
+
161
+ /** Trigger type determines how the trigger condition is evaluated. */
162
+ export type TriggerType = "temporal" | "semantic" | "event";
163
+
164
+ export interface MemoryTrigger {
165
+ id: string;
166
+ /** Which memory node this trigger belongs to. */
167
+ nodeId: string;
168
+ type: TriggerType;
169
+
170
+ // -- Temporal triggers --
171
+ /** Cron-like pattern: "day-of-week:monday", "date:04-08", "time:morning". */
172
+ schedule: string | null;
173
+
174
+ // -- Semantic triggers --
175
+ /** Natural language condition: "user graduates", "topic of cooking comes up". */
176
+ condition: string | null;
177
+ /** Pre-computed embedding of the condition text for fast cosine similarity. */
178
+ conditionEmbedding: Float32Array | null;
179
+ /** Cosine similarity threshold to fire (0–1). */
180
+ threshold: number | null;
181
+
182
+ // -- Event triggers --
183
+ /** Epoch ms of the event date. */
184
+ eventDate: number | null;
185
+ /** Days before the event to start ramping relevance. */
186
+ rampDays: number | null;
187
+ /** Days after the event to maintain elevated relevance. */
188
+ followUpDays: number | null;
189
+
190
+ // -- State --
191
+ /** Whether this trigger fires repeatedly or is consumed on first fire. */
192
+ recurring: boolean;
193
+ /** Whether a one-shot trigger has already fired. */
194
+ consumed: boolean;
195
+ /** Minimum ms between firings for recurring triggers. */
196
+ cooldownMs: number | null;
197
+ /** Epoch ms of last firing. */
198
+ lastFired: number | null;
199
+ }
200
+
201
+ // ---------------------------------------------------------------------------
202
+ // Diff — the extraction/consolidation output format
203
+ // ---------------------------------------------------------------------------
204
+
205
+ /** A node to be created (id assigned by store). */
206
+ export type NewNode = Omit<MemoryNode, "id">;
207
+
208
+ /** Partial update to an existing node. */
209
+ export interface NodeUpdate {
210
+ id: string;
211
+ changes: Partial<Omit<MemoryNode, "id">>;
212
+ }
213
+
214
+ /** A new edge to create (id assigned by store). */
215
+ export type NewEdge = Omit<MemoryEdge, "id">;
216
+
217
+ /** A new trigger to create (id assigned by store). */
218
+ export type NewTrigger = Omit<MemoryTrigger, "id">;
219
+
220
+ /**
221
+ * The atomic diff that extraction/consolidation produces.
222
+ * Applied transactionally to the graph store.
223
+ */
224
+ export interface MemoryDiff {
225
+ createNodes: NewNode[];
226
+ updateNodes: NodeUpdate[];
227
+ deleteNodeIds: string[];
228
+ createEdges: NewEdge[];
229
+ deleteEdgeIds: string[];
230
+ createTriggers: NewTrigger[];
231
+ deleteTriggerIds: string[];
232
+ /** Node IDs that were reinforced (confirmed/validated) by this extraction. */
233
+ reinforceNodeIds: string[];
234
+ }
235
+
236
+ // ---------------------------------------------------------------------------
237
+ // Scored candidates — used by retrieval pipeline
238
+ // ---------------------------------------------------------------------------
239
+
240
+ export interface ScoredNode {
241
+ node: MemoryNode;
242
+ /** Combined retrieval score (higher = more relevant right now). */
243
+ score: number;
244
+ /** Breakdown of score components for debugging/inspection. */
245
+ scoreBreakdown: {
246
+ semanticSimilarity: number;
247
+ effectiveSignificance: number;
248
+ emotionalIntensity: number;
249
+ temporalBoost: number;
250
+ recencyBoost: number;
251
+ triggerBoost: number;
252
+ activationBoost: number;
253
+ };
254
+ }
255
+
256
+ // ---------------------------------------------------------------------------
257
+ // Retrieval Metrics
258
+ // ---------------------------------------------------------------------------
259
+
260
+ export interface RetrievalMetrics {
261
+ semanticHits: number;
262
+ mergedCount: number;
263
+ selectedCount: number;
264
+ tier1Count: number;
265
+ tier2Count: number;
266
+ hybridSearchLatencyMs: number;
267
+ sparseVectorUsed: boolean;
268
+ embeddingProvider: string | null;
269
+ embeddingModel: string | null;
270
+ queryContext: string | null;
271
+ topCandidates: Array<{
272
+ nodeId: string;
273
+ type: string;
274
+ score: number;
275
+ semanticSimilarity: number;
276
+ recencyBoost: number;
277
+ }>;
278
+ }
279
+
280
+ // ---------------------------------------------------------------------------
281
+ // Results
282
+ // ---------------------------------------------------------------------------
283
+
284
+ export interface ApplyDiffResult {
285
+ nodesCreated: number;
286
+ nodesUpdated: number;
287
+ nodesDeleted: number;
288
+ edgesCreated: number;
289
+ edgesDeleted: number;
290
+ triggersCreated: number;
291
+ triggersDeleted: number;
292
+ nodesReinforced: number;
293
+ /** IDs of newly created nodes (in order of diff.createNodes). */
294
+ createdNodeIds: string[];
295
+ }
@@ -0,0 +1,191 @@
1
+ /**
2
+ * CRUD operations for conversation groups.
3
+ *
4
+ * All functions call ensureGroupMigration() before any DB access
5
+ * to guarantee the conversation_groups table exists.
6
+ */
7
+
8
+ import { v4 as uuid } from "uuid";
9
+
10
+ import { ensureGroupMigration } from "./conversation-group-migration.js";
11
+ import { rawAll, rawExec, rawGet, rawRun } from "./db.js";
12
+
13
+ export interface ConversationGroupRow {
14
+ id: string;
15
+ name: string;
16
+ sortPosition: number;
17
+ isSystemGroup: boolean;
18
+ createdAt?: number;
19
+ updatedAt?: number;
20
+ }
21
+
22
+ // ---------------------------------------------------------------------------
23
+ // List
24
+ // ---------------------------------------------------------------------------
25
+
26
+ export function listGroups(): ConversationGroupRow[] {
27
+ ensureGroupMigration();
28
+ const rows = rawAll<{
29
+ id: string;
30
+ name: string;
31
+ sort_position: number;
32
+ is_system_group: number;
33
+ created_at: number;
34
+ updated_at: number;
35
+ }>(
36
+ "SELECT id, name, sort_position, is_system_group, created_at, updated_at FROM conversation_groups WHERE id != '_backfill_complete' ORDER BY sort_position ASC",
37
+ );
38
+ return rows.map((r) => ({
39
+ id: r.id,
40
+ name: r.name,
41
+ sortPosition: r.sort_position,
42
+ isSystemGroup: r.is_system_group === 1,
43
+ createdAt: r.created_at,
44
+ updatedAt: r.updated_at,
45
+ }));
46
+ }
47
+
48
+ // ---------------------------------------------------------------------------
49
+ // Get
50
+ // ---------------------------------------------------------------------------
51
+
52
+ export function getGroup(groupId: string): ConversationGroupRow | null {
53
+ ensureGroupMigration();
54
+ const row = rawGet<{
55
+ id: string;
56
+ name: string;
57
+ sort_position: number;
58
+ is_system_group: number;
59
+ created_at: number;
60
+ updated_at: number;
61
+ }>(
62
+ "SELECT id, name, sort_position, is_system_group, created_at, updated_at FROM conversation_groups WHERE id = ?",
63
+ groupId,
64
+ );
65
+ if (!row) return null;
66
+ return {
67
+ id: row.id,
68
+ name: row.name,
69
+ sortPosition: row.sort_position,
70
+ isSystemGroup: row.is_system_group === 1,
71
+ createdAt: row.created_at,
72
+ updatedAt: row.updated_at,
73
+ };
74
+ }
75
+
76
+ // ---------------------------------------------------------------------------
77
+ // Create
78
+ // ---------------------------------------------------------------------------
79
+
80
+ /**
81
+ * Create a custom group. Server assigns sort_position as max(custom) + 1.
82
+ * System groups occupy positions 0 (pinned), 1 (scheduled), 2 (background).
83
+ * First custom group gets position 3. Fallback ?? 2 ensures 2 + 1 = 3 when
84
+ * no custom groups exist.
85
+ */
86
+ export function createGroup(name: string): ConversationGroupRow {
87
+ ensureGroupMigration();
88
+ const maxPos =
89
+ rawGet<{ max: number | null }>(
90
+ "SELECT MAX(sort_position) as max FROM conversation_groups WHERE is_system_group = 0",
91
+ )?.max ?? 2;
92
+ const sortPosition = maxPos + 1;
93
+ const id = uuid();
94
+ const now = Math.floor(Date.now() / 1000);
95
+ rawRun(
96
+ "INSERT INTO conversation_groups (id, name, sort_position, is_system_group, created_at, updated_at) VALUES (?, ?, ?, 0, ?, ?)",
97
+ id,
98
+ name,
99
+ sortPosition,
100
+ now,
101
+ now,
102
+ );
103
+ return {
104
+ id,
105
+ name,
106
+ sortPosition,
107
+ isSystemGroup: false,
108
+ createdAt: now,
109
+ updatedAt: now,
110
+ };
111
+ }
112
+
113
+ // ---------------------------------------------------------------------------
114
+ // Update
115
+ // ---------------------------------------------------------------------------
116
+
117
+ export function updateGroup(
118
+ groupId: string,
119
+ updates: { name?: string; sortPosition?: number },
120
+ ): ConversationGroupRow | null {
121
+ ensureGroupMigration();
122
+ const existing = getGroup(groupId);
123
+ if (!existing) return null;
124
+
125
+ const fields: string[] = [];
126
+ const values: (string | number)[] = [];
127
+
128
+ if (updates.name !== undefined) {
129
+ fields.push("name = ?");
130
+ values.push(updates.name);
131
+ }
132
+ if (updates.sortPosition !== undefined) {
133
+ fields.push("sort_position = ?");
134
+ values.push(updates.sortPosition);
135
+ }
136
+
137
+ if (fields.length === 0) return existing;
138
+
139
+ fields.push("updated_at = ?");
140
+ const now = Math.floor(Date.now() / 1000);
141
+ values.push(now);
142
+ values.push(groupId);
143
+
144
+ rawRun(
145
+ `UPDATE conversation_groups SET ${fields.join(", ")} WHERE id = ?`,
146
+ ...values,
147
+ );
148
+
149
+ return getGroup(groupId);
150
+ }
151
+
152
+ // ---------------------------------------------------------------------------
153
+ // Delete
154
+ // ---------------------------------------------------------------------------
155
+
156
+ // Relies on PRAGMA foreign_keys = ON (set at connection time) so that
157
+ // ON DELETE SET NULL fires and clears group_id on conversations when
158
+ // a group is deleted. If FK enforcement is ever disabled, orphaned
159
+ // group_id values would persist and conversations would appear in a
160
+ // non-existent group.
161
+ export function deleteGroup(groupId: string): boolean {
162
+ ensureGroupMigration();
163
+ rawRun("DELETE FROM conversation_groups WHERE id = ?", groupId);
164
+ return true;
165
+ }
166
+
167
+ // ---------------------------------------------------------------------------
168
+ // Reorder
169
+ // ---------------------------------------------------------------------------
170
+
171
+ export function reorderGroups(
172
+ updates: Array<{ groupId: string; sortPosition: number }>,
173
+ ): void {
174
+ ensureGroupMigration();
175
+ const now = Math.floor(Date.now() / 1000);
176
+ rawExec("BEGIN");
177
+ try {
178
+ for (const update of updates) {
179
+ rawRun(
180
+ "UPDATE conversation_groups SET sort_position = ?, updated_at = ? WHERE id = ?",
181
+ update.sortPosition,
182
+ now,
183
+ update.groupId,
184
+ );
185
+ }
186
+ rawExec("COMMIT");
187
+ } catch (err) {
188
+ rawExec("ROLLBACK");
189
+ throw err;
190
+ }
191
+ }
@@ -149,33 +149,47 @@ export async function indexMessageNow(
149
149
  tx,
150
150
  );
151
151
  }
152
-
153
152
  });
154
153
 
155
154
  // ── Batch extraction tracking ──────────────────────────────────────
156
155
  // Instead of per-message extraction, track pending unextracted messages
157
156
  // and trigger batch extraction when the threshold is reached or after idle.
158
- if (shouldExtract && isTrustedActor && !input.automated && config.extraction.useLLM) {
159
- const pendingKey = `batch_extract:${input.conversationId}:pending_count`;
160
- const currentVal = getMemoryCheckpoint(pendingKey);
161
- const pendingCount = (currentVal ? parseInt(currentVal, 10) : 0) + 1;
162
- setMemoryCheckpoint(pendingKey, String(pendingCount));
163
-
157
+ if (
158
+ shouldExtract &&
159
+ isTrustedActor &&
160
+ !input.automated &&
161
+ config.extraction.useLLM
162
+ ) {
164
163
  const batchSize = config.extraction.batchSize ?? 10;
165
164
  const idleTimeoutMs = config.extraction.idleTimeoutMs ?? 300_000;
166
165
 
167
- if (pendingCount >= batchSize) {
168
- // Threshold reached — trigger immediate batch extraction
169
- enqueueMemoryJob("batch_extract", {
166
+ // ── Graph extraction ────────────────────────────────────────────
167
+ const graphPendingKey = `graph_extract:${input.conversationId}:pending_count`;
168
+ const graphCurrentVal = getMemoryCheckpoint(graphPendingKey);
169
+ const graphPendingCount =
170
+ (graphCurrentVal ? parseInt(graphCurrentVal, 10) : 0) + 1;
171
+ setMemoryCheckpoint(graphPendingKey, String(graphPendingCount));
172
+
173
+ if (graphPendingCount >= batchSize) {
174
+ enqueueMemoryJob("graph_extract", {
170
175
  conversationId: input.conversationId,
171
176
  scopeId: input.scopeId ?? "default",
172
177
  });
178
+ setMemoryCheckpoint(graphPendingKey, "0");
173
179
  }
174
180
 
175
- // Also maintain idle debounce: enqueue a delayed batch_extract that fires
176
- // if no new messages arrive within the idle timeout window.
177
181
  upsertDebouncedJob(
178
- "batch_extract",
182
+ "graph_extract",
183
+ { conversationId: input.conversationId },
184
+ Date.now() + idleTimeoutMs,
185
+ );
186
+
187
+ // ── Conversation summarization (independent of extraction) ────────
188
+ // Summaries feed the graph retrieval pipeline via fetchRecentSummaries().
189
+ // Debounced on the same idle timeout — no threshold trigger needed since
190
+ // summaries compress the whole conversation, not incremental batches.
191
+ upsertDebouncedJob(
192
+ "build_conversation_summary",
179
193
  { conversationId: input.conversationId },
180
194
  Date.now() + idleTimeoutMs,
181
195
  );
@@ -203,15 +217,19 @@ export async function indexMessageNow(
203
217
  log.info("Skipping extraction jobs for automated message");
204
218
  }
205
219
 
206
- if (!config.extraction.useLLM && shouldExtract && isTrustedActor && !input.automated) {
207
- log.info("Skipping extraction job: LLM extraction is disabled (useLLM=false)");
220
+ if (
221
+ !config.extraction.useLLM &&
222
+ shouldExtract &&
223
+ isTrustedActor &&
224
+ !input.automated
225
+ ) {
226
+ log.info(
227
+ "Skipping extraction job: LLM extraction is disabled (useLLM=false)",
228
+ );
208
229
  }
209
230
 
210
231
  const storedSegments = segments.length - skippedShortSegments;
211
- const enqueuedJobs =
212
- storedSegments -
213
- skippedEmbedJobs +
214
- mediaBlocks.length;
232
+ const enqueuedJobs = storedSegments - skippedEmbedJobs + mediaBlocks.length;
215
233
  return {
216
234
  indexedSegments: storedSegments,
217
235
  enqueuedJobs,
@@ -1,65 +1,55 @@
1
- import { and, asc, eq, inArray, lt } from "drizzle-orm";
2
-
3
1
  import type { AssistantConfig } from "../../config/types.js";
4
2
  import { getLogger } from "../../util/logger.js";
5
- import { getDb, rawAll, rawRun } from "../db.js";
6
- import { asPositiveMs } from "../job-utils.js";
3
+ import { getDb, rawAll, rawChanges, rawRun } from "../db.js";
7
4
  import { enqueueMemoryJob, type MemoryJob } from "../jobs-store.js";
8
- import { memoryEmbeddings, memoryItems } from "../schema.js";
9
5
 
10
6
  const log = getLogger("memory-jobs-worker");
11
7
 
12
- const CLEANUP_BATCH_LIMIT = 250;
8
+ const PRUNE_BATCH_LIMIT = 100;
9
+ const PRUNE_LOG_BATCH_LIMIT = 1000;
13
10
 
14
- export function cleanupStaleSupersededItemsJob(
11
+ /**
12
+ * Delete LLM request/response logs older than the configured retention period.
13
+ * Processes in batches to avoid long DB locks and excessive WAL growth.
14
+ * Re-enqueues itself if more rows remain.
15
+ */
16
+ export function pruneOldLlmRequestLogsJob(
15
17
  job: MemoryJob,
16
18
  config: AssistantConfig,
17
19
  ): void {
18
- const db = getDb();
19
20
  const retentionMs =
20
- asPositiveMs(job.payload.retentionMs) ??
21
- config.memory.cleanup.supersededItemRetentionMs;
22
- const cutoff = Date.now() - retentionMs;
23
- const stale = db
24
- .select({ id: memoryItems.id })
25
- .from(memoryItems)
26
- .where(
27
- and(
28
- eq(memoryItems.status, "superseded"),
29
- lt(memoryItems.invalidAt, cutoff),
30
- ),
31
- )
32
- .orderBy(asc(memoryItems.invalidAt), asc(memoryItems.id))
33
- .limit(CLEANUP_BATCH_LIMIT)
34
- .all();
35
- if (stale.length === 0) return;
21
+ typeof job.payload.retentionMs === "number" &&
22
+ Number.isFinite(job.payload.retentionMs) &&
23
+ job.payload.retentionMs >= 0
24
+ ? job.payload.retentionMs
25
+ : config.memory.cleanup.llmRequestLogRetentionMs;
26
+
27
+ // 0 means disabled
28
+ if (retentionMs === 0) return;
36
29
 
37
- const ids = stale.map((row) => row.id);
38
- db.delete(memoryEmbeddings)
39
- .where(
40
- and(
41
- eq(memoryEmbeddings.targetType, "item"),
42
- inArray(memoryEmbeddings.targetId, ids),
43
- ),
44
- )
45
- .run();
46
- db.delete(memoryItems).where(inArray(memoryItems.id, ids)).run();
47
- if (stale.length === CLEANUP_BATCH_LIMIT) {
48
- enqueueMemoryJob("cleanup_stale_superseded_items", { retentionMs });
30
+ const cutoffMs = Date.now() - retentionMs;
31
+
32
+ rawRun(
33
+ `DELETE FROM llm_request_logs WHERE rowid IN (SELECT rowid FROM llm_request_logs WHERE created_at < ? LIMIT ?)`,
34
+ cutoffMs,
35
+ PRUNE_LOG_BATCH_LIMIT,
36
+ );
37
+ const deleted = rawChanges();
38
+
39
+ if (deleted >= PRUNE_LOG_BATCH_LIMIT) {
40
+ enqueueMemoryJob("prune_old_llm_request_logs", { retentionMs });
49
41
  }
50
42
 
51
- log.debug(
43
+ log.info(
52
44
  {
53
- removedItems: stale.length,
45
+ deleted,
54
46
  retentionMs,
55
- cutoff,
47
+ cutoffMs,
56
48
  },
57
- "Cleaned up stale superseded memory items",
49
+ "Pruned old LLM request logs",
58
50
  );
59
51
  }
60
52
 
61
- const PRUNE_BATCH_LIMIT = 100;
62
-
63
53
  /**
64
54
  * Delete conversations that have had no activity (updatedAt) for longer than
65
55
  * the configured retention period. Processes in batches so a single job doesn't