@vellumai/assistant 0.6.0 → 0.6.2

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 (358) hide show
  1. package/AGENTS.md +4 -0
  2. package/ARCHITECTURE.md +68 -15
  3. package/Dockerfile +2 -2
  4. package/bun.lock +6 -2
  5. package/docker-entrypoint.sh +42 -1
  6. package/docs/architecture/integrations.md +1 -1
  7. package/docs/architecture/memory.md +21 -24
  8. package/node_modules/@vellumai/ces-contracts/src/handles.ts +7 -9
  9. package/openapi.yaml +539 -4
  10. package/package.json +5 -1
  11. package/src/__tests__/anthropic-provider.test.ts +160 -95
  12. package/src/__tests__/app-dir-path-guard.test.ts +1 -0
  13. package/src/__tests__/app-executors.test.ts +47 -1
  14. package/src/__tests__/app-source-watcher.test.ts +159 -0
  15. package/src/__tests__/assistant-event-hub.test.ts +30 -0
  16. package/src/__tests__/checker.test.ts +138 -172
  17. package/src/__tests__/cli-command-risk-guard.test.ts +1 -1
  18. package/src/__tests__/config-schema.test.ts +5 -0
  19. package/src/__tests__/context-overflow-approval.test.ts +5 -5
  20. package/src/__tests__/conversation-agent-loop-overflow.test.ts +4 -6
  21. package/src/__tests__/conversation-agent-loop.test.ts +4 -51
  22. package/src/__tests__/conversation-analysis-routes.test.ts +169 -0
  23. package/src/__tests__/conversation-directories-parse.test.ts +105 -0
  24. package/src/__tests__/conversation-history-web-search.test.ts +1 -1
  25. package/src/__tests__/conversation-runtime-assembly.test.ts +653 -832
  26. package/src/__tests__/conversation-runtime-workspace.test.ts +1 -93
  27. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +17 -4
  28. package/src/__tests__/conversation-wipe.test.ts +2 -6
  29. package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -12
  30. package/src/__tests__/conversation-workspace-injection.test.ts +25 -26
  31. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -1
  32. package/src/__tests__/copy-composer-tc-templates.test.ts +335 -0
  33. package/src/__tests__/credential-execution-approval-bridge.test.ts +0 -2
  34. package/src/__tests__/date-context.test.ts +76 -210
  35. package/src/__tests__/db-schedule-syntax-migration.test.ts +16 -1
  36. package/src/__tests__/file-list-tool.test.ts +219 -0
  37. package/src/__tests__/first-greeting.test.ts +1 -1
  38. package/src/__tests__/heartbeat-service.test.ts +180 -3
  39. package/src/__tests__/identity-routes.test.ts +328 -0
  40. package/src/__tests__/init-feature-flag-overrides.test.ts +167 -0
  41. package/src/__tests__/injection-block.test.ts +24 -0
  42. package/src/__tests__/inline-command-runner.test.ts +7 -5
  43. package/src/__tests__/install-skill-routing.test.ts +7 -6
  44. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +15 -14
  45. package/src/__tests__/list-messages-tool-merge.test.ts +300 -0
  46. package/src/__tests__/llm-context-normalization.test.ts +18 -18
  47. package/src/__tests__/llm-context-route-provider.test.ts +101 -0
  48. package/src/__tests__/llm-request-log-turn-query.test.ts +162 -0
  49. package/src/__tests__/log-export-workspace.test.ts +257 -100
  50. package/src/__tests__/managed-credential-catalog-cli.test.ts +12 -14
  51. package/src/__tests__/mcp-abort-signal.test.ts +5 -0
  52. package/src/__tests__/mcp-client-auth.test.ts +5 -0
  53. package/src/__tests__/memory-recall-log-store.test.ts +132 -0
  54. package/src/__tests__/migration-export-streaming.test.ts +304 -0
  55. package/src/__tests__/migration-import-commit-http.test.ts +11 -10
  56. package/src/__tests__/mock-fetch.ts +87 -0
  57. package/src/__tests__/navigate-settings-tab.test.ts +14 -1
  58. package/src/__tests__/notification-broadcaster.test.ts +65 -0
  59. package/src/__tests__/notification-decision-recipient-context.test.ts +282 -0
  60. package/src/__tests__/onboarding-template-contract.test.ts +63 -14
  61. package/src/__tests__/parser.test.ts +32 -0
  62. package/src/__tests__/permission-checker-host-gate.test.ts +452 -0
  63. package/src/__tests__/permission-controls-v2-flag.test.ts +55 -0
  64. package/src/__tests__/permission-mode-sse.test.ts +418 -0
  65. package/src/__tests__/permission-mode-store.test.ts +277 -0
  66. package/src/__tests__/permission-mode.test.ts +101 -0
  67. package/src/__tests__/pkb-autoinject.test.ts +96 -0
  68. package/src/__tests__/platform-bash-auto-approve.test.ts +359 -0
  69. package/src/__tests__/profiler-routes.test.ts +502 -0
  70. package/src/__tests__/profiler-run-store.test.ts +441 -0
  71. package/src/__tests__/proxy-approval-callback.test.ts +4 -75
  72. package/src/__tests__/registry.test.ts +1 -1
  73. package/src/__tests__/require-fresh-approval.test.ts +0 -2
  74. package/src/__tests__/sandbox-diagnostics.test.ts +1 -32
  75. package/src/__tests__/sandbox-host-parity.test.ts +5 -4
  76. package/src/__tests__/scheduler-reuse-conversation.test.ts +368 -0
  77. package/src/__tests__/scrub-corrupted-image-attachments.test.ts +278 -0
  78. package/src/__tests__/search-skills-unified.test.ts +4 -3
  79. package/src/__tests__/send-endpoint-busy.test.ts +42 -3
  80. package/src/__tests__/set-permission-mode.test.ts +274 -0
  81. package/src/__tests__/skill-load-feature-flag.test.ts +12 -0
  82. package/src/__tests__/skill-memory.test.ts +2 -783
  83. package/src/__tests__/strip-memory-injections.test.ts +187 -0
  84. package/src/__tests__/subagent-detail.test.ts +84 -0
  85. package/src/__tests__/subagent-disposal.test.ts +308 -0
  86. package/src/__tests__/subagent-manager-notify.test.ts +19 -10
  87. package/src/__tests__/subagent-notify-parent.test.ts +390 -0
  88. package/src/__tests__/subagent-role-registry.test.ts +108 -0
  89. package/src/__tests__/subagent-tool-filtering.test.ts +71 -0
  90. package/src/__tests__/subagent-tools.test.ts +464 -4
  91. package/src/__tests__/system-prompt-ask-mode.test.ts +139 -0
  92. package/src/__tests__/task-memory-cleanup.test.ts +12 -12
  93. package/src/__tests__/terminal-sandbox.test.ts +1 -1
  94. package/src/__tests__/terminal-tools.test.ts +16 -29
  95. package/src/__tests__/test-preload.ts +18 -0
  96. package/src/__tests__/tool-domain-event-publisher.test.ts +0 -1
  97. package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -8
  98. package/src/__tests__/tool-executor.test.ts +4 -27
  99. package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
  100. package/src/__tests__/top-level-renderer.test.ts +10 -13
  101. package/src/__tests__/transport-hints-queue.test.ts +77 -0
  102. package/src/__tests__/trust-store.test.ts +4 -4
  103. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +116 -2
  104. package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +387 -0
  105. package/src/__tests__/workspace-migration-030-seed-pkb-autoinject.test.ts +168 -0
  106. package/src/__tests__/workspace-policy.test.ts +2 -7
  107. package/src/agent/loop.ts +6 -29
  108. package/src/approvals/guardian-request-resolvers.ts +24 -0
  109. package/src/avatar/traits-png-sync.ts +3 -3
  110. package/src/channels/types.ts +5 -0
  111. package/src/cli/__tests__/run-assistant-command.ts +56 -0
  112. package/src/cli/__tests__/unknown-command.test.ts +33 -0
  113. package/src/cli/commands/__tests__/email-download.test.ts +245 -0
  114. package/src/cli/commands/__tests__/email-list.test.ts +192 -0
  115. package/src/cli/commands/__tests__/email-register.test.ts +186 -0
  116. package/src/cli/commands/__tests__/email-send.test.ts +291 -0
  117. package/src/cli/commands/__tests__/email-status.test.ts +181 -0
  118. package/src/cli/commands/__tests__/email-unregister.test.ts +139 -0
  119. package/src/cli/commands/__tests__/routes.test.ts +562 -0
  120. package/src/cli/commands/conversations.ts +1 -8
  121. package/src/cli/commands/default-action.ts +68 -1
  122. package/src/cli/commands/email.ts +584 -835
  123. package/src/cli/commands/memory.ts +1 -34
  124. package/src/cli/commands/notifications.ts +7 -2
  125. package/src/cli/commands/oauth/__tests__/connect.test.ts +27 -0
  126. package/src/cli/commands/oauth/connect.ts +25 -5
  127. package/src/cli/commands/platform/__tests__/connect.test.ts +1 -1
  128. package/src/cli/commands/platform/__tests__/disconnect.test.ts +1 -1
  129. package/src/cli/commands/platform/__tests__/status.test.ts +1 -1
  130. package/src/cli/commands/routes.ts +396 -0
  131. package/src/cli/commands/skills.ts +130 -20
  132. package/src/cli/program.ts +11 -2
  133. package/src/cli.ts +1 -120
  134. package/src/config/assistant-feature-flags.ts +59 -55
  135. package/src/config/bundled-skills/app-builder/SKILL.md +91 -5
  136. package/src/config/bundled-skills/gmail/SKILL.md +13 -8
  137. package/src/config/bundled-skills/gmail/TOOLS.json +1 -1
  138. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +2 -1
  139. package/src/config/bundled-skills/messaging/SKILL.md +7 -0
  140. package/src/config/bundled-skills/schedule/SKILL.md +22 -2
  141. package/src/config/bundled-skills/schedule/TOOLS.json +8 -0
  142. package/src/config/bundled-skills/settings/TOOLS.json +1 -1
  143. package/src/config/bundled-skills/settings/tools/avatar-get.ts +3 -13
  144. package/src/config/bundled-skills/settings/tools/avatar-remove.ts +2 -4
  145. package/src/config/bundled-skills/settings/tools/avatar-update.ts +5 -2
  146. package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +8 -3
  147. package/src/config/bundled-skills/slack/SKILL.md +2 -0
  148. package/src/config/bundled-skills/subagent/SKILL.md +43 -3
  149. package/src/config/bundled-skills/subagent/TOOLS.json +29 -4
  150. package/src/config/env-registry.ts +63 -0
  151. package/src/config/feature-flag-registry.json +17 -1
  152. package/src/config/schema.ts +8 -0
  153. package/src/config/schemas/filing.ts +51 -0
  154. package/src/config/schemas/heartbeat.ts +15 -12
  155. package/src/config/schemas/memory-lifecycle.ts +12 -0
  156. package/src/config/schemas/security.ts +14 -0
  157. package/src/config/schemas/services.ts +8 -0
  158. package/src/credential-execution/approval-bridge.ts +0 -1
  159. package/src/credential-execution/managed-catalog.ts +3 -7
  160. package/src/daemon/app-source-watcher.ts +93 -0
  161. package/src/daemon/config-watcher.ts +85 -3
  162. package/src/daemon/context-overflow-approval.ts +0 -1
  163. package/src/daemon/conversation-agent-loop-handlers.ts +20 -0
  164. package/src/daemon/conversation-agent-loop.ts +179 -65
  165. package/src/daemon/conversation-attachments.ts +0 -1
  166. package/src/daemon/conversation-history.ts +4 -19
  167. package/src/daemon/conversation-lifecycle.ts +8 -14
  168. package/src/daemon/conversation-messaging.ts +3 -0
  169. package/src/daemon/conversation-process.ts +30 -8
  170. package/src/daemon/conversation-queue-manager.ts +8 -0
  171. package/src/daemon/conversation-runtime-assembly.ts +359 -308
  172. package/src/daemon/conversation-surfaces.ts +65 -0
  173. package/src/daemon/conversation-tool-setup.ts +44 -17
  174. package/src/daemon/conversation-workspace.ts +1 -2
  175. package/src/daemon/conversation.ts +19 -3
  176. package/src/daemon/date-context.ts +26 -53
  177. package/src/daemon/first-greeting.ts +1 -1
  178. package/src/daemon/handlers/conversations.ts +5 -7
  179. package/src/daemon/handlers/shared.test.ts +143 -0
  180. package/src/daemon/handlers/shared.ts +70 -5
  181. package/src/daemon/handlers/skills.ts +11 -18
  182. package/src/daemon/lifecycle.ts +220 -158
  183. package/src/daemon/message-types/conversations.ts +29 -6
  184. package/src/daemon/message-types/messages.ts +9 -2
  185. package/src/daemon/message-types/notifications.ts +12 -0
  186. package/src/daemon/message-types/schedules.ts +1 -0
  187. package/src/daemon/message-types/settings.ts +18 -0
  188. package/src/daemon/profiler-run-store.ts +557 -0
  189. package/src/daemon/server.ts +87 -10
  190. package/src/daemon/shutdown-handlers.ts +5 -0
  191. package/src/daemon/tool-side-effects.ts +23 -3
  192. package/src/daemon/transport-hints.ts +33 -0
  193. package/src/export/transcript-formatter.ts +148 -0
  194. package/src/filing/filing-service.ts +228 -0
  195. package/src/heartbeat/heartbeat-service.ts +96 -7
  196. package/src/index.ts +1 -1
  197. package/src/mcp/client.ts +6 -0
  198. package/src/mcp/mcp-oauth-provider.ts +149 -27
  199. package/src/memory/admin.ts +33 -32
  200. package/src/memory/app-store.ts +69 -0
  201. package/src/memory/conversation-bootstrap.ts +1 -1
  202. package/src/memory/conversation-crud.ts +151 -117
  203. package/src/memory/conversation-directories.ts +39 -0
  204. package/src/memory/conversation-group-migration.ts +66 -6
  205. package/src/memory/conversation-queries.ts +58 -12
  206. package/src/memory/conversation-title-service.ts +1 -0
  207. package/src/memory/db-init.ts +182 -376
  208. package/src/memory/embedding-local.ts +1 -1
  209. package/src/memory/graph/bootstrap.ts +75 -66
  210. package/src/memory/graph/capability-seed.ts +167 -17
  211. package/src/memory/graph/consolidation.ts +38 -4
  212. package/src/memory/graph/conversation-graph-memory.ts +133 -104
  213. package/src/memory/graph/extraction-job.ts +9 -4
  214. package/src/memory/graph/extraction.ts +66 -23
  215. package/src/memory/graph/graph-memory-state-store.ts +37 -0
  216. package/src/memory/graph/graph-search.ts +29 -15
  217. package/src/memory/graph/injection.ts +38 -8
  218. package/src/memory/graph/inspect.ts +12 -3
  219. package/src/memory/graph/retriever.ts +365 -262
  220. package/src/memory/graph/store.test.ts +48 -0
  221. package/src/memory/graph/store.ts +150 -11
  222. package/src/memory/graph/tool-handlers.ts +84 -209
  223. package/src/memory/graph/tools.ts +8 -52
  224. package/src/memory/graph/types.ts +24 -0
  225. package/src/memory/group-crud.ts +25 -9
  226. package/src/memory/job-handlers/cleanup.ts +44 -1
  227. package/src/memory/jobs-store.ts +70 -60
  228. package/src/memory/jobs-worker.ts +44 -28
  229. package/src/memory/llm-request-log-store.ts +96 -12
  230. package/src/memory/memory-recall-log-store.ts +49 -5
  231. package/src/memory/migrations/203-drop-memory-items-tables.ts +33 -1
  232. package/src/memory/migrations/206-memory-graph-node-edits.ts +19 -0
  233. package/src/memory/migrations/206-scrub-corrupted-image-attachments.ts +131 -0
  234. package/src/memory/migrations/207-conversation-graph-memory-state.ts +20 -0
  235. package/src/memory/migrations/208-conversations-last-message-at.ts +35 -0
  236. package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +85 -0
  237. package/src/memory/migrations/210-schedule-reuse-conversation.ts +13 -0
  238. package/src/memory/migrations/211-memory-recall-logs-query-context.ts +21 -0
  239. package/src/memory/migrations/212-llm-request-logs-created-at-index.ts +19 -0
  240. package/src/memory/migrations/index.ts +8 -0
  241. package/src/memory/migrations/registry.ts +8 -0
  242. package/src/memory/schema/conversations.ts +14 -0
  243. package/src/memory/schema/infrastructure.ts +8 -1
  244. package/src/memory/schema/memory-core.ts +0 -51
  245. package/src/memory/schema/memory-graph.ts +15 -0
  246. package/src/memory/task-memory-cleanup.ts +30 -11
  247. package/src/messaging/provider.ts +1 -1
  248. package/src/notifications/broadcaster.ts +6 -0
  249. package/src/notifications/conversation-pairing.ts +12 -4
  250. package/src/notifications/copy-composer.ts +86 -0
  251. package/src/notifications/decision-engine.ts +35 -0
  252. package/src/notifications/emit-signal.ts +14 -0
  253. package/src/notifications/signal.ts +11 -0
  254. package/src/oauth/platform-connection.test.ts +2 -2
  255. package/src/oauth/seed-providers.ts +1 -0
  256. package/src/permissions/checker.ts +15 -4
  257. package/src/permissions/defaults.ts +7 -8
  258. package/src/permissions/permission-mode-store.ts +180 -0
  259. package/src/permissions/permission-mode.ts +31 -0
  260. package/src/permissions/prompter.ts +0 -2
  261. package/src/permissions/workspace-policy.ts +9 -0
  262. package/src/platform/client.ts +1 -1
  263. package/src/prompts/system-prompt.ts +59 -7
  264. package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +100 -0
  265. package/src/prompts/templates/BOOTSTRAP.md +76 -162
  266. package/src/prompts/templates/HEARTBEAT.md +3 -1
  267. package/src/prompts/templates/SOUL.md +30 -9
  268. package/src/prompts/templates/UPDATES.md +8 -0
  269. package/src/providers/anthropic/client.ts +107 -219
  270. package/src/runtime/assistant-event-hub.ts +22 -0
  271. package/src/runtime/auth/route-policy.ts +23 -0
  272. package/src/runtime/auth/token-service.ts +8 -0
  273. package/src/runtime/http-server.ts +32 -2
  274. package/src/runtime/http-types.ts +12 -1
  275. package/src/runtime/migrations/vbundle-builder.ts +389 -3
  276. package/src/runtime/migrations/vbundle-importer.ts +8 -6
  277. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +378 -0
  278. package/src/runtime/routes/app-management-routes.ts +1 -11
  279. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +26 -0
  280. package/src/runtime/routes/archive-utils.ts +29 -0
  281. package/src/runtime/routes/avatar-routes.ts +2 -9
  282. package/src/runtime/routes/btw-routes.ts +14 -1
  283. package/src/runtime/routes/conversation-analysis-routes.ts +185 -0
  284. package/src/runtime/routes/conversation-management-routes.ts +1 -14
  285. package/src/runtime/routes/conversation-query-routes.ts +49 -3
  286. package/src/runtime/routes/conversation-routes.ts +270 -44
  287. package/src/runtime/routes/group-routes.ts +22 -8
  288. package/src/runtime/routes/heartbeat-routes.ts +4 -10
  289. package/src/runtime/routes/identity-routes.ts +53 -18
  290. package/src/runtime/routes/llm-context-normalization.ts +14 -10
  291. package/src/runtime/routes/log-export/AGENTS.md +104 -0
  292. package/src/runtime/routes/log-export/__tests__/workspace-allowlist-error-contract.test.ts +103 -0
  293. package/src/runtime/routes/log-export/__tests__/workspace-allowlist.test.ts +716 -0
  294. package/src/runtime/routes/log-export/workspace-allowlist.ts +458 -0
  295. package/src/runtime/routes/log-export-routes.ts +41 -278
  296. package/src/runtime/routes/memory-item-routes.test.ts +168 -233
  297. package/src/runtime/routes/migration-routes.ts +18 -7
  298. package/src/runtime/routes/profiler-routes.ts +350 -0
  299. package/src/runtime/routes/schedule-routes.ts +27 -12
  300. package/src/runtime/routes/settings-routes.ts +95 -8
  301. package/src/runtime/routes/subagents-routes.ts +28 -7
  302. package/src/runtime/routes/user-route-dispatcher.ts +223 -0
  303. package/src/runtime/routes/user-routes.ts +41 -0
  304. package/src/runtime/routes/workspace-routes.ts +0 -1
  305. package/src/schedule/schedule-store.ts +30 -0
  306. package/src/schedule/scheduler.ts +45 -18
  307. package/src/skills/catalog-install.ts +10 -2
  308. package/src/skills/inline-command-runner.ts +12 -14
  309. package/src/skills/managed-store.ts +2 -2
  310. package/src/skills/skill-memory.ts +1 -293
  311. package/src/subagent/index.ts +13 -3
  312. package/src/subagent/manager.ts +308 -29
  313. package/src/subagent/types.ts +68 -0
  314. package/src/tasks/task-runner.ts +4 -4
  315. package/src/tools/apps/executors.ts +29 -4
  316. package/src/tools/filesystem/list.ts +93 -0
  317. package/src/tools/permission-checker.ts +78 -18
  318. package/src/tools/registry.ts +4 -0
  319. package/src/tools/schedule/create.ts +3 -0
  320. package/src/tools/schedule/list.ts +1 -0
  321. package/src/tools/schedule/update.ts +6 -0
  322. package/src/tools/secret-detection-handler.ts +0 -1
  323. package/src/tools/shared/filesystem/errors.ts +5 -0
  324. package/src/tools/shared/filesystem/file-ops-service.ts +90 -2
  325. package/src/tools/shared/filesystem/types.ts +17 -0
  326. package/src/tools/shared/shell-output.ts +31 -2
  327. package/src/tools/skills/sandbox-runner.ts +3 -6
  328. package/src/tools/subagent/abort.ts +12 -2
  329. package/src/tools/subagent/message.ts +9 -2
  330. package/src/tools/subagent/notify-parent.ts +79 -0
  331. package/src/tools/subagent/read.ts +29 -8
  332. package/src/tools/subagent/resolve.ts +21 -0
  333. package/src/tools/subagent/spawn.ts +2 -0
  334. package/src/tools/subagent/status.ts +11 -1
  335. package/src/tools/system/avatar-generator.ts +3 -3
  336. package/src/tools/system/register.ts +23 -0
  337. package/src/tools/system/set-permission-mode.ts +103 -0
  338. package/src/tools/terminal/parser.ts +30 -5
  339. package/src/tools/terminal/safe-env.ts +16 -1
  340. package/src/tools/terminal/sandbox-diagnostics.ts +4 -4
  341. package/src/tools/terminal/sandbox.ts +4 -1
  342. package/src/tools/terminal/shell.ts +3 -5
  343. package/src/tools/tool-manifest.ts +6 -0
  344. package/src/tools/types.ts +2 -3
  345. package/src/util/logger.ts +1 -1
  346. package/src/util/platform.ts +50 -17
  347. package/src/watcher/provider-types.ts +1 -1
  348. package/src/workspace/migrations/023-move-config-files-to-workspace.ts +2 -2
  349. package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +2 -2
  350. package/src/workspace/migrations/028-recover-conversations-from-disk-view.ts +270 -0
  351. package/src/workspace/migrations/029-seed-pkb.ts +85 -0
  352. package/src/workspace/migrations/030-seed-pkb-autoinject.ts +73 -0
  353. package/src/workspace/migrations/registry.ts +6 -0
  354. package/src/workspace/top-level-renderer.ts +5 -9
  355. package/src/__tests__/cli-memory.test.ts +0 -377
  356. package/src/__tests__/clipboard.test.ts +0 -88
  357. package/src/cli/cli-memory.ts +0 -179
  358. package/src/util/clipboard.ts +0 -34
@@ -81,6 +81,8 @@ export interface HistorySurface {
81
81
  data: Record<string, unknown>;
82
82
  actions?: Array<{ id: string; label: string; style?: string }>;
83
83
  display?: string;
84
+ completed?: boolean;
85
+ completionSummary?: string;
84
86
  }
85
87
 
86
88
  export interface RenderedHistoryContent {
@@ -281,6 +283,11 @@ export function renderHistoryContent(content: unknown): RenderedHistoryContent {
281
283
  : {},
282
284
  actions: Array.isArray(block.actions) ? block.actions : undefined,
283
285
  display: typeof block.display === "string" ? block.display : undefined,
286
+ completed: block.completed === true ? true : undefined,
287
+ completionSummary:
288
+ typeof block.completionSummary === "string"
289
+ ? block.completionSummary
290
+ : undefined,
284
291
  };
285
292
  surfaces.push(surface);
286
293
  contentOrder.push(`surface:${surfaces.length - 1}`);
@@ -497,13 +504,71 @@ export function ensureSkillEntry(
497
504
  return entries[name] as Record<string, unknown>;
498
505
  }
499
506
 
500
- /** Compare two semver strings. Returns negative if a < b, 0 if equal, positive if a > b. */
507
+ /**
508
+ * Parse a version string into its core numeric parts and optional pre-release tag.
509
+ * Handles optional `v`/`V` prefix (e.g. "v0.6.0-staging.5").
510
+ */
511
+ function parseSemverParts(v: string): {
512
+ nums: [number, number, number];
513
+ pre: string | null;
514
+ } {
515
+ const stripped = v.replace(/^[vV]/, "");
516
+ const [core, ...rest] = stripped.split("-");
517
+ const pre = rest.length > 0 ? rest.join("-") : null;
518
+ const segs = (core ?? "").split(".").map(Number);
519
+ return {
520
+ nums: [segs[0] || 0, segs[1] || 0, segs[2] || 0],
521
+ pre,
522
+ };
523
+ }
524
+
525
+ /**
526
+ * Compare two pre-release strings per semver §11:
527
+ * - Dot-separated identifiers compared left to right.
528
+ * - Both numeric → compare as integers.
529
+ * - Both non-numeric → compare lexically.
530
+ * - Numeric vs non-numeric → numeric sorts lower (§11.4.4).
531
+ * - Fewer identifiers sorts earlier when all preceding are equal.
532
+ */
533
+ function comparePreRelease(a: string, b: string): number {
534
+ const pa = a.split(".");
535
+ const pb = b.split(".");
536
+ const len = Math.max(pa.length, pb.length);
537
+ for (let i = 0; i < len; i++) {
538
+ if (i >= pa.length) return -1; // a has fewer fields → a < b
539
+ if (i >= pb.length) return 1;
540
+ const aIsNum = /^\d+$/.test(pa[i]);
541
+ const bIsNum = /^\d+$/.test(pb[i]);
542
+ if (aIsNum && bIsNum) {
543
+ const diff = Number(pa[i]) - Number(pb[i]);
544
+ if (diff !== 0) return diff;
545
+ } else if (aIsNum !== bIsNum) {
546
+ return aIsNum ? -1 : 1; // numeric < non-numeric per §11.4.4
547
+ } else {
548
+ const cmp = (pa[i] ?? "").localeCompare(pb[i] ?? "");
549
+ if (cmp !== 0) return cmp;
550
+ }
551
+ }
552
+ return 0;
553
+ }
554
+
555
+ /**
556
+ * Compare two semver strings. Returns negative if a < b, 0 if equal, positive if a > b.
557
+ *
558
+ * Handles pre-release suffixes per semver spec:
559
+ * - `0.6.0-staging.1 < 0.6.0` (pre-release < release)
560
+ * - `0.6.0-staging.1 < 0.6.0-staging.2` (numeric postfix comparison)
561
+ */
501
562
  export function compareSemver(a: string, b: string): number {
502
- const pa = a.split(".").map(Number);
503
- const pb = b.split(".").map(Number);
563
+ const pa = parseSemverParts(a);
564
+ const pb = parseSemverParts(b);
504
565
  for (let i = 0; i < 3; i++) {
505
- const diff = (pa[i] ?? 0) - (pb[i] ?? 0);
566
+ const diff = pa.nums[i] - pb.nums[i];
506
567
  if (diff !== 0) return diff;
507
568
  }
508
- return 0;
569
+ // Same major.minor.patch — compare pre-release
570
+ if (pa.pre === null && pb.pre === null) return 0;
571
+ if (pa.pre !== null && pb.pre === null) return -1; // pre-release < release
572
+ if (pa.pre === null && pb.pre !== null) return 1;
573
+ return comparePreRelease(pa.pre!, pb.pre!);
509
574
  }
@@ -20,6 +20,11 @@ import {
20
20
  } from "../../config/loader.js";
21
21
  import { resolveSkillStates, skillFlagKey } from "../../config/skill-state.js";
22
22
  import { loadSkillCatalog, type SkillSummary } from "../../config/skills.js";
23
+ import {
24
+ deleteSkillCapabilityNode,
25
+ seedSkillGraphNodes,
26
+ seedUninstalledCatalogSkillMemories,
27
+ } from "../../memory/graph/capability-seed.js";
23
28
  import {
24
29
  createTimeout,
25
30
  extractText,
@@ -51,11 +56,6 @@ import {
51
56
  removeSkillsIndexEntry,
52
57
  validateManagedSkillId,
53
58
  } from "../../skills/managed-store.js";
54
- import {
55
- deleteSkillCapabilityMemory,
56
- seedCatalogSkillMemories,
57
- seedUninstalledCatalogSkillMemories,
58
- } from "../../skills/skill-memory.js";
59
59
  import {
60
60
  installExternalSkill,
61
61
  resolveSkillSource,
@@ -242,7 +242,7 @@ export function postInstallSkill(
242
242
  }
243
243
 
244
244
  // Seed skill memories
245
- seedCatalogSkillMemories();
245
+ seedSkillGraphNodes();
246
246
  void seedUninstalledCatalogSkillMemories().catch(() => {});
247
247
  }
248
248
 
@@ -603,7 +603,7 @@ export function enableSkill(
603
603
  name: skillId,
604
604
  state: "enabled",
605
605
  });
606
- seedCatalogSkillMemories();
606
+ seedSkillGraphNodes();
607
607
  void seedUninstalledCatalogSkillMemories().catch(() => {});
608
608
  return { success: true };
609
609
  } catch (err) {
@@ -626,7 +626,7 @@ export function disableSkill(
626
626
  name: skillId,
627
627
  state: "disabled",
628
628
  });
629
- seedCatalogSkillMemories();
629
+ seedSkillGraphNodes();
630
630
  void seedUninstalledCatalogSkillMemories().catch(() => {});
631
631
  return { success: true };
632
632
  } catch (err) {
@@ -719,7 +719,7 @@ export async function installSkill(
719
719
  "Failed to auto-enable bundled skill",
720
720
  );
721
721
  }
722
- seedCatalogSkillMemories();
722
+ seedSkillGraphNodes();
723
723
  void seedUninstalledCatalogSkillMemories().catch(() => {});
724
724
  return { success: true };
725
725
  }
@@ -847,14 +847,7 @@ export async function uninstallSkill(
847
847
  }
848
848
  // Best-effort cleanup of capability memory for uninstalled skill
849
849
  // (managed path handles this internally via deleteManagedSkill)
850
- deleteSkillCapabilityMemory(skillId);
851
- try {
852
- const { deleteSkillCapabilityNode } =
853
- await import("../../memory/graph/capability-seed.js");
854
- deleteSkillCapabilityNode(skillId);
855
- } catch {
856
- /* best effort */
857
- }
850
+ deleteSkillCapabilityNode(skillId);
858
851
  }
859
852
 
860
853
  // Clean config entry
@@ -1255,7 +1248,7 @@ export async function createSkill(
1255
1248
  );
1256
1249
  }
1257
1250
 
1258
- seedCatalogSkillMemories();
1251
+ seedSkillGraphNodes();
1259
1252
  void seedUninstalledCatalogSkillMemories().catch(() => {});
1260
1253
  return { success: true };
1261
1254
  } catch (err) {
@@ -5,7 +5,7 @@ import { reconcileCallsOnStartup } from "../calls/call-recovery.js";
5
5
  import { setRelayBroadcast } from "../calls/relay-server.js";
6
6
  import { TwilioConversationRelayProvider } from "../calls/twilio-provider.js";
7
7
  import { setVoiceBridgeDeps } from "../calls/voice-session-bridge.js";
8
- import { seedCliCommandMemories } from "../cli/cli-memory.js";
8
+ import { initFeatureFlagOverrides } from "../config/assistant-feature-flags.js";
9
9
  import {
10
10
  getPlatformAssistantId,
11
11
  getQdrantHttpPortEnv,
@@ -32,6 +32,7 @@ import {
32
32
  awaitCesClientWithTimeout,
33
33
  DEFAULT_CES_STARTUP_TIMEOUT_MS,
34
34
  } from "../credential-execution/startup-timeout.js";
35
+ import { FilingService } from "../filing/filing-service.js";
35
36
  import { HeartbeatService } from "../heartbeat/heartbeat-service.js";
36
37
  import { getHookManager } from "../hooks/manager.js";
37
38
  import { installTemplates } from "../hooks/templates.js";
@@ -82,10 +83,6 @@ import {
82
83
  setCesClient,
83
84
  setCesReconnect,
84
85
  } from "../security/secure-keys.js";
85
- import {
86
- seedCatalogSkillMemories,
87
- seedUninstalledCatalogSkillMemories,
88
- } from "../skills/skill-memory.js";
89
86
  import { UsageTelemetryReporter } from "../telemetry/usage-telemetry-reporter.js";
90
87
  import { getDeviceId } from "../util/device-id.js";
91
88
  import { getLogger, initLogger } from "../util/logger.js";
@@ -127,6 +124,7 @@ import {
127
124
  } from "./handlers/conversations.js";
128
125
  import { installAssistantSymlink } from "./install-symlink.js";
129
126
  import type { ServerMessage } from "./message-protocol.js";
127
+ import { runProfilerSweep } from "./profiler-run-store.js";
130
128
  import {
131
129
  initializeProvidersAndTools,
132
130
  registerMessagingProviders,
@@ -272,6 +270,15 @@ export async function runDaemon(): Promise<void> {
272
270
  const signingKey = resolveSigningKey();
273
271
  initAuthSigningKey(signingKey);
274
272
 
273
+ // Pre-populate the feature flag cache from the gateway so all
274
+ // subsequent sync isAssistantFeatureFlagEnabled() calls have data.
275
+ // Fired non-blocking so a slow or unreachable gateway doesn't delay
276
+ // daemon startup (the fetch has a 10s timeout that would otherwise
277
+ // stall the critical path).
278
+ void initFeatureFlagOverrides().catch((err) =>
279
+ log.warn({ err }, "Background feature flag init failed"),
280
+ );
281
+
275
282
  seedInterfaceFiles();
276
283
 
277
284
  log.info("Daemon startup: installing templates and initializing DB");
@@ -282,151 +289,191 @@ export async function runDaemon(): Promise<void> {
282
289
  // workspace migrations (e.g. 009-backfill-conversation-disk-view)
283
290
  // depend on DB migrations having run (e.g. the inline-attachment-to-disk
284
291
  // backfill that populates attachment filePaths).
285
- initializeDb();
286
- // Seed well-known OAuth provider configurations (insert-if-not-exists)
287
- seedOAuthProviders();
288
- log.info("Daemon startup: DB initialized");
289
-
290
- await runWorkspaceMigrations(getWorkspaceDir(), WORKSPACE_MIGRATIONS);
291
- log.info("Daemon startup: workspace migrations complete");
292
-
293
- // Backfill oauth_connection rows for manual-token providers (Telegram,
294
- // Slack channel) that already have stored credentials from before the
295
- // oauth_connection migration. Safe to call on every startup.
296
292
  //
297
- // Must run AFTER workspace migrations.
298
- // Otherwise syncManualTokenConnection sees no stored credentials and
299
- // incorrectly removes existing connection rows.
293
+ // If DB initialization fails (e.g. a migration error), the daemon
294
+ // continues in a degraded state DB-dependent features won't work but
295
+ // the HTTP server and config-based subsystems still start so the process
296
+ // remains reachable for health checks and diagnostics.
297
+ let dbReady = false;
300
298
  try {
301
- await backfillManualTokenConnections();
299
+ initializeDb();
300
+ dbReady = true;
301
+ log.info("Daemon startup: DB initialized");
302
302
  } catch (err) {
303
- log.warn(
303
+ log.error(
304
304
  { err },
305
- "Manual-token connection backfill failed — continuing startup",
305
+ "DB initialization failed — continuing startup in degraded mode",
306
306
  );
307
307
  }
308
308
 
309
- // Backfill injection templates on Slack bot token credentials so the
310
- // credential proxy can inject Authorization headers. Safe on every startup.
311
- try {
312
- backfillSlackInjectionTemplates();
313
- } catch (err) {
314
- log.warn(
315
- { err },
316
- "Slack injection template backfill failed — continuing startup",
317
- );
309
+ // Seed well-known OAuth provider configurations (insert-if-not-exists).
310
+ // Runs in its own try/catch so a seeding error doesn't force degraded mode
311
+ // when the DB itself initialized successfully.
312
+ if (dbReady) {
313
+ try {
314
+ seedOAuthProviders();
315
+ } catch (err) {
316
+ log.warn({ err }, "OAuth provider seeding failed — continuing startup");
317
+ }
318
318
  }
319
319
 
320
- // Now that workspace migrations have run (including 003-seed-device-id
321
- // which may copy the legacy installationId into device.json), it is safe
322
- // to read the device ID and set the Sentry tag.
323
- setSentryDeviceId(getDeviceId());
320
+ if (dbReady) {
321
+ await runWorkspaceMigrations(getWorkspaceDir(), WORKSPACE_MIGRATIONS);
322
+ log.info("Daemon startup: workspace migrations complete");
324
323
 
325
- // Purge private (temporary) conversations from the previous daemon run.
326
- // These are ephemeral by design and should not survive daemon restarts.
327
- const { count: purgedCount, deletedMemory } = purgePrivateConversations();
328
- if (purgedCount > 0) {
329
- log.info(
330
- { purgedCount },
331
- `Purged ${purgedCount} private conversation(s) from previous daemon run`,
332
- );
333
- // Qdrant may not be ready at startup, so enqueue vector cleanup jobs
334
- // rather than attempting direct deletion.
335
- for (const segId of deletedMemory.segmentIds) {
336
- enqueueMemoryJob("delete_qdrant_vectors", {
337
- targetType: "segment",
338
- targetId: segId,
339
- });
324
+ // Profiler retention sweep prune completed profiler runs to stay
325
+ // within configured byte-count, run-count, and free-space budgets.
326
+ // Runs on every startup and is safe to call from explicit cleanup routes.
327
+ try {
328
+ const sweepResult = runProfilerSweep();
329
+ if (sweepResult.prunedCount > 0 || sweepResult.activeRunOverBudget) {
330
+ log.info(
331
+ {
332
+ prunedCount: sweepResult.prunedCount,
333
+ freedBytes: sweepResult.freedBytes,
334
+ activeRunOverBudget: sweepResult.activeRunOverBudget,
335
+ remainingRuns: sweepResult.remainingRuns,
336
+ },
337
+ "Profiler retention sweep completed on startup",
338
+ );
339
+ }
340
+ } catch (err) {
341
+ log.warn(
342
+ { err },
343
+ "Profiler retention sweep failed — continuing startup",
344
+ );
340
345
  }
341
- for (const itemId of deletedMemory.orphanedItemIds) {
342
- enqueueMemoryJob("delete_qdrant_vectors", {
343
- targetType: "item",
344
- targetId: itemId,
345
- });
346
+
347
+ // Backfill oauth_connection rows for manual-token providers (Telegram,
348
+ // Slack channel) that already have stored credentials from before the
349
+ // oauth_connection migration. Safe to call on every startup.
350
+ //
351
+ // Must run AFTER workspace migrations.
352
+ // Otherwise syncManualTokenConnection sees no stored credentials and
353
+ // incorrectly removes existing connection rows.
354
+ try {
355
+ await backfillManualTokenConnections();
356
+ } catch (err) {
357
+ log.warn(
358
+ { err },
359
+ "Manual-token connection backfill failed — continuing startup",
360
+ );
346
361
  }
347
- for (const summaryId of deletedMemory.deletedSummaryIds) {
348
- enqueueMemoryJob("delete_qdrant_vectors", {
349
- targetType: "summary",
350
- targetId: summaryId,
351
- });
362
+
363
+ // Backfill injection templates on Slack bot token credentials so the
364
+ // credential proxy can inject Authorization headers. Safe on every startup.
365
+ try {
366
+ backfillSlackInjectionTemplates();
367
+ } catch (err) {
368
+ log.warn(
369
+ { err },
370
+ "Slack injection template backfill failed — continuing startup",
371
+ );
352
372
  }
353
- if (
354
- deletedMemory.segmentIds.length > 0 ||
355
- deletedMemory.orphanedItemIds.length > 0 ||
356
- deletedMemory.deletedSummaryIds.length > 0
357
- ) {
373
+
374
+ // Now that workspace migrations have run (including 003-seed-device-id
375
+ // which may copy the legacy installationId into device.json), it is safe
376
+ // to read the device ID and set the Sentry tag.
377
+ setSentryDeviceId(getDeviceId());
378
+
379
+ // Purge private (temporary) conversations from the previous daemon run.
380
+ // These are ephemeral by design and should not survive daemon restarts.
381
+ const { count: purgedCount, deletedMemory } = purgePrivateConversations();
382
+ if (purgedCount > 0) {
358
383
  log.info(
359
- {
360
- segments: deletedMemory.segmentIds.length,
361
- orphanedItems: deletedMemory.orphanedItemIds.length,
362
- deletedSummaries: deletedMemory.deletedSummaryIds.length,
363
- },
364
- "Enqueued Qdrant vector cleanup jobs for purged private conversations",
384
+ { purgedCount },
385
+ `Purged ${purgedCount} private conversation(s) from previous daemon run`,
365
386
  );
387
+ // Qdrant may not be ready at startup, so enqueue vector cleanup jobs
388
+ // rather than attempting direct deletion.
389
+ for (const segId of deletedMemory.segmentIds) {
390
+ enqueueMemoryJob("delete_qdrant_vectors", {
391
+ targetType: "segment",
392
+ targetId: segId,
393
+ });
394
+ }
395
+ for (const summaryId of deletedMemory.deletedSummaryIds) {
396
+ enqueueMemoryJob("delete_qdrant_vectors", {
397
+ targetType: "summary",
398
+ targetId: summaryId,
399
+ });
400
+ }
401
+ if (
402
+ deletedMemory.segmentIds.length > 0 ||
403
+ deletedMemory.deletedSummaryIds.length > 0
404
+ ) {
405
+ log.info(
406
+ {
407
+ segments: deletedMemory.segmentIds.length,
408
+ deletedSummaries: deletedMemory.deletedSummaryIds.length,
409
+ },
410
+ "Enqueued Qdrant vector cleanup jobs for purged private conversations",
411
+ );
412
+ }
366
413
  }
367
- }
368
414
 
369
- // Expire stale pending canonical guardian requests left over from before
370
- // this process started. Two categories are cleaned up:
371
- //
372
- // 1. Interaction-bound kinds (tool_approval, pending_question) — their
373
- // in-memory pending-interaction session references are gone, so they
374
- // can never be completed.
375
- // 2. Any pending request whose expiresAt has already passed — persistent
376
- // kinds (access_request, tool_grant_request) that expired while the
377
- // daemon was stopped are transitioned so dedup logic doesn't return
378
- // stale rows.
379
- const expiredCount = expireAllPendingCanonicalRequests();
380
- if (expiredCount > 0) {
381
- log.info(
382
- { event: "startup_expired_stale_requests", expiredCount },
383
- `Expired ${expiredCount} stale canonical request(s) from previous process`,
384
- );
385
- }
415
+ // Expire stale pending canonical guardian requests left over from before
416
+ // this process started. Two categories are cleaned up:
417
+ //
418
+ // 1. Interaction-bound kinds (tool_approval, pending_question) — their
419
+ // in-memory pending-interaction session references are gone, so they
420
+ // can never be completed.
421
+ // 2. Any pending request whose expiresAt has already passed — persistent
422
+ // kinds (access_request, tool_grant_request) that expired while the
423
+ // daemon was stopped are transitioned so dedup logic doesn't return
424
+ // stale rows.
425
+ const expiredCount = expireAllPendingCanonicalRequests();
426
+ if (expiredCount > 0) {
427
+ log.info(
428
+ { event: "startup_expired_stale_requests", expiredCount },
429
+ `Expired ${expiredCount} stale canonical request(s) from previous process`,
430
+ );
431
+ }
386
432
 
387
- // Ensure a vellum guardian binding exists so the identity system works
388
- // without requiring a manual bootstrap step.
389
- try {
390
- ensureVellumGuardianBinding(DAEMON_INTERNAL_ASSISTANT_ID);
391
- } catch (err) {
392
- log.warn(
393
- { err },
394
- "Vellum guardian binding backfill failed — continuing startup",
395
- );
396
- }
433
+ // Ensure a vellum guardian binding exists so the identity system works
434
+ // without requiring a manual bootstrap step.
435
+ try {
436
+ ensureVellumGuardianBinding(DAEMON_INTERNAL_ASSISTANT_ID);
437
+ } catch (err) {
438
+ log.warn(
439
+ { err },
440
+ "Vellum guardian binding backfill failed — continuing startup",
441
+ );
442
+ }
397
443
 
398
- try {
399
- syncUpdateBulletinOnStartup();
400
- } catch (err) {
401
- log.warn({ err }, "Bulletin sync failed — continuing startup");
402
- }
444
+ try {
445
+ syncUpdateBulletinOnStartup();
446
+ } catch (err) {
447
+ log.warn({ err }, "Bulletin sync failed — continuing startup");
448
+ }
403
449
 
404
- // Recover orphaned work items that were left in 'running' state when the
405
- // daemon previously crashed or was killed mid-task.
406
- const orphanedRunning = listWorkItems({ status: "running" });
407
- if (orphanedRunning.length > 0) {
408
- for (const item of orphanedRunning) {
409
- updateWorkItem(item.id, {
410
- status: "failed",
411
- lastRunStatus: "interrupted",
412
- });
450
+ // Recover orphaned work items that were left in 'running' state when the
451
+ // daemon previously crashed or was killed mid-task.
452
+ const orphanedRunning = listWorkItems({ status: "running" });
453
+ if (orphanedRunning.length > 0) {
454
+ for (const item of orphanedRunning) {
455
+ updateWorkItem(item.id, {
456
+ status: "failed",
457
+ lastRunStatus: "interrupted",
458
+ });
459
+ log.info(
460
+ { workItemId: item.id, title: item.title },
461
+ "Recovered orphaned running work item → failed (interrupted)",
462
+ );
463
+ }
413
464
  log.info(
414
- { workItemId: item.id, title: item.title },
415
- "Recovered orphaned running work item → failed (interrupted)",
465
+ { count: orphanedRunning.length },
466
+ "Recovered orphaned running work items",
416
467
  );
417
468
  }
418
- log.info(
419
- { count: orphanedRunning.length },
420
- "Recovered orphaned running work items",
421
- );
422
- }
423
469
 
424
- try {
425
- const twilioProvider = new TwilioConversationRelayProvider();
426
- await reconcileCallsOnStartup(twilioProvider, log);
427
- } catch (err) {
428
- log.warn({ err }, "Call recovery failed — continuing startup");
429
- }
470
+ try {
471
+ const twilioProvider = new TwilioConversationRelayProvider();
472
+ await reconcileCallsOnStartup(twilioProvider, log);
473
+ } catch (err) {
474
+ log.warn({ err }, "Call recovery failed — continuing startup");
475
+ }
476
+ } // end if (dbReady)
430
477
 
431
478
  // Merge CLI-provided default config (from VELLUM_DEFAULT_WORKSPACE_CONFIG_PATH)
432
479
  // into the workspace config file before the first loadConfig() call so
@@ -645,35 +692,21 @@ export async function runDaemon(): Promise<void> {
645
692
  log.info("Daemon startup: starting memory worker");
646
693
  bgRefs.memoryWorker = startMemoryJobsWorker();
647
694
 
648
- // Seed capability memories for all enabled skills so the memory
649
- // pipeline can surface relevant skills via semantic search.
650
- try {
651
- seedCatalogSkillMemories();
652
- } catch (err) {
653
- log.warn({ err }, "Catalog skill memory seeding failed — continuing");
654
- }
655
-
656
- // Seed memories for catalog skills not yet installed so they're
657
- // discoverable via memory injection and can be auto-installed.
658
- void seedUninstalledCatalogSkillMemories().catch((err) =>
659
- log.warn(
660
- { err },
661
- "Uninstalled catalog skill memory seeding failed — continuing",
662
- ),
663
- );
664
-
665
- try {
666
- seedCliCommandMemories();
667
- } catch (err) {
668
- log.warn({ err }, "CLI command memory seeding failed — continuing");
669
- }
670
-
671
695
  // Seed capability graph nodes (new memory graph system)
672
696
  try {
673
- const { seedSkillGraphNodes, seedCliGraphNodes } =
674
- await import("../memory/graph/capability-seed.js");
697
+ const {
698
+ seedSkillGraphNodes,
699
+ seedCliGraphNodes,
700
+ seedUninstalledCatalogSkillMemories,
701
+ } = await import("../memory/graph/capability-seed.js");
675
702
  seedSkillGraphNodes();
676
- seedCliGraphNodes();
703
+ await seedCliGraphNodes();
704
+ void seedUninstalledCatalogSkillMemories().catch((err) =>
705
+ log.warn(
706
+ { err },
707
+ "Uninstalled catalog skill memory seeding failed — continuing",
708
+ ),
709
+ );
677
710
  } catch (err) {
678
711
  log.warn({ err }, "Graph capability seeding failed — continuing");
679
712
  }
@@ -682,10 +715,8 @@ export async function runDaemon(): Promise<void> {
682
715
  // segments exist, enqueue a one-time graph_bootstrap job to populate the
683
716
  // graph from conversation history and journal files.
684
717
  try {
685
- const {
686
- maybeEnqueueGraphBootstrap,
687
- cleanupStaleItemVectors,
688
- } = await import("../memory/graph/bootstrap.js");
718
+ const { maybeEnqueueGraphBootstrap, cleanupStaleItemVectors } =
719
+ await import("../memory/graph/bootstrap.js");
689
720
  maybeEnqueueGraphBootstrap();
690
721
  // Fire-and-forget: clean up orphaned Qdrant vectors from dropped memory_items table
691
722
  void cleanupStaleItemVectors().catch((err) =>
@@ -742,6 +773,11 @@ export async function runDaemon(): Promise<void> {
742
773
  },
743
774
  routingIntent: schedule.routingIntent,
744
775
  routingHints: schedule.routingHints,
776
+ conversationMetadata: {
777
+ groupId: "system:scheduled",
778
+ scheduleJobId: schedule.id,
779
+ source: "schedule",
780
+ },
745
781
  dedupeKey: `schedule:notify:${schedule.id}:${Date.now()}`,
746
782
  throwOnError: true,
747
783
  });
@@ -761,6 +797,11 @@ export async function runDaemon(): Promise<void> {
761
797
  scheduleId: schedule.id,
762
798
  name: schedule.name,
763
799
  },
800
+ conversationMetadata: {
801
+ groupId: "system:scheduled",
802
+ scheduleJobId: schedule.id,
803
+ source: "schedule",
804
+ },
764
805
  dedupeKey: `schedule:complete:${schedule.id}:${Date.now()}`,
765
806
  });
766
807
  },
@@ -849,8 +890,8 @@ export async function runDaemon(): Promise<void> {
849
890
  guardianFollowUpConversationGenerator:
850
891
  createGuardianFollowUpConversationGenerator(),
851
892
  sendMessageDeps: {
852
- getOrCreateConversation: (conversationId) =>
853
- server.getConversationForMessages(conversationId),
893
+ getOrCreateConversation: (conversationId, options) =>
894
+ server.getConversationForMessages(conversationId, options),
854
895
  assistantEventHub,
855
896
  resolveAttachments: (attachmentIds) => {
856
897
  const resolved = attachmentsStore.getAttachmentsByIds(attachmentIds, {
@@ -1226,6 +1267,26 @@ export async function runDaemon(): Promise<void> {
1226
1267
  "Heartbeat service configured",
1227
1268
  );
1228
1269
 
1270
+ const filingConfig = config.filing;
1271
+ const filing = new FilingService({
1272
+ processMessage: (conversationId, content, options) =>
1273
+ server.processMessage(conversationId, content, undefined, {
1274
+ trustContext: {
1275
+ sourceChannel: "vellum",
1276
+ trustClass: "guardian",
1277
+ },
1278
+ ...options,
1279
+ }),
1280
+ });
1281
+ filing.start();
1282
+ log.info(
1283
+ {
1284
+ enabled: filingConfig.enabled,
1285
+ intervalMs: filingConfig.intervalMs,
1286
+ },
1287
+ "Filing service configured",
1288
+ );
1289
+
1229
1290
  // Retrieve the MCP manager if MCP servers were configured.
1230
1291
  // The manager is a singleton created during initializeProvidersAndTools().
1231
1292
  const mcpManager =
@@ -1237,6 +1298,7 @@ export async function runDaemon(): Promise<void> {
1237
1298
  server,
1238
1299
  workspaceHeartbeat,
1239
1300
  heartbeat,
1301
+ filing,
1240
1302
  hookManager,
1241
1303
  runtimeHttp,
1242
1304
  scheduler,