@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,521 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Memory Graph — Bootstrap from historical conversations
3
+ //
4
+ // Re-extracts all historical conversations into the graph from scratch.
5
+ // Processes conversations chronologically so reinforcements, edges, and
6
+ // patterns build up naturally — the graph represents what the system
7
+ // WOULD have produced if running from the start.
8
+ //
9
+ // Checkpointed and resumable. Progress tracked via memory_checkpoints.
10
+ // ---------------------------------------------------------------------------
11
+
12
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
13
+ import { join } from "node:path";
14
+
15
+ import { and, asc, ne, sql } from "drizzle-orm";
16
+ import { v4 as uuid } from "uuid";
17
+
18
+ import { getConfig } from "../../config/loader.js";
19
+ import { getLogger } from "../../util/logger.js";
20
+ import { getWorkspaceDir } from "../../util/platform.js";
21
+ import { getMemoryCheckpoint, setMemoryCheckpoint } from "../checkpoints.js";
22
+ import { getDb, rawAll, rawGet, rawRun } from "../db.js";
23
+ import { enqueueMemoryJob, hasActiveJobOfType } from "../jobs-store.js";
24
+ import { initQdrantClient } from "../qdrant-client.js";
25
+ import { conversations, memoryGraphNodes, memorySegments } from "../schema.js";
26
+ import { runGraphExtraction } from "./extraction.js";
27
+ import { countNodes } from "./store.js";
28
+
29
+ const log = getLogger("graph-bootstrap");
30
+
31
+ const CHECKPOINT_KEY = "graph_bootstrap:last_conversation_id";
32
+
33
+ export interface BootstrapOptions {
34
+ scopeId?: string;
35
+ /** Skip conversations created before this epoch ms. */
36
+ after?: number;
37
+ /** Maximum conversations to process (for testing). */
38
+ limit?: number;
39
+ /** Log progress every N conversations. */
40
+ progressInterval?: number;
41
+ /** If true, just report what would be done without executing. */
42
+ dryRun?: boolean;
43
+ }
44
+
45
+ export interface BootstrapResult {
46
+ conversationsProcessed: number;
47
+ conversationsSkipped: number;
48
+ totalNodesCreated: number;
49
+ totalNodesUpdated: number;
50
+ totalNodesReinforced: number;
51
+ totalEdgesCreated: number;
52
+ totalTriggersCreated: number;
53
+ errors: Array<{ conversationId: string; error: string }>;
54
+ elapsedMs: number;
55
+ }
56
+
57
+ /**
58
+ * Re-extract all historical conversations into the memory graph.
59
+ *
60
+ * Processes conversations chronologically. Resumable via checkpoint —
61
+ * if interrupted, re-run and it picks up where it left off.
62
+ */
63
+ export async function bootstrapFromHistory(
64
+ options?: BootstrapOptions,
65
+ ): Promise<BootstrapResult> {
66
+ const start = Date.now();
67
+ const scopeId = options?.scopeId ?? "default";
68
+ const progressInterval = options?.progressInterval ?? 25;
69
+ const config = getConfig();
70
+
71
+ // Initialize Qdrant client for inline embedding
72
+ try {
73
+ initQdrantClient({
74
+ url: config.memory.qdrant.url ?? "http://127.0.0.1:6333",
75
+ collection: config.memory.qdrant.collection,
76
+ vectorSize: config.memory.qdrant.vectorSize,
77
+ onDisk: config.memory.qdrant.onDisk ?? true,
78
+ quantization: config.memory.qdrant.quantization ?? "none",
79
+ });
80
+ } catch {
81
+ // May already be initialized
82
+ }
83
+
84
+ const result: BootstrapResult = {
85
+ conversationsProcessed: 0,
86
+ conversationsSkipped: 0,
87
+ totalNodesCreated: 0,
88
+ totalNodesUpdated: 0,
89
+ totalNodesReinforced: 0,
90
+ totalEdgesCreated: 0,
91
+ totalTriggersCreated: 0,
92
+ errors: [],
93
+ elapsedMs: 0,
94
+ };
95
+
96
+ // Load all conversations, ordered chronologically
97
+ const db = getDb();
98
+ const allConversations = db
99
+ .select({
100
+ id: conversations.id,
101
+ createdAt: conversations.createdAt,
102
+ })
103
+ .from(conversations)
104
+ .orderBy(asc(conversations.createdAt))
105
+ .all();
106
+
107
+ log.info(
108
+ { total: allConversations.length },
109
+ "Starting graph bootstrap from historical conversations",
110
+ );
111
+
112
+ // Resume from checkpoint
113
+ const lastProcessedId = getMemoryCheckpoint(CHECKPOINT_KEY);
114
+ let foundCheckpoint = !lastProcessedId; // If no checkpoint, start from beginning
115
+
116
+ for (const conv of allConversations) {
117
+ // Skip until we pass the checkpoint
118
+ if (!foundCheckpoint) {
119
+ if (conv.id === lastProcessedId) {
120
+ foundCheckpoint = true;
121
+ }
122
+ result.conversationsSkipped++;
123
+ continue;
124
+ }
125
+
126
+ // Apply filters
127
+ if (options?.after && conv.createdAt < options.after) {
128
+ result.conversationsSkipped++;
129
+ continue;
130
+ }
131
+
132
+ if (options?.limit && result.conversationsProcessed >= options.limit) {
133
+ break;
134
+ }
135
+
136
+ if (options?.dryRun) {
137
+ result.conversationsProcessed++;
138
+ continue;
139
+ }
140
+
141
+ // Process this conversation
142
+ try {
143
+ const extractionResult = await runGraphExtraction(
144
+ conv.id,
145
+ scopeId,
146
+ config,
147
+ {
148
+ skipQdrant: true, // Use DB query for candidates (no Qdrant dependency)
149
+ conversationTimestamp: conv.createdAt, // Use actual conversation time
150
+ embedInline: true, // Embed synchronously so nodes are searchable immediately
151
+ },
152
+ );
153
+
154
+ result.totalNodesCreated += extractionResult.nodesCreated;
155
+ result.totalNodesUpdated += extractionResult.nodesUpdated;
156
+ result.totalNodesReinforced += extractionResult.nodesReinforced;
157
+ result.totalEdgesCreated += extractionResult.edgesCreated;
158
+ result.totalTriggersCreated += extractionResult.triggersCreated;
159
+ result.conversationsProcessed++;
160
+
161
+ // Update checkpoint after each successful extraction
162
+ setMemoryCheckpoint(CHECKPOINT_KEY, conv.id);
163
+
164
+ // Progress logging
165
+ if (result.conversationsProcessed % progressInterval === 0) {
166
+ const nodeCount = countNodes(scopeId);
167
+ log.info(
168
+ {
169
+ processed: result.conversationsProcessed,
170
+ total: allConversations.length - result.conversationsSkipped,
171
+ nodes: nodeCount,
172
+ elapsed: `${((Date.now() - start) / 1000).toFixed(1)}s`,
173
+ },
174
+ "Bootstrap progress",
175
+ );
176
+ }
177
+ } catch (err) {
178
+ const errMsg = err instanceof Error ? err.message : String(err);
179
+ log.warn(
180
+ { conversationId: conv.id, err: errMsg },
181
+ "Failed to extract conversation, continuing",
182
+ );
183
+ result.errors.push({ conversationId: conv.id, error: errMsg });
184
+
185
+ // Still checkpoint — don't re-process failed conversations
186
+ setMemoryCheckpoint(CHECKPOINT_KEY, conv.id);
187
+ }
188
+ }
189
+
190
+ result.elapsedMs = Date.now() - start;
191
+
192
+ log.info(
193
+ {
194
+ conversationsProcessed: result.conversationsProcessed,
195
+ conversationsSkipped: result.conversationsSkipped,
196
+ totalNodesCreated: result.totalNodesCreated,
197
+ totalEdgesCreated: result.totalEdgesCreated,
198
+ totalTriggersCreated: result.totalTriggersCreated,
199
+ errors: result.errors.length,
200
+ elapsedMs: result.elapsedMs,
201
+ },
202
+ "Graph bootstrap complete",
203
+ );
204
+
205
+ return result;
206
+ }
207
+
208
+ /**
209
+ * Also extract from journal files on disk.
210
+ */
211
+ export async function bootstrapFromJournal(
212
+ scopeId: string = "default",
213
+ ): Promise<{ extracted: number; errors: number }> {
214
+ const config = getConfig();
215
+ const journalDir = join(getWorkspaceDir(), "journal");
216
+ let extracted = 0;
217
+ let errors = 0;
218
+
219
+ if (!existsSync(journalDir)) return { extracted, errors };
220
+
221
+ // Iterate user slug directories
222
+ for (const slug of readdirSync(journalDir)) {
223
+ const slugDir = join(journalDir, slug);
224
+ let files: string[];
225
+ try {
226
+ files = readdirSync(slugDir).filter(
227
+ (f) =>
228
+ f.endsWith(".md") &&
229
+ !f.startsWith(".") &&
230
+ f.toLowerCase() !== "readme.md",
231
+ );
232
+ } catch {
233
+ continue;
234
+ }
235
+
236
+ for (const file of files) {
237
+ try {
238
+ const content = readFileSync(join(slugDir, file), "utf-8");
239
+ if (content.trim().length < 50) continue;
240
+
241
+ const transcript = `[journal entry: ${file}]\n\n${content}`;
242
+ const journalTimestamp = parseJournalDate(file);
243
+ await runGraphExtraction(`journal:${slug}:${file}`, scopeId, config, {
244
+ transcript,
245
+ conversationTimestamp: journalTimestamp,
246
+ });
247
+ extracted++;
248
+ } catch (err) {
249
+ log.warn(
250
+ { file, slug, err: err instanceof Error ? err.message : String(err) },
251
+ "Failed to extract journal entry",
252
+ );
253
+ errors++;
254
+ }
255
+ }
256
+ }
257
+
258
+ return { extracted, errors };
259
+ }
260
+
261
+ /**
262
+ * Parse a date from a journal filename like "2026-03-30-0045.md" or "2026-03-28-early.md".
263
+ * Returns epoch ms, defaulting to noon on the parsed date.
264
+ * Falls back to Date.now() if unparseable.
265
+ */
266
+ function parseJournalDate(filename: string): number {
267
+ const match = filename.match(/^(\d{4})-(\d{2})-(\d{2})/);
268
+ if (!match) return Date.now();
269
+
270
+ const [, year, month, day] = match;
271
+ // Check for a time-like suffix (e.g. "0045" → 00:45)
272
+ const timeMatch = filename.match(/^\d{4}-\d{2}-\d{2}-(\d{4})\./);
273
+ let hours = 12;
274
+ let minutes = 0;
275
+ if (timeMatch) {
276
+ hours = parseInt(timeMatch[1].slice(0, 2), 10);
277
+ minutes = parseInt(timeMatch[1].slice(2), 10);
278
+ } else if (filename.includes("dawn")) {
279
+ hours = 6;
280
+ } else if (filename.includes("early")) {
281
+ hours = 5;
282
+ } else if (
283
+ filename.includes("night") ||
284
+ filename.includes("midnight") ||
285
+ filename.includes("late")
286
+ ) {
287
+ hours = 23;
288
+ }
289
+
290
+ return new Date(
291
+ `${year}-${month}-${day}T${String(hours).padStart(2, "0")}:${String(
292
+ minutes,
293
+ ).padStart(2, "0")}:00`,
294
+ ).getTime();
295
+ }
296
+
297
+ /**
298
+ * Reset the bootstrap checkpoint so it can be re-run from scratch.
299
+ */
300
+ export function resetBootstrapCheckpoint(): void {
301
+ setMemoryCheckpoint(CHECKPOINT_KEY, "");
302
+ }
303
+
304
+ /**
305
+ * Enqueue a graph_bootstrap job if the graph is empty (no non-procedural nodes)
306
+ * but historical data exists (segments or journal files). Called on daemon startup
307
+ * to auto-populate the graph for users upgrading from the old extraction system.
308
+ *
309
+ * Idempotent: does nothing if graph nodes already exist or a bootstrap job is
310
+ * already pending/running.
311
+ */
312
+ export function maybeEnqueueGraphBootstrap(): void {
313
+ const db = getDb();
314
+
315
+ // Check for non-procedural graph nodes (procedural = capability seeds, not real memories)
316
+ const nonProceduralCount =
317
+ db
318
+ .select({ count: sql<number>`count(*)` })
319
+ .from(memoryGraphNodes)
320
+ .where(
321
+ and(
322
+ ne(memoryGraphNodes.type, "procedural"),
323
+ sql`${memoryGraphNodes.fidelity} != 'gone'`,
324
+ ),
325
+ )
326
+ .get()?.count ?? 0;
327
+
328
+ if (nonProceduralCount > 0) return; // Graph already populated
329
+
330
+ // Check for historical data to bootstrap from
331
+ const segmentCount =
332
+ db
333
+ .select({ count: sql<number>`count(*)` })
334
+ .from(memorySegments)
335
+ .get()?.count ?? 0;
336
+
337
+ const hasJournalFiles = existsSync(join(getWorkspaceDir(), "journal"));
338
+
339
+ if (segmentCount === 0 && !hasJournalFiles) return; // Nothing to bootstrap from
340
+
341
+ // Don't enqueue if already in progress
342
+ if (hasActiveJobOfType("graph_bootstrap")) return;
343
+
344
+ log.info(
345
+ { segmentCount, hasJournalFiles },
346
+ "Graph empty with historical data — enqueueing bootstrap",
347
+ );
348
+ enqueueMemoryJob("graph_bootstrap", {});
349
+ }
350
+
351
+ // ---------------------------------------------------------------------------
352
+ // One-time migration: port tool-created memoryItems to graph nodes
353
+ // ---------------------------------------------------------------------------
354
+
355
+ const MIGRATE_ITEMS_CHECKPOINT = "graph_bootstrap:migrated_tool_items";
356
+
357
+ interface LegacyItem {
358
+ id: string;
359
+ kind: string;
360
+ subject: string;
361
+ statement: string;
362
+ confidence: number;
363
+ importance: number;
364
+ scope_id: string;
365
+ first_seen_at: number;
366
+ }
367
+
368
+ /** Source prefix mapping from old kind to new sourceConversations key. */
369
+ const KIND_TO_PREFIX: Record<string, string> = {
370
+ playbook: "playbook:",
371
+ style: "style:",
372
+ relationship: "relationship:",
373
+ };
374
+
375
+ /**
376
+ * Migrate tool-created memoryItems (playbooks, style patterns, relationship
377
+ * dynamics) into graph nodes. These were created directly by tool handlers
378
+ * and won't be picked up by the conversation-based graph bootstrap.
379
+ *
380
+ * Idempotent: uses a checkpoint to run only once. Skips items whose
381
+ * sourceKey already exists in the graph.
382
+ *
383
+ * Uses raw SQL for the INSERT to avoid coupling to the evolving Drizzle
384
+ * schema. ORM-based inserts include every column in the schema definition,
385
+ * so adding a column in a later migration would cause this migration to
386
+ * fail with "table has no column named …" on upgrade paths.
387
+ */
388
+ export function migrateToolCreatedItems(): void {
389
+ if (getMemoryCheckpoint(MIGRATE_ITEMS_CHECKPOINT)) return;
390
+
391
+ const kinds = Object.keys(KIND_TO_PREFIX);
392
+ const placeholders = kinds.map(() => "?").join(", ");
393
+
394
+ let rows: LegacyItem[];
395
+ try {
396
+ rows = rawAll<LegacyItem>(
397
+ `SELECT id, kind, subject, statement, confidence, importance, scope_id, first_seen_at
398
+ FROM memory_items
399
+ WHERE kind IN (${placeholders}) AND status = 'active'`,
400
+ ...kinds,
401
+ );
402
+ } catch (err) {
403
+ // Table may not exist (fresh install) — nothing to migrate
404
+ if (err instanceof Error && err.message.includes("no such table")) {
405
+ setMemoryCheckpoint(MIGRATE_ITEMS_CHECKPOINT, "done");
406
+ return;
407
+ }
408
+ throw err;
409
+ }
410
+
411
+ if (rows.length === 0) {
412
+ setMemoryCheckpoint(MIGRATE_ITEMS_CHECKPOINT, "done");
413
+ return;
414
+ }
415
+
416
+ let migrated = 0;
417
+
418
+ for (const row of rows) {
419
+ const prefix = KIND_TO_PREFIX[row.kind];
420
+ if (!prefix) continue;
421
+
422
+ // Build content in the format the new tools expect
423
+ const content = `${row.subject}\n${row.statement}`;
424
+
425
+ // Check if already migrated (sourceKey exists in graph)
426
+ const sourceKey = `${prefix}${row.id}`;
427
+ const existing = rawGet<{ id: string }>(
428
+ `SELECT id FROM memory_graph_nodes WHERE source_conversations LIKE ?`,
429
+ `%${sourceKey}%`,
430
+ );
431
+ if (existing) continue;
432
+
433
+ const now = Date.now();
434
+ const id = uuid();
435
+ const emotionalCharge = JSON.stringify({
436
+ valence: 0,
437
+ intensity: 0.1,
438
+ decayCurve: "linear",
439
+ decayRate: 0.05,
440
+ originalIntensity: 0.1,
441
+ });
442
+
443
+ rawRun(
444
+ `INSERT INTO memory_graph_nodes (
445
+ id, content, type, created, last_accessed, last_consolidated,
446
+ event_date, emotional_charge, fidelity, confidence, significance,
447
+ stability, reinforcement_count, last_reinforced,
448
+ source_conversations, source_type, narrative_role, part_of_story,
449
+ image_refs, scope_id
450
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
451
+ id,
452
+ content,
453
+ "semantic",
454
+ row.first_seen_at || now,
455
+ now,
456
+ now,
457
+ null,
458
+ emotionalCharge,
459
+ "vivid",
460
+ row.confidence,
461
+ row.importance,
462
+ 14,
463
+ 0,
464
+ now,
465
+ JSON.stringify([sourceKey]),
466
+ "direct",
467
+ null,
468
+ null,
469
+ null,
470
+ row.scope_id || "default",
471
+ );
472
+
473
+ enqueueMemoryJob("embed_graph_node", { nodeId: id });
474
+ migrated++;
475
+ }
476
+
477
+ setMemoryCheckpoint(MIGRATE_ITEMS_CHECKPOINT, "done");
478
+
479
+ if (migrated > 0) {
480
+ log.info(
481
+ { migrated, total: rows.length },
482
+ "Migrated tool-created items to graph nodes",
483
+ );
484
+ }
485
+ }
486
+
487
+ // ---------------------------------------------------------------------------
488
+ // One-time cleanup: remove stale Qdrant vectors with target_type "item"
489
+ // ---------------------------------------------------------------------------
490
+
491
+ const CLEANUP_ITEM_VECTORS_CHECKPOINT = "graph_bootstrap:cleaned_item_vectors";
492
+
493
+ /**
494
+ * Delete Qdrant vectors with target_type "item" left over from the legacy
495
+ * memory_items system. The backing SQLite rows have been dropped (migration
496
+ * 203), so these vectors are orphaned and waste index space.
497
+ *
498
+ * Checkpoint-gated: runs exactly once per workspace.
499
+ */
500
+ export async function cleanupStaleItemVectors(): Promise<void> {
501
+ if (getMemoryCheckpoint(CLEANUP_ITEM_VECTORS_CHECKPOINT)) return;
502
+
503
+ let qdrant;
504
+ try {
505
+ qdrant = (await import("../qdrant-client.js")).getQdrantClient();
506
+ } catch {
507
+ // Qdrant not initialized yet — skip; will run on next startup.
508
+ return;
509
+ }
510
+
511
+ try {
512
+ await qdrant.deleteByTargetType("item");
513
+ setMemoryCheckpoint(CLEANUP_ITEM_VECTORS_CHECKPOINT, "done");
514
+ log.info("Cleaned up stale Qdrant vectors with target_type 'item'");
515
+ } catch (err) {
516
+ log.warn(
517
+ { err: err instanceof Error ? err.message : String(err) },
518
+ "Failed to clean up stale item vectors — will retry on next startup",
519
+ );
520
+ }
521
+ }