@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
@@ -5,7 +5,7 @@
5
5
  * suggestion chips shown on the empty conversation page.
6
6
  */
7
7
 
8
- import { and, desc, eq } from "drizzle-orm";
8
+ import { and, desc, eq, sql } from "drizzle-orm";
9
9
  import { v4 as uuid } from "uuid";
10
10
 
11
11
  import { loadSkillCatalog } from "../../config/skills.js";
@@ -26,7 +26,7 @@ import { rawAll, rawGet } from "../raw-query.js";
26
26
  import {
27
27
  conversationStarters,
28
28
  memoryCheckpoints,
29
- memoryItems,
29
+ memoryGraphNodes,
30
30
  } from "../schema.js";
31
31
 
32
32
  const log = getLogger("conversation-starters-gen");
@@ -42,32 +42,47 @@ const CK_LAST_GEN_AT = "conversation_starters:last_gen_at";
42
42
  // ── Rollup construction ───────────────────────────────────────────
43
43
 
44
44
  export function buildMemoryRollup(scopeId: string): string {
45
- const db = getDb();
46
- const items = db
47
- .select({
48
- kind: memoryItems.kind,
49
- subject: memoryItems.subject,
50
- statement: memoryItems.statement,
51
- importance: memoryItems.importance,
52
- })
53
- .from(memoryItems)
54
- .where(
55
- and(eq(memoryItems.status, "active"), eq(memoryItems.scopeId, scopeId)),
56
- )
57
- .orderBy(desc(memoryItems.importance))
58
- .limit(60)
59
- .all();
60
-
61
- if (items.length === 0) return "";
45
+ let rows: Array<{
46
+ type: string;
47
+ content: string;
48
+ significance: number | null;
49
+ }>;
50
+ try {
51
+ const db = getDb();
52
+ rows = db
53
+ .select({
54
+ type: memoryGraphNodes.type,
55
+ content: memoryGraphNodes.content,
56
+ significance: memoryGraphNodes.significance,
57
+ })
58
+ .from(memoryGraphNodes)
59
+ .where(
60
+ and(
61
+ sql`${memoryGraphNodes.fidelity} != 'gone'`,
62
+ eq(memoryGraphNodes.scopeId, scopeId),
63
+ )
64
+ )
65
+ .orderBy(desc(memoryGraphNodes.significance))
66
+ .limit(60)
67
+ .all();
68
+ } catch {
69
+ // Table may have been dropped (migration 203)
70
+ return "";
71
+ }
72
+
73
+ if (rows.length === 0) return "";
62
74
 
63
75
  const byKind = new Map<string, string[]>();
64
- for (const item of items) {
65
- let lines = byKind.get(item.kind);
76
+ for (const item of rows) {
77
+ const nl = item.content.indexOf("\n");
78
+ const subject = nl >= 0 ? item.content.slice(0, nl) : item.content;
79
+ const statement = nl >= 0 ? item.content.slice(nl + 1) : item.content;
80
+ let lines = byKind.get(item.type);
66
81
  if (!lines) {
67
82
  lines = [];
68
- byKind.set(item.kind, lines);
83
+ byKind.set(item.type, lines);
69
84
  }
70
- lines.push(`- ${item.subject}: ${item.statement}`);
85
+ lines.push(`- ${subject}: ${statement}`);
71
86
  }
72
87
 
73
88
  let rollup = "";
@@ -90,21 +105,25 @@ function buildNewItemsDiff(scopeId: string): string {
90
105
 
91
106
  const newItems = rawAll<{
92
107
  kind: string;
93
- subject: string;
94
- statement: string;
108
+ content: string;
95
109
  }>(
96
- `SELECT kind, subject, statement FROM memory_items
97
- WHERE status = 'active' AND scope_id = ? AND first_seen_at > ?
98
- ORDER BY first_seen_at DESC LIMIT 20`,
110
+ `SELECT type AS kind, content FROM memory_graph_nodes
111
+ WHERE fidelity != 'gone' AND scope_id = ? AND created > ?
112
+ ORDER BY created DESC LIMIT 20`,
99
113
  scopeId,
100
- lastGenAt,
114
+ lastGenAt
101
115
  );
102
116
 
103
117
  if (newItems.length === 0) return "";
104
118
 
105
119
  return (
106
120
  "## New since last generation\n" +
107
- newItems.map((i) => `- (${i.kind}) ${i.subject}: ${i.statement}`).join("\n")
121
+ newItems.map((i) => {
122
+ const nl = i.content.indexOf("\n");
123
+ const subject = nl >= 0 ? i.content.slice(0, nl) : i.content;
124
+ const statement = nl >= 0 ? i.content.slice(nl + 1) : i.content;
125
+ return `- (${i.kind}) ${subject}: ${statement}`;
126
+ }).join("\n")
108
127
  );
109
128
  }
110
129
 
@@ -143,8 +162,7 @@ export const CONVERSATION_STARTER_CATEGORIES = [
143
162
  "integration",
144
163
  ] as const;
145
164
 
146
- export type ConversationStarterCategory =
147
- (typeof CONVERSATION_STARTER_CATEGORIES)[number];
165
+ export type ConversationStarterCategory = typeof CONVERSATION_STARTER_CATEGORIES[number];
148
166
 
149
167
  interface GeneratedStarter {
150
168
  label: string;
@@ -168,7 +186,15 @@ async function generateStarters(scopeId: string): Promise<GeneratedStarter[]> {
168
186
  const skills = buildSkillsSummary();
169
187
 
170
188
  const now = new Date();
171
- const timeContext = `Current time: ${now.toLocaleString("en-US", { weekday: "long", year: "numeric", month: "long", day: "numeric", hour: "numeric", minute: "2-digit", hour12: true })}`;
189
+ const timeContext = `Current time: ${now.toLocaleString("en-US", {
190
+ weekday: "long",
191
+ year: "numeric",
192
+ month: "long",
193
+ day: "numeric",
194
+ hour: "numeric",
195
+ minute: "2-digit",
196
+ hour12: true,
197
+ })}`;
172
198
 
173
199
  // Truncate identity context to prevent oversized prompts when SOUL.md /
174
200
  // IDENTITY.md / USER.md are large.
@@ -185,7 +211,11 @@ ${timeContext}
185
211
 
186
212
  Your goal: suggest the 4 most useful things this person could ask you to do right now.
187
213
 
188
- ${identityContext ? `## Assistant identity & user profile\n\n${identityContext}\n\n` : ""}## What you know
214
+ ${
215
+ identityContext
216
+ ? `## Assistant identity & user profile\n\n${identityContext}\n\n`
217
+ : ""
218
+ }## What you know
189
219
 
190
220
  ${rollup}
191
221
  ${diff}
@@ -253,7 +283,7 @@ Bad → Good (assistant voice → user voice):
253
283
  const response = await provider.sendMessage(
254
284
  [
255
285
  userMessage(
256
- "Generate personalized conversation starters based on my context.",
286
+ "Generate personalized conversation starters based on my context."
257
287
  ),
258
288
  ],
259
289
  [
@@ -303,14 +333,14 @@ Bad → Good (assistant voice → user voice):
303
333
  },
304
334
  },
305
335
  signal,
306
- },
336
+ }
307
337
  );
308
338
  cleanup();
309
339
 
310
340
  const toolBlock = extractToolUse(response);
311
341
  if (!toolBlock) {
312
342
  log.warn(
313
- "No tool_use block in conversation starters generation response",
343
+ "No tool_use block in conversation starters generation response"
314
344
  );
315
345
  return [];
316
346
  }
@@ -327,7 +357,7 @@ Bad → Good (assistant voice → user voice):
327
357
  typeof s.label === "string" &&
328
358
  s.label.length > 0 &&
329
359
  typeof s.prompt === "string" &&
330
- s.prompt.length > 0,
360
+ s.prompt.length > 0
331
361
  )
332
362
  .slice(0, 4)
333
363
  .map((s) => ({
@@ -336,7 +366,7 @@ Bad → Good (assistant voice → user voice):
336
366
  category:
337
367
  typeof s.category === "string" &&
338
368
  (CONVERSATION_STARTER_CATEGORIES as readonly string[]).includes(
339
- s.category,
369
+ s.category
340
370
  )
341
371
  ? s.category
342
372
  : "productivity",
@@ -350,7 +380,7 @@ Bad → Good (assistant voice → user voice):
350
380
  // ── Job handler ───────────────────────────────────────────────────
351
381
 
352
382
  export async function generateConversationStartersJob(
353
- job: MemoryJob,
383
+ job: MemoryJob
354
384
  ): Promise<void> {
355
385
  const scopeId = asString(job.payload.scopeId) ?? "default";
356
386
 
@@ -373,16 +403,24 @@ export async function generateConversationStartersJob(
373
403
  ? parseInt(batchCheckpoint.value, 10) + 1
374
404
  : 1;
375
405
 
376
- // Collect the memory kinds that informed this batch
377
- const kindRows = db
378
- .select({ kind: memoryItems.kind })
379
- .from(memoryItems)
380
- .where(
381
- and(eq(memoryItems.status, "active"), eq(memoryItems.scopeId, scopeId)),
382
- )
383
- .groupBy(memoryItems.kind)
384
- .all();
385
- const sourceKinds = kindRows.map((r) => r.kind).join(",");
406
+ // Collect the memory types that informed this batch
407
+ let sourceKinds = "";
408
+ try {
409
+ const kindRows = db
410
+ .select({ kind: memoryGraphNodes.type })
411
+ .from(memoryGraphNodes)
412
+ .where(
413
+ and(
414
+ sql`${memoryGraphNodes.fidelity} != 'gone'`,
415
+ eq(memoryGraphNodes.scopeId, scopeId),
416
+ )
417
+ )
418
+ .groupBy(memoryGraphNodes.type)
419
+ .all();
420
+ sourceKinds = kindRows.map((r) => r.kind).join(",");
421
+ } catch {
422
+ // Table may have been dropped (migration 203)
423
+ }
386
424
 
387
425
  // Remove previous starters for this scope before inserting the new batch
388
426
  db.delete(conversationStarters)
@@ -408,8 +446,8 @@ export async function generateConversationStartersJob(
408
446
 
409
447
  // Count active items for checkpoint
410
448
  const countRow = rawGet<{ c: number }>(
411
- `SELECT COUNT(*) AS c FROM memory_items WHERE status = 'active' AND scope_id = ?`,
412
- scopeId,
449
+ `SELECT COUNT(*) AS c FROM memory_graph_nodes WHERE fidelity != 'gone' AND scope_id = ?`,
450
+ scopeId
413
451
  );
414
452
  const totalActive = countRow?.c ?? 0;
415
453
 
@@ -430,6 +468,6 @@ export async function generateConversationStartersJob(
430
468
 
431
469
  log.info(
432
470
  { scopeId, batch: nextBatch, count: starters.length },
433
- "Generated conversation starters",
471
+ "Generated conversation starters"
434
472
  );
435
473
  }
@@ -11,7 +11,6 @@ import type { MemoryJob } from "../jobs-store.js";
11
11
  import { extractMediaBlocks } from "../message-content.js";
12
12
  import {
13
13
  mediaAssets,
14
- memoryItems,
15
14
  memorySegments,
16
15
  memorySummaries,
17
16
  messages,
@@ -19,7 +18,7 @@ import {
19
18
 
20
19
  export async function embedSegmentJob(
21
20
  job: MemoryJob,
22
- config: AssistantConfig,
21
+ config: AssistantConfig
23
22
  ): Promise<void> {
24
23
  const segmentId = asString(job.payload.segmentId);
25
24
  if (!segmentId) return;
@@ -38,34 +37,9 @@ export async function embedSegmentJob(
38
37
  });
39
38
  }
40
39
 
41
- export async function embedItemJob(
42
- job: MemoryJob,
43
- config: AssistantConfig,
44
- ): Promise<void> {
45
- const itemId = asString(job.payload.itemId);
46
- if (!itemId) return;
47
- const db = getDb();
48
- const item = db
49
- .select()
50
- .from(memoryItems)
51
- .where(eq(memoryItems.id, itemId))
52
- .get();
53
- if (!item || item.status !== "active") return;
54
- const text = `<kind>${item.kind}</kind> ${item.subject}: ${item.statement}`;
55
- await embedAndUpsert(config, "item", item.id, text, {
56
- kind: item.kind,
57
- subject: item.subject,
58
- status: item.status,
59
- confidence: item.confidence,
60
- created_at: item.firstSeenAt,
61
- last_seen_at: item.lastSeenAt,
62
- memory_scope_id: item.scopeId,
63
- });
64
- }
65
-
66
40
  export async function embedSummaryJob(
67
41
  job: MemoryJob,
68
- config: AssistantConfig,
42
+ config: AssistantConfig
69
43
  ): Promise<void> {
70
44
  const summaryId = asString(job.payload.summaryId);
71
45
  if (!summaryId) return;
@@ -86,13 +60,13 @@ export async function embedSummaryJob(
86
60
  created_at: summary.startAt,
87
61
  last_seen_at: summary.endAt,
88
62
  memory_scope_id: summary.scopeId,
89
- },
63
+ }
90
64
  );
91
65
  }
92
66
 
93
67
  export async function embedMediaJob(
94
68
  job: MemoryJob,
95
- config: AssistantConfig,
69
+ config: AssistantConfig
96
70
  ): Promise<void> {
97
71
  const assetId = asString(job.payload.assetId);
98
72
  if (!assetId) return;
@@ -125,7 +99,7 @@ export async function embedMediaJob(
125
99
 
126
100
  export async function embedAttachmentJob(
127
101
  job: MemoryJob,
128
- config: AssistantConfig,
102
+ config: AssistantConfig
129
103
  ): Promise<void> {
130
104
  const messageId = asString(job.payload.messageId);
131
105
  const blockIndex = job.payload.blockIndex as number;
@@ -1,4 +1,4 @@
1
- import { eq, like } from "drizzle-orm";
1
+ import { eq, isNotNull, like, ne } from "drizzle-orm";
2
2
 
3
3
  import { getConfig } from "../../config/loader.js";
4
4
  import { getLogger } from "../../util/logger.js";
@@ -12,7 +12,8 @@ import { getQdrantClient } from "../qdrant-client.js";
12
12
  import {
13
13
  mediaAssets,
14
14
  memoryEmbeddings,
15
- memoryItems,
15
+ memoryGraphNodes,
16
+ memoryGraphTriggers,
16
17
  memorySegments,
17
18
  memorySummaries,
18
19
  messages,
@@ -24,15 +25,6 @@ export async function rebuildIndexJob(): Promise<void> {
24
25
  const db = getDb();
25
26
  db.delete(memoryEmbeddings).run();
26
27
 
27
- const items = db
28
- .select({ id: memoryItems.id })
29
- .from(memoryItems)
30
- .where(eq(memoryItems.status, "active"))
31
- .all();
32
- for (const item of items) {
33
- enqueueMemoryJob("embed_item", { itemId: item.id });
34
- }
35
-
36
28
  const summaries = db
37
29
  .select({ id: memorySummaries.id })
38
30
  .from(memorySummaries)
@@ -77,6 +69,26 @@ export async function rebuildIndexJob(): Promise<void> {
77
69
  }
78
70
  }
79
71
  }
72
+
73
+ // Re-embed graph nodes stored in the memory graph.
74
+ const graphNodes = db
75
+ .select({ id: memoryGraphNodes.id })
76
+ .from(memoryGraphNodes)
77
+ .where(ne(memoryGraphNodes.fidelity, "gone"))
78
+ .all();
79
+ for (const node of graphNodes) {
80
+ enqueueMemoryJob("embed_graph_node", { nodeId: node.id });
81
+ }
82
+
83
+ // Re-embed semantic triggers that have condition text.
84
+ const triggers = db
85
+ .select({ id: memoryGraphTriggers.id })
86
+ .from(memoryGraphTriggers)
87
+ .where(isNotNull(memoryGraphTriggers.condition))
88
+ .all();
89
+ for (const trigger of triggers) {
90
+ enqueueMemoryJob("graph_trigger_embed", { triggerId: trigger.id });
91
+ }
80
92
  }
81
93
 
82
94
  export async function deleteQdrantVectorsJob(job: MemoryJob): Promise<void> {
@@ -1,4 +1,4 @@
1
- import { and, desc, eq, sql } from "drizzle-orm";
1
+ import { and, asc, eq, gt, sql } from "drizzle-orm";
2
2
  import { v4 as uuid } from "uuid";
3
3
 
4
4
  import type { AssistantConfig } from "../../config/types.js";
@@ -19,7 +19,7 @@ import { memorySegments, memorySummaries } from "../schema.js";
19
19
  const log = getLogger("memory-jobs-worker");
20
20
 
21
21
  const SUMMARY_LLM_TIMEOUT_MS = 20_000;
22
- const SUMMARY_MAX_TOKENS = 500;
22
+ const SUMMARY_MAX_TOKENS = 1000;
23
23
 
24
24
  const CONVERSATION_SUMMARY_SYSTEM_PROMPT = [
25
25
  "You compress conversation transcripts into compact summaries for semantic search and memory retrieval.",
@@ -37,7 +37,7 @@ const CONVERSATION_SUMMARY_SYSTEM_PROMPT = [
37
37
  "## Open Items",
38
38
  "Unresolved questions, pending tasks, or follow-ups (omit section if none).",
39
39
  "",
40
- "Target 200-400 tokens. Be dense.",
40
+ "Target 400-800 tokens. Be thorough — capture nuance, tone, and relationship dynamics, not just facts.",
41
41
  ].join("\n");
42
42
 
43
43
  export async function buildConversationSummaryJob(
@@ -47,14 +47,6 @@ export async function buildConversationSummaryJob(
47
47
  const conversationId = asString(job.payload.conversationId);
48
48
  if (!conversationId) return;
49
49
  const db = getDb();
50
- const rows = db
51
- .select()
52
- .from(memorySegments)
53
- .where(eq(memorySegments.conversationId, conversationId))
54
- .orderBy(desc(memorySegments.createdAt))
55
- .limit(40)
56
- .all();
57
- if (rows.length === 0) return;
58
50
 
59
51
  const existing = db
60
52
  .select()
@@ -67,9 +59,27 @@ export async function buildConversationSummaryJob(
67
59
  )
68
60
  .get();
69
61
 
70
- // Build segment text for LLM input (chronological order)
62
+ // Fetch only segments newer than what the existing summary already covers.
63
+ // For first-time summaries, fetch all segments.
64
+ const lastCoveredAt = existing
65
+ ? Math.max(existing.startAt, existing.endAt)
66
+ : 0;
67
+
68
+ const conditions = [eq(memorySegments.conversationId, conversationId)];
69
+ if (lastCoveredAt > 0) {
70
+ conditions.push(gt(memorySegments.createdAt, lastCoveredAt));
71
+ }
72
+
73
+ const rows = db
74
+ .select()
75
+ .from(memorySegments)
76
+ .where(and(...conditions))
77
+ .orderBy(asc(memorySegments.createdAt))
78
+ .all();
79
+ if (rows.length === 0) return;
80
+
81
+ // Build segment text for LLM input (already in chronological order)
71
82
  const segmentTexts = rows
72
- .reverse()
73
83
  .map((row) => `[${row.role}] ${truncate(row.text, 600)}`)
74
84
  .join("\n\n");
75
85
 
@@ -88,6 +98,11 @@ export async function buildConversationSummaryJob(
88
98
  const now = Date.now();
89
99
  const summaryId = existing?.id ?? uuid();
90
100
  const nextVersion = (existing?.version ?? 0) + 1;
101
+ const earliestCovered = existing
102
+ ? Math.min(existing.startAt, existing.endAt, rows[0].createdAt)
103
+ : rows[0].createdAt;
104
+ const latestCovered = rows[rows.length - 1].createdAt;
105
+
91
106
  db.insert(memorySummaries)
92
107
  .values({
93
108
  id: summaryId,
@@ -97,8 +112,8 @@ export async function buildConversationSummaryJob(
97
112
  summary: summaryText,
98
113
  tokenEstimate: estimateTextTokens(summaryText),
99
114
  version: nextVersion,
100
- startAt: rows[rows.length - 1].createdAt,
101
- endAt: rows[0].createdAt,
115
+ startAt: earliestCovered,
116
+ endAt: latestCovered,
102
117
  createdAt: now,
103
118
  updatedAt: now,
104
119
  })
@@ -109,8 +124,8 @@ export async function buildConversationSummaryJob(
109
124
  tokenEstimate: estimateTextTokens(summaryText),
110
125
  version: sql`${memorySummaries.version} + 1`,
111
126
  scopeId,
112
- startAt: rows[rows.length - 1].createdAt,
113
- endAt: rows[0].createdAt,
127
+ startAt: earliestCovered,
128
+ endAt: latestCovered,
114
129
  updatedAt: now,
115
130
  },
116
131
  })
@@ -147,7 +147,7 @@ export function truncate(text: string, max: number): string {
147
147
 
148
148
  export async function embedAndUpsert(
149
149
  config: AssistantConfig,
150
- targetType: "segment" | "item" | "summary" | "media",
150
+ targetType: "segment" | "item" | "summary" | "media" | "graph_node",
151
151
  targetId: string,
152
152
  input: EmbeddingInput,
153
153
  extraPayload?: Record<string, unknown>,
@@ -14,16 +14,9 @@ const log = getLogger("memory-jobs-store");
14
14
 
15
15
  export type MemoryJobType =
16
16
  | "embed_segment"
17
- | "embed_item"
18
17
  | "embed_summary"
19
- | "extract_items"
20
- | "extract_entities"
21
- | "batch_extract"
22
- | "cleanup_stale_superseded_items"
23
18
  | "prune_old_conversations"
24
- | "backfill_entity_relations"
25
- | "refresh_weekly_summary"
26
- | "refresh_monthly_summary"
19
+ | "prune_old_llm_request_logs"
27
20
  | "build_conversation_summary"
28
21
  | "backfill"
29
22
  | "rebuild_index"
@@ -32,16 +25,22 @@ export type MemoryJobType =
32
25
  | "embed_media"
33
26
  | "embed_attachment"
34
27
  | "generate_conversation_starters"
35
- | "journal_carry_forward"
36
- | "generate_capability_cards" // legacy compat — silently dropped by worker (capability cards removed)
37
- | "generate_thread_starters"; // legacy compat — silently dropped by worker (renamed to generate_conversation_starters)
28
+ | "embed_graph_node"
29
+ | "graph_extract"
30
+ | "graph_decay"
31
+ | "graph_consolidate"
32
+ | "graph_pattern_scan"
33
+ | "graph_narrative_refine"
34
+ | "graph_trigger_embed"
35
+ | "graph_bootstrap";
38
36
 
39
37
  const EMBED_JOB_TYPES: MemoryJobType[] = [
40
38
  "embed_segment",
41
- "embed_item",
42
39
  "embed_summary",
43
40
  "embed_media",
44
41
  "embed_attachment",
42
+ "embed_graph_node",
43
+ "graph_trigger_embed",
45
44
  ];
46
45
 
47
46
  export interface MemoryJob<T = Record<string, unknown>> {
@@ -129,14 +128,10 @@ export function upsertDebouncedJob(
129
128
  }
130
129
 
131
130
  /**
132
- * Check whether a pending or running `journal_carry_forward` job already
133
- * exists for the given filename + userSlug. Used to prevent duplicate
134
- * enqueues while a carry-forward job is still in flight.
131
+ * Check whether a pending or running job of the given type already exists.
132
+ * Used to prevent duplicate enqueues for long-running maintenance jobs.
135
133
  */
136
- export function hasActiveCarryForwardJob(
137
- filename: string,
138
- userSlug: string,
139
- ): boolean {
134
+ export function hasActiveJobOfType(type: MemoryJobType): boolean {
140
135
  const db = getDb();
141
136
  return (
142
137
  db
@@ -144,27 +139,22 @@ export function hasActiveCarryForwardJob(
144
139
  .from(memoryJobs)
145
140
  .where(
146
141
  and(
147
- eq(memoryJobs.type, "journal_carry_forward"),
142
+ eq(memoryJobs.type, type),
148
143
  inArray(memoryJobs.status, ["pending", "running"]),
149
- sql`json_extract(${memoryJobs.payload}, '$.filename') = ${filename}`,
150
- sql`json_extract(${memoryJobs.payload}, '$.userSlug') = ${userSlug}`,
151
144
  ),
152
145
  )
153
146
  .get() != null
154
147
  );
155
148
  }
156
149
 
157
- export function enqueueCleanupStaleSupersededItemsJob(
158
- retentionMs?: number,
159
- ): string {
150
+ export function enqueuePruneOldLlmRequestLogsJob(retentionMs?: number): string {
160
151
  const db = getDb();
161
- const now = Date.now();
162
152
  const existing = db
163
153
  .select()
164
154
  .from(memoryJobs)
165
155
  .where(
166
156
  and(
167
- eq(memoryJobs.type, "cleanup_stale_superseded_items"),
157
+ eq(memoryJobs.type, "prune_old_llm_request_logs"),
168
158
  inArray(memoryJobs.status, ["pending", "running"]),
169
159
  ),
170
160
  )
@@ -175,7 +165,7 @@ export function enqueueCleanupStaleSupersededItemsJob(
175
165
  existing.status === "pending" &&
176
166
  typeof retentionMs === "number" &&
177
167
  Number.isFinite(retentionMs) &&
178
- retentionMs > 0
168
+ retentionMs >= 0
179
169
  ) {
180
170
  let payload: Record<string, unknown> = {};
181
171
  try {
@@ -187,7 +177,7 @@ export function enqueueCleanupStaleSupersededItemsJob(
187
177
  db.update(memoryJobs)
188
178
  .set({
189
179
  payload: JSON.stringify({ ...payload, retentionMs }),
190
- updatedAt: now,
180
+ updatedAt: Date.now(),
191
181
  })
192
182
  .where(eq(memoryJobs.id, existing.id))
193
183
  .run();
@@ -198,10 +188,10 @@ export function enqueueCleanupStaleSupersededItemsJob(
198
188
  const payload =
199
189
  typeof retentionMs === "number" &&
200
190
  Number.isFinite(retentionMs) &&
201
- retentionMs > 0
191
+ retentionMs >= 0
202
192
  ? { retentionMs }
203
193
  : {};
204
- return enqueueMemoryJob("cleanup_stale_superseded_items", payload);
194
+ return enqueueMemoryJob("prune_old_llm_request_logs", payload);
205
195
  }
206
196
 
207
197
  export function enqueuePruneOldConversationsJob(