@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
@@ -9,78 +9,78 @@ const log = getLogger("task-memory-cleanup");
9
9
  * so the check survives daemon restarts.
10
10
  */
11
11
  export function isConversationFailed(conversationId: string): boolean {
12
+ // For reused schedule conversations the same conversation_id appears in
13
+ // multiple cron_runs. A single failed run should NOT mark the conversation
14
+ // as permanently failed — only the *most recent* run for that conversation
15
+ // matters. We therefore check whether the latest cron_run (by created_at,
16
+ // which is a monotonically increasing epoch timestamp) has an error status.
17
+ // Note: cron_runs.id is a UUID v4 (random), so we cannot use MAX(id).
12
18
  const row = rawGet<{ found: number }>(
13
19
  `SELECT 1 AS found
14
20
  FROM (
15
21
  SELECT 1 FROM task_runs WHERE conversation_id = ? AND status = 'failed'
16
22
  UNION ALL
17
- SELECT 1 FROM cron_runs WHERE conversation_id = ? AND status = 'error'
23
+ SELECT 1 FROM cron_runs
24
+ WHERE conversation_id = ?
25
+ AND status = 'error'
26
+ AND id = (
27
+ SELECT id FROM cron_runs WHERE conversation_id = ?
28
+ ORDER BY created_at DESC LIMIT 1
29
+ )
18
30
  )
19
31
  LIMIT 1`,
20
32
  conversationId,
21
33
  conversationId,
34
+ conversationId,
22
35
  );
23
36
  return row != null;
24
37
  }
25
38
 
26
39
  /**
27
- * Invalidate assistant-extracted memory items sourced *exclusively* from
28
- * messages in the given conversation. Called when a background task or
29
- * schedule fails — the assistant's optimistic claims (e.g., "I booked an
30
- * appointment") are not trustworthy if the task didn't complete.
31
- *
32
- * The failed state is derived from durable storage (task_runs / cron_runs),
33
- * so any pending or future extraction jobs for this conversation are blocked
34
- * from creating new assistant-extracted items — even after daemon restarts.
40
+ * Invalidate assistant-inferred memory graph nodes sourced *exclusively* from
41
+ * the given conversation. Called when a background task or schedule fails —
42
+ * the assistant's optimistic claims are not trustworthy if the task didn't
43
+ * complete.
35
44
  *
36
- * Items that also have sources from other conversations are left alone
37
- * only when those conversations come from non-failed task/schedule runs
38
- * (or are ordinary user conversations). This prevents cascading failures
39
- * from mutually protecting each other — if two conversations both source
40
- * a memory item and both fail, the item is correctly invalidated.
45
+ * Nodes that also have sources from other non-failed conversations are left
46
+ * alone (corroboration). Uses the `source_conversations` JSON array to
47
+ * determine provenance.
41
48
  */
42
49
  export function invalidateAssistantInferredItemsForConversation(
43
50
  conversationId: string,
44
51
  ): number {
45
- // Cancel pending extraction jobs for this conversation's messages
46
- // so the worker never processes them. Jobs already running will be
47
- // caught by the isConversationFailed check in the extraction handler.
48
- // NOTE: Only extract_items jobs are cancelled here — not embed_item or
49
- // other job types. Multi-sourced items may still be valid (corroborated
50
- // by other conversations), and their embedding jobs must not be killed.
51
- // The broader cancelPendingJobsForConversation is used by the wipe path.
52
52
  cancelPendingExtractionJobsForConversation(conversationId);
53
53
 
54
54
  const affected = rawRun(
55
- `UPDATE memory_items
56
- SET status = 'invalidated',
57
- invalid_at = ?
58
- WHERE source_type = 'extraction'
59
- AND source_message_role = 'assistant'
60
- AND status = 'active'
61
- AND id IN (
62
- SELECT mis.memory_item_id
63
- FROM memory_item_sources mis
64
- JOIN messages m ON m.id = mis.message_id
65
- WHERE m.conversation_id = ?
55
+ `UPDATE memory_graph_nodes
56
+ SET fidelity = 'gone',
57
+ last_accessed = ?
58
+ WHERE source_type = 'inferred'
59
+ AND fidelity != 'gone'
60
+ AND EXISTS (
61
+ SELECT 1 FROM json_each(source_conversations) jc
62
+ WHERE jc.value = ?
66
63
  )
67
64
  AND NOT EXISTS (
68
- SELECT 1
69
- FROM memory_item_sources mis2
70
- JOIN messages m2 ON m2.id = mis2.message_id
71
- WHERE mis2.memory_item_id = memory_items.id
72
- AND m2.conversation_id != ?
73
- -- Only count as corroboration if the other conversation is NOT
74
- -- from a failed task run or failed schedule run.
65
+ SELECT 1 FROM json_each(source_conversations) jc2
66
+ WHERE jc2.value != ?
75
67
  AND NOT EXISTS (
76
68
  SELECT 1 FROM task_runs tr
77
- WHERE tr.conversation_id = m2.conversation_id
69
+ WHERE tr.conversation_id = jc2.value
78
70
  AND tr.status = 'failed'
79
71
  )
80
72
  AND NOT EXISTS (
73
+ -- Check only the most recent cron_run for each conversation
74
+ -- so reused conversations with historical errors but recent
75
+ -- successes are still treated as valid corroborators.
81
76
  SELECT 1 FROM cron_runs cr
82
- WHERE cr.conversation_id = m2.conversation_id
77
+ WHERE cr.conversation_id = jc2.value
83
78
  AND cr.status = 'error'
79
+ AND cr.id = (
80
+ SELECT cr2.id FROM cron_runs cr2
81
+ WHERE cr2.conversation_id = jc2.value
82
+ ORDER BY cr2.created_at DESC LIMIT 1
83
+ )
84
84
  )
85
85
  )`,
86
86
  Date.now(),
@@ -91,7 +91,7 @@ export function invalidateAssistantInferredItemsForConversation(
91
91
  if (affected > 0) {
92
92
  log.info(
93
93
  { conversationId, affected },
94
- "Invalidated assistant-inferred memory items after task failure",
94
+ "Invalidated assistant-inferred memory graph nodes after task failure",
95
95
  );
96
96
  }
97
97
 
@@ -100,10 +100,10 @@ export function invalidateAssistantInferredItemsForConversation(
100
100
 
101
101
  /**
102
102
  * Cancel all pending/running memory jobs referencing the given conversation.
103
- * Covers every job type: `extract_items`, `embed_attachment` (keyed by messageId),
103
+ * Covers every job type: `embed_attachment` (keyed by messageId),
104
104
  * `embed_segment` (keyed by segmentId via memory_segments),
105
- * `build_conversation_summary` (keyed by conversationId),
106
- * and `embed_item` (keyed by itemId sourced from the conversation's messages).
105
+ * `graph_extract`, `build_conversation_summary` (keyed by conversationId),
106
+ * and `embed_graph_node` (keyed by nodeId sourced from the conversation).
107
107
  */
108
108
  export function cancelPendingJobsForConversation(
109
109
  conversationId: string,
@@ -112,7 +112,7 @@ export function cancelPendingJobsForConversation(
112
112
  const now = Date.now();
113
113
  let total = 0;
114
114
 
115
- // Jobs keyed by messageId: extract_items, embed_attachment
115
+ // Jobs keyed by messageId: embed_attachment
116
116
  total += rawRun(
117
117
  `UPDATE memory_jobs
118
118
  SET status = 'failed',
@@ -127,7 +127,7 @@ export function cancelPendingJobsForConversation(
127
127
  conversationId,
128
128
  );
129
129
 
130
- // Jobs keyed by conversationId: build_conversation_summary
130
+ // Jobs keyed by conversationId: graph_extract, build_conversation_summary
131
131
  total += rawRun(
132
132
  `UPDATE memory_jobs
133
133
  SET status = 'failed',
@@ -155,18 +155,17 @@ export function cancelPendingJobsForConversation(
155
155
  conversationId,
156
156
  );
157
157
 
158
- // Jobs keyed by itemId: embed_item (items sourced from this conversation)
158
+ // Jobs keyed by nodeId: embed_graph_node (nodes sourced from this conversation)
159
159
  total += rawRun(
160
160
  `UPDATE memory_jobs
161
161
  SET status = 'failed',
162
162
  last_error = ?,
163
163
  updated_at = ?
164
164
  WHERE status IN ('pending', 'running')
165
- AND json_extract(payload, '$.itemId') IN (
166
- SELECT mis.memory_item_id
167
- FROM memory_item_sources mis
168
- JOIN messages m ON m.id = mis.message_id
169
- WHERE m.conversation_id = ?
165
+ AND json_extract(payload, '$.nodeId') IN (
166
+ SELECT mgn.id
167
+ FROM memory_graph_nodes mgn, json_each(mgn.source_conversations) jc
168
+ WHERE jc.value = ?
170
169
  )`,
171
170
  reason,
172
171
  now,
@@ -184,10 +183,10 @@ export function cancelPendingJobsForConversation(
184
183
  }
185
184
 
186
185
  /**
187
- * Cancel only pending/running `extract_items` jobs for messages in the
188
- * given conversation. Used by the task-failure path where we want to
189
- * stop new extractions but must NOT cancel `embed_item` jobs — those
190
- * items may be multi-sourced and still valid.
186
+ * Cancel only pending/running `graph_extract` jobs for the given
187
+ * conversation. Used by the task-failure path where we want to
188
+ * stop new extractions but must NOT cancel `embed_graph_node` jobs —
189
+ * those nodes may be multi-sourced and still valid.
191
190
  */
192
191
  function cancelPendingExtractionJobsForConversation(
193
192
  conversationId: string,
@@ -199,10 +198,8 @@ function cancelPendingExtractionJobsForConversation(
199
198
  last_error = 'conversation_failed',
200
199
  updated_at = ?
201
200
  WHERE status IN ('pending', 'running')
202
- AND type = 'extract_items'
203
- AND json_extract(payload, '$.messageId') IN (
204
- SELECT id FROM messages WHERE conversation_id = ?
205
- )`,
201
+ AND type = 'graph_extract'
202
+ AND json_extract(payload, '$.conversationId') = ?`,
206
203
  now,
207
204
  conversationId,
208
205
  );
@@ -65,7 +65,14 @@ export const outlookMessagingProvider: MessagingProvider = {
65
65
  id: "outlook",
66
66
  displayName: "Outlook",
67
67
  credentialService: "outlook",
68
- capabilities: new Set(["threads", "folders"]),
68
+ capabilities: new Set([
69
+ "threads",
70
+ "folders",
71
+ "categories",
72
+ "drafts_native",
73
+ "archive",
74
+ "unsubscribe",
75
+ ]),
69
76
 
70
77
  async testConnection(connection?: OAuthConnection): Promise<ConnectionInfo> {
71
78
  const conn = requireConnection(connection);
@@ -3,10 +3,20 @@ import type {
3
3
  OAuthConnectionResponse,
4
4
  } from "../../../oauth/connection.js";
5
5
  import type {
6
+ OutlookAttachmentListResponse,
7
+ OutlookAutoReplySettings,
8
+ OutlookDeltaResponse,
9
+ OutlookDraftMessage,
10
+ OutlookFileAttachment,
6
11
  OutlookMailFolder,
7
12
  OutlookMailFolderListResponse,
13
+ OutlookMasterCategoryListResponse,
8
14
  OutlookMessage,
15
+ OutlookMessageFlag,
9
16
  OutlookMessageListResponse,
17
+ OutlookMessageRule,
18
+ OutlookMessageRuleListResponse,
19
+ OutlookRecipient,
10
20
  OutlookSendMessagePayload,
11
21
  OutlookUserProfile,
12
22
  } from "./types.js";
@@ -268,6 +278,22 @@ export async function markMessageRead(
268
278
  );
269
279
  }
270
280
 
281
+ /** Patch arbitrary fields on a message (e.g. to update recipients on a draft). */
282
+ export async function patchMessage(
283
+ connection: OAuthConnection,
284
+ messageId: string,
285
+ fields: Record<string, unknown>,
286
+ ): Promise<OutlookMessage> {
287
+ return request<OutlookMessage>(
288
+ connection,
289
+ `/v1.0/me/messages/${encodeURIComponent(messageId)}`,
290
+ {
291
+ method: "PATCH",
292
+ body: JSON.stringify(fields),
293
+ },
294
+ );
295
+ }
296
+
271
297
  /** Move a message to a different folder (e.g. for archiving). */
272
298
  export async function moveMessage(
273
299
  connection: OAuthConnection,
@@ -284,6 +310,84 @@ export async function moveMessage(
284
310
  );
285
311
  }
286
312
 
313
+ /** Create a draft message in the user's Drafts folder. */
314
+ export async function createDraft(
315
+ connection: OAuthConnection,
316
+ draft: OutlookDraftMessage,
317
+ ): Promise<OutlookMessage> {
318
+ return request<OutlookMessage>(connection, "/v1.0/me/messages", {
319
+ method: "POST",
320
+ body: JSON.stringify(draft),
321
+ });
322
+ }
323
+
324
+ /** Send an existing draft message by its ID. Returns void (202 No Content). */
325
+ export async function sendDraft(
326
+ connection: OAuthConnection,
327
+ messageId: string,
328
+ ): Promise<void> {
329
+ await request<void>(
330
+ connection,
331
+ `/v1.0/me/messages/${encodeURIComponent(messageId)}/send`,
332
+ {
333
+ method: "POST",
334
+ },
335
+ );
336
+ }
337
+
338
+ /** Create a reply draft for a message. */
339
+ export async function createReplyDraft(
340
+ connection: OAuthConnection,
341
+ messageId: string,
342
+ comment?: string,
343
+ ): Promise<OutlookMessage> {
344
+ return request<OutlookMessage>(
345
+ connection,
346
+ `/v1.0/me/messages/${encodeURIComponent(messageId)}/createReply`,
347
+ {
348
+ method: "POST",
349
+ body: JSON.stringify(comment !== undefined ? { comment } : {}),
350
+ },
351
+ );
352
+ }
353
+
354
+ /** Create a reply-all draft for a message. */
355
+ export async function createReplyAllDraft(
356
+ connection: OAuthConnection,
357
+ messageId: string,
358
+ comment?: string,
359
+ ): Promise<OutlookMessage> {
360
+ return request<OutlookMessage>(
361
+ connection,
362
+ `/v1.0/me/messages/${encodeURIComponent(messageId)}/createReplyAll`,
363
+ {
364
+ method: "POST",
365
+ body: JSON.stringify(comment !== undefined ? { comment } : {}),
366
+ },
367
+ );
368
+ }
369
+
370
+ /** Create a forward draft for a message. */
371
+ export async function createForwardDraft(
372
+ connection: OAuthConnection,
373
+ messageId: string,
374
+ toRecipients?: OutlookRecipient[],
375
+ comment?: string,
376
+ ): Promise<OutlookMessage> {
377
+ const body: Record<string, unknown> = {};
378
+ if (toRecipients !== undefined) body.toRecipients = toRecipients;
379
+ if (comment !== undefined) body.comment = comment;
380
+
381
+ return request<OutlookMessage>(
382
+ connection,
383
+ `/v1.0/me/messages/${encodeURIComponent(messageId)}/createForward`,
384
+ {
385
+ method: "POST",
386
+ body: JSON.stringify(body),
387
+ },
388
+ );
389
+ }
390
+
287
391
  /** Max concurrent individual getMessage requests for batch fetching. */
288
392
  const BATCH_CONCURRENCY = 5;
289
393
 
@@ -309,3 +413,198 @@ export async function batchGetMessages(
309
413
  }
310
414
  return results;
311
415
  }
416
+
417
+ /** List attachments on a message. */
418
+ export async function listAttachments(
419
+ connection: OAuthConnection,
420
+ messageId: string,
421
+ ): Promise<OutlookAttachmentListResponse> {
422
+ return request<OutlookAttachmentListResponse>(
423
+ connection,
424
+ `/v1.0/me/messages/${encodeURIComponent(messageId)}/attachments`,
425
+ undefined,
426
+ { $select: "id,name,contentType,size,isInline" },
427
+ );
428
+ }
429
+
430
+ /** Get a single attachment by ID (includes file content). */
431
+ export async function getAttachment(
432
+ connection: OAuthConnection,
433
+ messageId: string,
434
+ attachmentId: string,
435
+ ): Promise<OutlookFileAttachment> {
436
+ return request<OutlookFileAttachment>(
437
+ connection,
438
+ `/v1.0/me/messages/${encodeURIComponent(messageId)}/attachments/${encodeURIComponent(attachmentId)}`,
439
+ );
440
+ }
441
+
442
+ /** Move a message to the Deleted Items folder. */
443
+ export async function trashMessage(
444
+ connection: OAuthConnection,
445
+ messageId: string,
446
+ ): Promise<OutlookMessage> {
447
+ return request<OutlookMessage>(
448
+ connection,
449
+ `/v1.0/me/messages/${encodeURIComponent(messageId)}/move`,
450
+ {
451
+ method: "POST",
452
+ body: JSON.stringify({ destinationId: "deleteditems" }),
453
+ },
454
+ );
455
+ }
456
+
457
+ /** List inbox message rules. */
458
+ export async function listMailRules(
459
+ connection: OAuthConnection,
460
+ ): Promise<OutlookMessageRuleListResponse> {
461
+ return request<OutlookMessageRuleListResponse>(
462
+ connection,
463
+ "/v1.0/me/mailFolders/inbox/messageRules",
464
+ );
465
+ }
466
+
467
+ /** Create a new inbox message rule. */
468
+ export async function createMailRule(
469
+ connection: OAuthConnection,
470
+ rule: Omit<OutlookMessageRule, "id">,
471
+ ): Promise<OutlookMessageRule> {
472
+ return request<OutlookMessageRule>(
473
+ connection,
474
+ "/v1.0/me/mailFolders/inbox/messageRules",
475
+ {
476
+ method: "POST",
477
+ body: JSON.stringify(rule),
478
+ },
479
+ );
480
+ }
481
+
482
+ /** Update the categories on a message. */
483
+ export async function updateMessageCategories(
484
+ connection: OAuthConnection,
485
+ messageId: string,
486
+ categories: string[],
487
+ ): Promise<void> {
488
+ await request<void>(
489
+ connection,
490
+ `/v1.0/me/messages/${encodeURIComponent(messageId)}`,
491
+ {
492
+ method: "PATCH",
493
+ body: JSON.stringify({ categories }),
494
+ },
495
+ );
496
+ }
497
+
498
+ /** Update the flag on a message. */
499
+ export async function updateMessageFlag(
500
+ connection: OAuthConnection,
501
+ messageId: string,
502
+ flag: OutlookMessageFlag,
503
+ ): Promise<void> {
504
+ await request<void>(
505
+ connection,
506
+ `/v1.0/me/messages/${encodeURIComponent(messageId)}`,
507
+ {
508
+ method: "PATCH",
509
+ body: JSON.stringify({ flag }),
510
+ },
511
+ );
512
+ }
513
+
514
+ /** List the user's master categories. */
515
+ export async function listMasterCategories(
516
+ connection: OAuthConnection,
517
+ ): Promise<OutlookMasterCategoryListResponse> {
518
+ return request<OutlookMasterCategoryListResponse>(
519
+ connection,
520
+ "/v1.0/me/outlook/masterCategories",
521
+ );
522
+ }
523
+
524
+ /** Get a message with internet message headers included. */
525
+ export async function getMessageWithHeaders(
526
+ connection: OAuthConnection,
527
+ messageId: string,
528
+ ): Promise<OutlookMessage> {
529
+ return request<OutlookMessage>(
530
+ connection,
531
+ `/v1.0/me/messages/${encodeURIComponent(messageId)}`,
532
+ undefined,
533
+ {
534
+ $select:
535
+ "id,subject,from,internetMessageHeaders,bodyPreview,body,hasAttachments,receivedDateTime",
536
+ },
537
+ );
538
+ }
539
+
540
+ /** Delete an inbox message rule by ID. */
541
+ export async function deleteMailRule(
542
+ connection: OAuthConnection,
543
+ ruleId: string,
544
+ ): Promise<void> {
545
+ await request<void>(
546
+ connection,
547
+ `/v1.0/me/mailFolders/inbox/messageRules/${encodeURIComponent(ruleId)}`,
548
+ { method: "DELETE" },
549
+ );
550
+ }
551
+
552
+ /** Get automatic reply (out-of-office) settings. */
553
+ export async function getAutoReplySettings(
554
+ connection: OAuthConnection,
555
+ ): Promise<OutlookAutoReplySettings> {
556
+ return request<OutlookAutoReplySettings>(
557
+ connection,
558
+ "/v1.0/me/mailboxSettings/automaticRepliesSetting",
559
+ );
560
+ }
561
+
562
+ /** Update automatic reply (out-of-office) settings. */
563
+ export async function updateAutoReplySettings(
564
+ connection: OAuthConnection,
565
+ settings: OutlookAutoReplySettings,
566
+ ): Promise<void> {
567
+ await request<void>(connection, "/v1.0/me/mailboxSettings", {
568
+ method: "PATCH",
569
+ body: JSON.stringify({ automaticRepliesSetting: settings }),
570
+ });
571
+ }
572
+
573
+ /**
574
+ * Fetch messages via delta query for incremental sync.
575
+ *
576
+ * On the initial call, omit `deltaLink` to start a fresh delta enumeration
577
+ * for the given folder. On subsequent calls, pass the `@odata.deltaLink`
578
+ * from the previous response to get only changes since then.
579
+ */
580
+ export async function listMessagesDelta(
581
+ connection: OAuthConnection,
582
+ folderId: string,
583
+ deltaLink?: string,
584
+ ): Promise<OutlookDeltaResponse<OutlookMessage>> {
585
+ if (deltaLink) {
586
+ // Parse the deltaLink URL and extract its query params
587
+ const url = new URL(deltaLink);
588
+ const query: Record<string, string> = {};
589
+ url.searchParams.forEach((v, k) => {
590
+ query[k] = v;
591
+ });
592
+ return request<OutlookDeltaResponse<OutlookMessage>>(
593
+ connection,
594
+ url.pathname,
595
+ undefined,
596
+ Object.keys(query).length > 0 ? query : undefined,
597
+ );
598
+ }
599
+
600
+ return request<OutlookDeltaResponse<OutlookMessage>>(
601
+ connection,
602
+ `/v1.0/me/mailFolders/${encodeURIComponent(folderId)}/messages/delta`,
603
+ undefined,
604
+ {
605
+ $select:
606
+ "id,subject,from,receivedDateTime,isRead,parentFolderId,conversationId,bodyPreview,hasAttachments",
607
+ $top: "50",
608
+ },
609
+ );
610
+ }
@@ -28,6 +28,12 @@ export interface OutlookItemBody {
28
28
  content: string;
29
29
  }
30
30
 
31
+ /** Internet message header (e.g. List-Unsubscribe, X-Mailer) */
32
+ export interface OutlookInternetMessageHeader {
33
+ name: string;
34
+ value: string;
35
+ }
36
+
31
37
  /** Full Outlook message from Microsoft Graph */
32
38
  export interface OutlookMessage {
33
39
  id: string;
@@ -46,6 +52,7 @@ export interface OutlookMessage {
46
52
  flag: {
47
53
  flagStatus: "notFlagged" | "flagged" | "complete";
48
54
  };
55
+ internetMessageHeaders?: OutlookInternetMessageHeader[];
49
56
  }
50
57
 
51
58
  /** Outlook mail folder */
@@ -75,9 +82,120 @@ export interface OutlookSendMessagePayload {
75
82
  saveToSentItems?: boolean;
76
83
  }
77
84
 
85
+ /** Draft message for creating in Drafts folder */
86
+ export interface OutlookDraftMessage {
87
+ subject: string;
88
+ body: OutlookItemBody;
89
+ toRecipients?: OutlookRecipient[];
90
+ ccRecipients?: OutlookRecipient[];
91
+ bccRecipients?: OutlookRecipient[];
92
+ }
93
+
94
+ /** Forward message payload (Graph API's /createForward returns a draft) */
95
+ export interface OutlookForwardMessage {
96
+ toRecipients: OutlookRecipient[];
97
+ comment?: string;
98
+ }
99
+
78
100
  /** Microsoft Graph user profile */
79
101
  export interface OutlookUserProfile {
80
102
  displayName: string;
81
103
  mail: string;
82
104
  userPrincipalName: string;
83
105
  }
106
+
107
+ /** Outlook attachment metadata */
108
+ export interface OutlookAttachment {
109
+ id: string;
110
+ name: string;
111
+ contentType: string;
112
+ size: number;
113
+ isInline: boolean;
114
+ "@odata.type"?: string;
115
+ }
116
+
117
+ /** Outlook file attachment with base64-encoded content */
118
+ export interface OutlookFileAttachment extends OutlookAttachment {
119
+ contentBytes: string;
120
+ }
121
+
122
+ /** Outlook attachment list response (paginated) */
123
+ export interface OutlookAttachmentListResponse {
124
+ value?: OutlookAttachment[];
125
+ "@odata.nextLink"?: string;
126
+ }
127
+
128
+ /** Outlook message flag with optional due/start dates */
129
+ export interface OutlookMessageFlag {
130
+ flagStatus: "notFlagged" | "flagged" | "complete";
131
+ dueDateTime?: { dateTime: string; timeZone: string };
132
+ startDateTime?: { dateTime: string; timeZone: string };
133
+ }
134
+
135
+ /** Outlook master category */
136
+ export interface OutlookMasterCategory {
137
+ displayName: string;
138
+ color: string;
139
+ }
140
+
141
+ /** Outlook master category list response */
142
+ export interface OutlookMasterCategoryListResponse {
143
+ value?: OutlookMasterCategory[];
144
+ }
145
+
146
+ /** Predicates for matching messages in a mail rule */
147
+ export interface OutlookMessageRulePredicates {
148
+ senderContains?: string[];
149
+ subjectContains?: string[];
150
+ bodyContains?: string[];
151
+ fromAddresses?: OutlookRecipient[];
152
+ hasAttachments?: boolean;
153
+ importance?: "low" | "normal" | "high";
154
+ }
155
+
156
+ /** Actions to take when a mail rule matches */
157
+ export interface OutlookMessageRuleActions {
158
+ moveToFolder?: string;
159
+ delete?: boolean;
160
+ stopProcessingRules?: boolean;
161
+ markAsRead?: boolean;
162
+ forwardTo?: OutlookRecipient[];
163
+ markImportance?: "low" | "normal" | "high";
164
+ }
165
+
166
+ /** A mail rule for inbox message processing */
167
+ export interface OutlookMessageRule {
168
+ id?: string;
169
+ displayName: string;
170
+ sequence: number;
171
+ isEnabled: boolean;
172
+ conditions?: OutlookMessageRulePredicates;
173
+ actions?: OutlookMessageRuleActions;
174
+ }
175
+
176
+ /** Response from listing mail rules */
177
+ export interface OutlookMessageRuleListResponse {
178
+ value?: OutlookMessageRule[];
179
+ }
180
+
181
+ /** Automatic reply (out-of-office) settings */
182
+ export interface OutlookAutoReplySettings {
183
+ status: "disabled" | "alwaysEnabled" | "scheduled";
184
+ externalAudience: "none" | "contactsOnly" | "all";
185
+ internalReplyMessage?: string;
186
+ externalReplyMessage?: string;
187
+ scheduledStartDateTime?: { dateTime: string; timeZone: string };
188
+ scheduledEndDateTime?: { dateTime: string; timeZone: string };
189
+ }
190
+
191
+ /** Mailbox settings containing automatic replies configuration */
192
+ export interface OutlookMailboxSettings {
193
+ automaticRepliesSetting?: OutlookAutoReplySettings;
194
+ }
195
+
196
+ /** Delta query response with pagination support */
197
+ export interface OutlookDeltaResponse<T> {
198
+ value?: T[];
199
+ "@odata.deltaLink"?: string;
200
+ "@odata.nextLink"?: string;
201
+ }