@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,130 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+ import { getSqliteFrom } from "../db-connection.js";
3
+
4
+ /**
5
+ * Create the memory graph tables: nodes, edges, and triggers.
6
+ *
7
+ * Uses CREATE TABLE IF NOT EXISTS so this is inherently idempotent
8
+ * and does not need a registry entry.
9
+ */
10
+ export function migrateCreateMemoryGraphTables(database: DrizzleDb): void {
11
+ const raw = getSqliteFrom(database);
12
+
13
+ // -- Nodes --
14
+ raw.exec(`
15
+ CREATE TABLE IF NOT EXISTS memory_graph_nodes (
16
+ id TEXT PRIMARY KEY,
17
+ content TEXT NOT NULL,
18
+ type TEXT NOT NULL,
19
+ created INTEGER NOT NULL,
20
+ last_accessed INTEGER NOT NULL,
21
+ last_consolidated INTEGER NOT NULL,
22
+ emotional_charge TEXT NOT NULL,
23
+ fidelity TEXT NOT NULL DEFAULT 'vivid',
24
+ confidence REAL NOT NULL,
25
+ significance REAL NOT NULL,
26
+ stability REAL NOT NULL DEFAULT 14,
27
+ reinforcement_count INTEGER NOT NULL DEFAULT 0,
28
+ last_reinforced INTEGER NOT NULL,
29
+ source_conversations TEXT NOT NULL DEFAULT '[]',
30
+ source_type TEXT NOT NULL DEFAULT 'inferred',
31
+ narrative_role TEXT,
32
+ part_of_story TEXT,
33
+ scope_id TEXT NOT NULL DEFAULT 'default'
34
+ )
35
+ `);
36
+
37
+ // -- Edges --
38
+ raw.exec(`
39
+ CREATE TABLE IF NOT EXISTS memory_graph_edges (
40
+ id TEXT PRIMARY KEY,
41
+ source_node_id TEXT NOT NULL REFERENCES memory_graph_nodes(id) ON DELETE CASCADE,
42
+ target_node_id TEXT NOT NULL REFERENCES memory_graph_nodes(id) ON DELETE CASCADE,
43
+ relationship TEXT NOT NULL,
44
+ weight REAL NOT NULL DEFAULT 1.0,
45
+ created INTEGER NOT NULL
46
+ )
47
+ `);
48
+
49
+ // -- Triggers --
50
+ raw.exec(`
51
+ CREATE TABLE IF NOT EXISTS memory_graph_triggers (
52
+ id TEXT PRIMARY KEY,
53
+ node_id TEXT NOT NULL REFERENCES memory_graph_nodes(id) ON DELETE CASCADE,
54
+ type TEXT NOT NULL,
55
+ schedule TEXT,
56
+ condition TEXT,
57
+ condition_embedding BLOB,
58
+ threshold REAL,
59
+ event_date INTEGER,
60
+ ramp_days INTEGER,
61
+ follow_up_days INTEGER,
62
+ recurring INTEGER NOT NULL DEFAULT 0,
63
+ consumed INTEGER NOT NULL DEFAULT 0,
64
+ cooldown_ms INTEGER,
65
+ last_fired INTEGER
66
+ )
67
+ `);
68
+
69
+ // -- Indexes (IF NOT EXISTS for idempotency) --
70
+ raw.exec(
71
+ `CREATE INDEX IF NOT EXISTS idx_graph_nodes_scope_id ON memory_graph_nodes(scope_id)`,
72
+ );
73
+ raw.exec(
74
+ `CREATE INDEX IF NOT EXISTS idx_graph_nodes_type ON memory_graph_nodes(type)`,
75
+ );
76
+ raw.exec(
77
+ `CREATE INDEX IF NOT EXISTS idx_graph_nodes_fidelity ON memory_graph_nodes(fidelity)`,
78
+ );
79
+ raw.exec(
80
+ `CREATE INDEX IF NOT EXISTS idx_graph_nodes_created ON memory_graph_nodes(created)`,
81
+ );
82
+ raw.exec(
83
+ `CREATE INDEX IF NOT EXISTS idx_graph_nodes_significance ON memory_graph_nodes(significance)`,
84
+ );
85
+ raw.exec(
86
+ `CREATE INDEX IF NOT EXISTS idx_graph_edges_source ON memory_graph_edges(source_node_id)`,
87
+ );
88
+ raw.exec(
89
+ `CREATE INDEX IF NOT EXISTS idx_graph_edges_target ON memory_graph_edges(target_node_id)`,
90
+ );
91
+ raw.exec(
92
+ `CREATE INDEX IF NOT EXISTS idx_graph_triggers_node_id ON memory_graph_triggers(node_id)`,
93
+ );
94
+ raw.exec(
95
+ `CREATE INDEX IF NOT EXISTS idx_graph_triggers_type ON memory_graph_triggers(type)`,
96
+ );
97
+
98
+ // -- Add event_date column to nodes (idempotent) --
99
+ try {
100
+ raw.exec(
101
+ `ALTER TABLE memory_graph_nodes ADD COLUMN event_date INTEGER`,
102
+ );
103
+ } catch {
104
+ // Column already exists — safe to ignore.
105
+ }
106
+
107
+ raw.exec(
108
+ `CREATE INDEX IF NOT EXISTS idx_graph_nodes_event_date ON memory_graph_nodes(event_date)`,
109
+ );
110
+
111
+ // -- Backfill event_date from existing event triggers --
112
+ raw.exec(`
113
+ UPDATE memory_graph_nodes
114
+ SET event_date = (
115
+ SELECT t.event_date
116
+ FROM memory_graph_triggers t
117
+ WHERE t.node_id = memory_graph_nodes.id
118
+ AND t.type = 'event'
119
+ AND t.event_date IS NOT NULL
120
+ LIMIT 1
121
+ )
122
+ WHERE event_date IS NULL
123
+ AND id IN (
124
+ SELECT t2.node_id
125
+ FROM memory_graph_triggers t2
126
+ WHERE t2.type = 'event'
127
+ AND t2.event_date IS NOT NULL
128
+ )
129
+ `);
130
+ }
@@ -0,0 +1,55 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+ import { getSqliteFrom } from "../db-connection.js";
3
+
4
+ /**
5
+ * Drop the legacy memory_items and memory_item_sources tables.
6
+ *
7
+ * All consumers have been migrated to memory_graph_nodes (#22698).
8
+ * These tables are now dead weight.
9
+ *
10
+ * Safety: only drops tables when they are empty or the tool-created-items
11
+ * migration has already copied relevant rows into memory_graph_nodes.
12
+ * Workspaces that haven't run migrateToolCreatedItems() yet keep the tables
13
+ * so data isn't silently lost.
14
+ */
15
+ export function migrateDropMemoryItemsTables(database: DrizzleDb): void {
16
+ const raw = getSqliteFrom(database);
17
+
18
+ // Guard: verify tables are safe to drop (empty or already migrated).
19
+ try {
20
+ const row = raw
21
+ .prepare(
22
+ /*sql*/ `SELECT COUNT(*) as cnt FROM memory_items WHERE status = 'active'`,
23
+ )
24
+ .get() as { cnt: number } | undefined;
25
+
26
+ if (row && row.cnt > 0) {
27
+ // Tables have active rows — only drop if the migration checkpoint exists.
28
+ const checkpoint = raw
29
+ .prepare(
30
+ /*sql*/ `SELECT value FROM memory_checkpoints WHERE key = ?`,
31
+ )
32
+ .get("graph_bootstrap:migrated_tool_items") as
33
+ | { value: string }
34
+ | undefined;
35
+
36
+ if (!checkpoint?.value) {
37
+ // Data exists but hasn't been migrated — skip the drop to prevent data loss.
38
+ return;
39
+ }
40
+ }
41
+ } catch {
42
+ // Table doesn't exist (fresh install) — proceed with drop (IF EXISTS is a no-op).
43
+ }
44
+
45
+ // Drop indexes first (idempotent — IF EXISTS).
46
+ raw.exec(
47
+ /*sql*/ `DROP INDEX IF EXISTS idx_memory_item_sources_memory_item_id`,
48
+ );
49
+ raw.exec(/*sql*/ `DROP INDEX IF EXISTS idx_memory_items_scope_id`);
50
+ raw.exec(/*sql*/ `DROP INDEX IF EXISTS idx_memory_items_fingerprint`);
51
+
52
+ // Drop tables (idempotent — IF EXISTS). Child table first.
53
+ raw.exec(/*sql*/ `DROP TABLE IF EXISTS memory_item_sources`);
54
+ raw.exec(/*sql*/ `DROP TABLE IF EXISTS memory_items`);
55
+ }
@@ -0,0 +1,46 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+ import { getSqliteFrom } from "../db-connection.js";
3
+ import { withCrashRecovery } from "./validate-migration-state.js";
4
+
5
+ /**
6
+ * One-shot migration: rename legacy memory graph node type values.
7
+ *
8
+ * The PR that introduced the memory graph used "style" and "relationship"
9
+ * as type values. These were renamed to "behavioral" and "semantic" in
10
+ * code, but existing rows in the database still carry the old values.
11
+ */
12
+ export function migrateRenameMemoryGraphTypeValues(database: DrizzleDb): void {
13
+ withCrashRecovery(
14
+ database,
15
+ "migration_rename_memory_graph_type_values_v1",
16
+ () => {
17
+ const raw = getSqliteFrom(database);
18
+ raw
19
+ .prepare(
20
+ /*sql*/ `UPDATE memory_graph_nodes SET type = 'behavioral' WHERE type = 'style'`,
21
+ )
22
+ .run();
23
+ raw
24
+ .prepare(
25
+ /*sql*/ `UPDATE memory_graph_nodes SET type = 'semantic' WHERE type = 'relationship'`,
26
+ )
27
+ .run();
28
+ },
29
+ );
30
+ }
31
+
32
+ /**
33
+ * Reverse: no-op.
34
+ *
35
+ * A blanket revert (`behavioral` → `style`, `semantic` → `relationship`) is
36
+ * unsafe because normal runtime may have created new `behavioral` / `semantic`
37
+ * nodes after the forward migration ran. Those nodes were never `style` /
38
+ * `relationship` and reverting them would corrupt data. Since the forward
39
+ * migration is idempotent and the old type values are no longer referenced in
40
+ * code, a no-op rollback is the safest option.
41
+ */
42
+ export function migrateRenameMemoryGraphTypeValuesDown(
43
+ _database: DrizzleDb,
44
+ ): void {
45
+ // intentional no-op — see comment above
46
+ }
@@ -0,0 +1,11 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+ import { getSqliteFrom } from "../db-connection.js";
3
+
4
+ export function migrateMemoryGraphImageRefs(database: DrizzleDb): void {
5
+ const raw = getSqliteFrom(database);
6
+ try {
7
+ raw.exec(`ALTER TABLE memory_graph_nodes ADD COLUMN image_refs TEXT`);
8
+ } catch {
9
+ // Column already exists — idempotent
10
+ }
11
+ }
@@ -0,0 +1,19 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+ import { getSqliteFrom } from "../db-connection.js";
3
+
4
+ export function migrateCreateMemoryGraphNodeEdits(database: DrizzleDb): void {
5
+ const raw = getSqliteFrom(database);
6
+ raw.exec(`
7
+ CREATE TABLE IF NOT EXISTS memory_graph_node_edits (
8
+ id TEXT PRIMARY KEY,
9
+ node_id TEXT NOT NULL REFERENCES memory_graph_nodes(id) ON DELETE CASCADE,
10
+ previous_content TEXT NOT NULL,
11
+ new_content TEXT NOT NULL,
12
+ source TEXT NOT NULL,
13
+ conversation_id TEXT,
14
+ created INTEGER NOT NULL
15
+ );
16
+ CREATE INDEX IF NOT EXISTS idx_graph_node_edits_node_id ON memory_graph_node_edits(node_id);
17
+ CREATE INDEX IF NOT EXISTS idx_graph_node_edits_created ON memory_graph_node_edits(created);
18
+ `);
19
+ }
@@ -0,0 +1,131 @@
1
+ import { readFileSync, unlinkSync } from "node:fs";
2
+
3
+ import type { DrizzleDb } from "../db-connection.js";
4
+ import { getSqliteFrom } from "../db-connection.js";
5
+ import { withCrashRecovery } from "./validate-migration-state.js";
6
+
7
+ /**
8
+ * Remove image attachments that contain HTML error pages instead of actual
9
+ * image data. This can happen when a CDN (e.g. Slack) returns an HTML sign-in
10
+ * page due to a missing OAuth scope, and the gateway stores the response body
11
+ * as an image attachment.
12
+ *
13
+ * Handles both inline (data_base64) and on-disk (file_path) storage.
14
+ */
15
+
16
+ const HTML_MARKERS = ["<!doctype", "<html"];
17
+
18
+ function looksLikeHtml(bytes: Buffer): boolean {
19
+ // Strip leading BOM / whitespace
20
+ const text = bytes.toString("utf-8").trimStart().toLowerCase();
21
+ return HTML_MARKERS.some((marker) => text.startsWith(marker));
22
+ }
23
+
24
+ export function migrateScrubCorruptedImageAttachments(
25
+ database: DrizzleDb,
26
+ ): void {
27
+ withCrashRecovery(
28
+ database,
29
+ "migration_scrub_corrupted_image_attachments_v1",
30
+ () => {
31
+ const raw = getSqliteFrom(database);
32
+
33
+ function deleteCorruptedAttachment(
34
+ id: string,
35
+ filePath: string | null,
36
+ ): void {
37
+ raw
38
+ .query(`DELETE FROM message_attachments WHERE attachment_id = ?`)
39
+ .run(id);
40
+ raw.query(`DELETE FROM attachments WHERE id = ?`).run(id);
41
+
42
+ if (filePath) {
43
+ try {
44
+ unlinkSync(filePath);
45
+ } catch {
46
+ // File already missing — ignore
47
+ }
48
+ }
49
+
50
+ console.log(
51
+ `[scrub-corrupted-attachments] Removed corrupted attachment ${id}`,
52
+ );
53
+ }
54
+
55
+ // Step A — Find and remove corrupted attachments stored inline (data_base64)
56
+ // Process in batches using rowid cursor to ensure all rows are scanned
57
+ // even when corrupted rows are non-contiguous.
58
+ const BATCH_SIZE = 100;
59
+ let lastRowid = 0;
60
+ for (;;) {
61
+ const rows = raw
62
+ .query(
63
+ `SELECT rowid, id, data_base64, file_path FROM attachments
64
+ WHERE mime_type LIKE 'image/%'
65
+ AND data_base64 IS NOT NULL
66
+ AND data_base64 != ''
67
+ AND rowid > ?
68
+ ORDER BY rowid
69
+ LIMIT ?`,
70
+ )
71
+ .all(lastRowid, BATCH_SIZE) as Array<{
72
+ rowid: number;
73
+ id: string;
74
+ data_base64: string;
75
+ file_path: string | null;
76
+ }>;
77
+
78
+ if (rows.length === 0) break;
79
+
80
+ for (const row of rows) {
81
+ lastRowid = row.rowid;
82
+ try {
83
+ const decoded = Buffer.from(
84
+ row.data_base64.slice(0, 200),
85
+ "base64",
86
+ );
87
+ if (looksLikeHtml(decoded)) {
88
+ deleteCorruptedAttachment(row.id, row.file_path);
89
+ }
90
+ } catch {
91
+ // Skip rows with invalid base64
92
+ }
93
+ }
94
+ }
95
+
96
+ // Step B — Find and remove corrupted attachments stored on disk (file_path)
97
+ // Disk-backed attachments are typically fewer; query all at once.
98
+ const diskRows = raw
99
+ .query(
100
+ `SELECT id, file_path FROM attachments
101
+ WHERE mime_type LIKE 'image/%'
102
+ AND file_path IS NOT NULL
103
+ AND (data_base64 IS NULL OR data_base64 = '')`,
104
+ )
105
+ .all() as Array<{ id: string; file_path: string }>;
106
+
107
+ for (const row of diskRows) {
108
+ try {
109
+ const bytes = readFileSync(row.file_path);
110
+ const head = bytes.subarray(0, 100);
111
+ if (looksLikeHtml(head)) {
112
+ deleteCorruptedAttachment(row.id, row.file_path);
113
+ }
114
+ } catch {
115
+ // File doesn't exist or can't be read — skip
116
+ }
117
+ }
118
+ },
119
+ );
120
+ }
121
+
122
+ /**
123
+ * Reverse: no-op.
124
+ *
125
+ * Corrupted data (HTML stored as image) has no value to restore.
126
+ */
127
+ export function migrateScrubCorruptedImageAttachmentsDown(
128
+ _database: DrizzleDb,
129
+ ): void {
130
+ // No-op — corrupted data (HTML stored as image) has no value to restore.
131
+ }
@@ -0,0 +1,20 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+ import { getSqliteFrom } from "../db-connection.js";
3
+
4
+ /**
5
+ * Persist ConversationGraphMemory + InContextTracker state across eviction.
6
+ * Idempotent — uses CREATE TABLE IF NOT EXISTS.
7
+ */
8
+ export function migrateCreateConversationGraphMemoryState(
9
+ database: DrizzleDb,
10
+ ): void {
11
+ const raw = getSqliteFrom(database);
12
+ raw.exec(`
13
+ CREATE TABLE IF NOT EXISTS conversation_graph_memory_state (
14
+ conversation_id TEXT PRIMARY KEY REFERENCES conversations(id) ON DELETE CASCADE,
15
+ state_json TEXT NOT NULL,
16
+ created_at INTEGER NOT NULL,
17
+ updated_at INTEGER NOT NULL
18
+ )
19
+ `);
20
+ }
@@ -0,0 +1,35 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+ import { getSqliteFrom } from "../db-connection.js";
3
+
4
+ /**
5
+ * Add last_message_at denormalized column to conversations for sorting by
6
+ * latest message timestamp instead of updatedAt (which is bumped by non-message
7
+ * events like title changes and context compaction).
8
+ *
9
+ * Idempotent — uses ALTER TABLE try/catch and IF NOT EXISTS guards.
10
+ */
11
+ export function migrateConversationsLastMessageAt(database: DrizzleDb): void {
12
+ const raw = getSqliteFrom(database);
13
+
14
+ try {
15
+ raw.exec(`ALTER TABLE conversations ADD COLUMN last_message_at INTEGER`);
16
+ } catch {
17
+ // Column already exists
18
+ }
19
+
20
+ // Backfill from the latest message in each conversation.
21
+ // Idempotent: re-running produces the same result.
22
+ raw.exec(`
23
+ UPDATE conversations
24
+ SET last_message_at = (
25
+ SELECT MAX(created_at) FROM messages
26
+ WHERE messages.conversation_id = conversations.id
27
+ )
28
+ WHERE last_message_at IS NULL
29
+ `);
30
+
31
+ raw.exec(`
32
+ CREATE INDEX IF NOT EXISTS idx_conversations_last_message_at
33
+ ON conversations(last_message_at)
34
+ `);
35
+ }
@@ -0,0 +1,85 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+ import { getSqliteFrom } from "../db-connection.js";
3
+ import { withCrashRecovery } from "./validate-migration-state.js";
4
+
5
+ /**
6
+ * Strip thinking and redacted_thinking blocks from all assistant messages.
7
+ *
8
+ * Consolidated messages merge thinking blocks from different API responses,
9
+ * making their cryptographic signatures invalid. Previously the Anthropic
10
+ * provider stripped these on every request, mutating the conversation prefix
11
+ * and defeating prompt caching. This migration cleans them at rest so the
12
+ * provider no longer needs to strip, enabling append-only conversation
13
+ * history and stable prefix caching.
14
+ *
15
+ * Idempotent — safe to re-run.
16
+ */
17
+ export function migrateStripThinkingFromConsolidated(
18
+ database: DrizzleDb,
19
+ ): void {
20
+ withCrashRecovery(
21
+ database,
22
+ "migration_strip_thinking_from_consolidated_v1",
23
+ () => {
24
+ const raw = getSqliteFrom(database);
25
+
26
+ const BATCH_SIZE = 100;
27
+ let lastRowid = 0;
28
+
29
+ for (;;) {
30
+ const rows = raw
31
+ .query(
32
+ `SELECT rowid, id, content FROM messages
33
+ WHERE role = 'assistant'
34
+ AND rowid > ?
35
+ ORDER BY rowid
36
+ LIMIT ?`,
37
+ )
38
+ .all(lastRowid, BATCH_SIZE) as Array<{
39
+ rowid: number;
40
+ id: string;
41
+ content: string;
42
+ }>;
43
+
44
+ if (rows.length === 0) break;
45
+
46
+ for (const row of rows) {
47
+ lastRowid = row.rowid;
48
+
49
+ let blocks: Array<{ type: string }>;
50
+ try {
51
+ const parsed = JSON.parse(row.content);
52
+ if (!Array.isArray(parsed)) continue;
53
+ blocks = parsed;
54
+ } catch {
55
+ continue;
56
+ }
57
+
58
+ const hasThinking = blocks.some(
59
+ (b) => b.type === "thinking" || b.type === "redacted_thinking",
60
+ );
61
+ if (!hasThinking) continue;
62
+
63
+ const stripped = blocks.filter(
64
+ (b) => b.type !== "thinking" && b.type !== "redacted_thinking",
65
+ );
66
+
67
+ // Preserve at least one block so the message isn't empty.
68
+ const finalContent =
69
+ stripped.length > 0
70
+ ? stripped
71
+ : [
72
+ {
73
+ type: "text" as const,
74
+ text: "\x00__PLACEHOLDER__[internal blocks omitted]",
75
+ },
76
+ ];
77
+
78
+ raw
79
+ .query(`UPDATE messages SET content = ? WHERE id = ?`)
80
+ .run(JSON.stringify(finalContent), row.id);
81
+ }
82
+ }
83
+ },
84
+ );
85
+ }
@@ -0,0 +1,13 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+ import { getSqliteFrom } from "../db-connection.js";
3
+
4
+ export function migrateScheduleReuseConversation(database: DrizzleDb): void {
5
+ const raw = getSqliteFrom(database);
6
+ try {
7
+ raw.exec(
8
+ `ALTER TABLE cron_jobs ADD COLUMN reuse_conversation INTEGER NOT NULL DEFAULT 0`,
9
+ );
10
+ } catch {
11
+ // Column already exists — nothing to do.
12
+ }
13
+ }
@@ -0,0 +1,21 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+ import { getSqliteFrom } from "../db-connection.js";
3
+ import { tableHasColumn } from "./schema-introspection.js";
4
+ import { withCrashRecovery } from "./validate-migration-state.js";
5
+
6
+ const CHECKPOINT_KEY = "migration_memory_recall_logs_query_context_v1";
7
+
8
+ /**
9
+ * Add query_context column to memory_recall_logs to persist the query text
10
+ * that drove semantic search, enabling the inspector to show what was searched.
11
+ */
12
+ export function migrateMemoryRecallLogsQueryContext(database: DrizzleDb): void {
13
+ withCrashRecovery(database, CHECKPOINT_KEY, () => {
14
+ if (!tableHasColumn(database, "memory_recall_logs", "query_context")) {
15
+ const raw = getSqliteFrom(database);
16
+ raw.exec(
17
+ `ALTER TABLE memory_recall_logs ADD COLUMN query_context TEXT`,
18
+ );
19
+ }
20
+ });
21
+ }
@@ -0,0 +1,19 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+ import { getSqliteFrom } from "../db-connection.js";
3
+ import { withCrashRecovery } from "./validate-migration-state.js";
4
+
5
+ const CHECKPOINT_KEY = "migration_llm_request_logs_created_at_index_v1";
6
+
7
+ /**
8
+ * Add an index on `llm_request_logs.created_at` so time-range deletes
9
+ * (used by the log-pruning GC job) can scan efficiently without a full
10
+ * table scan.
11
+ */
12
+ export function migrateLlmRequestLogsCreatedAtIndex(database: DrizzleDb): void {
13
+ withCrashRecovery(database, CHECKPOINT_KEY, () => {
14
+ const raw = getSqliteFrom(database);
15
+ raw.exec(
16
+ `CREATE INDEX IF NOT EXISTS idx_llm_request_logs_created_at ON llm_request_logs(created_at)`,
17
+ );
18
+ });
19
+ }
@@ -142,6 +142,18 @@ export { migrateGuardianRequestEnrichmentColumns } from "./199-guardian-request-
142
142
  export { migrateUsageLlmCallCount } from "./200-usage-llm-call-count.js";
143
143
  export { migrateOAuthProvidersFeatureFlag } from "./201-oauth-providers-feature-flag.js";
144
144
  export { migrateDropCallbackTransportColumn } from "./202-drop-callback-transport-column.js";
145
+ export { migrateCreateMemoryGraphTables } from "./202-memory-graph-tables.js";
146
+ export { migrateDropMemoryItemsTables } from "./203-drop-memory-items-tables.js";
147
+ export { migrateRenameMemoryGraphTypeValues } from "./204-rename-memory-graph-type-values.js";
148
+ export { migrateMemoryGraphImageRefs } from "./205-memory-graph-image-refs.js";
149
+ export { migrateCreateMemoryGraphNodeEdits } from "./206-memory-graph-node-edits.js";
150
+ export { migrateScrubCorruptedImageAttachments } from "./206-scrub-corrupted-image-attachments.js";
151
+ export { migrateCreateConversationGraphMemoryState } from "./207-conversation-graph-memory-state.js";
152
+ export { migrateConversationsLastMessageAt } from "./208-conversations-last-message-at.js";
153
+ export { migrateStripThinkingFromConsolidated } from "./209-strip-thinking-from-consolidated.js";
154
+ export { migrateScheduleReuseConversation } from "./210-schedule-reuse-conversation.js";
155
+ export { migrateMemoryRecallLogsQueryContext } from "./211-memory-recall-logs-query-context.js";
156
+ export { migrateLlmRequestLogsCreatedAtIndex } from "./212-llm-request-logs-created-at-index.js";
145
157
  export {
146
158
  MIGRATION_REGISTRY,
147
159
  type MigrationRegistryEntry,
@@ -39,6 +39,8 @@ import { migrateRenameThreadStartersCheckpointsDown } from "./181-rename-thread-
39
39
  import { migrateBackfillAudioAttachmentMimeTypesDown } from "./191-backfill-audio-attachment-mime-types.js";
40
40
  import { migrateAddSourceTypeColumnsDown } from "./193-add-source-type-columns.js";
41
41
  import { migrateStripIntegrationPrefixFromProviderKeysDown } from "./196-strip-integration-prefix-from-provider-keys.js";
42
+ import { migrateRenameMemoryGraphTypeValuesDown } from "./204-rename-memory-graph-type-values.js";
43
+ import { migrateScrubCorruptedImageAttachmentsDown } from "./206-scrub-corrupted-image-attachments.js";
42
44
 
43
45
  export interface MigrationRegistryEntry {
44
46
  /** The checkpoint key written to memory_checkpoints on completion. */
@@ -341,6 +343,20 @@ export const MIGRATION_REGISTRY: MigrationRegistryEntry[] = [
341
343
  "Strip integration: prefix from provider_key across oauth_providers, oauth_apps, and oauth_connections",
342
344
  down: migrateStripIntegrationPrefixFromProviderKeysDown,
343
345
  },
346
+ {
347
+ key: "migration_rename_memory_graph_type_values_v1",
348
+ version: 39,
349
+ description:
350
+ "Rename legacy memory graph node type values: style → behavioral, relationship → semantic",
351
+ down: migrateRenameMemoryGraphTypeValuesDown,
352
+ },
353
+ {
354
+ key: "migration_scrub_corrupted_image_attachments_v1",
355
+ version: 40,
356
+ description:
357
+ "Remove image attachments containing HTML error pages instead of image data",
358
+ down: migrateScrubCorruptedImageAttachmentsDown,
359
+ },
344
360
  ];
345
361
 
346
362
  export function getMaxMigrationVersion(): number {