@vellumai/assistant 0.5.16 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (592) hide show
  1. package/AGENTS.md +4 -0
  2. package/ARCHITECTURE.md +69 -16
  3. package/Dockerfile +2 -5
  4. package/bun.lock +6 -2
  5. package/docker-entrypoint.sh +32 -1
  6. package/docs/architecture/integrations.md +1 -1
  7. package/docs/architecture/memory.md +21 -24
  8. package/knip.json +2 -1
  9. package/openapi.yaml +1198 -83
  10. package/package.json +5 -1
  11. package/src/__tests__/actor-token-service.test.ts +68 -0
  12. package/src/__tests__/agent-loop.test.ts +0 -32
  13. package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
  14. package/src/__tests__/anthropic-provider.test.ts +217 -98
  15. package/src/__tests__/app-compiler.test.ts +120 -0
  16. package/src/__tests__/app-dir-path-guard.test.ts +1 -0
  17. package/src/__tests__/app-executors.test.ts +47 -1
  18. package/src/__tests__/app-source-watcher.test.ts +159 -0
  19. package/src/__tests__/assistant-feature-flags-integration.test.ts +2 -2
  20. package/src/__tests__/call-conversation-messages.test.ts +2 -6
  21. package/src/__tests__/call-domain.test.ts +2 -6
  22. package/src/__tests__/call-pointer-messages.test.ts +2 -14
  23. package/src/__tests__/call-recovery.test.ts +2 -6
  24. package/src/__tests__/call-routes-http.test.ts +2 -6
  25. package/src/__tests__/call-store.test.ts +2 -6
  26. package/src/__tests__/cancel-resolves-conversation-key.test.ts +2 -6
  27. package/src/__tests__/canonical-guardian-store.test.ts +2 -6
  28. package/src/__tests__/channel-delivery-store.test.ts +2 -6
  29. package/src/__tests__/channel-retry-sweep.test.ts +2 -6
  30. package/src/__tests__/checker.test.ts +63 -9
  31. package/src/__tests__/clawhub.test.ts +54 -24
  32. package/src/__tests__/cli-command-risk-guard.test.ts +14 -0
  33. package/src/__tests__/config-schema.test.ts +6 -1
  34. package/src/__tests__/config-set-platform-guard.test.ts +302 -0
  35. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +2 -6
  36. package/src/__tests__/contacts-tools.test.ts +31 -0
  37. package/src/__tests__/context-overflow-reducer.test.ts +86 -0
  38. package/src/__tests__/context-token-estimator.test.ts +175 -10
  39. package/src/__tests__/conversation-agent-loop-overflow.test.ts +13 -6
  40. package/src/__tests__/conversation-agent-loop.test.ts +13 -51
  41. package/src/__tests__/conversation-attachments.test.ts +2 -6
  42. package/src/__tests__/conversation-attention-store.test.ts +2 -6
  43. package/src/__tests__/conversation-clear-safety.test.ts +2 -6
  44. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +4 -10
  45. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -6
  46. package/src/__tests__/conversation-disk-view.test.ts +2 -6
  47. package/src/__tests__/conversation-error.test.ts +33 -2
  48. package/src/__tests__/conversation-fork-crud.test.ts +2 -6
  49. package/src/__tests__/conversation-history-web-search.test.ts +6 -1
  50. package/src/__tests__/conversation-load-history-repair.test.ts +5 -1
  51. package/src/__tests__/conversation-media-retry.test.ts +91 -0
  52. package/src/__tests__/conversation-runtime-assembly.test.ts +653 -832
  53. package/src/__tests__/conversation-runtime-workspace.test.ts +1 -93
  54. package/src/__tests__/conversation-starter-routes.test.ts +20 -11
  55. package/src/__tests__/conversation-store.test.ts +2 -6
  56. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +17 -4
  57. package/src/__tests__/conversation-usage.test.ts +2 -6
  58. package/src/__tests__/conversation-wipe.test.ts +13 -414
  59. package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -12
  60. package/src/__tests__/conversation-workspace-injection.test.ts +25 -26
  61. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -1
  62. package/src/__tests__/copy-composer-tc-templates.test.ts +335 -0
  63. package/src/__tests__/credential-execution-feature-gates.test.ts +3 -3
  64. package/src/__tests__/credential-execution-shell-lockdown.test.ts +2 -2
  65. package/src/__tests__/credential-security-e2e.test.ts +2 -0
  66. package/src/__tests__/date-context.test.ts +76 -210
  67. package/src/__tests__/db-schedule-syntax-migration.test.ts +16 -1
  68. package/src/__tests__/file-list-tool.test.ts +219 -0
  69. package/src/__tests__/first-greeting.test.ts +1 -1
  70. package/src/__tests__/followup-tools.test.ts +2 -6
  71. package/src/__tests__/graph-extraction-event-date.test.ts +186 -0
  72. package/src/__tests__/guardian-action-conversation-turn.test.ts +2 -6
  73. package/src/__tests__/guardian-action-followup-executor.test.ts +2 -6
  74. package/src/__tests__/guardian-action-followup-store.test.ts +2 -6
  75. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +2 -6
  76. package/src/__tests__/guardian-action-late-reply.test.ts +2 -6
  77. package/src/__tests__/guardian-action-store.test.ts +2 -6
  78. package/src/__tests__/guardian-binding-drift-heal.test.ts +2 -6
  79. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +8 -8
  80. package/src/__tests__/guardian-dispatch.test.ts +2 -6
  81. package/src/__tests__/guardian-grant-minting.test.ts +2 -14
  82. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +2 -6
  83. package/src/__tests__/guardian-routing-invariants.test.ts +192 -6
  84. package/src/__tests__/guardian-routing-state.test.ts +2 -6
  85. package/src/__tests__/guardian-verification-voice-binding.test.ts +2 -6
  86. package/src/__tests__/heartbeat-service.test.ts +180 -3
  87. package/src/__tests__/identity-routes.test.ts +328 -0
  88. package/src/__tests__/inbound-invite-redemption.test.ts +2 -6
  89. package/src/__tests__/injection-block.test.ts +178 -0
  90. package/src/__tests__/install-meta.test.ts +506 -0
  91. package/src/__tests__/install-skill-routing.test.ts +293 -0
  92. package/src/__tests__/invite-redemption-service.test.ts +2 -6
  93. package/src/__tests__/invite-routes-http.test.ts +2 -6
  94. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +17 -28
  95. package/src/__tests__/list-messages-attachments.test.ts +2 -6
  96. package/src/__tests__/list-messages-tool-merge.test.ts +300 -0
  97. package/src/__tests__/llm-context-normalization.test.ts +18 -18
  98. package/src/__tests__/llm-context-route-provider.test.ts +103 -6
  99. package/src/__tests__/llm-request-log-turn-query.test.ts +164 -6
  100. package/src/__tests__/llm-usage-store.test.ts +2 -6
  101. package/src/__tests__/log-export-workspace.test.ts +74 -111
  102. package/src/__tests__/managed-store.test.ts +38 -11
  103. package/src/__tests__/mcp-abort-signal.test.ts +5 -0
  104. package/src/__tests__/mcp-client-auth.test.ts +5 -0
  105. package/src/__tests__/memory-jobs-worker-backoff.test.ts +2 -8
  106. package/src/__tests__/memory-recall-log-store.test.ts +134 -6
  107. package/src/__tests__/memory-upsert-concurrency.test.ts +4 -112
  108. package/src/__tests__/migration-export-streaming.test.ts +304 -0
  109. package/src/__tests__/migration-import-commit-http.test.ts +11 -10
  110. package/src/__tests__/mock-fetch.ts +87 -0
  111. package/src/__tests__/non-member-access-request.test.ts +2 -6
  112. package/src/__tests__/notification-decision-recipient-context.test.ts +282 -0
  113. package/src/__tests__/notification-guardian-path.test.ts +2 -6
  114. package/src/__tests__/oauth-cli.test.ts +364 -2
  115. package/src/__tests__/oauth2-gateway-transport.test.ts +18 -3
  116. package/src/__tests__/onboarding-template-contract.test.ts +62 -14
  117. package/src/__tests__/outlook-attachments.test.ts +301 -0
  118. package/src/__tests__/outlook-automation-tools.test.ts +425 -0
  119. package/src/__tests__/outlook-categories.test.ts +212 -0
  120. package/src/__tests__/outlook-client-automation.test.ts +246 -0
  121. package/src/__tests__/outlook-compose-tools.test.ts +325 -0
  122. package/src/__tests__/outlook-declutter-tools.test.ts +585 -0
  123. package/src/__tests__/outlook-email-watcher.test.ts +322 -0
  124. package/src/__tests__/outlook-follow-up.test.ts +196 -0
  125. package/src/__tests__/outlook-messaging-provider.test.ts +498 -3
  126. package/src/__tests__/outlook-trash.test.ts +77 -0
  127. package/src/__tests__/outlook-unsubscribe.test.ts +250 -0
  128. package/src/__tests__/parser.test.ts +32 -0
  129. package/src/__tests__/permission-checker-host-gate.test.ts +452 -0
  130. package/src/__tests__/permission-controls-v2-flag.test.ts +55 -0
  131. package/src/__tests__/permission-mode-sse.test.ts +418 -0
  132. package/src/__tests__/permission-mode-store.test.ts +277 -0
  133. package/src/__tests__/permission-mode.test.ts +101 -0
  134. package/src/__tests__/platform-bash-auto-approve.test.ts +359 -0
  135. package/src/__tests__/platform-callback-registration.test.ts +4 -4
  136. package/src/__tests__/playbook-execution.test.ts +76 -80
  137. package/src/__tests__/playbook-tools.test.ts +5 -7
  138. package/src/__tests__/profiler-routes.test.ts +502 -0
  139. package/src/__tests__/profiler-run-store.test.ts +441 -0
  140. package/src/__tests__/provider-error-scenarios.test.ts +21 -0
  141. package/src/__tests__/proxy-approval-callback.test.ts +4 -75
  142. package/src/__tests__/rebuild-index-graph-nodes.test.ts +273 -0
  143. package/src/__tests__/registry.test.ts +3 -3
  144. package/src/__tests__/require-fresh-approval.test.ts +64 -2
  145. package/src/__tests__/runtime-events-sse-parity.test.ts +2 -6
  146. package/src/__tests__/runtime-events-sse.test.ts +2 -6
  147. package/src/__tests__/sandbox-host-parity.test.ts +5 -4
  148. package/src/__tests__/schedule-store.test.ts +2 -6
  149. package/src/__tests__/schedule-tools.test.ts +2 -6
  150. package/src/__tests__/scheduler-recurrence.test.ts +1 -5
  151. package/src/__tests__/scheduler-reuse-conversation.test.ts +368 -0
  152. package/src/__tests__/scoped-approval-grants.test.ts +2 -6
  153. package/src/__tests__/scoped-grant-security-matrix.test.ts +2 -6
  154. package/src/__tests__/scrub-corrupted-image-attachments.test.ts +278 -0
  155. package/src/__tests__/search-skills-unified.test.ts +422 -0
  156. package/src/__tests__/secret-onetime-send.test.ts +2 -0
  157. package/src/__tests__/send-endpoint-busy.test.ts +44 -9
  158. package/src/__tests__/sequence-store.test.ts +2 -6
  159. package/src/__tests__/server-history-render.test.ts +2 -6
  160. package/src/__tests__/set-permission-mode.test.ts +274 -0
  161. package/src/__tests__/skill-feature-flags-integration.test.ts +38 -31
  162. package/src/__tests__/skill-feature-flags.test.ts +6 -6
  163. package/src/__tests__/skill-load-feature-flag.test.ts +23 -11
  164. package/src/__tests__/skill-memory.test.ts +2 -741
  165. package/src/__tests__/skills-uninstall.test.ts +2 -2
  166. package/src/__tests__/skills.test.ts +1 -1
  167. package/src/__tests__/slack-inbound-verification.test.ts +2 -6
  168. package/src/__tests__/strip-memory-injections.test.ts +187 -0
  169. package/src/__tests__/subagent-detail.test.ts +84 -0
  170. package/src/__tests__/subagent-disposal.test.ts +308 -0
  171. package/src/__tests__/subagent-manager-notify.test.ts +19 -10
  172. package/src/__tests__/subagent-notify-parent.test.ts +390 -0
  173. package/src/__tests__/subagent-role-registry.test.ts +108 -0
  174. package/src/__tests__/subagent-tool-filtering.test.ts +71 -0
  175. package/src/__tests__/subagent-tools.test.ts +464 -4
  176. package/src/__tests__/system-prompt-ask-mode.test.ts +139 -0
  177. package/src/__tests__/task-compiler.test.ts +2 -6
  178. package/src/__tests__/task-management-tools.test.ts +2 -6
  179. package/src/__tests__/task-memory-cleanup.test.ts +185 -241
  180. package/src/__tests__/task-runner.test.ts +2 -6
  181. package/src/__tests__/task-scheduler.test.ts +2 -6
  182. package/src/__tests__/terminal-tools.test.ts +17 -27
  183. package/src/__tests__/test-preload.ts +7 -0
  184. package/src/__tests__/tool-approval-handler.test.ts +2 -6
  185. package/src/__tests__/tool-executor.test.ts +4 -26
  186. package/src/__tests__/tool-grant-request-escalation.test.ts +2 -6
  187. package/src/__tests__/tool-side-effects-slack-dm.test.ts +277 -0
  188. package/src/__tests__/top-level-renderer.test.ts +10 -13
  189. package/src/__tests__/trust-store.test.ts +1 -1
  190. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +2 -6
  191. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +118 -8
  192. package/src/__tests__/trusted-contact-multichannel.test.ts +2 -6
  193. package/src/__tests__/trusted-contact-verification.test.ts +2 -6
  194. package/src/__tests__/turn-boundary-resolution.test.ts +2 -6
  195. package/src/__tests__/usage-cache-backfill-migration.test.ts +1 -6
  196. package/src/__tests__/usage-routes.test.ts +2 -6
  197. package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
  198. package/src/__tests__/voice-invite-redemption.test.ts +2 -6
  199. package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -6
  200. package/src/__tests__/voice-session-bridge.test.ts +2 -6
  201. package/src/__tests__/volume-security-guard.test.ts +2 -0
  202. package/src/__tests__/workspace-lifecycle.test.ts +29 -1
  203. package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +2 -6
  204. package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +2 -6
  205. package/src/__tests__/workspace-migration-026-backfill-install-meta.test.ts +558 -0
  206. package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +387 -0
  207. package/src/__tests__/workspace-policy.test.ts +1 -1
  208. package/src/agent/attachments.ts +7 -2
  209. package/src/agent/image-optimize.ts +165 -0
  210. package/src/agent/loop.ts +7 -15
  211. package/src/approvals/guardian-request-resolvers.ts +24 -0
  212. package/src/avatar/traits-png-sync.ts +3 -3
  213. package/src/bundler/app-compiler.ts +179 -2
  214. package/src/bundler/package-resolver.ts +3 -5
  215. package/src/cli/__tests__/notifications.test.ts +1 -2
  216. package/src/cli/__tests__/run-assistant-command.ts +29 -0
  217. package/src/cli/commands/__tests__/email-download.test.ts +245 -0
  218. package/src/cli/commands/__tests__/email-list.test.ts +192 -0
  219. package/src/cli/commands/__tests__/email-register.test.ts +186 -0
  220. package/src/cli/commands/__tests__/email-send.test.ts +291 -0
  221. package/src/cli/commands/__tests__/email-status.test.ts +181 -0
  222. package/src/cli/commands/__tests__/email-unregister.test.ts +139 -0
  223. package/src/cli/commands/__tests__/routes.test.ts +562 -0
  224. package/src/cli/commands/avatar.ts +3 -3
  225. package/src/cli/commands/config.ts +26 -13
  226. package/src/cli/commands/conversations.ts +1 -8
  227. package/src/cli/commands/doctor.ts +2 -2
  228. package/src/cli/commands/email.ts +584 -835
  229. package/src/cli/commands/memory.ts +37 -84
  230. package/src/cli/commands/notifications.ts +7 -2
  231. package/src/cli/commands/oauth/__tests__/connect.test.ts +2 -2
  232. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +2 -2
  233. package/src/cli/commands/oauth/__tests__/mode.test.ts +8 -1
  234. package/src/cli/commands/oauth/__tests__/status.test.ts +2 -2
  235. package/src/cli/commands/oauth/connect.ts +25 -11
  236. package/src/cli/commands/oauth/mode.ts +7 -0
  237. package/src/cli/commands/oauth/shared.ts +39 -3
  238. package/src/cli/commands/platform/__tests__/connect.test.ts +1 -1
  239. package/src/cli/commands/platform/__tests__/disconnect.test.ts +1 -1
  240. package/src/cli/commands/platform/__tests__/status.test.ts +5 -5
  241. package/src/cli/commands/platform/index.ts +16 -16
  242. package/src/cli/commands/routes.ts +396 -0
  243. package/src/cli/commands/skills.ts +218 -36
  244. package/src/cli/commands/trust.ts +2 -2
  245. package/src/cli/lib/daemon-credential-client.ts +2 -3
  246. package/src/cli/program.ts +2 -0
  247. package/src/cli.ts +1 -120
  248. package/src/config/bundled-skills/acp/TOOLS.json +1 -1
  249. package/src/config/bundled-skills/app-builder/SKILL.md +4 -1
  250. package/src/config/bundled-skills/contacts/SKILL.md +0 -1
  251. package/src/config/bundled-skills/contacts/TOOLS.json +0 -8
  252. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -4
  253. package/src/config/bundled-skills/gmail/SKILL.md +4 -12
  254. package/src/config/bundled-skills/google-calendar/SKILL.md +1 -9
  255. package/src/config/bundled-skills/messaging/SKILL.md +17 -18
  256. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +40 -33
  257. package/src/config/bundled-skills/outlook/SKILL.md +189 -0
  258. package/src/config/bundled-skills/outlook/TOOLS.json +530 -0
  259. package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +85 -0
  260. package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +77 -0
  261. package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +84 -0
  262. package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +94 -0
  263. package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +49 -0
  264. package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +237 -0
  265. package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +161 -0
  266. package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +32 -0
  267. package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +272 -0
  268. package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +29 -0
  269. package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +129 -0
  270. package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +87 -0
  271. package/src/config/bundled-skills/outlook/tools/shared.ts +20 -0
  272. package/src/config/bundled-skills/outlook-calendar/SKILL.md +51 -0
  273. package/src/config/bundled-skills/outlook-calendar/TOOLS.json +221 -0
  274. package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +252 -0
  275. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +53 -0
  276. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +74 -0
  277. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +18 -0
  278. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +46 -0
  279. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +36 -0
  280. package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +17 -0
  281. package/src/config/bundled-skills/outlook-calendar/types.ts +120 -0
  282. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +47 -40
  283. package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +16 -29
  284. package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +16 -18
  285. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +39 -47
  286. package/src/config/bundled-skills/schedule/SKILL.md +22 -2
  287. package/src/config/bundled-skills/schedule/TOOLS.json +8 -0
  288. package/src/config/bundled-skills/settings/tools/avatar-get.ts +3 -13
  289. package/src/config/bundled-skills/settings/tools/avatar-remove.ts +2 -4
  290. package/src/config/bundled-skills/settings/tools/avatar-update.ts +5 -2
  291. package/src/config/bundled-skills/slack/SKILL.md +3 -7
  292. package/src/config/bundled-skills/subagent/SKILL.md +43 -3
  293. package/src/config/bundled-skills/subagent/TOOLS.json +29 -4
  294. package/src/config/bundled-tool-registry.ts +56 -4
  295. package/src/config/env-registry.ts +78 -8
  296. package/src/config/feature-flag-registry.json +38 -125
  297. package/src/config/schema.ts +8 -0
  298. package/src/config/schemas/filing.ts +51 -0
  299. package/src/config/schemas/heartbeat.ts +15 -12
  300. package/src/config/schemas/memory-lifecycle.ts +12 -0
  301. package/src/config/schemas/platform.ts +8 -0
  302. package/src/config/schemas/security.ts +14 -0
  303. package/src/config/schemas/timeouts.ts +1 -1
  304. package/src/config/skills.ts +18 -7
  305. package/src/context/token-estimator.ts +25 -18
  306. package/src/context/window-manager.ts +6 -2
  307. package/src/credential-execution/process-manager.ts +3 -1
  308. package/src/daemon/app-source-watcher.ts +93 -0
  309. package/src/daemon/config-watcher.ts +79 -1
  310. package/src/daemon/context-overflow-reducer.ts +46 -2
  311. package/src/daemon/conversation-agent-loop-handlers.ts +143 -82
  312. package/src/daemon/conversation-agent-loop.ts +236 -108
  313. package/src/daemon/conversation-error.ts +31 -8
  314. package/src/daemon/conversation-history.ts +4 -19
  315. package/src/daemon/conversation-lifecycle.ts +36 -9
  316. package/src/daemon/conversation-media-retry.ts +85 -7
  317. package/src/daemon/conversation-notifiers.ts +4 -1
  318. package/src/daemon/conversation-process.ts +13 -7
  319. package/src/daemon/conversation-runtime-assembly.ts +305 -306
  320. package/src/daemon/conversation-tool-setup.ts +44 -14
  321. package/src/daemon/conversation-workspace.ts +1 -2
  322. package/src/daemon/conversation.ts +59 -2
  323. package/src/daemon/daemon-control.ts +8 -2
  324. package/src/daemon/date-context.ts +26 -53
  325. package/src/daemon/first-greeting.ts +1 -1
  326. package/src/daemon/handlers/conversations.ts +4 -7
  327. package/src/daemon/handlers/shared.test.ts +143 -0
  328. package/src/daemon/handlers/shared.ts +85 -17
  329. package/src/daemon/handlers/skills.ts +416 -209
  330. package/src/daemon/lifecycle.ts +212 -131
  331. package/src/daemon/main.ts +5 -1
  332. package/src/daemon/message-types/conversations.ts +29 -7
  333. package/src/daemon/message-types/messages.ts +12 -2
  334. package/src/daemon/message-types/schedules.ts +1 -0
  335. package/src/daemon/message-types/settings.ts +6 -0
  336. package/src/daemon/message-types/skills.ts +97 -36
  337. package/src/daemon/profiler-run-store.ts +557 -0
  338. package/src/daemon/providers-setup.ts +5 -0
  339. package/src/daemon/server.ts +100 -11
  340. package/src/daemon/shutdown-handlers.ts +5 -0
  341. package/src/daemon/tool-side-effects.ts +50 -8
  342. package/src/export/transcript-formatter.ts +148 -0
  343. package/src/filing/filing-service.ts +228 -0
  344. package/src/heartbeat/heartbeat-service.ts +97 -7
  345. package/src/hooks/cli.ts +2 -2
  346. package/src/hooks/runner.ts +15 -38
  347. package/src/inbound/platform-callback-registration.ts +14 -14
  348. package/src/mcp/client.ts +6 -0
  349. package/src/mcp/mcp-oauth-provider.ts +149 -27
  350. package/src/memory/admin.ts +42 -75
  351. package/src/memory/app-store.ts +69 -0
  352. package/src/memory/conversation-bootstrap.ts +3 -1
  353. package/src/memory/conversation-crud.ts +211 -288
  354. package/src/memory/conversation-group-migration.ts +157 -0
  355. package/src/memory/conversation-queries.ts +61 -13
  356. package/src/memory/conversation-title-service.ts +1 -0
  357. package/src/memory/db-init.ts +194 -361
  358. package/src/memory/embed.ts +73 -0
  359. package/src/memory/embedding-backend.ts +8 -14
  360. package/src/memory/embedding-runtime-manager.ts +12 -114
  361. package/src/memory/fingerprint.ts +2 -2
  362. package/src/memory/graph/bootstrap.ts +521 -0
  363. package/src/memory/graph/capability-seed.ts +449 -0
  364. package/src/memory/graph/consolidation.ts +725 -0
  365. package/src/memory/graph/conversation-graph-memory.ts +659 -0
  366. package/src/memory/graph/decay.test.ts +208 -0
  367. package/src/memory/graph/decay.ts +195 -0
  368. package/src/memory/graph/extraction-job.ts +74 -0
  369. package/src/memory/graph/extraction.test.ts +936 -0
  370. package/src/memory/graph/extraction.ts +1297 -0
  371. package/src/memory/graph/graph-memory-state-store.ts +37 -0
  372. package/src/memory/graph/graph-search.ts +280 -0
  373. package/src/memory/graph/image-ref-utils.ts +29 -0
  374. package/src/memory/graph/injection.test.ts +513 -0
  375. package/src/memory/graph/injection.ts +469 -0
  376. package/src/memory/graph/inspect.ts +543 -0
  377. package/src/memory/graph/narrative.ts +267 -0
  378. package/src/memory/graph/pattern-scan.ts +269 -0
  379. package/src/memory/graph/retriever.ts +1111 -0
  380. package/src/memory/graph/scoring.test.ts +548 -0
  381. package/src/memory/graph/scoring.ts +232 -0
  382. package/src/memory/graph/serendipity.ts +65 -0
  383. package/src/memory/graph/store.test.ts +1098 -0
  384. package/src/memory/graph/store.ts +838 -0
  385. package/src/memory/graph/tool-handlers.ts +301 -0
  386. package/src/memory/graph/tools.ts +97 -0
  387. package/src/memory/graph/triggers.test.ts +487 -0
  388. package/src/memory/graph/triggers.ts +223 -0
  389. package/src/memory/graph/types.ts +295 -0
  390. package/src/memory/group-crud.ts +191 -0
  391. package/src/memory/indexer.ts +37 -19
  392. package/src/memory/job-handlers/cleanup.ts +32 -42
  393. package/src/memory/job-handlers/conversation-starters.ts +91 -53
  394. package/src/memory/job-handlers/embedding.ts +5 -31
  395. package/src/memory/job-handlers/index-maintenance.ts +23 -11
  396. package/src/memory/job-handlers/summarization.ts +32 -17
  397. package/src/memory/job-utils.ts +1 -1
  398. package/src/memory/jobs-store.ts +21 -31
  399. package/src/memory/jobs-worker.ts +180 -129
  400. package/src/memory/llm-request-log-store.ts +96 -12
  401. package/src/memory/memory-recall-log-store.ts +49 -5
  402. package/src/memory/message-content.ts +1 -0
  403. package/src/memory/migrations/202-memory-graph-tables.ts +130 -0
  404. package/src/memory/migrations/203-drop-memory-items-tables.ts +55 -0
  405. package/src/memory/migrations/204-rename-memory-graph-type-values.ts +46 -0
  406. package/src/memory/migrations/205-memory-graph-image-refs.ts +11 -0
  407. package/src/memory/migrations/206-memory-graph-node-edits.ts +19 -0
  408. package/src/memory/migrations/206-scrub-corrupted-image-attachments.ts +131 -0
  409. package/src/memory/migrations/207-conversation-graph-memory-state.ts +20 -0
  410. package/src/memory/migrations/208-conversations-last-message-at.ts +35 -0
  411. package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +85 -0
  412. package/src/memory/migrations/210-schedule-reuse-conversation.ts +13 -0
  413. package/src/memory/migrations/211-memory-recall-logs-query-context.ts +21 -0
  414. package/src/memory/migrations/212-llm-request-logs-created-at-index.ts +19 -0
  415. package/src/memory/migrations/index.ts +12 -0
  416. package/src/memory/migrations/registry.ts +16 -0
  417. package/src/memory/qdrant-client.ts +44 -17
  418. package/src/memory/schema/conversations.ts +14 -0
  419. package/src/memory/schema/index.ts +1 -0
  420. package/src/memory/schema/infrastructure.ts +8 -1
  421. package/src/memory/schema/memory-core.ts +0 -51
  422. package/src/memory/schema/memory-graph.ts +154 -0
  423. package/src/memory/search/semantic.ts +47 -91
  424. package/src/memory/task-memory-cleanup.ts +58 -61
  425. package/src/messaging/providers/outlook/adapter.ts +8 -1
  426. package/src/messaging/providers/outlook/client.ts +299 -0
  427. package/src/messaging/providers/outlook/types.ts +118 -0
  428. package/src/notifications/adapters/macos.ts +1 -0
  429. package/src/notifications/copy-composer.ts +95 -0
  430. package/src/notifications/decision-engine.ts +35 -0
  431. package/src/notifications/signal.ts +16 -0
  432. package/src/oauth/seed-providers.ts +2 -1
  433. package/src/permissions/checker.ts +36 -4
  434. package/src/permissions/defaults.ts +4 -4
  435. package/src/permissions/permission-mode-store.ts +180 -0
  436. package/src/permissions/permission-mode.ts +31 -0
  437. package/src/permissions/workspace-policy.ts +10 -1
  438. package/src/playbooks/playbook-compiler.ts +19 -18
  439. package/src/playbooks/types.ts +4 -3
  440. package/src/prompts/system-prompt.ts +62 -36
  441. package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +100 -0
  442. package/src/prompts/templates/BOOTSTRAP.md +70 -165
  443. package/src/prompts/templates/HEARTBEAT.md +3 -1
  444. package/src/prompts/templates/SOUL.md +25 -4
  445. package/src/prompts/templates/UPDATES.md +8 -0
  446. package/src/providers/anthropic/client.ts +136 -220
  447. package/src/providers/gemini/client.ts +1 -1
  448. package/src/providers/openai/client.ts +1 -1
  449. package/src/providers/registry.ts +1 -1
  450. package/src/providers/retry.ts +19 -3
  451. package/src/runtime/actor-trust-resolver.ts +5 -1
  452. package/src/runtime/auth/route-policy.ts +30 -0
  453. package/src/runtime/guardian-reply-router.ts +5 -1
  454. package/src/runtime/http-server.ts +55 -5
  455. package/src/runtime/http-types.ts +12 -1
  456. package/src/runtime/middleware/auth.ts +20 -0
  457. package/src/runtime/migrations/vbundle-builder.ts +389 -3
  458. package/src/runtime/migrations/vbundle-importer.ts +8 -6
  459. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +378 -0
  460. package/src/runtime/routes/app-management-routes.ts +1 -11
  461. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +26 -0
  462. package/src/runtime/routes/archive-utils.ts +29 -0
  463. package/src/runtime/routes/attachment-routes.test.ts +106 -0
  464. package/src/runtime/routes/attachment-routes.ts +106 -16
  465. package/src/runtime/routes/avatar-routes.ts +2 -9
  466. package/src/runtime/routes/brain-graph-routes.ts +21 -22
  467. package/src/runtime/routes/btw-routes.ts +22 -1
  468. package/src/runtime/routes/conversation-analysis-routes.ts +173 -0
  469. package/src/runtime/routes/conversation-management-routes.ts +3 -14
  470. package/src/runtime/routes/conversation-query-routes.ts +49 -3
  471. package/src/runtime/routes/conversation-routes.ts +264 -44
  472. package/src/runtime/routes/conversation-starter-routes.ts +2 -2
  473. package/src/runtime/routes/debug-routes.ts +1 -1
  474. package/src/runtime/routes/global-search-routes.ts +21 -19
  475. package/src/runtime/routes/group-routes.ts +207 -0
  476. package/src/runtime/routes/guardian-action-routes.ts +21 -10
  477. package/src/runtime/routes/guardian-bootstrap-routes.ts +23 -19
  478. package/src/runtime/routes/heartbeat-routes.ts +4 -10
  479. package/src/runtime/routes/identity-routes.ts +53 -18
  480. package/src/runtime/routes/inbound-message-handler.ts +19 -0
  481. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +292 -0
  482. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +207 -0
  483. package/src/runtime/routes/llm-context-normalization.ts +14 -10
  484. package/src/runtime/routes/log-export-routes.ts +23 -275
  485. package/src/runtime/routes/memory-item-routes.test.ts +170 -247
  486. package/src/runtime/routes/memory-item-routes.ts +341 -388
  487. package/src/runtime/routes/migration-routes.ts +18 -7
  488. package/src/runtime/routes/profiler-routes.ts +350 -0
  489. package/src/runtime/routes/schedule-routes.ts +28 -11
  490. package/src/runtime/routes/settings-routes.ts +95 -8
  491. package/src/runtime/routes/skills-routes.ts +103 -37
  492. package/src/runtime/routes/subagents-routes.ts +28 -7
  493. package/src/runtime/routes/user-route-dispatcher.ts +223 -0
  494. package/src/runtime/routes/user-routes.ts +41 -0
  495. package/src/runtime/routes/work-items-routes.test.ts +2 -6
  496. package/src/runtime/routes/workspace-routes.ts +0 -1
  497. package/src/schedule/schedule-store.ts +30 -0
  498. package/src/schedule/scheduler.ts +52 -18
  499. package/src/security/oauth2.ts +1 -1
  500. package/src/security/secure-keys.ts +4 -8
  501. package/src/shared/provider-env-vars.ts +19 -0
  502. package/src/skills/catalog-cache.ts +5 -0
  503. package/src/skills/catalog-install.ts +25 -16
  504. package/src/skills/clawhub.ts +134 -154
  505. package/src/skills/install-meta.ts +208 -0
  506. package/src/skills/managed-store.ts +29 -18
  507. package/src/skills/skill-memory.ts +12 -229
  508. package/src/skills/skillssh-registry.ts +19 -17
  509. package/src/subagent/index.ts +13 -3
  510. package/src/subagent/manager.ts +308 -29
  511. package/src/subagent/types.ts +68 -0
  512. package/src/tasks/task-runner.ts +7 -5
  513. package/src/telemetry/usage-telemetry-reporter.test.ts +3 -5
  514. package/src/tools/apps/executors.ts +29 -4
  515. package/src/tools/browser/runtime-check.ts +3 -1
  516. package/src/tools/filesystem/list.ts +93 -0
  517. package/src/tools/memory/register.ts +63 -46
  518. package/src/tools/permission-checker.ts +85 -1
  519. package/src/tools/registry.ts +4 -0
  520. package/src/tools/schedule/create.ts +3 -0
  521. package/src/tools/schedule/list.ts +1 -0
  522. package/src/tools/schedule/update.ts +6 -0
  523. package/src/tools/shared/filesystem/errors.ts +5 -0
  524. package/src/tools/shared/filesystem/file-ops-service.ts +90 -2
  525. package/src/tools/shared/filesystem/image-read.ts +22 -85
  526. package/src/tools/shared/filesystem/types.ts +17 -0
  527. package/src/tools/shared/shell-output.ts +31 -2
  528. package/src/tools/subagent/abort.ts +12 -2
  529. package/src/tools/subagent/message.ts +9 -2
  530. package/src/tools/subagent/notify-parent.ts +79 -0
  531. package/src/tools/subagent/read.ts +29 -8
  532. package/src/tools/subagent/resolve.ts +21 -0
  533. package/src/tools/subagent/spawn.ts +2 -0
  534. package/src/tools/subagent/status.ts +11 -1
  535. package/src/tools/system/avatar-generator.ts +3 -3
  536. package/src/tools/system/register.ts +23 -0
  537. package/src/tools/system/set-permission-mode.ts +103 -0
  538. package/src/tools/terminal/parser.ts +30 -5
  539. package/src/tools/terminal/safe-env.ts +17 -1
  540. package/src/tools/tool-manifest.ts +9 -3
  541. package/src/tools/types.ts +2 -0
  542. package/src/util/browser.ts +25 -10
  543. package/src/util/bun-runtime.ts +172 -0
  544. package/src/util/logger.ts +1 -1
  545. package/src/util/platform.ts +50 -17
  546. package/src/watcher/providers/outlook-calendar.ts +343 -0
  547. package/src/watcher/providers/outlook.ts +198 -0
  548. package/src/workspace/migrations/023-move-config-files-to-workspace.ts +2 -2
  549. package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +2 -2
  550. package/src/workspace/migrations/025-remove-oauth-app-setup-skills.ts +76 -0
  551. package/src/workspace/migrations/026-backfill-install-meta.ts +325 -0
  552. package/src/workspace/migrations/027-remove-orphaned-optimized-images-cache.ts +42 -0
  553. package/src/workspace/migrations/028-recover-conversations-from-disk-view.ts +270 -0
  554. package/src/workspace/migrations/029-seed-pkb.ts +84 -0
  555. package/src/workspace/migrations/registry.ts +10 -0
  556. package/src/workspace/top-level-renderer.ts +5 -9
  557. package/src/__tests__/cli-memory.test.ts +0 -372
  558. package/src/__tests__/clipboard.test.ts +0 -88
  559. package/src/__tests__/context-memory-e2e.test.ts +0 -415
  560. package/src/__tests__/journal-context.test.ts +0 -268
  561. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +0 -297
  562. package/src/__tests__/memory-lifecycle-e2e.test.ts +0 -459
  563. package/src/__tests__/memory-query-builder.test.ts +0 -59
  564. package/src/__tests__/memory-recall-quality.test.ts +0 -1046
  565. package/src/__tests__/memory-regressions.experimental.test.ts +0 -629
  566. package/src/__tests__/memory-regressions.test.ts +0 -3696
  567. package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -295
  568. package/src/cli/cli-memory.ts +0 -176
  569. package/src/daemon/conversation-memory.ts +0 -207
  570. package/src/memory/conversation-starters-cadence.ts +0 -74
  571. package/src/memory/items-extractor.ts +0 -860
  572. package/src/memory/job-handlers/batch-extraction.ts +0 -753
  573. package/src/memory/job-handlers/extraction.ts +0 -40
  574. package/src/memory/job-handlers/journal-carry-forward.test.ts +0 -355
  575. package/src/memory/job-handlers/journal-carry-forward.ts +0 -255
  576. package/src/memory/journal-memory.ts +0 -224
  577. package/src/memory/query-builder.ts +0 -47
  578. package/src/memory/query-expansion.ts +0 -83
  579. package/src/memory/retriever.test.ts +0 -1592
  580. package/src/memory/retriever.ts +0 -1331
  581. package/src/memory/search/formatting.test.ts +0 -140
  582. package/src/memory/search/formatting.ts +0 -262
  583. package/src/memory/search/mmr.ts +0 -139
  584. package/src/memory/search/ranking.ts +0 -15
  585. package/src/memory/search/staleness.ts +0 -40
  586. package/src/memory/search/tier-classifier.ts +0 -18
  587. package/src/memory/search/types.ts +0 -121
  588. package/src/prompts/journal-context.ts +0 -154
  589. package/src/tools/memory/definitions.ts +0 -69
  590. package/src/tools/memory/handlers.test.ts +0 -562
  591. package/src/tools/memory/handlers.ts +0 -434
  592. package/src/util/clipboard.ts +0 -34
@@ -0,0 +1,84 @@
1
+ import { existsSync, mkdirSync, rmdirSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
4
+ import type { WorkspaceMigration } from "./types.js";
5
+
6
+ const INDEX_TEMPLATE = `_ Lines starting with _ are comments - they won't appear in the injected context
7
+
8
+ # Knowledge Base
9
+
10
+ **Remember aggressively.** When you learn ANY fact — a preference, a name, a date, a habit, a plan, an opinion — call \`remember\` immediately. Don't filter, don't judge importance. Remembering too much costs nothing. Forgetting something that mattered costs trust.
11
+
12
+ ## Always Loaded
13
+ - essentials.md — Core facts, patterns, and biographical info
14
+ - threads.md — Active commitments, follow-ups, and projects in progress
15
+ - buffer.md — Inbox of recently learned facts (filed periodically)
16
+
17
+ ## Topics
18
+ `;
19
+
20
+ const ESSENTIALS_TEMPLATE = `_ Lines starting with _ are comments - they won't appear in the injected context
21
+
22
+ # Essentials
23
+
24
+ _ The most important facts — things you'd be embarrassed to forget.
25
+ _ This file is always loaded into every conversation. Keep it focused.
26
+ _ Promote facts here from topic files when they come up constantly.
27
+ _ Demote facts to topic files when they stop being essential.
28
+ `;
29
+
30
+ const THREADS_TEMPLATE = `_ Lines starting with _ are comments - they won't appear in the injected context
31
+
32
+ # Active Threads
33
+
34
+ _ Commitments, follow-ups, and projects in progress.
35
+ _ This file is always loaded into every conversation.
36
+ _ Remove items when they're completed or no longer relevant.
37
+ `;
38
+
39
+ export const seedPkbMigration: WorkspaceMigration = {
40
+ id: "029-seed-pkb",
41
+ description: "Create pkb/ knowledge base directory with seed files",
42
+
43
+ down(workspaceDir: string): void {
44
+ // Best-effort: only remove empty directories. Never delete user content.
45
+ const pkbDir = join(workspaceDir, "pkb");
46
+ if (!existsSync(pkbDir)) return;
47
+
48
+ try {
49
+ // Try removing subdirectories first, then the root. rmdirSync fails
50
+ // on non-empty directories, which is exactly what we want.
51
+ for (const sub of ["archive"]) {
52
+ try {
53
+ rmdirSync(join(pkbDir, sub));
54
+ } catch {
55
+ // Non-empty or doesn't exist — skip
56
+ }
57
+ }
58
+ rmdirSync(pkbDir);
59
+ } catch {
60
+ // Non-empty — leave it alone
61
+ }
62
+ },
63
+
64
+ run(workspaceDir: string): void {
65
+ const pkbDir = join(workspaceDir, "pkb");
66
+ mkdirSync(pkbDir, { recursive: true });
67
+ mkdirSync(join(pkbDir, "archive"), { recursive: true });
68
+
69
+ // Seed files only if they don't already exist (idempotent)
70
+ const seeds: Array<[string, string]> = [
71
+ ["INDEX.md", INDEX_TEMPLATE],
72
+ ["essentials.md", ESSENTIALS_TEMPLATE],
73
+ ["threads.md", THREADS_TEMPLATE],
74
+ ["buffer.md", ""],
75
+ ];
76
+
77
+ for (const [filename, content] of seeds) {
78
+ const filePath = join(pkbDir, filename);
79
+ if (!existsSync(filePath)) {
80
+ writeFileSync(filePath, content, "utf-8");
81
+ }
82
+ }
83
+ },
84
+ };
@@ -21,6 +21,11 @@ import { moveSignalsToWorkspaceMigration } from "./021-move-signals-to-workspace
21
21
  import { moveHooksToWorkspaceMigration } from "./022-move-hooks-to-workspace.js";
22
22
  import { moveConfigFilesToWorkspaceMigration } from "./023-move-config-files-to-workspace.js";
23
23
  import { moveRuntimeFilesToWorkspaceMigration } from "./024-move-runtime-files-to-workspace.js";
24
+ import { removeOauthAppSetupSkillsMigration } from "./025-remove-oauth-app-setup-skills.js";
25
+ import { backfillInstallMetaMigration } from "./026-backfill-install-meta.js";
26
+ import { removeOrphanedOptimizedImagesCacheMigration } from "./027-remove-orphaned-optimized-images-cache.js";
27
+ import { recoverConversationsFromDiskViewMigration } from "./028-recover-conversations-from-disk-view.js";
28
+ import { seedPkbMigration } from "./029-seed-pkb.js";
24
29
  import { migrateToWorkspaceVolumeMigration } from "./migrate-to-workspace-volume.js";
25
30
  import type { WorkspaceMigration } from "./types.js";
26
31
 
@@ -53,4 +58,9 @@ export const WORKSPACE_MIGRATIONS: WorkspaceMigration[] = [
53
58
  moveHooksToWorkspaceMigration,
54
59
  moveConfigFilesToWorkspaceMigration,
55
60
  moveRuntimeFilesToWorkspaceMigration,
61
+ removeOauthAppSetupSkillsMigration,
62
+ backfillInstallMetaMigration,
63
+ removeOrphanedOptimizedImagesCacheMigration,
64
+ recoverConversationsFromDiskViewMigration,
65
+ seedPkbMigration,
56
66
  ];
@@ -1,8 +1,7 @@
1
1
  import type { TopLevelSnapshot } from "./top-level-scanner.js";
2
2
 
3
3
  export interface WorkspaceTopLevelRenderOptions {
4
- currentConversationPath?: string | null;
5
- currentConversationAttachmentsPath?: string | null;
4
+ conversationAttachmentsPath?: string | null;
6
5
  }
7
6
 
8
7
  /**
@@ -15,19 +14,16 @@ export function renderWorkspaceTopLevelContext(
15
14
  snapshot: TopLevelSnapshot,
16
15
  options: WorkspaceTopLevelRenderOptions = {},
17
16
  ): string {
18
- const lines: string[] = ["<workspace_top_level>"];
17
+ const lines: string[] = ["<workspace>"];
19
18
  lines.push(`Root: ${snapshot.rootPath}`);
20
19
  lines.push(`Directories: ${snapshot.directories.join(", ")}`);
21
20
  lines.push(`Files: ${snapshot.files.join(", ")}`);
22
- if (options.currentConversationPath) {
23
- lines.push(`Current conversation folder: ${options.currentConversationPath}`);
24
- }
25
- if (options.currentConversationAttachmentsPath) {
26
- lines.push(`Attachment files: ${options.currentConversationAttachmentsPath}`);
21
+ if (options.conversationAttachmentsPath) {
22
+ lines.push(`Current conversation attachments: ${options.conversationAttachmentsPath}`);
27
23
  }
28
24
  if (snapshot.truncated) {
29
25
  lines.push("(list truncated — more entries exist)");
30
26
  }
31
- lines.push("</workspace_top_level>");
27
+ lines.push("</workspace>");
32
28
  return lines.join("\n");
33
29
  }
@@ -1,372 +0,0 @@
1
- import { rmSync } from "node:fs";
2
- import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
3
-
4
- import { Command } from "commander";
5
- import { eq } from "drizzle-orm";
6
-
7
- mock.module("../util/logger.js", () => ({
8
- getLogger: () =>
9
- new Proxy({} as Record<string, unknown>, {
10
- get: () => () => {},
11
- }),
12
- }));
13
-
14
- mock.module("../memory/qdrant-client.js", () => ({
15
- getQdrantClient: () => ({
16
- searchWithFilter: async () => [],
17
- hybridSearch: async () => [],
18
- upsertPoints: async () => {},
19
- deletePoints: async () => {},
20
- }),
21
- initQdrantClient: () => {},
22
- }));
23
-
24
- // Controllable mock for buildCliProgram
25
- let mockCommands: { name: string; description: string }[] = [];
26
-
27
- function makeMockProgram(): Command {
28
- const program = new Command();
29
- for (const cmd of mockCommands) {
30
- program.command(cmd.name).description(cmd.description);
31
- }
32
- return program;
33
- }
34
-
35
- mock.module("../cli/program.js", () => ({
36
- buildCliProgram: () => makeMockProgram(),
37
- }));
38
-
39
- import { DEFAULT_CONFIG } from "../config/defaults.js";
40
-
41
- const TEST_CONFIG = {
42
- ...DEFAULT_CONFIG,
43
- memory: {
44
- ...DEFAULT_CONFIG.memory,
45
- enabled: true,
46
- extraction: {
47
- ...DEFAULT_CONFIG.memory.extraction,
48
- useLLM: false,
49
- },
50
- },
51
- };
52
-
53
- mock.module("../config/loader.js", () => ({
54
- loadConfig: () => TEST_CONFIG,
55
- getConfig: () => TEST_CONFIG,
56
- loadRawConfig: () => ({}),
57
- saveRawConfig: () => {},
58
- invalidateConfigCache: () => {},
59
- }));
60
-
61
- import {
62
- buildCliCapabilityStatement,
63
- seedCliCommandMemories,
64
- upsertCliCapabilityMemory,
65
- } from "../cli/cli-memory.js";
66
- import { getDb, initializeDb, resetDb } from "../memory/db.js";
67
- import { memoryItems, memoryJobs } from "../memory/schema.js";
68
- import { ensureDataDir, getDbPath } from "../util/platform.js";
69
-
70
- ensureDataDir();
71
- initializeDb();
72
-
73
- afterAll(() => {
74
- resetDb();
75
- });
76
-
77
- function resetTables() {
78
- const db = getDb();
79
- db.run("DELETE FROM memory_item_sources");
80
- db.run("DELETE FROM memory_embeddings");
81
- db.run("DELETE FROM memory_items");
82
- db.run("DELETE FROM memory_jobs");
83
- }
84
-
85
- // ─── buildCliCapabilityStatement ────────────────────────────────────────────
86
-
87
- describe("buildCliCapabilityStatement", () => {
88
- test("includes 'assistant' prefix, name, and description", () => {
89
- const result = buildCliCapabilityStatement("doctor", "Run diagnostic checks");
90
- expect(result).toContain('"assistant doctor"');
91
- expect(result).toContain("Run diagnostic checks");
92
- });
93
-
94
- test("truncates long statements to 500 chars", () => {
95
- const longDesc = "x".repeat(600);
96
- const result = buildCliCapabilityStatement("test", longDesc);
97
- expect(result.length).toBe(500);
98
- });
99
- });
100
-
101
- // ─── upsertCliCapabilityMemory ──────────────────────────────────────────────
102
-
103
- describe("upsertCliCapabilityMemory", () => {
104
- beforeEach(resetTables);
105
-
106
- test("inserts with correct kind, subject, confidence, importance", () => {
107
- upsertCliCapabilityMemory("doctor", "Run diagnostic checks");
108
-
109
- const db = getDb();
110
- const items = db.select().from(memoryItems).all();
111
- expect(items).toHaveLength(1);
112
- expect(items[0].kind).toBe("capability");
113
- expect(items[0].subject).toBe("cli:doctor");
114
- expect(items[0].confidence).toBe(1.0);
115
- expect(items[0].importance).toBe(0.7);
116
- expect(items[0].status).toBe("active");
117
- expect(items[0].scopeId).toBe("default");
118
-
119
- // Should also enqueue an embed_item job
120
- const jobs = db.select().from(memoryJobs).all();
121
- expect(jobs).toHaveLength(1);
122
- expect(jobs[0].type).toBe("embed_item");
123
- });
124
-
125
- test("is idempotent (same entry only touches lastSeenAt)", () => {
126
- upsertCliCapabilityMemory("doctor", "Run diagnostic checks");
127
-
128
- const db = getDb();
129
- const before = db.select().from(memoryItems).all();
130
- expect(before).toHaveLength(1);
131
- const originalLastSeen = before[0].lastSeenAt;
132
-
133
- // Upsert again
134
- upsertCliCapabilityMemory("doctor", "Run diagnostic checks");
135
-
136
- const after = db.select().from(memoryItems).all();
137
- expect(after).toHaveLength(1);
138
- // Fingerprint should be the same, so only lastSeenAt changes
139
- expect(after[0].fingerprint).toBe(before[0].fingerprint);
140
- expect(after[0].lastSeenAt).toBeGreaterThanOrEqual(originalLastSeen);
141
-
142
- // Should NOT enqueue a second embed job (only 1 from initial insert)
143
- const jobs = db.select().from(memoryJobs).all();
144
- expect(jobs).toHaveLength(1);
145
- });
146
-
147
- test("updates statement when description changes", () => {
148
- upsertCliCapabilityMemory("doctor", "Original description");
149
-
150
- const db = getDb();
151
- const before = db.select().from(memoryItems).all();
152
- expect(before).toHaveLength(1);
153
- expect(before[0].statement).toContain("Original description");
154
-
155
- // Change description
156
- upsertCliCapabilityMemory("doctor", "Updated description");
157
-
158
- const after = db.select().from(memoryItems).all();
159
- expect(after).toHaveLength(1);
160
- expect(after[0].statement).toContain("Updated description");
161
- expect(after[0].fingerprint).not.toBe(before[0].fingerprint);
162
-
163
- // Should enqueue a second embed job
164
- const jobs = db.select().from(memoryJobs).all();
165
- expect(jobs).toHaveLength(2);
166
- });
167
-
168
- test("reactivates soft-deleted items", () => {
169
- upsertCliCapabilityMemory("doctor", "Run diagnostic checks");
170
-
171
- const db = getDb();
172
- // Soft-delete the item
173
- db.update(memoryItems)
174
- .set({ status: "deleted" })
175
- .where(eq(memoryItems.subject, "cli:doctor"))
176
- .run();
177
-
178
- const deleted = db.select().from(memoryItems).all();
179
- expect(deleted[0].status).toBe("deleted");
180
-
181
- // Clear jobs from initial insert
182
- db.run("DELETE FROM memory_jobs");
183
-
184
- // Upsert again — should reactivate
185
- upsertCliCapabilityMemory("doctor", "Run diagnostic checks");
186
-
187
- const reactivated = db.select().from(memoryItems).all();
188
- expect(reactivated).toHaveLength(1);
189
- expect(reactivated[0].status).toBe("active");
190
-
191
- // Should enqueue embed job for reactivated item
192
- const jobs = db.select().from(memoryJobs).all();
193
- expect(jobs).toHaveLength(1);
194
- expect(jobs[0].type).toBe("embed_item");
195
- });
196
-
197
- test("does not throw on DB error", () => {
198
- resetDb();
199
- const db = getDb();
200
- db.run("DROP TABLE IF EXISTS memory_items");
201
-
202
- expect(() => {
203
- upsertCliCapabilityMemory("doctor", "Run diagnostic checks");
204
- }).not.toThrow();
205
-
206
- // Restore DB state for subsequent tests.
207
- resetDb();
208
- const dbPath = getDbPath();
209
- for (const ext of ["", "-wal", "-shm"]) {
210
- rmSync(`${dbPath}${ext}`, { force: true });
211
- }
212
- initializeDb();
213
- });
214
- });
215
-
216
- // ─── seedCliCommandMemories ─────────────────────────────────────────────────
217
-
218
- describe("seedCliCommandMemories", () => {
219
- beforeEach(() => {
220
- resetTables();
221
- // Reset mock commands
222
- mockCommands = [];
223
- });
224
-
225
- test("upserts capability memories for all commands", () => {
226
- mockCommands = [
227
- { name: "doctor", description: "Run diagnostic checks" },
228
- { name: "config", description: "Manage configuration" },
229
- { name: "keys", description: "Manage API keys" },
230
- ];
231
-
232
- seedCliCommandMemories();
233
-
234
- const db = getDb();
235
- const items = db
236
- .select()
237
- .from(memoryItems)
238
- .where(eq(memoryItems.kind, "capability"))
239
- .all();
240
- expect(items).toHaveLength(3);
241
-
242
- const subjects = items.map((i) => i.subject).sort();
243
- expect(subjects).toEqual([
244
- "cli:config",
245
- "cli:doctor",
246
- "cli:keys",
247
- ]);
248
-
249
- // All should be active
250
- for (const item of items) {
251
- expect(item.status).toBe("active");
252
- }
253
- });
254
-
255
- test("prunes stale capabilities for commands no longer registered", () => {
256
- // First seed with three commands
257
- mockCommands = [
258
- { name: "doctor", description: "Run diagnostic checks" },
259
- { name: "config", description: "Manage configuration" },
260
- { name: "keys", description: "Manage API keys" },
261
- ];
262
- seedCliCommandMemories();
263
-
264
- const db = getDb();
265
- const beforeItems = db
266
- .select()
267
- .from(memoryItems)
268
- .where(eq(memoryItems.kind, "capability"))
269
- .all();
270
- expect(beforeItems).toHaveLength(3);
271
- expect(beforeItems.every((i) => i.status === "active")).toBe(true);
272
-
273
- // Now seed with only doctor — config and keys should be pruned
274
- mockCommands = [
275
- { name: "doctor", description: "Run diagnostic checks" },
276
- ];
277
- seedCliCommandMemories();
278
-
279
- const afterItems = db
280
- .select()
281
- .from(memoryItems)
282
- .where(eq(memoryItems.kind, "capability"))
283
- .all();
284
- expect(afterItems).toHaveLength(3); // still 3 rows, but 2 are soft-deleted
285
-
286
- const active = afterItems.filter((i) => i.status === "active");
287
- const deleted = afterItems.filter((i) => i.status === "deleted");
288
-
289
- expect(active).toHaveLength(1);
290
- expect(active[0].subject).toBe("cli:doctor");
291
-
292
- expect(deleted).toHaveLength(2);
293
- const deletedSubjects = deleted.map((i) => i.subject).sort();
294
- expect(deletedSubjects).toEqual(["cli:config", "cli:keys"]);
295
- });
296
-
297
- test("handles empty command list without errors", () => {
298
- // Pre-populate a CLI command so we can verify it gets pruned
299
- upsertCliCapabilityMemory("old-command", "An old command");
300
-
301
- const db = getDb();
302
- const beforeItems = db.select().from(memoryItems).all();
303
- expect(beforeItems).toHaveLength(1);
304
- expect(beforeItems[0].status).toBe("active");
305
-
306
- // Seed with empty commands
307
- mockCommands = [];
308
- seedCliCommandMemories();
309
-
310
- // The existing command should be pruned (soft-deleted)
311
- const afterItems = db.select().from(memoryItems).all();
312
- expect(afterItems).toHaveLength(1);
313
- expect(afterItems[0].status).toBe("deleted");
314
- });
315
-
316
- test("does not prune non-cli capability memories", () => {
317
- // Pre-insert a skill capability memory directly into the DB
318
- const db = getDb();
319
- const now = Date.now();
320
- db.insert(memoryItems)
321
- .values({
322
- id: "skill-test-item",
323
- kind: "capability",
324
- subject: "skill:test-skill",
325
- statement: "The test skill does things.",
326
- status: "active",
327
- confidence: 1.0,
328
- importance: 0.7,
329
- fingerprint: "skill-test-fp",
330
- sourceType: "extraction",
331
- scopeId: "default",
332
- firstSeenAt: now,
333
- lastSeenAt: now,
334
- })
335
- .run();
336
-
337
- // Seed with empty commands — CLI pruner runs but should skip skill:* items
338
- mockCommands = [];
339
- seedCliCommandMemories();
340
-
341
- const item = db
342
- .select()
343
- .from(memoryItems)
344
- .where(eq(memoryItems.subject, "skill:test-skill"))
345
- .get();
346
- expect(item).toBeDefined();
347
- expect(item!.status).toBe("active");
348
- });
349
-
350
- test("does not throw on error", () => {
351
- mockCommands = [
352
- { name: "doctor", description: "Run diagnostic checks" },
353
- ];
354
-
355
- // Drop memory_items to force a DB error during the prune phase
356
- resetDb();
357
- const db = getDb();
358
- db.run("DROP TABLE IF EXISTS memory_items");
359
-
360
- expect(() => {
361
- seedCliCommandMemories();
362
- }).not.toThrow();
363
-
364
- // Restore DB state for subsequent tests.
365
- resetDb();
366
- const dbPath = getDbPath();
367
- for (const ext of ["", "-wal", "-shm"]) {
368
- rmSync(`${dbPath}${ext}`, { force: true });
369
- }
370
- initializeDb();
371
- });
372
- });
@@ -1,88 +0,0 @@
1
- import { describe, expect, test } from "bun:test";
2
-
3
- import {
4
- extractLastCodeBlock,
5
- formatConversationForExport,
6
- } from "../util/clipboard.js";
7
-
8
- describe("formatConversationForExport", () => {
9
- test("formats user and assistant messages", () => {
10
- const messages = [
11
- { role: "user", text: "Hello" },
12
- { role: "assistant", text: "Hi there!" },
13
- ];
14
- expect(formatConversationForExport(messages)).toBe(
15
- "you> Hello\n\nassistant> Hi there!",
16
- );
17
- });
18
-
19
- test("handles a single message", () => {
20
- const messages = [{ role: "user", text: "Just me" }];
21
- expect(formatConversationForExport(messages)).toBe("you> Just me");
22
- });
23
-
24
- test("handles empty messages array", () => {
25
- expect(formatConversationForExport([])).toBe("");
26
- });
27
-
28
- test("preserves multiline message text", () => {
29
- const messages = [{ role: "assistant", text: "Line 1\nLine 2\nLine 3" }];
30
- expect(formatConversationForExport(messages)).toBe(
31
- "assistant> Line 1\nLine 2\nLine 3",
32
- );
33
- });
34
- });
35
-
36
- describe("extractLastCodeBlock", () => {
37
- test("extracts a simple code block", () => {
38
- const text = "```\nhello world\n```";
39
- expect(extractLastCodeBlock(text)).toBe("hello world");
40
- });
41
-
42
- test("extracts code block with language tag", () => {
43
- const text = "```typescript\nconst x = 1;\n```";
44
- expect(extractLastCodeBlock(text)).toBe("const x = 1;");
45
- });
46
-
47
- test("returns the last code block when multiple exist", () => {
48
- const text = "```\nfirst\n```\nsome text\n```\nsecond\n```";
49
- expect(extractLastCodeBlock(text)).toBe("second");
50
- });
51
-
52
- test("handles empty code blocks", () => {
53
- const text = "```\n```";
54
- expect(extractLastCodeBlock(text)).toBe("");
55
- });
56
-
57
- test("handles empty code blocks with language tag", () => {
58
- const text = "```python\n```";
59
- expect(extractLastCodeBlock(text)).toBe("");
60
- });
61
-
62
- test("does not match inline backticks as closing fence", () => {
63
- const text = '```\nconst s = "```"\n```';
64
- expect(extractLastCodeBlock(text)).toBe('const s = "```"');
65
- });
66
-
67
- test("handles multi-line code blocks", () => {
68
- const text = "```js\nfunction foo() {\n return 42;\n}\n```";
69
- expect(extractLastCodeBlock(text)).toBe(
70
- "function foo() {\n return 42;\n}",
71
- );
72
- });
73
-
74
- test("returns null when no code blocks exist", () => {
75
- expect(extractLastCodeBlock("no code here")).toBeNull();
76
- expect(extractLastCodeBlock("`inline code`")).toBeNull();
77
- });
78
-
79
- test("extracts last block when separated by text", () => {
80
- const text = "```\nfirst\n```\nSome explanation\n```\nsecond\n```";
81
- expect(extractLastCodeBlock(text)).toBe("second");
82
- });
83
-
84
- test("handles non-empty block followed by empty block with text between", () => {
85
- const text = "```\nreal code\n```\nSome text\n```\n```";
86
- expect(extractLastCodeBlock(text)).toBe("");
87
- });
88
- });