@vellumai/assistant 0.8.0 → 0.8.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 (692) hide show
  1. package/AGENTS.md +11 -0
  2. package/Dockerfile +5 -4
  3. package/README.md +2 -2
  4. package/docker-entrypoint.sh +16 -0
  5. package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +420 -0
  6. package/eslint-rules/cli-no-daemon-internals.js +283 -0
  7. package/eslint.config.mjs +12 -0
  8. package/knip.json +2 -1
  9. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -1
  10. package/openapi.yaml +4847 -1698
  11. package/package.json +3 -1
  12. package/scripts/generate-openapi.ts +52 -4
  13. package/scripts/sync-llm-catalog.ts +165 -0
  14. package/scripts/sync-web-search-catalog.ts +107 -0
  15. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +169 -0
  16. package/src/__tests__/agent-loop-override-profile.test.ts +26 -1
  17. package/src/__tests__/anthropic-provider.test.ts +92 -2
  18. package/src/__tests__/app-control-flow.test.ts +7 -0
  19. package/src/__tests__/assistant-events-sse-shed.test.ts +232 -0
  20. package/src/__tests__/avatar-identity-sync.test.ts +87 -0
  21. package/src/__tests__/background-workers-disk-pressure.test.ts +11 -22
  22. package/src/__tests__/btw-routes.test.ts +1 -0
  23. package/src/__tests__/call-site-routing-provider.test.ts +172 -45
  24. package/src/__tests__/cancel-resolves-conversation-key.test.ts +44 -3
  25. package/src/__tests__/channel-policy.test.ts +12 -0
  26. package/src/__tests__/checker.test.ts +89 -0
  27. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +35 -7
  28. package/src/__tests__/compact-event-conversation-id-guard.test.ts +33 -5
  29. package/src/__tests__/compaction-strip-metadata-clear.test.ts +26 -1
  30. package/src/__tests__/config-loader-backfill.test.ts +526 -102
  31. package/src/__tests__/config-loader-corrupt.test.ts +68 -0
  32. package/src/__tests__/config-loader-platform-defaults.test.ts +77 -23
  33. package/src/__tests__/config-schema-cmd.test.ts +63 -29
  34. package/src/__tests__/config-schema.test.ts +14 -3
  35. package/src/__tests__/config-set-platform-guard.test.ts +75 -152
  36. package/src/__tests__/config-set-route.test.ts +198 -0
  37. package/src/__tests__/config-watcher.test.ts +6 -0
  38. package/src/__tests__/contacts-tools.test.ts +51 -199
  39. package/src/__tests__/context-search-agent-protocol.test.ts +21 -2
  40. package/src/__tests__/context-search-agent-runner.test.ts +22 -138
  41. package/src/__tests__/context-search-conversations-source.test.ts +42 -16
  42. package/src/__tests__/context-search-fanout.test.ts +20 -157
  43. package/src/__tests__/context-search-memory-v2-source.test.ts +3 -3
  44. package/src/__tests__/context-search-types.test.ts +7 -2
  45. package/src/__tests__/context-window-manager.test.ts +389 -1
  46. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
  47. package/src/__tests__/conversation-crud-inference-profile.test.ts +100 -0
  48. package/src/__tests__/conversation-error.test.ts +38 -0
  49. package/src/__tests__/conversation-fork-crud.test.ts +241 -1
  50. package/src/__tests__/conversation-inference-profile-route.test.ts +14 -14
  51. package/src/__tests__/conversation-init.benchmark.test.ts +1 -0
  52. package/src/__tests__/conversation-lifecycle.test.ts +124 -0
  53. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +100 -1
  54. package/src/__tests__/conversation-process-callsite.test.ts +21 -1
  55. package/src/__tests__/conversation-runtime-assembly.test.ts +4 -4
  56. package/src/__tests__/conversation-slash-commands.test.ts +194 -2
  57. package/src/__tests__/conversation-surfaces-app-control.test.ts +323 -3
  58. package/src/__tests__/credential-security-invariants.test.ts +5 -6
  59. package/src/__tests__/daemon-credential-client.test.ts +56 -1
  60. package/src/__tests__/db-activation-state-fk-cascade.test.ts +132 -0
  61. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +37 -0
  62. package/src/__tests__/db-memory-graph-event-date-repair.test.ts +43 -20
  63. package/src/__tests__/db-proxy-transaction.test.ts +206 -0
  64. package/src/__tests__/external-plugin-loader.test.ts +458 -0
  65. package/src/__tests__/filing-service.test.ts +23 -3
  66. package/src/__tests__/fixtures/mock-chrome-extension.ts +5 -0
  67. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  68. package/src/__tests__/graph-extraction-event-date.test.ts +34 -0
  69. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +0 -8
  70. package/src/__tests__/heartbeat-disk-pressure.test.ts +21 -8
  71. package/src/__tests__/heartbeat-service.test.ts +50 -233
  72. package/src/__tests__/history-repair.test.ts +89 -0
  73. package/src/__tests__/host-app-control-proxy.test.ts +109 -1
  74. package/src/__tests__/host-app-control-routes.test.ts +247 -1
  75. package/src/__tests__/host-browser-proxy.test.ts +416 -20
  76. package/src/__tests__/host-browser-routes.test.ts +325 -33
  77. package/src/__tests__/host-proxy-preactivation.test.ts +211 -0
  78. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +246 -0
  79. package/src/__tests__/inference-profile-reaper.test.ts +154 -0
  80. package/src/__tests__/inference-profile-session-handler.test.ts +398 -0
  81. package/src/__tests__/inference-profile-session-ipc.test.ts +236 -0
  82. package/src/__tests__/inline-skill-load-permissions.test.ts +6 -1
  83. package/src/__tests__/install-skill-routing.test.ts +2 -2
  84. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +15 -0
  85. package/src/__tests__/llm-callsite-catalog.test.ts +20 -1
  86. package/src/__tests__/llm-catalog-parity.test.ts +146 -0
  87. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +188 -0
  88. package/src/__tests__/llm-request-log-source-factory.test.ts +124 -0
  89. package/src/__tests__/llm-resolver.test.ts +46 -0
  90. package/src/__tests__/managed-profile-guard.test.ts +131 -2
  91. package/src/__tests__/mcp-auth-routes.test.ts +1 -0
  92. package/src/__tests__/mcp-cli.test.ts +182 -220
  93. package/src/__tests__/mcp-health-check.test.ts +56 -27
  94. package/src/__tests__/memory-jobs-worker-lanes.test.ts +18 -11
  95. package/src/__tests__/message-complete-display-id.test.ts +175 -0
  96. package/src/__tests__/notification-platform-adapter.test.ts +229 -0
  97. package/src/__tests__/oauth-cli.test.ts +38 -2009
  98. package/src/__tests__/oauth-commands-routes.test.ts +711 -0
  99. package/src/__tests__/oauth-connect-routes.test.ts +174 -11
  100. package/src/__tests__/oauth-providers-routes.test.ts +14 -10
  101. package/src/__tests__/openai-responses-cutover-guard.test.ts +33 -12
  102. package/src/__tests__/openai-responses-provider.test.ts +17 -0
  103. package/src/__tests__/plugin-bootstrap.test.ts +31 -2
  104. package/src/__tests__/plugin-route-contribution.test.ts +31 -3
  105. package/src/__tests__/plugin-tool-contribution.test.ts +31 -3
  106. package/src/__tests__/plugin-types.test.ts +13 -11
  107. package/src/__tests__/process-message-background-slack.test.ts +46 -0
  108. package/src/__tests__/profile-entry-status.test.ts +43 -0
  109. package/src/__tests__/provider-managed-proxy-integration.test.ts +12 -4
  110. package/src/__tests__/provider-registry-ollama.test.ts +12 -4
  111. package/src/__tests__/provider-send-message-override-profile.test.ts +10 -4
  112. package/src/__tests__/relay-server.test.ts +118 -0
  113. package/src/__tests__/retry-thinking-tool-choice.test.ts +15 -0
  114. package/src/__tests__/schedule-retry.test.ts +56 -4
  115. package/src/__tests__/schedule-routes.test.ts +104 -0
  116. package/src/__tests__/scheduler-disk-pressure.test.ts +0 -4
  117. package/src/__tests__/scheduler-recurrence.test.ts +87 -34
  118. package/src/__tests__/scheduler-reuse-conversation.test.ts +161 -5
  119. package/src/__tests__/scheduler-wake.test.ts +0 -63
  120. package/src/__tests__/secret-allowlist.test.ts +1 -0
  121. package/src/__tests__/secret-routes-managed-proxy.test.ts +12 -4
  122. package/src/__tests__/shell-credential-ref.test.ts +95 -3
  123. package/src/__tests__/shell-tool-proxy-mode.test.ts +14 -0
  124. package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
  125. package/src/__tests__/skill-load-tool.test.ts +2 -4
  126. package/src/__tests__/subagent-call-site-routing.test.ts +78 -16
  127. package/src/__tests__/suggestion-routes.test.ts +3 -3
  128. package/src/__tests__/sync-message-contract.test.ts +63 -0
  129. package/src/__tests__/task-scheduler.test.ts +88 -23
  130. package/src/__tests__/update-bulletin-job.test.ts +96 -193
  131. package/src/__tests__/usage-cli.test.ts +11 -73
  132. package/src/__tests__/user-plugin-loader.test.ts +145 -0
  133. package/src/__tests__/vercel-config.test.ts +168 -0
  134. package/src/__tests__/web-search-catalog-parity.test.ts +86 -0
  135. package/src/__tests__/web-search.test.ts +303 -2
  136. package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +1 -21
  137. package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +58 -0
  138. package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +53 -20
  139. package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +191 -0
  140. package/src/__tests__/workspace-migration-076-drop-services-inference-mode.test.ts +211 -0
  141. package/src/__tests__/workspace-migration-077-seed-memory-router-callsite.test.ts +174 -0
  142. package/src/__tests__/workspace-migration-079-home-feed-notification-only.test.ts +323 -0
  143. package/src/__tests__/workspace-migration-080-restrict-vercel-api-token-metadata.test.ts +299 -0
  144. package/src/__tests__/workspace-migration-081-backfill-bash-allowed-tools.test.ts +410 -0
  145. package/src/__tests__/workspace-migration-082-backfill-managed-profile-labels.test.ts +268 -0
  146. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +3 -3
  147. package/src/__tests__/workspace-release-notes-feature-flag-guard.test.ts +115 -0
  148. package/src/acp/__tests__/helpers/which-stub.ts +4 -2
  149. package/src/acp/resolve-agent.test.ts +25 -0
  150. package/src/acp/resolve-agent.ts +13 -2
  151. package/src/acp/session-manager.ts +14 -0
  152. package/src/approvals/guardian-request-resolvers.ts +32 -87
  153. package/src/calls/relay-server.ts +35 -0
  154. package/src/calls/relay-setup-router.ts +36 -0
  155. package/src/calls/types.ts +1 -0
  156. package/src/calls/voice-session-bridge.ts +23 -4
  157. package/src/channels/config.ts +14 -1
  158. package/src/channels/types.ts +1 -0
  159. package/src/cli/AGENTS.md +164 -4
  160. package/src/cli/__tests__/notifications.test.ts +54 -0
  161. package/src/cli/commands/__tests__/avatar.test.ts +540 -0
  162. package/src/cli/commands/__tests__/backup.test.ts +236 -776
  163. package/src/cli/commands/__tests__/cache.test.ts +1 -1
  164. package/src/cli/commands/__tests__/changelog.test.ts +593 -0
  165. package/src/cli/commands/__tests__/channel-verification-sessions.test.ts +503 -0
  166. package/src/cli/commands/__tests__/conversations-import.test.ts +515 -0
  167. package/src/cli/commands/__tests__/domain-register.test.ts +140 -167
  168. package/src/cli/commands/__tests__/domain-status.test.ts +137 -76
  169. package/src/cli/commands/__tests__/email-attachment.test.ts +314 -337
  170. package/src/cli/commands/__tests__/email-core.test.ts +579 -0
  171. package/src/cli/commands/__tests__/image-generation.test.ts +87 -824
  172. package/src/cli/commands/__tests__/inference-send.test.ts +30 -266
  173. package/src/cli/commands/__tests__/inference-session.test.ts +423 -0
  174. package/src/cli/commands/__tests__/memory-v2.test.ts +81 -110
  175. package/src/cli/commands/__tests__/skills.test.ts +563 -0
  176. package/src/cli/commands/__tests__/status.test.ts +249 -0
  177. package/src/cli/commands/__tests__/stt.test.ts +320 -0
  178. package/src/cli/commands/__tests__/tts-synthesize.test.ts +4 -603
  179. package/src/cli/commands/__tests__/tts.test.ts +321 -0
  180. package/src/cli/commands/__tests__/webhooks.test.ts +86 -511
  181. package/src/cli/commands/attachment.ts +8 -3
  182. package/src/cli/commands/audit.ts +95 -64
  183. package/src/cli/commands/auth.ts +61 -58
  184. package/src/cli/commands/avatar.ts +276 -390
  185. package/src/cli/commands/backup.ts +409 -505
  186. package/src/cli/commands/bash.ts +9 -5
  187. package/src/cli/commands/browser.ts +28 -9
  188. package/src/cli/commands/cache.ts +9 -4
  189. package/src/cli/commands/changelog.ts +414 -0
  190. package/src/cli/commands/channel-verification-sessions.ts +238 -317
  191. package/src/cli/commands/clients.ts +8 -3
  192. package/src/cli/commands/completions.ts +9 -9
  193. package/src/cli/commands/config.ts +102 -72
  194. package/src/cli/commands/contacts.ts +575 -696
  195. package/src/cli/commands/conversations-defer.ts +17 -69
  196. package/src/cli/commands/conversations-import.ts +90 -253
  197. package/src/cli/commands/conversations.ts +346 -436
  198. package/src/cli/commands/credential-execution.ts +9 -6
  199. package/src/cli/commands/credentials.ts +456 -736
  200. package/src/cli/commands/domain.ts +128 -206
  201. package/src/cli/commands/email.ts +606 -794
  202. package/src/cli/commands/gateway.ts +8 -1
  203. package/src/cli/commands/image-generation.ts +157 -205
  204. package/src/cli/commands/inference-providers.ts +352 -0
  205. package/src/cli/commands/inference-session.ts +415 -0
  206. package/src/cli/commands/inference.ts +87 -65
  207. package/src/cli/commands/keys.ts +8 -3
  208. package/src/cli/commands/mcp.ts +103 -287
  209. package/src/cli/commands/memory-v2.ts +162 -516
  210. package/src/cli/commands/notifications.ts +33 -7
  211. package/src/cli/commands/oauth/apps.ts +292 -261
  212. package/src/cli/commands/oauth/connect.ts +176 -297
  213. package/src/cli/commands/oauth/disconnect.ts +16 -215
  214. package/src/cli/commands/oauth/index.ts +49 -45
  215. package/src/cli/commands/oauth/mode.ts +43 -199
  216. package/src/cli/commands/oauth/ping.ts +17 -125
  217. package/src/cli/commands/oauth/providers.ts +732 -921
  218. package/src/cli/commands/oauth/request.ts +60 -350
  219. package/src/cli/commands/oauth/shared.ts +11 -121
  220. package/src/cli/commands/oauth/status.ts +31 -121
  221. package/src/cli/commands/oauth/token.ts +13 -55
  222. package/src/cli/commands/pending.ts +19 -10
  223. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +133 -183
  224. package/src/cli/commands/platform/__tests__/connect.test.ts +66 -181
  225. package/src/cli/commands/platform/__tests__/disconnect.test.ts +71 -227
  226. package/src/cli/commands/platform/__tests__/status.test.ts +169 -287
  227. package/src/cli/commands/platform/connect.ts +16 -80
  228. package/src/cli/commands/platform/disconnect.ts +14 -112
  229. package/src/cli/commands/platform/index.ts +177 -246
  230. package/src/cli/commands/routes.ts +153 -336
  231. package/src/cli/commands/sequence.ts +316 -360
  232. package/src/cli/commands/skills.ts +449 -671
  233. package/src/cli/commands/status.ts +58 -37
  234. package/src/cli/commands/stt.ts +94 -262
  235. package/src/cli/commands/task.ts +14 -40
  236. package/src/cli/commands/trust.ts +8 -3
  237. package/src/cli/commands/tts.ts +162 -167
  238. package/src/cli/commands/ui.ts +35 -42
  239. package/src/cli/commands/usage.ts +188 -126
  240. package/src/cli/commands/watchers.ts +8 -3
  241. package/src/cli/commands/webhooks.ts +99 -193
  242. package/src/cli/lib/__tests__/register-command.test.ts +85 -0
  243. package/src/cli/lib/daemon-credential-client.ts +4 -5
  244. package/src/cli/lib/nested-value.ts +44 -0
  245. package/src/cli/lib/open-browser.ts +36 -0
  246. package/src/cli/lib/register-command.ts +19 -0
  247. package/src/cli/lib/time-ago.ts +34 -0
  248. package/src/cli/program.ts +2 -4
  249. package/src/cli/utils/__tests__/conversation-id.test.ts +66 -0
  250. package/src/cli/utils/__tests__/parse-duration.test.ts +49 -0
  251. package/src/cli/utils/conversation-id.ts +30 -0
  252. package/src/cli/utils/parse-duration.ts +41 -0
  253. package/src/config/acp-defaults.test.ts +5 -1
  254. package/src/config/acp-defaults.ts +11 -4
  255. package/src/config/bundled-skills/acp/TOOLS.json +2 -2
  256. package/src/config/bundled-skills/app-control/TOOLS.json +32 -0
  257. package/src/config/bundled-skills/contacts/SKILL.md +12 -45
  258. package/src/config/bundled-skills/contacts/TOOLS.json +0 -57
  259. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +0 -12
  260. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -58
  261. package/src/config/bundled-tool-registry.ts +0 -2
  262. package/src/config/feature-flag-registry.json +16 -0
  263. package/src/config/llm-resolver.ts +16 -1
  264. package/src/config/loader.ts +76 -14
  265. package/src/config/raw-config-utils.ts +2 -30
  266. package/src/config/schema.ts +4 -0
  267. package/src/config/schemas/__tests__/memory-v2.test.ts +49 -0
  268. package/src/config/schemas/call-site-catalog.ts +29 -7
  269. package/src/config/schemas/llm-request-logs.ts +57 -0
  270. package/src/config/schemas/llm.ts +52 -2
  271. package/src/config/schemas/memory-retrospective.ts +48 -0
  272. package/src/config/schemas/memory-v2.ts +32 -1
  273. package/src/config/schemas/memory.ts +4 -0
  274. package/src/config/schemas/services.ts +15 -12
  275. package/src/config/seed-inference-profiles.ts +195 -134
  276. package/src/contacts/contact-store.ts +0 -61
  277. package/src/context/window-manager.ts +191 -5
  278. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +79 -0
  279. package/src/daemon/__tests__/conversation-tool-setup.test.ts +109 -4
  280. package/src/daemon/__tests__/daemon-skill-host.test.ts +10 -4
  281. package/src/daemon/approval-generators.ts +23 -29
  282. package/src/daemon/config-watcher.ts +2 -0
  283. package/src/daemon/conversation-agent-loop-handlers.ts +24 -0
  284. package/src/daemon/conversation-agent-loop.ts +127 -97
  285. package/src/daemon/conversation-error.ts +21 -0
  286. package/src/daemon/conversation-lifecycle.ts +46 -5
  287. package/src/daemon/conversation-process.ts +36 -19
  288. package/src/daemon/conversation-runtime-assembly.ts +14 -5
  289. package/src/daemon/conversation-slash.ts +175 -23
  290. package/src/daemon/conversation-store.ts +17 -10
  291. package/src/daemon/conversation-surfaces.ts +76 -12
  292. package/src/daemon/conversation-tool-setup.ts +24 -14
  293. package/src/daemon/conversation.ts +48 -9
  294. package/src/daemon/external-plugins-bootstrap.ts +18 -8
  295. package/src/daemon/guardian-action-generators.ts +7 -22
  296. package/src/daemon/handlers/config-model.ts +8 -126
  297. package/src/daemon/handlers/config-slack-channel.ts +10 -7
  298. package/src/daemon/handlers/config-vercel.ts +3 -1
  299. package/src/daemon/handlers/skills.ts +84 -5
  300. package/src/daemon/history-repair.ts +33 -6
  301. package/src/daemon/host-app-control-proxy.ts +44 -19
  302. package/src/daemon/host-bash-proxy.ts +85 -158
  303. package/src/daemon/host-browser-proxy.ts +96 -35
  304. package/src/daemon/host-proxy-base.ts +13 -1
  305. package/src/daemon/host-proxy-preactivation.ts +25 -1
  306. package/src/daemon/identity-helpers.ts +19 -0
  307. package/src/daemon/lifecycle.ts +42 -43
  308. package/src/daemon/meet-host-supervisor.ts +15 -15
  309. package/src/daemon/memory-v2-startup.ts +9 -2
  310. package/src/daemon/message-protocol.ts +6 -0
  311. package/src/daemon/message-types/bookmarks.ts +18 -0
  312. package/src/daemon/message-types/conversations.ts +12 -9
  313. package/src/daemon/message-types/messages.ts +9 -1
  314. package/src/daemon/message-types/sync.ts +60 -0
  315. package/src/daemon/pkb-reminder-builder.test.ts +54 -13
  316. package/src/daemon/pkb-reminder-builder.ts +21 -7
  317. package/src/daemon/process-message.ts +56 -23
  318. package/src/daemon/server.ts +23 -18
  319. package/src/daemon/shutdown-handlers.ts +0 -2
  320. package/src/daemon/tool-setup-types.ts +9 -0
  321. package/src/daemon/tool-side-effects.ts +6 -4
  322. package/src/daemon/wake-target-adapter.ts +11 -0
  323. package/src/export/transcript-formatter.ts +61 -2
  324. package/src/filing/filing-service.ts +40 -53
  325. package/src/heartbeat/__tests__/heartbeat-service.test.ts +359 -0
  326. package/src/heartbeat/heartbeat-run-store.ts +2 -1
  327. package/src/heartbeat/heartbeat-service.ts +148 -127
  328. package/src/home/__tests__/feed-types.test.ts +63 -131
  329. package/src/home/__tests__/feed-writer.test.ts +77 -278
  330. package/src/home/__tests__/post-connect-feed.test.ts +9 -12
  331. package/src/home/feed-types.ts +19 -73
  332. package/src/home/feed-writer.ts +25 -156
  333. package/src/home/post-connect-feed.ts +1 -3
  334. package/src/ipc/__tests__/cli-ipc.test.ts +2 -0
  335. package/src/ipc/__tests__/email-ipc.test.ts +506 -0
  336. package/src/ipc/__tests__/exit-helper.test.ts +104 -0
  337. package/src/ipc/__tests__/streaming-client.test.ts +237 -0
  338. package/src/ipc/__tests__/streaming-framing.test.ts +142 -0
  339. package/src/ipc/assistant-server.ts +55 -6
  340. package/src/ipc/cli-client.ts +370 -50
  341. package/src/ipc/routes/db-proxy-transaction.ts +151 -0
  342. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +60 -0
  343. package/src/ipc/skill-routes/events.ts +30 -3
  344. package/src/live-voice/__tests__/live-voice-session-manager.test.ts +46 -0
  345. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +1 -0
  346. package/src/live-voice/live-voice-session-manager.ts +11 -4
  347. package/src/live-voice/live-voice-session.ts +14 -6
  348. package/src/memory/__tests__/bookmark-crud.test.ts +258 -0
  349. package/src/memory/__tests__/bookmark-schema.test.ts +181 -0
  350. package/src/memory/__tests__/conversation-types.test.ts +36 -0
  351. package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +130 -0
  352. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +177 -0
  353. package/src/memory/__tests__/memory-retrospective-job.test.ts +328 -0
  354. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +213 -0
  355. package/src/memory/__tests__/memory-retrospective-trigger-check.test.ts +90 -0
  356. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +69 -0
  357. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -0
  358. package/src/memory/bookmark-crud.ts +179 -0
  359. package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +31 -9
  360. package/src/memory/context-search/agent-protocol.ts +5 -1
  361. package/src/memory/context-search/agent-runner.ts +60 -85
  362. package/src/memory/context-search/limits.ts +1 -4
  363. package/src/memory/context-search/search.ts +23 -113
  364. package/src/memory/context-search/sources/conversations.ts +18 -6
  365. package/src/memory/context-search/sources/memory-v2.ts +39 -14
  366. package/src/memory/context-search/sources/memory.ts +7 -0
  367. package/src/memory/context-search/sources/workspace.ts +13 -10
  368. package/src/memory/context-search/types.ts +1 -1
  369. package/src/memory/conversation-bootstrap.ts +11 -0
  370. package/src/memory/conversation-crud.ts +312 -10
  371. package/src/memory/conversation-queries.ts +9 -5
  372. package/src/memory/conversation-title-service.ts +1 -0
  373. package/src/memory/conversation-types.ts +16 -0
  374. package/src/memory/db-init.ts +14 -0
  375. package/src/memory/embedding-backend.ts +2 -1
  376. package/src/memory/embedding-runtime-manager.ts +1 -2
  377. package/src/memory/graph/__tests__/remember-description.test.ts +55 -0
  378. package/src/memory/graph/conversation-graph-memory.ts +76 -5
  379. package/src/memory/graph/extraction.ts +4 -0
  380. package/src/memory/graph/graph-memory-state-store.ts +16 -3
  381. package/src/memory/graph/tool-handlers.ts +17 -7
  382. package/src/memory/graph/tools.ts +44 -5
  383. package/src/memory/indexer.ts +17 -0
  384. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +13 -15
  385. package/src/memory/jobs/embed-concept-page.ts +45 -9
  386. package/src/memory/jobs-store.ts +51 -1
  387. package/src/memory/jobs-worker.ts +52 -3
  388. package/src/memory/llm-request-log-source-clickhouse.ts +317 -0
  389. package/src/memory/llm-request-log-source-local.ts +26 -0
  390. package/src/memory/llm-request-log-source.ts +97 -0
  391. package/src/memory/llm-request-log-store.ts +1 -1
  392. package/src/memory/memory-retrospective-constants.ts +13 -0
  393. package/src/memory/memory-retrospective-enqueue.ts +114 -0
  394. package/src/memory/memory-retrospective-job.ts +351 -0
  395. package/src/memory/memory-retrospective-startup-cleanup.ts +108 -0
  396. package/src/memory/memory-retrospective-state.ts +162 -0
  397. package/src/memory/memory-retrospective-trigger-check.ts +91 -0
  398. package/src/memory/memory-v2-activation-log-store.ts +49 -5
  399. package/src/memory/memory-v2-concept-frequency.ts +4 -0
  400. package/src/memory/message-content.ts +38 -1
  401. package/src/memory/migrations/227-add-conversation-inference-profile.ts +6 -1
  402. package/src/memory/migrations/228-rename-inference-profile-snake-case.ts +20 -7
  403. package/src/memory/migrations/229-delete-private-conversations.test.ts +70 -1
  404. package/src/memory/migrations/229-delete-private-conversations.ts +12 -0
  405. package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +16 -2
  406. package/src/memory/migrations/240-conversation-inference-profile-session.ts +25 -0
  407. package/src/memory/migrations/241-activation-state-fk-cascade.ts +50 -0
  408. package/src/memory/migrations/242-message-bookmarks.ts +38 -0
  409. package/src/memory/migrations/243-provider-connections.ts +68 -0
  410. package/src/memory/migrations/244-provider-connection-status-label.ts +23 -0
  411. package/src/memory/migrations/245-memory-retrospective-state.ts +36 -0
  412. package/src/memory/migrations/246-backfill-provider-connection-label.ts +81 -0
  413. package/src/memory/migrations/__tests__/244-provider-connection-status-label.test.ts +84 -0
  414. package/src/memory/migrations/__tests__/245-memory-retrospective-state.test.ts +125 -0
  415. package/src/memory/migrations/__tests__/246-backfill-provider-connection-label.test.ts +192 -0
  416. package/src/memory/migrations/index.ts +7 -0
  417. package/src/memory/published-pages-store.ts +16 -0
  418. package/src/memory/schema/bookmarks.ts +38 -0
  419. package/src/memory/schema/conversations.ts +2 -0
  420. package/src/memory/schema/index.ts +2 -0
  421. package/src/memory/schema/inference.ts +29 -0
  422. package/src/memory/schema/memory-core.ts +9 -0
  423. package/src/memory/search/semantic.ts +1 -4
  424. package/src/memory/v2/__tests__/__snapshots__/prompts-router.test.ts.snap +27 -0
  425. package/src/memory/v2/__tests__/activation-store.test.ts +5 -5
  426. package/src/memory/v2/__tests__/activation.test.ts +11 -4
  427. package/src/memory/v2/__tests__/backfill-jobs.test.ts +38 -21
  428. package/src/memory/v2/__tests__/consolidation-job.test.ts +123 -135
  429. package/src/memory/v2/__tests__/edge-index.test.ts +1 -1
  430. package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +111 -0
  431. package/src/memory/v2/__tests__/injection.test.ts +628 -10
  432. package/src/memory/v2/__tests__/migration.test.ts +7 -3
  433. package/src/memory/v2/__tests__/page-index.test.ts +277 -0
  434. package/src/memory/v2/__tests__/page-store.test.ts +14 -1
  435. package/src/memory/v2/__tests__/prompts-router.test.ts +257 -0
  436. package/src/memory/v2/__tests__/qdrant.test.ts +72 -0
  437. package/src/memory/v2/__tests__/reranker.test.ts +4 -4
  438. package/src/memory/v2/__tests__/router.test.ts +516 -0
  439. package/src/memory/v2/__tests__/sim.test.ts +45 -1
  440. package/src/memory/v2/__tests__/skill-store.test.ts +58 -3
  441. package/src/memory/v2/__tests__/static-context.test.ts +7 -22
  442. package/src/memory/v2/__tests__/sweep-job.test.ts +95 -0
  443. package/src/memory/v2/activation-store.ts +34 -5
  444. package/src/memory/v2/activation.ts +40 -27
  445. package/src/memory/v2/backfill-jobs.ts +17 -84
  446. package/src/memory/v2/consolidation-job.ts +85 -78
  447. package/src/memory/v2/frontmatter-sweep.ts +91 -0
  448. package/src/memory/v2/injection.ts +440 -109
  449. package/src/memory/v2/migration.ts +117 -20
  450. package/src/memory/v2/page-index.ts +191 -0
  451. package/src/memory/v2/page-store.ts +3 -0
  452. package/src/memory/v2/prompts/consolidation.ts +9 -7
  453. package/src/memory/v2/prompts/router.ts +192 -0
  454. package/src/memory/v2/qdrant.ts +100 -87
  455. package/src/memory/v2/reranker.ts +14 -7
  456. package/src/memory/v2/router.ts +322 -0
  457. package/src/memory/v2/sim.ts +25 -12
  458. package/src/memory/v2/skill-store.ts +118 -29
  459. package/src/memory/v2/static-context.ts +16 -9
  460. package/src/memory/v2/sweep-job.ts +122 -96
  461. package/src/memory/v2/types.ts +10 -6
  462. package/src/memory/validation.ts +13 -0
  463. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +182 -0
  464. package/src/notifications/__tests__/home-feed-side-effect.test.ts +199 -0
  465. package/src/notifications/__tests__/signal-registry.test.ts +17 -0
  466. package/src/notifications/adapters/platform.ts +171 -0
  467. package/src/notifications/conversation-pairing.ts +2 -2
  468. package/src/notifications/copy-composer.ts +15 -0
  469. package/src/notifications/destination-resolver.ts +21 -0
  470. package/src/notifications/emit-signal.ts +28 -1
  471. package/src/notifications/home-feed-side-effect.ts +111 -0
  472. package/src/notifications/signal.ts +5 -0
  473. package/src/permissions/checker.ts +12 -0
  474. package/src/permissions/ipc-risk-types.ts +2 -0
  475. package/src/plugin-api/index.ts +13 -0
  476. package/src/plugin-api/package.json +12 -0
  477. package/src/plugin-api/types.ts +62 -0
  478. package/src/plugins/defaults/injectors.ts +19 -3
  479. package/src/plugins/external-plugin-loader.ts +294 -0
  480. package/src/plugins/types.ts +46 -30
  481. package/src/plugins/user-loader.ts +64 -41
  482. package/src/proactive-artifact/job.test.ts +12 -4
  483. package/src/proactive-artifact/job.ts +4 -0
  484. package/src/proactive-artifact/trigger-state.test.ts +9 -0
  485. package/src/proactive-artifact/trigger-state.ts +4 -0
  486. package/src/prompts/__tests__/system-prompt.test.ts +105 -0
  487. package/src/prompts/system-prompt.ts +22 -1
  488. package/src/prompts/update-bulletin-job.ts +61 -73
  489. package/src/providers/__tests__/dispatch-connection-routing.test.ts +279 -0
  490. package/src/providers/__tests__/inference.test.ts +288 -0
  491. package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
  492. package/src/providers/__tests__/provider-secret-catalog.test.ts +6 -0
  493. package/src/providers/__tests__/retry-callsite.test.ts +14 -32
  494. package/src/providers/__tests__/satellite-connection-routing.test.ts +510 -0
  495. package/src/providers/__tests__/search-provider-catalog.test.ts +80 -0
  496. package/src/providers/anthropic/client.ts +95 -26
  497. package/src/providers/call-site-routing.ts +94 -16
  498. package/src/providers/connection-resolution.ts +163 -0
  499. package/src/providers/inference/__tests__/connections-status-label.test.ts +250 -0
  500. package/src/providers/inference/adapter-factory.ts +173 -0
  501. package/src/providers/inference/auth.ts +112 -0
  502. package/src/providers/inference/backfill.ts +196 -0
  503. package/src/providers/inference/connections.ts +356 -0
  504. package/src/providers/inference/resolve-auth.ts +65 -0
  505. package/src/providers/model-catalog.ts +104 -6
  506. package/src/providers/openai/responses-provider.ts +4 -2
  507. package/src/providers/provider-env-vars.ts +17 -7
  508. package/src/providers/provider-secret-catalog.ts +49 -30
  509. package/src/providers/provider-send-message.ts +41 -20
  510. package/src/providers/registry.ts +143 -159
  511. package/src/providers/retry.ts +18 -10
  512. package/src/providers/search-provider-catalog.ts +121 -0
  513. package/src/runtime/AGENTS.md +18 -5
  514. package/src/runtime/__tests__/background-job-runner.test.ts +357 -0
  515. package/src/runtime/__tests__/pre-first-message-gate.test.ts +82 -0
  516. package/src/runtime/actor-trust-resolver.ts +32 -10
  517. package/src/runtime/agent-wake.ts +35 -6
  518. package/src/runtime/assistant-event-hub.ts +3 -85
  519. package/src/runtime/auth/route-policy.ts +303 -8
  520. package/src/runtime/auth/same-actor.ts +2 -0
  521. package/src/runtime/background-job-runner.ts +339 -0
  522. package/src/runtime/btw-sidechain.ts +1 -0
  523. package/src/runtime/http-router.ts +36 -1
  524. package/src/runtime/http-server.ts +31 -5
  525. package/src/runtime/http-types.ts +2 -0
  526. package/src/runtime/middleware/__tests__/request-logger.test.ts +162 -0
  527. package/src/runtime/middleware/request-logger.ts +62 -1
  528. package/src/runtime/pre-first-message-gate.ts +83 -0
  529. package/src/runtime/routes/__tests__/backup-routes.test.ts +8 -1
  530. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +251 -0
  531. package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +142 -0
  532. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +315 -0
  533. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +189 -0
  534. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +15 -136
  535. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +736 -0
  536. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +4 -4
  537. package/src/runtime/routes/__tests__/stt-routes.test.ts +5 -1
  538. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +384 -0
  539. package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
  540. package/src/runtime/routes/acp-routes.ts +10 -8
  541. package/src/runtime/routes/app-management-routes.ts +228 -3
  542. package/src/runtime/routes/approval-routes.ts +0 -18
  543. package/src/runtime/routes/audit-routes.ts +43 -0
  544. package/src/runtime/routes/auth-routes.ts +72 -0
  545. package/src/runtime/routes/avatar-routes.ts +273 -20
  546. package/src/runtime/routes/backup-routes.ts +406 -2
  547. package/src/runtime/routes/bookmark-routes.ts +154 -0
  548. package/src/runtime/routes/channel-verification-routes.ts +2 -1
  549. package/src/runtime/routes/contact-routes.ts +0 -160
  550. package/src/runtime/routes/conversation-cli-routes.ts +192 -0
  551. package/src/runtime/routes/conversation-management-routes.ts +30 -43
  552. package/src/runtime/routes/conversation-query-routes.ts +334 -86
  553. package/src/runtime/routes/conversation-routes.ts +31 -10
  554. package/src/runtime/routes/conversations-import-routes.ts +229 -0
  555. package/src/runtime/routes/credential-routes.ts +540 -0
  556. package/src/runtime/routes/debug-routes.ts +2 -2
  557. package/src/runtime/routes/document-pdf-renderer.ts +5 -1
  558. package/src/runtime/routes/domain-routes.ts +167 -0
  559. package/src/runtime/routes/email-routes.ts +603 -0
  560. package/src/runtime/routes/errors.ts +2 -2
  561. package/src/runtime/routes/events-routes.ts +192 -0
  562. package/src/runtime/routes/home-feed-routes.ts +6 -78
  563. package/src/runtime/routes/host-app-control-routes.ts +44 -2
  564. package/src/runtime/routes/host-browser-routes.ts +103 -22
  565. package/src/runtime/routes/http-adapter.ts +2 -0
  566. package/src/runtime/routes/identity-routes.ts +5 -0
  567. package/src/runtime/routes/image-generation-routes.ts +99 -0
  568. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +137 -1
  569. package/src/runtime/routes/inbound-stages/background-dispatch.ts +87 -7
  570. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +156 -0
  571. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +22 -4
  572. package/src/runtime/routes/index.ts +36 -0
  573. package/src/runtime/routes/inference-profile-session-handler.ts +312 -0
  574. package/src/runtime/routes/inference-profile-session-reaper.ts +98 -0
  575. package/src/runtime/routes/inference-profile-session-routes.ts +146 -0
  576. package/src/runtime/routes/inference-provider-connection-routes.ts +317 -0
  577. package/src/runtime/routes/inference-send-routes.ts +115 -0
  578. package/src/runtime/routes/integrations/twilio.ts +1 -0
  579. package/src/runtime/routes/mcp-auth-routes.ts +283 -9
  580. package/src/runtime/routes/memory-v2-routes.ts +13 -398
  581. package/src/runtime/routes/notification-routes.ts +2 -0
  582. package/src/runtime/routes/oauth-apps.ts +112 -7
  583. package/src/runtime/routes/oauth-commands-routes.ts +1007 -0
  584. package/src/runtime/routes/oauth-connect-routes.ts +67 -5
  585. package/src/runtime/routes/oauth-providers.ts +298 -8
  586. package/src/runtime/routes/platform-routes.ts +336 -0
  587. package/src/runtime/routes/playground/inject-failures.ts +2 -1
  588. package/src/runtime/routes/playground/reset-circuit.ts +2 -1
  589. package/src/runtime/routes/playground/state.ts +2 -1
  590. package/src/runtime/routes/publish-routes.ts +221 -0
  591. package/src/runtime/routes/schedule-routes.ts +82 -0
  592. package/src/runtime/routes/sequence-routes.ts +291 -0
  593. package/src/runtime/routes/settings-routes.ts +2 -10
  594. package/src/runtime/routes/skills-routes.ts +31 -1
  595. package/src/runtime/routes/stt-routes.ts +240 -3
  596. package/src/runtime/routes/surface-action-routes.ts +43 -7
  597. package/src/runtime/routes/tts-routes.ts +67 -0
  598. package/src/runtime/routes/types.ts +32 -0
  599. package/src/runtime/routes/user-routes-cli.ts +243 -0
  600. package/src/runtime/routes/webhook-routes.ts +165 -0
  601. package/src/runtime/sync/resource-sync-events.ts +25 -0
  602. package/src/runtime/sync/sync-publisher.test.ts +105 -0
  603. package/src/runtime/sync/sync-publisher.ts +21 -0
  604. package/src/schedule/scheduler.ts +200 -123
  605. package/src/security/__tests__/provider-key-env-fallback.test.ts +12 -6
  606. package/src/security/secret-patterns.ts +3 -0
  607. package/src/sequence/engine.ts +38 -40
  608. package/src/subagent/manager.ts +20 -15
  609. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +206 -0
  610. package/src/tools/browser/browser-execution.ts +15 -4
  611. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +174 -0
  612. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +16 -13
  613. package/src/tools/browser/cdp-client/extension-cdp-client.ts +24 -1
  614. package/src/tools/browser/cdp-client/factory.ts +66 -5
  615. package/src/tools/browser/runtime-check.ts +77 -0
  616. package/src/tools/memory/register.test.ts +3 -3
  617. package/src/tools/memory/register.ts +9 -1
  618. package/src/tools/network/__tests__/web-search.test.ts +156 -0
  619. package/src/tools/network/web-search.ts +280 -37
  620. package/src/tools/permission-checker.ts +13 -5
  621. package/src/tools/subagent/spawn.ts +3 -3
  622. package/src/tools/terminal/shell.ts +44 -0
  623. package/src/usage/attribution.ts +3 -2
  624. package/src/util/pricing.ts +86 -160
  625. package/src/watcher/__tests__/engine.test.ts +301 -0
  626. package/src/watcher/constants.ts +7 -0
  627. package/src/watcher/engine.ts +90 -90
  628. package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +6 -9
  629. package/src/workspace/migrations/054-seed-recall-callsite.ts +10 -1
  630. package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +28 -4
  631. package/src/workspace/migrations/069-seed-onboarding-threads.ts +8 -2
  632. package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +104 -0
  633. package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +93 -0
  634. package/src/workspace/migrations/074-drop-deprecated-secret-detection-keys.ts +117 -0
  635. package/src/workspace/migrations/075-memory-v2-bm25-b-default-reembed.ts +61 -0
  636. package/src/workspace/migrations/076-drop-services-inference-mode.ts +62 -0
  637. package/src/workspace/migrations/077-seed-memory-router-callsite.ts +89 -0
  638. package/src/workspace/migrations/078-release-notes-tavily-web-search.ts +66 -0
  639. package/src/workspace/migrations/079-home-feed-notification-only.ts +197 -0
  640. package/src/workspace/migrations/080-restrict-vercel-api-token-metadata.ts +182 -0
  641. package/src/workspace/migrations/081-backfill-bash-allowed-tools-for-injection-credentials.ts +160 -0
  642. package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +154 -0
  643. package/src/workspace/migrations/registry.ts +22 -0
  644. package/src/workspace/migrations/runner.ts +13 -2
  645. package/src/workspace/migrations/types.ts +13 -3
  646. package/src/workspace/provider-commit-message-generator.ts +3 -2
  647. package/src/__tests__/context-search-pkb-source.test.ts +0 -498
  648. package/src/__tests__/credentials-cli.test.ts +0 -1225
  649. package/src/__tests__/memory-admin-recall.test.ts +0 -213
  650. package/src/approvals/__tests__/guardian-feed-event.test.ts +0 -303
  651. package/src/cli/commands/__tests__/email-download.test.ts +0 -260
  652. package/src/cli/commands/__tests__/email-list.test.ts +0 -216
  653. package/src/cli/commands/__tests__/email-register.test.ts +0 -186
  654. package/src/cli/commands/__tests__/email-send.test.ts +0 -416
  655. package/src/cli/commands/__tests__/email-status.test.ts +0 -185
  656. package/src/cli/commands/__tests__/email-unregister.test.ts +0 -168
  657. package/src/cli/commands/__tests__/routes.test.ts +0 -562
  658. package/src/cli/commands/__tests__/stt-transcribe.test.ts +0 -454
  659. package/src/cli/commands/autonomy.ts +0 -365
  660. package/src/cli/commands/memory.ts +0 -424
  661. package/src/cli/commands/oauth/__tests__/connect.test.ts +0 -947
  662. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +0 -686
  663. package/src/cli/commands/oauth/__tests__/mode.test.ts +0 -632
  664. package/src/cli/commands/oauth/__tests__/ping.test.ts +0 -631
  665. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +0 -573
  666. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +0 -330
  667. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +0 -521
  668. package/src/cli/commands/oauth/__tests__/status.test.ts +0 -551
  669. package/src/cli/commands/oauth/__tests__/token.test.ts +0 -420
  670. package/src/cli/lib/daemon-avatar-client.ts +0 -37
  671. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -87
  672. package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +0 -207
  673. package/src/daemon/__tests__/conversation-feed-event.test.ts +0 -304
  674. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +0 -233
  675. package/src/home/__tests__/assistant-feed-authoring.test.ts +0 -156
  676. package/src/home/__tests__/emit-feed-event.test.ts +0 -169
  677. package/src/home/__tests__/feed-population-integration.test.ts +0 -312
  678. package/src/home/__tests__/feed-scheduler.test.ts +0 -222
  679. package/src/home/__tests__/phase5-exit-criteria.test.ts +0 -229
  680. package/src/home/__tests__/platform-gmail-digest.test.ts +0 -222
  681. package/src/home/__tests__/rollup-producer.test.ts +0 -507
  682. package/src/home/assistant-feed-authoring.ts +0 -135
  683. package/src/home/emit-feed-event.ts +0 -169
  684. package/src/home/feed-scheduler.ts +0 -281
  685. package/src/home/platform-gmail-digest.ts +0 -163
  686. package/src/home/rewrite-command-preview.ts +0 -66
  687. package/src/home/rewrite-feed-title.ts +0 -58
  688. package/src/home/rollup-producer.ts +0 -426
  689. package/src/memory/admin.ts +0 -326
  690. package/src/memory/context-search/sources/pkb.ts +0 -476
  691. package/src/memory/graph/compaction.ts +0 -299
  692. /package/src/cli/{commands → lib}/cache-fs.ts +0 -0
@@ -47,6 +47,10 @@ export function migrateDeletePrivateConversations(database: DrizzleDb): void {
47
47
  database.run(/*sql*/ `
48
48
  DELETE FROM scoped_approval_grants
49
49
  WHERE conversation_id IN (${PRIVATE_CONVERSATION_IDS})
50
+ OR call_session_id IN (
51
+ SELECT id FROM call_sessions
52
+ WHERE conversation_id IN (${PRIVATE_CONVERSATION_IDS})
53
+ )
50
54
  `);
51
55
  database.run(/*sql*/ `
52
56
  DELETE FROM guardian_action_deliveries
@@ -193,6 +197,14 @@ export function migrateDeletePrivateConversations(database: DrizzleDb): void {
193
197
  DELETE FROM messages
194
198
  WHERE conversation_id IN (${PRIVATE_CONVERSATION_IDS})
195
199
  `);
200
+ database.run(/*sql*/ `
201
+ DELETE FROM attachments
202
+ WHERE NOT EXISTS (
203
+ SELECT 1
204
+ FROM message_attachments ma
205
+ WHERE ma.attachment_id = attachments.id
206
+ )
207
+ `);
196
208
  database.run(/*sql*/ `
197
209
  DELETE FROM memory_summaries
198
210
  WHERE scope_id LIKE 'private:%'
@@ -12,6 +12,7 @@ interface GraphNodeEventDateRow {
12
12
  id: string;
13
13
  created: number;
14
14
  event_date: number;
15
+ content: string;
15
16
  }
16
17
 
17
18
  interface EventDateRepair {
@@ -37,9 +38,14 @@ function replaceUtcYear(epochMs: number, year: number): number {
37
38
  );
38
39
  }
39
40
 
41
+ function contentMentionsYear(content: string, year: number): boolean {
42
+ return new RegExp(`\\b${year}\\b`).test(content);
43
+ }
44
+
40
45
  export function repairMemoryGraphEventDate(
41
46
  createdMs: number,
42
47
  eventDateMs: number,
48
+ content: string,
43
49
  ): number | null {
44
50
  if (!Number.isFinite(createdMs) || !Number.isFinite(eventDateMs)) {
45
51
  return null;
@@ -50,6 +56,10 @@ export function repairMemoryGraphEventDate(
50
56
  if (createdYear !== REPAIR_CREATED_YEAR) return null;
51
57
  if (!CORRUPT_EVENT_YEARS.includes(eventYear as 2024 | 2025)) return null;
52
58
 
59
+ // If the memory's prose explicitly mentions the prior year, the date is
60
+ // user-anchored history — not the partial-date inference bug — so leave it.
61
+ if (contentMentionsYear(content, eventYear)) return null;
62
+
53
63
  const corrected = replaceUtcYear(eventDateMs, createdYear);
54
64
  if (corrected === eventDateMs) return null;
55
65
 
@@ -71,7 +81,7 @@ export function migrate231RepairMemoryGraphEventDates(
71
81
  const rows = raw
72
82
  .query(
73
83
  /*sql*/ `
74
- SELECT id, created, event_date
84
+ SELECT id, created, event_date, content
75
85
  FROM memory_graph_nodes
76
86
  WHERE event_date IS NOT NULL
77
87
  AND CAST(strftime('%Y', created / 1000, 'unixepoch') AS INTEGER) = ?
@@ -85,7 +95,11 @@ export function migrate231RepairMemoryGraphEventDates(
85
95
 
86
96
  const repairs: EventDateRepair[] = [];
87
97
  for (const row of rows) {
88
- const corrected = repairMemoryGraphEventDate(row.created, row.event_date);
98
+ const corrected = repairMemoryGraphEventDate(
99
+ row.created,
100
+ row.event_date,
101
+ row.content ?? "",
102
+ );
89
103
  if (corrected == null) continue;
90
104
  repairs.push({
91
105
  id: row.id,
@@ -0,0 +1,25 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+ import { getSqliteFrom } from "../db-connection.js";
3
+
4
+ export function migrateConversationInferenceProfileSession(
5
+ database: DrizzleDb,
6
+ ): void {
7
+ const raw = getSqliteFrom(database);
8
+ try {
9
+ raw.exec(
10
+ `ALTER TABLE conversations ADD COLUMN inference_profile_session_id TEXT DEFAULT NULL`,
11
+ );
12
+ } catch {
13
+ // Column already exists — nothing to do.
14
+ }
15
+ try {
16
+ raw.exec(
17
+ `ALTER TABLE conversations ADD COLUMN inference_profile_expires_at INTEGER DEFAULT NULL`,
18
+ );
19
+ } catch {
20
+ // Column already exists — nothing to do.
21
+ }
22
+ raw.exec(
23
+ `CREATE INDEX IF NOT EXISTS idx_conversations_inference_profile_expires_at ON conversations (inference_profile_expires_at) WHERE inference_profile_expires_at IS NOT NULL`,
24
+ );
25
+ }
@@ -0,0 +1,50 @@
1
+ import { type DrizzleDb, getSqliteFrom } from "../db-connection.js";
2
+
3
+ /**
4
+ * Rebuild activation_state to add a foreign key on conversation_id with
5
+ * ON DELETE CASCADE so rows are cleaned up when their conversation is
6
+ * deleted, matching the pattern of conversation_graph_memory_state and
7
+ * every other conversation-keyed table. SQLite doesn't support
8
+ * ALTER TABLE ADD CONSTRAINT, so we rebuild the table; the INSERT...SELECT
9
+ * filters out any orphan rows already accumulated under the prior schema.
10
+ */
11
+ export function migrateActivationStateFkCascade(database: DrizzleDb): void {
12
+ const raw = getSqliteFrom(database);
13
+ const row = raw
14
+ .query(
15
+ `SELECT sql FROM sqlite_master WHERE type='table' AND name='activation_state'`,
16
+ )
17
+ .get() as { sql: string } | null;
18
+ if (!row) return;
19
+ if (row.sql.includes("ON DELETE CASCADE")) return;
20
+
21
+ raw.exec("PRAGMA foreign_keys = OFF");
22
+ try {
23
+ raw.exec(/*sql*/ `
24
+ BEGIN;
25
+ CREATE TABLE activation_state_new (
26
+ conversation_id TEXT PRIMARY KEY REFERENCES conversations(id) ON DELETE CASCADE,
27
+ message_id TEXT NOT NULL,
28
+ state_json TEXT NOT NULL,
29
+ ever_injected_json TEXT NOT NULL DEFAULT '[]',
30
+ current_turn INTEGER NOT NULL DEFAULT 0,
31
+ updated_at INTEGER NOT NULL
32
+ );
33
+ INSERT INTO activation_state_new
34
+ SELECT a.* FROM activation_state a
35
+ WHERE EXISTS (SELECT 1 FROM conversations c WHERE c.id = a.conversation_id);
36
+ DROP TABLE activation_state;
37
+ ALTER TABLE activation_state_new RENAME TO activation_state;
38
+ COMMIT;
39
+ `);
40
+ } catch (e) {
41
+ try {
42
+ raw.exec("ROLLBACK");
43
+ } catch {
44
+ /* no active transaction */
45
+ }
46
+ throw e;
47
+ } finally {
48
+ raw.exec("PRAGMA foreign_keys = ON");
49
+ }
50
+ }
@@ -0,0 +1,38 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+ import { getSqliteFrom } from "../db-connection.js";
3
+ import { withCrashRecovery } from "./validate-migration-state.js";
4
+
5
+ const CHECKPOINT_KEY = "migration_message_bookmarks_v1";
6
+
7
+ /**
8
+ * Create the message_bookmarks table for user-saved message bookmarks.
9
+ *
10
+ * Both foreign keys cascade so bookmarks are cleaned up automatically when
11
+ * their parent message or conversation is deleted. A unique index on
12
+ * message_id keeps the create-bookmark code path idempotent (a message can
13
+ * be bookmarked at most once at a time).
14
+ */
15
+ export function migrateMessageBookmarks(database: DrizzleDb): void {
16
+ withCrashRecovery(database, CHECKPOINT_KEY, () => {
17
+ const raw = getSqliteFrom(database);
18
+
19
+ raw.exec(/*sql*/ `
20
+ CREATE TABLE IF NOT EXISTS message_bookmarks (
21
+ id TEXT PRIMARY KEY,
22
+ message_id TEXT NOT NULL REFERENCES messages(id) ON DELETE CASCADE,
23
+ conversation_id TEXT NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
24
+ created_at INTEGER NOT NULL
25
+ )
26
+ `);
27
+
28
+ raw.exec(/*sql*/ `
29
+ CREATE UNIQUE INDEX IF NOT EXISTS message_bookmarks_message_id_uniq
30
+ ON message_bookmarks (message_id)
31
+ `);
32
+
33
+ raw.exec(/*sql*/ `
34
+ CREATE INDEX IF NOT EXISTS message_bookmarks_created_at_idx
35
+ ON message_bookmarks (created_at)
36
+ `);
37
+ });
38
+ }
@@ -0,0 +1,68 @@
1
+ import { type DrizzleDb, getSqliteFrom } from "../db-connection.js";
2
+
3
+ /**
4
+ * Creates the `provider_connections` table and seeds the three canonical
5
+ * connections that every installation ships with.
6
+ *
7
+ * Canonical connections:
8
+ * - anthropic-managed → provider=anthropic, auth={type:platform}
9
+ * - openai-managed → provider=openai, auth={type:platform}
10
+ * - gemini-managed → provider=gemini, auth={type:platform}
11
+ *
12
+ * Idempotent: checks sqlite_master for the table before running DDL;
13
+ * canonical rows are inserted with INSERT OR IGNORE.
14
+ */
15
+ export function migrateCreateProviderConnections(database: DrizzleDb): void {
16
+ const raw = getSqliteFrom(database);
17
+
18
+ const tableExists = raw
19
+ .query(
20
+ `SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'provider_connections'`,
21
+ )
22
+ .get();
23
+
24
+ if (!tableExists) {
25
+ try {
26
+ raw.exec("BEGIN");
27
+
28
+ raw.exec(/*sql*/ `
29
+ CREATE TABLE provider_connections (
30
+ name TEXT PRIMARY KEY,
31
+ provider TEXT NOT NULL,
32
+ auth TEXT NOT NULL,
33
+ created_at INTEGER NOT NULL,
34
+ updated_at INTEGER NOT NULL
35
+ )
36
+ `);
37
+
38
+ raw.exec(/*sql*/ `
39
+ CREATE INDEX idx_provider_connections_provider
40
+ ON provider_connections(provider)
41
+ `);
42
+
43
+ raw.exec("COMMIT");
44
+ } catch (e) {
45
+ try {
46
+ raw.exec("ROLLBACK");
47
+ } catch {
48
+ /* no active transaction */
49
+ }
50
+ throw e;
51
+ }
52
+ }
53
+
54
+ // Seed canonical connections — idempotent via INSERT OR IGNORE.
55
+ const now = Date.now();
56
+ const canonicals = [
57
+ { name: "anthropic-managed", provider: "anthropic", auth: JSON.stringify({ type: "platform" }) },
58
+ { name: "openai-managed", provider: "openai", auth: JSON.stringify({ type: "platform" }) },
59
+ { name: "gemini-managed", provider: "gemini", auth: JSON.stringify({ type: "platform" }) },
60
+ ];
61
+
62
+ for (const { name, provider, auth } of canonicals) {
63
+ raw.run(
64
+ `INSERT OR IGNORE INTO provider_connections (name, provider, auth, created_at, updated_at) VALUES (?, ?, ?, ?, ?)`,
65
+ [name, provider, auth, now, now],
66
+ );
67
+ }
68
+ }
@@ -0,0 +1,23 @@
1
+ import { type DrizzleDb, getSqliteFrom } from "../db-connection.js";
2
+
3
+ /**
4
+ * Adds `status` (NOT NULL DEFAULT 'active') and `label` (nullable) columns
5
+ * to the `provider_connections` table.
6
+ *
7
+ * Idempotent: reads PRAGMA table_info before each ALTER so re-running on a
8
+ * database that already has the columns is a no-op.
9
+ */
10
+ export function migrateProviderConnectionStatusLabel(database: DrizzleDb): void {
11
+ const raw = getSqliteFrom(database);
12
+
13
+ const columns = raw.query(`PRAGMA table_info(provider_connections)`).all() as Array<{ name: string }>;
14
+ const columnNames = new Set(columns.map((c) => c.name));
15
+
16
+ if (!columnNames.has("status")) {
17
+ raw.exec(`ALTER TABLE provider_connections ADD COLUMN status TEXT NOT NULL DEFAULT 'active'`);
18
+ }
19
+
20
+ if (!columnNames.has("label")) {
21
+ raw.exec(`ALTER TABLE provider_connections ADD COLUMN label TEXT`);
22
+ }
23
+ }
@@ -0,0 +1,36 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+ import { getSqliteFrom } from "../db-connection.js";
3
+ import { withCrashRecovery } from "./validate-migration-state.js";
4
+
5
+ const CHECKPOINT_KEY = "migration_memory_retrospective_state_v1";
6
+
7
+ /**
8
+ * Create the memory_retrospective_state table.
9
+ *
10
+ * One row per source conversation tracks two independent pointers used by
11
+ * the memory-retrospective background job:
12
+ *
13
+ * - `last_processed_message_id`: advances ONLY when a retrospective run
14
+ * completes successfully (wake invoked + returned without error). On any
15
+ * failure path this stays unchanged so the next run reprocesses the same
16
+ * messages — the load-bearing correctness invariant.
17
+ * - `last_run_at`: advances on EVERY job end (success or failure). Drives
18
+ * the per-conversation cooldown gate in the trigger-check helper so a
19
+ * failing job can't loop in tight retries across trigger types.
20
+ *
21
+ * The foreign key cascades so the state row dies with its source
22
+ * conversation. Without the cascade, deleted conversations would leak rows.
23
+ */
24
+ export function migrateMemoryRetrospectiveState(database: DrizzleDb): void {
25
+ withCrashRecovery(database, CHECKPOINT_KEY, () => {
26
+ const raw = getSqliteFrom(database);
27
+
28
+ raw.exec(/*sql*/ `
29
+ CREATE TABLE IF NOT EXISTS memory_retrospective_state (
30
+ conversation_id TEXT PRIMARY KEY REFERENCES conversations(id) ON DELETE CASCADE,
31
+ last_processed_message_id TEXT NOT NULL,
32
+ last_run_at INTEGER NOT NULL
33
+ )
34
+ `);
35
+ });
36
+ }
@@ -0,0 +1,81 @@
1
+ import { type DrizzleDb, getSqliteFrom } from "../db-connection.js";
2
+
3
+ /**
4
+ * One-shot backfill: set `label = name` for any `provider_connections` row
5
+ * whose `label` is NULL (or empty after trim). Migration 244 added the
6
+ * `label` column as nullable with no default, so every row that existed
7
+ * pre-244 (and any row created against an older client that didn't yet
8
+ * write a label) ended up with NULL.
9
+ *
10
+ * Why this matters for users: in 0.8.x the editor modal renders Display
11
+ * Name from `label` and shows the empty-state placeholder ("e.g. My
12
+ * OpenAI") whenever it's null. Users who created connections before the
13
+ * label field existed open the editor and see what looks like an empty
14
+ * field, then conclude their data was wiped during the upgrade.
15
+ *
16
+ * The fix is to give every pre-feature row a sensible default — its own
17
+ * connection name. The list view already falls back to `name` when label
18
+ * is empty (see ProvidersSheet.swift `connectionRow`), so this brings the
19
+ * editor into agreement with what's already on screen.
20
+ *
21
+ * Idempotency: guarded by `memory_checkpoints` so a second boot won't
22
+ * re-clobber a label the user has intentionally cleared after the
23
+ * backfill ran. New rows created post-backfill follow the normal
24
+ * label-is-optional contract.
25
+ */
26
+ export function migrateBackfillProviderConnectionLabel(database: DrizzleDb): void {
27
+ const raw = getSqliteFrom(database);
28
+ const checkpointKey = "backfill_provider_connection_label";
29
+
30
+ const checkpoint = raw
31
+ .query(`SELECT 1 FROM memory_checkpoints WHERE key = ?`)
32
+ .get(checkpointKey);
33
+ if (checkpoint) return;
34
+
35
+ // Guard: skip if the table doesn't exist yet (first-boot edge case where
36
+ // migration 243 hasn't run, e.g. fresh install ordering test harness).
37
+ const tableExists = raw
38
+ .query(
39
+ `SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'provider_connections'`,
40
+ )
41
+ .get();
42
+ if (!tableExists) {
43
+ raw
44
+ .query(
45
+ `INSERT OR IGNORE INTO memory_checkpoints (key, value, updated_at) VALUES (?, '1', ?)`,
46
+ )
47
+ .run(checkpointKey, Date.now());
48
+ return;
49
+ }
50
+
51
+ // Guard: also skip if the label column hasn't been added yet (migration
52
+ // 244 hasn't run). Treat as no-op + don't checkpoint, so the backfill
53
+ // runs the next time it gets a chance against a populated schema.
54
+ const columns = raw
55
+ .query(`PRAGMA table_info(provider_connections)`)
56
+ .all() as Array<{ name: string }>;
57
+ if (!columns.some((c) => c.name === "label")) {
58
+ return;
59
+ }
60
+
61
+ try {
62
+ raw.exec("BEGIN");
63
+
64
+ raw.exec(/*sql*/ `
65
+ UPDATE provider_connections
66
+ SET label = name
67
+ WHERE label IS NULL OR TRIM(label) = ''
68
+ `);
69
+
70
+ raw
71
+ .query(
72
+ `INSERT OR IGNORE INTO memory_checkpoints (key, value, updated_at) VALUES (?, '1', ?)`,
73
+ )
74
+ .run(checkpointKey, Date.now());
75
+
76
+ raw.exec("COMMIT");
77
+ } catch (err) {
78
+ raw.exec("ROLLBACK");
79
+ throw err;
80
+ }
81
+ }
@@ -0,0 +1,84 @@
1
+ import { Database } from "bun:sqlite";
2
+ import { describe, expect, test } from "bun:test";
3
+
4
+ import { drizzle } from "drizzle-orm/bun-sqlite";
5
+
6
+ import { getSqliteFrom } from "../../db-connection.js";
7
+ import * as schema from "../../schema.js";
8
+ import { migrateCreateProviderConnections } from "../243-provider-connections.js";
9
+ import { migrateProviderConnectionStatusLabel } from "../244-provider-connection-status-label.js";
10
+
11
+ interface ColumnRow {
12
+ name: string;
13
+ type: string;
14
+ notnull: number;
15
+ dflt_value: string | null;
16
+ pk: number;
17
+ }
18
+
19
+ function createTestDb() {
20
+ const sqlite = new Database(":memory:");
21
+ sqlite.exec("PRAGMA journal_mode=WAL");
22
+ sqlite.exec("PRAGMA foreign_keys = ON");
23
+ return drizzle(sqlite, { schema });
24
+ }
25
+
26
+ describe("migration 244 — provider_connection status + label", () => {
27
+ test("adds status (NOT NULL DEFAULT active) and label (nullable) columns", () => {
28
+ const db = createTestDb();
29
+ const raw = getSqliteFrom(db);
30
+
31
+ // Bootstrap provider_connections table via migration 243.
32
+ migrateCreateProviderConnections(db);
33
+
34
+ // Verify the new columns are absent before migration 244.
35
+ const colsBefore = raw.query(`PRAGMA table_info(provider_connections)`).all() as ColumnRow[];
36
+ const namesBefore = colsBefore.map((c) => c.name);
37
+ expect(namesBefore).not.toContain("status");
38
+ expect(namesBefore).not.toContain("label");
39
+
40
+ migrateProviderConnectionStatusLabel(db);
41
+
42
+ const cols = raw.query(`PRAGMA table_info(provider_connections)`).all() as ColumnRow[];
43
+ const colMap = Object.fromEntries(cols.map((c) => [c.name, c]));
44
+
45
+ // status: NOT NULL, default 'active'
46
+ expect(colMap["status"]).toBeDefined();
47
+ expect(colMap["status"].notnull).toBe(1);
48
+ expect(colMap["status"].dflt_value).toBe("'active'");
49
+
50
+ // label: nullable
51
+ expect(colMap["label"]).toBeDefined();
52
+ expect(colMap["label"].notnull).toBe(0);
53
+ expect(colMap["label"].dflt_value).toBeNull();
54
+ });
55
+
56
+ test("is idempotent — running twice does not throw", () => {
57
+ const db = createTestDb();
58
+ migrateCreateProviderConnections(db);
59
+ migrateProviderConnectionStatusLabel(db);
60
+ expect(() => migrateProviderConnectionStatusLabel(db)).not.toThrow();
61
+ });
62
+
63
+ test("existing rows get status=active from column default", () => {
64
+ const db = createTestDb();
65
+ const raw = getSqliteFrom(db);
66
+
67
+ // Seed a row before adding the status column.
68
+ migrateCreateProviderConnections(db);
69
+
70
+ // Verify canonical connections got the default.
71
+ migrateProviderConnectionStatusLabel(db);
72
+
73
+ const rows = raw.query(`SELECT name, status, label FROM provider_connections`).all() as Array<{
74
+ name: string;
75
+ status: string;
76
+ label: string | null;
77
+ }>;
78
+ expect(rows.length).toBeGreaterThan(0);
79
+ for (const row of rows) {
80
+ expect(row.status).toBe("active");
81
+ expect(row.label).toBeNull();
82
+ }
83
+ });
84
+ });
@@ -0,0 +1,125 @@
1
+ import { Database } from "bun:sqlite";
2
+ import { describe, expect, test } from "bun:test";
3
+
4
+ import { drizzle } from "drizzle-orm/bun-sqlite";
5
+
6
+ import { getSqliteFrom } from "../../db-connection.js";
7
+ import * as schema from "../../schema.js";
8
+ import { migrateMemoryRetrospectiveState } from "../245-memory-retrospective-state.js";
9
+
10
+ interface ColumnRow {
11
+ name: string;
12
+ type: string;
13
+ notnull: number;
14
+ dflt_value: string | null;
15
+ pk: number;
16
+ }
17
+
18
+ interface ForeignKeyRow {
19
+ id: number;
20
+ seq: number;
21
+ table: string;
22
+ from: string;
23
+ to: string;
24
+ on_update: string;
25
+ on_delete: string;
26
+ }
27
+
28
+ function createTestDb() {
29
+ const sqlite = new Database(":memory:");
30
+ sqlite.exec("PRAGMA journal_mode=WAL");
31
+ sqlite.exec("PRAGMA foreign_keys = ON");
32
+ // `withCrashRecovery` (used by the migration) reads/writes a
33
+ // `memory_checkpoints` table. Seed a minimal version so the migration's
34
+ // structural setup can be exercised without booting the entire
35
+ // db-init pipeline.
36
+ sqlite.exec(`
37
+ CREATE TABLE memory_checkpoints (
38
+ key TEXT PRIMARY KEY,
39
+ value TEXT NOT NULL,
40
+ updated_at INTEGER NOT NULL
41
+ )
42
+ `);
43
+ // The state table FK references `conversations(id)`, so the test DB needs
44
+ // that table to exist before we can apply the FK. Use a minimal table —
45
+ // we're only checking the migration's structural output, not exercising
46
+ // cascade behavior end-to-end.
47
+ sqlite.exec(`
48
+ CREATE TABLE conversations (
49
+ id TEXT PRIMARY KEY,
50
+ created_at INTEGER NOT NULL
51
+ )
52
+ `);
53
+ return drizzle(sqlite, { schema });
54
+ }
55
+
56
+ describe("migration 245 — memory_retrospective_state", () => {
57
+ test("creates the table with the expected columns and primary key", () => {
58
+ const db = createTestDb();
59
+ const raw = getSqliteFrom(db);
60
+
61
+ migrateMemoryRetrospectiveState(db);
62
+
63
+ const cols = raw
64
+ .query(`PRAGMA table_info(memory_retrospective_state)`)
65
+ .all() as ColumnRow[];
66
+ const colMap = Object.fromEntries(cols.map((c) => [c.name, c]));
67
+
68
+ expect(colMap["conversation_id"]).toBeDefined();
69
+ expect(colMap["conversation_id"].pk).toBe(1);
70
+
71
+ expect(colMap["last_processed_message_id"]).toBeDefined();
72
+ expect(colMap["last_processed_message_id"].notnull).toBe(1);
73
+
74
+ expect(colMap["last_run_at"]).toBeDefined();
75
+ expect(colMap["last_run_at"].notnull).toBe(1);
76
+ });
77
+
78
+ test("FK on conversation_id is ON DELETE CASCADE", () => {
79
+ const db = createTestDb();
80
+ const raw = getSqliteFrom(db);
81
+
82
+ migrateMemoryRetrospectiveState(db);
83
+
84
+ const fks = raw
85
+ .query(`PRAGMA foreign_key_list(memory_retrospective_state)`)
86
+ .all() as ForeignKeyRow[];
87
+
88
+ expect(fks).toHaveLength(1);
89
+ expect(fks[0]!.from).toBe("conversation_id");
90
+ expect(fks[0]!.table).toBe("conversations");
91
+ expect(fks[0]!.to).toBe("id");
92
+ expect(fks[0]!.on_delete).toBe("CASCADE");
93
+ });
94
+
95
+ test("is idempotent — running twice does not throw", () => {
96
+ const db = createTestDb();
97
+
98
+ migrateMemoryRetrospectiveState(db);
99
+ expect(() => migrateMemoryRetrospectiveState(db)).not.toThrow();
100
+ });
101
+
102
+ test("deleting a conversation cascades to its state row", () => {
103
+ const db = createTestDb();
104
+ const raw = getSqliteFrom(db);
105
+
106
+ migrateMemoryRetrospectiveState(db);
107
+
108
+ raw.exec(`INSERT INTO conversations (id, created_at) VALUES ('c1', 0)`);
109
+ raw.exec(
110
+ `INSERT INTO memory_retrospective_state (conversation_id, last_processed_message_id, last_run_at) VALUES ('c1', 'm1', 1000)`,
111
+ );
112
+
113
+ const before = raw
114
+ .query(`SELECT COUNT(*) AS c FROM memory_retrospective_state`)
115
+ .get() as { c: number };
116
+ expect(before.c).toBe(1);
117
+
118
+ raw.exec(`DELETE FROM conversations WHERE id = 'c1'`);
119
+
120
+ const after = raw
121
+ .query(`SELECT COUNT(*) AS c FROM memory_retrospective_state`)
122
+ .get() as { c: number };
123
+ expect(after.c).toBe(0);
124
+ });
125
+ });