@vellumai/assistant 0.7.3 → 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 (778) hide show
  1. package/AGENTS.md +11 -0
  2. package/ARCHITECTURE.md +29 -28
  3. package/Dockerfile +6 -4
  4. package/README.md +2 -2
  5. package/__tests__/permissions/gateway-threshold-reader.test.ts +236 -9
  6. package/bun.lock +3 -0
  7. package/docker-entrypoint.sh +16 -0
  8. package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +420 -0
  9. package/eslint-rules/cli-no-daemon-internals.js +283 -0
  10. package/eslint.config.mjs +12 -0
  11. package/knip.json +3 -1
  12. package/node_modules/@vellumai/ipc-server-utils/bun.lock +24 -0
  13. package/node_modules/@vellumai/ipc-server-utils/package.json +18 -0
  14. package/node_modules/@vellumai/ipc-server-utils/src/index.ts +6 -0
  15. package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.test.ts +430 -0
  16. package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.ts +221 -0
  17. package/node_modules/@vellumai/ipc-server-utils/tsconfig.json +20 -0
  18. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -1
  19. package/openapi.yaml +4126 -959
  20. package/package.json +5 -1
  21. package/scripts/generate-openapi.ts +52 -4
  22. package/scripts/sync-llm-catalog.ts +165 -0
  23. package/scripts/sync-web-search-catalog.ts +107 -0
  24. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +169 -0
  25. package/src/__tests__/agent-loop-override-profile.test.ts +26 -1
  26. package/src/__tests__/annotate-risk-options.test.ts +291 -0
  27. package/src/__tests__/anthropic-provider.test.ts +92 -2
  28. package/src/__tests__/app-control-flow.test.ts +7 -0
  29. package/src/__tests__/approval-cascade.test.ts +8 -16
  30. package/src/__tests__/approval-routes-http.test.ts +6 -0
  31. package/src/__tests__/assistant-events-sse-shed.test.ts +232 -0
  32. package/src/__tests__/auto-analysis-end-to-end.test.ts +12 -25
  33. package/src/__tests__/avatar-identity-sync.test.ts +87 -0
  34. package/src/__tests__/background-workers-disk-pressure.test.ts +11 -22
  35. package/src/__tests__/btw-routes.test.ts +1 -0
  36. package/src/__tests__/call-constants.test.ts +10 -1
  37. package/src/__tests__/call-controller.test.ts +127 -0
  38. package/src/__tests__/call-site-routing-provider.test.ts +172 -45
  39. package/src/__tests__/cancel-resolves-conversation-key.test.ts +44 -3
  40. package/src/__tests__/channel-policy.test.ts +12 -0
  41. package/src/__tests__/checker.test.ts +89 -0
  42. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +88 -30
  43. package/src/__tests__/compact-event-conversation-id-guard.test.ts +33 -5
  44. package/src/__tests__/compaction-strip-metadata-clear.test.ts +26 -1
  45. package/src/__tests__/config-loader-backfill.test.ts +526 -102
  46. package/src/__tests__/config-loader-corrupt.test.ts +68 -0
  47. package/src/__tests__/config-loader-platform-defaults.test.ts +345 -8
  48. package/src/__tests__/config-schema-cmd.test.ts +63 -29
  49. package/src/__tests__/config-schema.test.ts +14 -3
  50. package/src/__tests__/config-set-platform-guard.test.ts +75 -152
  51. package/src/__tests__/config-set-route.test.ts +198 -0
  52. package/src/__tests__/config-watcher.test.ts +6 -0
  53. package/src/__tests__/contacts-tools.test.ts +51 -199
  54. package/src/__tests__/context-search-agent-protocol.test.ts +21 -2
  55. package/src/__tests__/context-search-agent-runner.test.ts +22 -138
  56. package/src/__tests__/context-search-conversations-source.test.ts +42 -16
  57. package/src/__tests__/context-search-fanout.test.ts +20 -157
  58. package/src/__tests__/context-search-memory-source.test.ts +3 -26
  59. package/src/__tests__/context-search-memory-v2-source.test.ts +3 -3
  60. package/src/__tests__/context-search-types.test.ts +7 -2
  61. package/src/__tests__/context-window-manager.test.ts +389 -1
  62. package/src/__tests__/conversation-abort-tool-results.test.ts +1 -6
  63. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -1
  64. package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -1
  65. package/src/__tests__/conversation-agent-loop.test.ts +3 -3
  66. package/src/__tests__/conversation-confirmation-signals.test.ts +5 -13
  67. package/src/__tests__/conversation-crud-inference-profile.test.ts +100 -0
  68. package/src/__tests__/conversation-error.test.ts +38 -0
  69. package/src/__tests__/conversation-fork-crud.test.ts +241 -1
  70. package/src/__tests__/conversation-inference-profile-route.test.ts +14 -14
  71. package/src/__tests__/conversation-init.benchmark.test.ts +2 -1
  72. package/src/__tests__/conversation-lifecycle.test.ts +124 -0
  73. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +100 -1
  74. package/src/__tests__/conversation-process-callsite.test.ts +22 -7
  75. package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -6
  76. package/src/__tests__/conversation-runtime-assembly.test.ts +19 -10
  77. package/src/__tests__/conversation-slash-commands.test.ts +194 -2
  78. package/src/__tests__/conversation-slash-unknown.test.ts +1 -6
  79. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +170 -9
  80. package/src/__tests__/conversation-surfaces-app-control.test.ts +323 -3
  81. package/src/__tests__/conversation-surfaces-data-persist.test.ts +73 -1
  82. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +59 -0
  83. package/src/__tests__/conversation-workspace-injection.test.ts +1 -7
  84. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -7
  85. package/src/__tests__/credential-security-invariants.test.ts +5 -6
  86. package/src/__tests__/daemon-credential-client.test.ts +56 -1
  87. package/src/__tests__/db-activation-state-fk-cascade.test.ts +132 -0
  88. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +37 -0
  89. package/src/__tests__/db-memory-graph-event-date-repair.test.ts +43 -20
  90. package/src/__tests__/db-proxy-transaction.test.ts +206 -0
  91. package/src/__tests__/external-plugin-loader.test.ts +458 -0
  92. package/src/__tests__/filing-service.test.ts +25 -22
  93. package/src/__tests__/fixtures/mock-chrome-extension.ts +5 -0
  94. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  95. package/src/__tests__/graph-extraction-event-date.test.ts +34 -0
  96. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +10 -34
  97. package/src/__tests__/heartbeat-disk-pressure.test.ts +21 -8
  98. package/src/__tests__/heartbeat-service.test.ts +50 -233
  99. package/src/__tests__/history-repair.test.ts +89 -0
  100. package/src/__tests__/host-app-control-proxy.test.ts +109 -1
  101. package/src/__tests__/host-app-control-routes.test.ts +247 -1
  102. package/src/__tests__/host-browser-proxy.test.ts +416 -20
  103. package/src/__tests__/host-browser-routes.test.ts +325 -33
  104. package/src/__tests__/host-proxy-preactivation.test.ts +211 -0
  105. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +246 -0
  106. package/src/__tests__/inference-profile-reaper.test.ts +154 -0
  107. package/src/__tests__/inference-profile-session-handler.test.ts +398 -0
  108. package/src/__tests__/inference-profile-session-ipc.test.ts +236 -0
  109. package/src/__tests__/injector-chain.test.ts +24 -16
  110. package/src/__tests__/injector-pkb-v2-silenced.test.ts +10 -7
  111. package/src/__tests__/inline-skill-load-permissions.test.ts +6 -1
  112. package/src/__tests__/install-skill-routing.test.ts +2 -2
  113. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +169 -67
  114. package/src/__tests__/llm-callsite-catalog.test.ts +20 -1
  115. package/src/__tests__/llm-catalog-parity.test.ts +146 -0
  116. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +188 -0
  117. package/src/__tests__/llm-request-log-source-factory.test.ts +124 -0
  118. package/src/__tests__/llm-resolver.test.ts +46 -0
  119. package/src/__tests__/managed-profile-guard.test.ts +131 -2
  120. package/src/__tests__/mcp-auth-routes.test.ts +1 -0
  121. package/src/__tests__/mcp-cli.test.ts +182 -220
  122. package/src/__tests__/mcp-health-check.test.ts +56 -27
  123. package/src/__tests__/memory-jobs-worker-lanes.test.ts +18 -11
  124. package/src/__tests__/message-complete-display-id.test.ts +175 -0
  125. package/src/__tests__/notification-decision-fallback.test.ts +91 -0
  126. package/src/__tests__/notification-decision-strategy.test.ts +22 -0
  127. package/src/__tests__/notification-platform-adapter.test.ts +229 -0
  128. package/src/__tests__/oauth-cli.test.ts +38 -1888
  129. package/src/__tests__/oauth-commands-routes.test.ts +711 -0
  130. package/src/__tests__/oauth-connect-routes.test.ts +174 -11
  131. package/src/__tests__/oauth-providers-routes.test.ts +14 -10
  132. package/src/__tests__/openai-responses-cutover-guard.test.ts +33 -12
  133. package/src/__tests__/openai-responses-provider.test.ts +17 -0
  134. package/src/__tests__/plugin-bootstrap.test.ts +31 -2
  135. package/src/__tests__/plugin-route-contribution.test.ts +31 -3
  136. package/src/__tests__/plugin-tool-contribution.test.ts +31 -3
  137. package/src/__tests__/plugin-types.test.ts +13 -11
  138. package/src/__tests__/process-message-background-slack.test.ts +46 -0
  139. package/src/__tests__/profile-entry-status.test.ts +43 -0
  140. package/src/__tests__/provider-managed-proxy-integration.test.ts +12 -4
  141. package/src/__tests__/provider-registry-ollama.test.ts +12 -4
  142. package/src/__tests__/provider-send-message-override-profile.test.ts +10 -4
  143. package/src/__tests__/relay-server.test.ts +164 -2
  144. package/src/__tests__/retry-thinking-tool-choice.test.ts +15 -0
  145. package/src/__tests__/schedule-retry.test.ts +56 -4
  146. package/src/__tests__/schedule-routes.test.ts +104 -0
  147. package/src/__tests__/scheduler-disk-pressure.test.ts +0 -4
  148. package/src/__tests__/scheduler-recurrence.test.ts +87 -34
  149. package/src/__tests__/scheduler-reuse-conversation.test.ts +161 -5
  150. package/src/__tests__/scheduler-wake.test.ts +0 -63
  151. package/src/__tests__/secret-allowlist.test.ts +1 -0
  152. package/src/__tests__/secret-prompt-log-hygiene.test.ts +7 -5
  153. package/src/__tests__/secret-prompter-channel-fallback.test.ts +7 -5
  154. package/src/__tests__/secret-response-routing.test.ts +7 -5
  155. package/src/__tests__/secret-routes-managed-proxy.test.ts +12 -4
  156. package/src/__tests__/server-history-render.test.ts +82 -0
  157. package/src/__tests__/shell-credential-ref.test.ts +95 -3
  158. package/src/__tests__/shell-tool-proxy-mode.test.ts +14 -0
  159. package/src/__tests__/skill-include-graph.test.ts +31 -0
  160. package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
  161. package/src/__tests__/skill-load-tool.test.ts +42 -16
  162. package/src/__tests__/skills.test.ts +39 -0
  163. package/src/__tests__/subagent-call-site-routing.test.ts +78 -16
  164. package/src/__tests__/suggestion-routes.test.ts +3 -3
  165. package/src/__tests__/sync-message-contract.test.ts +63 -0
  166. package/src/__tests__/task-scheduler.test.ts +88 -23
  167. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -42
  168. package/src/__tests__/tool-executor.test.ts +155 -0
  169. package/src/__tests__/update-bulletin-job.test.ts +96 -193
  170. package/src/__tests__/usage-cli.test.ts +11 -73
  171. package/src/__tests__/user-plugin-loader.test.ts +145 -0
  172. package/src/__tests__/vercel-config.test.ts +168 -0
  173. package/src/__tests__/voice-session-bridge.test.ts +3 -0
  174. package/src/__tests__/web-search-catalog-parity.test.ts +86 -0
  175. package/src/__tests__/web-search.test.ts +303 -2
  176. package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +1 -21
  177. package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +58 -0
  178. package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +153 -0
  179. package/src/__tests__/workspace-migration-071-remove-safe-storage-release-note.test.ts +206 -0
  180. package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +191 -0
  181. package/src/__tests__/workspace-migration-076-drop-services-inference-mode.test.ts +211 -0
  182. package/src/__tests__/workspace-migration-077-seed-memory-router-callsite.test.ts +174 -0
  183. package/src/__tests__/workspace-migration-079-home-feed-notification-only.test.ts +323 -0
  184. package/src/__tests__/workspace-migration-080-restrict-vercel-api-token-metadata.test.ts +299 -0
  185. package/src/__tests__/workspace-migration-081-backfill-bash-allowed-tools.test.ts +410 -0
  186. package/src/__tests__/workspace-migration-082-backfill-managed-profile-labels.test.ts +268 -0
  187. package/src/__tests__/workspace-migration-safe-storage-limits-release.test.ts +15 -27
  188. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +3 -3
  189. package/src/__tests__/workspace-release-notes-feature-flag-guard.test.ts +115 -0
  190. package/src/acp/__tests__/helpers/which-stub.ts +4 -2
  191. package/src/acp/resolve-agent.test.ts +25 -0
  192. package/src/acp/resolve-agent.ts +13 -2
  193. package/src/acp/session-manager.ts +14 -0
  194. package/src/agent/loop.ts +11 -0
  195. package/src/approvals/guardian-decision-primitive.ts +0 -13
  196. package/src/approvals/guardian-request-resolvers.ts +19 -102
  197. package/src/calls/call-constants.ts +5 -8
  198. package/src/calls/call-controller.ts +130 -67
  199. package/src/calls/relay-server.ts +42 -1
  200. package/src/calls/relay-setup-router.ts +36 -0
  201. package/src/calls/types.ts +1 -0
  202. package/src/calls/voice-session-bridge.ts +24 -5
  203. package/src/channels/config.ts +14 -1
  204. package/src/channels/types.ts +1 -0
  205. package/src/cli/AGENTS.md +164 -4
  206. package/src/cli/__tests__/notifications.test.ts +54 -0
  207. package/src/cli/commands/__tests__/avatar.test.ts +540 -0
  208. package/src/cli/commands/__tests__/backup.test.ts +236 -776
  209. package/src/cli/commands/__tests__/cache.test.ts +1 -1
  210. package/src/cli/commands/__tests__/changelog.test.ts +593 -0
  211. package/src/cli/commands/__tests__/channel-verification-sessions.test.ts +503 -0
  212. package/src/cli/commands/__tests__/conversations-import.test.ts +515 -0
  213. package/src/cli/commands/__tests__/domain-register.test.ts +140 -167
  214. package/src/cli/commands/__tests__/domain-status.test.ts +137 -76
  215. package/src/cli/commands/__tests__/email-attachment.test.ts +314 -337
  216. package/src/cli/commands/__tests__/email-core.test.ts +579 -0
  217. package/src/cli/commands/__tests__/image-generation.test.ts +87 -824
  218. package/src/cli/commands/__tests__/inference-send.test.ts +30 -266
  219. package/src/cli/commands/__tests__/inference-session.test.ts +423 -0
  220. package/src/cli/commands/__tests__/memory-v2.test.ts +81 -110
  221. package/src/cli/commands/__tests__/skills.test.ts +563 -0
  222. package/src/cli/commands/__tests__/status.test.ts +249 -0
  223. package/src/cli/commands/__tests__/stt.test.ts +320 -0
  224. package/src/cli/commands/__tests__/tts-synthesize.test.ts +4 -603
  225. package/src/cli/commands/__tests__/tts.test.ts +321 -0
  226. package/src/cli/commands/__tests__/webhooks.test.ts +86 -511
  227. package/src/cli/commands/attachment.ts +8 -3
  228. package/src/cli/commands/audit.ts +95 -64
  229. package/src/cli/commands/auth.ts +61 -58
  230. package/src/cli/commands/avatar.ts +276 -390
  231. package/src/cli/commands/backup.ts +409 -505
  232. package/src/cli/commands/bash.ts +9 -5
  233. package/src/cli/commands/browser.ts +28 -9
  234. package/src/cli/commands/cache.ts +9 -4
  235. package/src/cli/commands/changelog.ts +414 -0
  236. package/src/cli/commands/channel-verification-sessions.ts +238 -317
  237. package/src/cli/commands/clients.ts +8 -3
  238. package/src/cli/commands/completions.ts +9 -9
  239. package/src/cli/commands/config.ts +102 -72
  240. package/src/cli/commands/contacts.ts +575 -696
  241. package/src/cli/commands/conversations-defer.ts +17 -69
  242. package/src/cli/commands/conversations-import.ts +90 -253
  243. package/src/cli/commands/conversations.ts +346 -436
  244. package/src/cli/commands/credential-execution.ts +9 -6
  245. package/src/cli/commands/credentials.ts +456 -736
  246. package/src/cli/commands/domain.ts +128 -206
  247. package/src/cli/commands/email.ts +606 -794
  248. package/src/cli/commands/gateway.ts +8 -1
  249. package/src/cli/commands/image-generation.ts +157 -205
  250. package/src/cli/commands/inference-providers.ts +352 -0
  251. package/src/cli/commands/inference-session.ts +415 -0
  252. package/src/cli/commands/inference.ts +87 -65
  253. package/src/cli/commands/keys.ts +8 -3
  254. package/src/cli/commands/mcp.ts +103 -287
  255. package/src/cli/commands/memory-v2.ts +163 -517
  256. package/src/cli/commands/notifications.ts +33 -7
  257. package/src/cli/commands/oauth/apps.ts +292 -261
  258. package/src/cli/commands/oauth/connect.ts +182 -345
  259. package/src/cli/commands/oauth/disconnect.ts +16 -215
  260. package/src/cli/commands/oauth/index.ts +49 -45
  261. package/src/cli/commands/oauth/mode.ts +43 -199
  262. package/src/cli/commands/oauth/ping.ts +17 -125
  263. package/src/cli/commands/oauth/providers.ts +732 -921
  264. package/src/cli/commands/oauth/request.ts +60 -350
  265. package/src/cli/commands/oauth/shared.ts +11 -121
  266. package/src/cli/commands/oauth/status.ts +31 -121
  267. package/src/cli/commands/oauth/token.ts +13 -55
  268. package/src/cli/commands/pending.ts +19 -10
  269. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +133 -183
  270. package/src/cli/commands/platform/__tests__/connect.test.ts +66 -181
  271. package/src/cli/commands/platform/__tests__/disconnect.test.ts +71 -227
  272. package/src/cli/commands/platform/__tests__/status.test.ts +169 -287
  273. package/src/cli/commands/platform/connect.ts +16 -80
  274. package/src/cli/commands/platform/disconnect.ts +14 -112
  275. package/src/cli/commands/platform/index.ts +177 -246
  276. package/src/cli/commands/routes.ts +153 -336
  277. package/src/cli/commands/sequence.ts +316 -360
  278. package/src/cli/commands/skills.ts +449 -671
  279. package/src/cli/commands/status.ts +58 -37
  280. package/src/cli/commands/stt.ts +94 -262
  281. package/src/cli/commands/task.ts +14 -40
  282. package/src/cli/commands/trust.ts +8 -3
  283. package/src/cli/commands/tts.ts +162 -167
  284. package/src/cli/commands/ui.ts +35 -42
  285. package/src/cli/commands/usage.ts +188 -126
  286. package/src/cli/commands/watchers.ts +8 -3
  287. package/src/cli/commands/webhooks.ts +99 -193
  288. package/src/cli/lib/__tests__/register-command.test.ts +85 -0
  289. package/src/cli/lib/daemon-credential-client.ts +4 -5
  290. package/src/cli/lib/nested-value.ts +44 -0
  291. package/src/cli/lib/open-browser.ts +36 -0
  292. package/src/cli/lib/register-command.ts +19 -0
  293. package/src/cli/lib/time-ago.ts +34 -0
  294. package/src/cli/program.ts +2 -4
  295. package/src/cli/utils/__tests__/conversation-id.test.ts +66 -0
  296. package/src/cli/utils/__tests__/parse-duration.test.ts +49 -0
  297. package/src/cli/utils/conversation-id.ts +30 -0
  298. package/src/cli/utils/parse-duration.ts +41 -0
  299. package/src/config/acp-defaults.test.ts +5 -1
  300. package/src/config/acp-defaults.ts +11 -4
  301. package/src/config/bundled-skills/acp/TOOLS.json +2 -2
  302. package/src/config/bundled-skills/app-builder/SKILL.md +1 -3
  303. package/src/config/bundled-skills/app-control/TOOLS.json +32 -0
  304. package/src/config/bundled-skills/contacts/SKILL.md +12 -45
  305. package/src/config/bundled-skills/contacts/TOOLS.json +0 -57
  306. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +0 -12
  307. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -58
  308. package/src/config/bundled-tool-registry.ts +0 -2
  309. package/src/config/feature-flag-registry.json +17 -17
  310. package/src/config/llm-resolver.ts +16 -1
  311. package/src/config/loader.ts +148 -33
  312. package/src/config/raw-config-utils.ts +2 -30
  313. package/src/config/schema.ts +4 -0
  314. package/src/config/schemas/__tests__/memory-v2.test.ts +49 -0
  315. package/src/config/schemas/call-site-catalog.ts +29 -7
  316. package/src/config/schemas/llm-request-logs.ts +57 -0
  317. package/src/config/schemas/llm.ts +52 -2
  318. package/src/config/schemas/memory-retrospective.ts +48 -0
  319. package/src/config/schemas/memory-v2.ts +33 -2
  320. package/src/config/schemas/memory.ts +4 -0
  321. package/src/config/schemas/services.ts +15 -12
  322. package/src/config/seed-inference-profiles.ts +195 -134
  323. package/src/contacts/contact-store.ts +0 -61
  324. package/src/context/window-manager.ts +191 -5
  325. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +111 -0
  326. package/src/daemon/__tests__/conversation-tool-setup.test.ts +109 -4
  327. package/src/daemon/__tests__/daemon-skill-host.test.ts +10 -4
  328. package/src/daemon/approval-generators.ts +23 -29
  329. package/src/daemon/config-watcher.ts +2 -0
  330. package/src/daemon/conversation-agent-loop-handlers.ts +56 -0
  331. package/src/daemon/conversation-agent-loop.ts +140 -107
  332. package/src/daemon/conversation-error.ts +21 -0
  333. package/src/daemon/conversation-lifecycle.ts +68 -13
  334. package/src/daemon/conversation-process.ts +36 -19
  335. package/src/daemon/conversation-runtime-assembly.ts +14 -5
  336. package/src/daemon/conversation-slash.ts +175 -23
  337. package/src/daemon/conversation-store.ts +17 -10
  338. package/src/daemon/conversation-surfaces.ts +92 -26
  339. package/src/daemon/conversation-tool-setup.ts +33 -19
  340. package/src/daemon/conversation.ts +49 -10
  341. package/src/daemon/external-plugins-bootstrap.ts +18 -8
  342. package/src/daemon/guardian-action-generators.ts +7 -22
  343. package/src/daemon/handlers/config-model.ts +8 -126
  344. package/src/daemon/handlers/config-slack-channel.ts +10 -7
  345. package/src/daemon/handlers/config-vercel.ts +3 -1
  346. package/src/daemon/handlers/shared.ts +26 -0
  347. package/src/daemon/handlers/skills.ts +84 -5
  348. package/src/daemon/history-repair.ts +33 -6
  349. package/src/daemon/host-app-control-proxy.ts +44 -19
  350. package/src/daemon/host-bash-proxy.ts +85 -158
  351. package/src/daemon/host-browser-proxy.ts +97 -36
  352. package/src/daemon/host-cu-proxy.ts +1 -1
  353. package/src/daemon/host-file-proxy.ts +1 -1
  354. package/src/daemon/host-proxy-base.ts +13 -1
  355. package/src/daemon/host-proxy-preactivation.ts +25 -1
  356. package/src/daemon/host-transfer-proxy.ts +2 -2
  357. package/src/daemon/identity-helpers.ts +19 -0
  358. package/src/daemon/lifecycle.ts +128 -114
  359. package/src/daemon/meet-host-supervisor.ts +15 -15
  360. package/src/daemon/memory-v2-startup.ts +62 -14
  361. package/src/daemon/message-protocol.ts +6 -0
  362. package/src/daemon/message-types/bookmarks.ts +18 -0
  363. package/src/daemon/message-types/conversations.ts +12 -9
  364. package/src/daemon/message-types/messages.ts +28 -2
  365. package/src/daemon/message-types/sync.ts +60 -0
  366. package/src/daemon/pkb-reminder-builder.test.ts +54 -13
  367. package/src/daemon/pkb-reminder-builder.ts +21 -7
  368. package/src/daemon/process-message.ts +56 -23
  369. package/src/daemon/server.ts +23 -18
  370. package/src/daemon/shutdown-handlers.ts +0 -2
  371. package/src/daemon/tool-setup-types.ts +9 -0
  372. package/src/daemon/tool-side-effects.ts +6 -4
  373. package/src/daemon/wake-target-adapter.ts +11 -0
  374. package/src/documents/document-store.ts +35 -1
  375. package/src/export/transcript-formatter.ts +61 -2
  376. package/src/filing/filing-service.ts +42 -56
  377. package/src/heartbeat/__tests__/heartbeat-service.test.ts +359 -0
  378. package/src/heartbeat/heartbeat-run-store.ts +2 -1
  379. package/src/heartbeat/heartbeat-service.ts +149 -128
  380. package/src/home/__tests__/feed-types.test.ts +63 -131
  381. package/src/home/__tests__/feed-writer.test.ts +77 -278
  382. package/src/home/__tests__/post-connect-feed.test.ts +9 -12
  383. package/src/home/feed-types.ts +19 -73
  384. package/src/home/feed-writer.ts +25 -156
  385. package/src/home/post-connect-feed.ts +1 -3
  386. package/src/ipc/__tests__/cli-ipc.test.ts +2 -0
  387. package/src/ipc/__tests__/email-ipc.test.ts +506 -0
  388. package/src/ipc/__tests__/exit-helper.test.ts +104 -0
  389. package/src/ipc/__tests__/streaming-client.test.ts +237 -0
  390. package/src/ipc/__tests__/streaming-framing.test.ts +142 -0
  391. package/src/ipc/assistant-server.ts +148 -42
  392. package/src/ipc/cli-client.ts +370 -50
  393. package/src/ipc/routes/db-proxy-transaction.ts +151 -0
  394. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +60 -0
  395. package/src/ipc/skill-routes/events.ts +30 -3
  396. package/src/ipc/skill-server.ts +99 -42
  397. package/src/live-voice/__tests__/live-voice-session-manager.test.ts +46 -0
  398. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +1 -0
  399. package/src/live-voice/live-voice-session-manager.ts +11 -4
  400. package/src/live-voice/live-voice-session.ts +14 -6
  401. package/src/memory/__tests__/bookmark-crud.test.ts +258 -0
  402. package/src/memory/__tests__/bookmark-schema.test.ts +181 -0
  403. package/src/memory/__tests__/conversation-types.test.ts +36 -0
  404. package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +130 -0
  405. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +10 -57
  406. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +177 -0
  407. package/src/memory/__tests__/memory-retrospective-job.test.ts +328 -0
  408. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +213 -0
  409. package/src/memory/__tests__/memory-retrospective-trigger-check.test.ts +90 -0
  410. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +69 -0
  411. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -0
  412. package/src/memory/bookmark-crud.ts +179 -0
  413. package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +31 -9
  414. package/src/memory/context-search/agent-protocol.ts +5 -1
  415. package/src/memory/context-search/agent-runner.ts +60 -85
  416. package/src/memory/context-search/limits.ts +1 -4
  417. package/src/memory/context-search/search.ts +23 -113
  418. package/src/memory/context-search/sources/conversations.ts +18 -6
  419. package/src/memory/context-search/sources/memory-v2.ts +40 -31
  420. package/src/memory/context-search/sources/memory.ts +9 -2
  421. package/src/memory/context-search/sources/workspace.ts +13 -10
  422. package/src/memory/context-search/types.ts +1 -1
  423. package/src/memory/conversation-bootstrap.ts +11 -0
  424. package/src/memory/conversation-crud.ts +312 -10
  425. package/src/memory/conversation-queries.ts +9 -5
  426. package/src/memory/conversation-title-service.ts +1 -0
  427. package/src/memory/conversation-types.ts +16 -0
  428. package/src/memory/db-init.ts +14 -0
  429. package/src/memory/embedding-backend.ts +2 -1
  430. package/src/memory/embedding-runtime-manager.ts +1 -2
  431. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +104 -61
  432. package/src/memory/graph/__tests__/handle-remember-v2.test.ts +11 -26
  433. package/src/memory/graph/__tests__/remember-description.test.ts +55 -0
  434. package/src/memory/graph/conversation-graph-memory.ts +108 -14
  435. package/src/memory/graph/extraction.ts +4 -0
  436. package/src/memory/graph/graph-memory-state-store.ts +16 -3
  437. package/src/memory/graph/graph-search.test.ts +6 -5
  438. package/src/memory/graph/graph-search.ts +3 -4
  439. package/src/memory/graph/retriever.test.ts +12 -7
  440. package/src/memory/graph/retriever.ts +4 -5
  441. package/src/memory/graph/tool-handlers.ts +20 -11
  442. package/src/memory/graph/tools.ts +48 -9
  443. package/src/memory/indexer.ts +18 -2
  444. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +120 -6
  445. package/src/memory/jobs/embed-concept-page.ts +261 -89
  446. package/src/memory/jobs-store.ts +51 -1
  447. package/src/memory/jobs-worker.ts +60 -7
  448. package/src/memory/llm-request-log-source-clickhouse.ts +317 -0
  449. package/src/memory/llm-request-log-source-local.ts +26 -0
  450. package/src/memory/llm-request-log-source.ts +97 -0
  451. package/src/memory/llm-request-log-store.ts +1 -1
  452. package/src/memory/memory-retrospective-constants.ts +13 -0
  453. package/src/memory/memory-retrospective-enqueue.ts +114 -0
  454. package/src/memory/memory-retrospective-job.ts +351 -0
  455. package/src/memory/memory-retrospective-startup-cleanup.ts +108 -0
  456. package/src/memory/memory-retrospective-state.ts +162 -0
  457. package/src/memory/memory-retrospective-trigger-check.ts +91 -0
  458. package/src/memory/memory-v2-activation-log-store.ts +49 -5
  459. package/src/memory/memory-v2-concept-frequency.ts +4 -0
  460. package/src/memory/message-content.ts +38 -1
  461. package/src/memory/migrations/227-add-conversation-inference-profile.ts +6 -1
  462. package/src/memory/migrations/228-rename-inference-profile-snake-case.ts +20 -7
  463. package/src/memory/migrations/229-delete-private-conversations.test.ts +70 -1
  464. package/src/memory/migrations/229-delete-private-conversations.ts +12 -0
  465. package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +16 -2
  466. package/src/memory/migrations/240-conversation-inference-profile-session.ts +25 -0
  467. package/src/memory/migrations/241-activation-state-fk-cascade.ts +50 -0
  468. package/src/memory/migrations/242-message-bookmarks.ts +38 -0
  469. package/src/memory/migrations/243-provider-connections.ts +68 -0
  470. package/src/memory/migrations/244-provider-connection-status-label.ts +23 -0
  471. package/src/memory/migrations/245-memory-retrospective-state.ts +36 -0
  472. package/src/memory/migrations/246-backfill-provider-connection-label.ts +81 -0
  473. package/src/memory/migrations/__tests__/244-provider-connection-status-label.test.ts +84 -0
  474. package/src/memory/migrations/__tests__/245-memory-retrospective-state.test.ts +125 -0
  475. package/src/memory/migrations/__tests__/246-backfill-provider-connection-label.test.ts +192 -0
  476. package/src/memory/migrations/index.ts +7 -0
  477. package/src/memory/pkb/pkb-search.test.ts +6 -5
  478. package/src/memory/pkb/pkb-search.ts +4 -5
  479. package/src/memory/published-pages-store.ts +16 -0
  480. package/src/memory/qdrant-client.ts +3 -0
  481. package/src/memory/schema/bookmarks.ts +38 -0
  482. package/src/memory/schema/conversations.ts +2 -0
  483. package/src/memory/schema/index.ts +2 -0
  484. package/src/memory/schema/inference.ts +29 -0
  485. package/src/memory/schema/memory-core.ts +9 -0
  486. package/src/memory/search/semantic.ts +5 -9
  487. package/src/memory/v2/__tests__/__snapshots__/prompts-router.test.ts.snap +27 -0
  488. package/src/memory/v2/__tests__/activation-store.test.ts +5 -5
  489. package/src/memory/v2/__tests__/activation.test.ts +46 -9
  490. package/src/memory/v2/__tests__/backfill-jobs.test.ts +38 -21
  491. package/src/memory/v2/__tests__/consolidation-job.test.ts +140 -163
  492. package/src/memory/v2/__tests__/edge-index.test.ts +1 -1
  493. package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +111 -0
  494. package/src/memory/v2/__tests__/injection.test.ts +768 -33
  495. package/src/memory/v2/__tests__/migration.test.ts +7 -3
  496. package/src/memory/v2/__tests__/page-index.test.ts +277 -0
  497. package/src/memory/v2/__tests__/page-store.test.ts +14 -1
  498. package/src/memory/v2/__tests__/prompts-router.test.ts +257 -0
  499. package/src/memory/v2/__tests__/qdrant.test.ts +382 -9
  500. package/src/memory/v2/__tests__/reranker.test.ts +4 -4
  501. package/src/memory/v2/__tests__/router.test.ts +516 -0
  502. package/src/memory/v2/__tests__/sim.test.ts +163 -8
  503. package/src/memory/v2/__tests__/skill-store.test.ts +58 -3
  504. package/src/memory/v2/__tests__/static-context.test.ts +8 -35
  505. package/src/memory/v2/__tests__/sweep-job.test.ts +114 -33
  506. package/src/memory/v2/activation-store.ts +34 -5
  507. package/src/memory/v2/activation.ts +40 -27
  508. package/src/memory/v2/backfill-jobs.ts +17 -84
  509. package/src/memory/v2/consolidation-job.ts +92 -86
  510. package/src/memory/v2/frontmatter-sweep.ts +91 -0
  511. package/src/memory/v2/injection.ts +466 -115
  512. package/src/memory/v2/migration.ts +117 -20
  513. package/src/memory/v2/page-index.ts +191 -0
  514. package/src/memory/v2/page-store.ts +42 -0
  515. package/src/memory/v2/prompts/consolidation.ts +14 -7
  516. package/src/memory/v2/prompts/router.ts +192 -0
  517. package/src/memory/v2/qdrant.ts +307 -133
  518. package/src/memory/v2/reranker.ts +14 -7
  519. package/src/memory/v2/router.ts +322 -0
  520. package/src/memory/v2/sim.ts +88 -34
  521. package/src/memory/v2/skill-store.ts +118 -29
  522. package/src/memory/v2/static-context.ts +20 -17
  523. package/src/memory/v2/sweep-job.ts +127 -102
  524. package/src/memory/v2/types.ts +16 -5
  525. package/src/memory/validation.ts +13 -0
  526. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +182 -0
  527. package/src/notifications/__tests__/home-feed-side-effect.test.ts +199 -0
  528. package/src/notifications/__tests__/signal-registry.test.ts +17 -0
  529. package/src/notifications/adapters/platform.ts +171 -0
  530. package/src/notifications/conversation-pairing.ts +2 -2
  531. package/src/notifications/copy-composer.ts +61 -12
  532. package/src/notifications/decision-engine.ts +46 -0
  533. package/src/notifications/destination-resolver.ts +21 -0
  534. package/src/notifications/emit-signal.ts +28 -1
  535. package/src/notifications/home-feed-side-effect.ts +111 -0
  536. package/src/notifications/signal.ts +5 -0
  537. package/src/permissions/checker.ts +12 -0
  538. package/src/permissions/gateway-threshold-reader.ts +116 -8
  539. package/src/permissions/ipc-risk-types.ts +2 -0
  540. package/src/permissions/prompter.ts +86 -96
  541. package/src/permissions/secret-prompter.ts +31 -31
  542. package/src/plugin-api/index.ts +13 -0
  543. package/src/plugin-api/package.json +12 -0
  544. package/src/plugin-api/types.ts +62 -0
  545. package/src/plugins/defaults/injectors.ts +20 -5
  546. package/src/plugins/external-plugin-loader.ts +294 -0
  547. package/src/plugins/types.ts +46 -30
  548. package/src/plugins/user-loader.ts +64 -41
  549. package/src/proactive-artifact/job.test.ts +63 -8
  550. package/src/proactive-artifact/job.ts +20 -2
  551. package/src/proactive-artifact/message-copy.ts +18 -1
  552. package/src/proactive-artifact/trigger-state.test.ts +9 -0
  553. package/src/proactive-artifact/trigger-state.ts +4 -0
  554. package/src/prompts/__tests__/system-prompt.test.ts +105 -0
  555. package/src/prompts/system-prompt.ts +22 -1
  556. package/src/prompts/templates/SOUL.md +13 -28
  557. package/src/prompts/update-bulletin-job.ts +61 -73
  558. package/src/providers/__tests__/dispatch-connection-routing.test.ts +279 -0
  559. package/src/providers/__tests__/inference.test.ts +288 -0
  560. package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
  561. package/src/providers/__tests__/provider-secret-catalog.test.ts +6 -0
  562. package/src/providers/__tests__/retry-callsite.test.ts +14 -32
  563. package/src/providers/__tests__/satellite-connection-routing.test.ts +510 -0
  564. package/src/providers/__tests__/search-provider-catalog.test.ts +80 -0
  565. package/src/providers/anthropic/client.ts +95 -26
  566. package/src/providers/call-site-routing.ts +94 -16
  567. package/src/providers/connection-resolution.ts +163 -0
  568. package/src/providers/inference/__tests__/connections-status-label.test.ts +250 -0
  569. package/src/providers/inference/adapter-factory.ts +173 -0
  570. package/src/providers/inference/auth.ts +112 -0
  571. package/src/providers/inference/backfill.ts +196 -0
  572. package/src/providers/inference/connections.ts +356 -0
  573. package/src/providers/inference/resolve-auth.ts +65 -0
  574. package/src/providers/model-catalog.ts +104 -6
  575. package/src/providers/openai/responses-provider.ts +4 -2
  576. package/src/providers/provider-env-vars.ts +17 -7
  577. package/src/providers/provider-secret-catalog.ts +49 -30
  578. package/src/providers/provider-send-message.ts +41 -20
  579. package/src/providers/registry.ts +143 -159
  580. package/src/providers/retry.ts +18 -10
  581. package/src/providers/search-provider-catalog.ts +121 -0
  582. package/src/runtime/AGENTS.md +18 -5
  583. package/src/runtime/__tests__/background-job-runner.test.ts +357 -0
  584. package/src/runtime/__tests__/pre-first-message-gate.test.ts +82 -0
  585. package/src/runtime/actor-trust-resolver.ts +32 -10
  586. package/src/runtime/agent-wake.ts +35 -6
  587. package/src/runtime/assistant-event-hub.ts +3 -85
  588. package/src/runtime/auth/route-policy.ts +304 -8
  589. package/src/runtime/auth/same-actor.ts +2 -0
  590. package/src/runtime/background-job-runner.ts +339 -0
  591. package/src/runtime/btw-sidechain.ts +1 -0
  592. package/src/runtime/channel-approvals.ts +3 -2
  593. package/src/runtime/guardian-reply-router.ts +0 -10
  594. package/src/runtime/http-router.ts +36 -1
  595. package/src/runtime/http-server.ts +31 -5
  596. package/src/runtime/http-types.ts +2 -0
  597. package/src/runtime/middleware/__tests__/request-logger.test.ts +162 -0
  598. package/src/runtime/middleware/request-logger.ts +62 -1
  599. package/src/runtime/pending-interactions.ts +19 -15
  600. package/src/runtime/pre-first-message-gate.ts +83 -0
  601. package/src/runtime/routes/__tests__/backup-routes.test.ts +8 -1
  602. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +251 -0
  603. package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +142 -0
  604. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +315 -0
  605. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +189 -0
  606. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +15 -136
  607. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +736 -0
  608. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +147 -0
  609. package/src/runtime/routes/__tests__/stt-routes.test.ts +5 -1
  610. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +384 -0
  611. package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
  612. package/src/runtime/routes/acp-routes.ts +10 -8
  613. package/src/runtime/routes/app-management-routes.ts +228 -3
  614. package/src/runtime/routes/approval-routes.ts +7 -21
  615. package/src/runtime/routes/audit-routes.ts +43 -0
  616. package/src/runtime/routes/auth-routes.ts +72 -0
  617. package/src/runtime/routes/avatar-routes.ts +273 -20
  618. package/src/runtime/routes/backup-routes.ts +406 -2
  619. package/src/runtime/routes/bookmark-routes.ts +154 -0
  620. package/src/runtime/routes/channel-verification-routes.ts +2 -1
  621. package/src/runtime/routes/consolidation-routes.ts +8 -9
  622. package/src/runtime/routes/contact-routes.ts +0 -160
  623. package/src/runtime/routes/conversation-cli-routes.ts +192 -0
  624. package/src/runtime/routes/conversation-management-routes.ts +30 -43
  625. package/src/runtime/routes/conversation-query-routes.ts +373 -82
  626. package/src/runtime/routes/conversation-routes.ts +31 -10
  627. package/src/runtime/routes/conversations-import-routes.ts +229 -0
  628. package/src/runtime/routes/credential-routes.ts +540 -0
  629. package/src/runtime/routes/debug-bash-routes.ts +2 -0
  630. package/src/runtime/routes/debug-routes.ts +2 -2
  631. package/src/runtime/routes/document-pdf-renderer.ts +5 -1
  632. package/src/runtime/routes/domain-routes.ts +167 -0
  633. package/src/runtime/routes/email-routes.ts +603 -0
  634. package/src/runtime/routes/errors.ts +2 -2
  635. package/src/runtime/routes/events-routes.ts +192 -0
  636. package/src/runtime/routes/filing-routes.ts +2 -3
  637. package/src/runtime/routes/home-feed-routes.ts +6 -78
  638. package/src/runtime/routes/host-app-control-routes.ts +44 -2
  639. package/src/runtime/routes/host-browser-routes.ts +103 -22
  640. package/src/runtime/routes/http-adapter.ts +2 -0
  641. package/src/runtime/routes/identity-routes.ts +5 -0
  642. package/src/runtime/routes/image-generation-routes.ts +99 -0
  643. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +137 -1
  644. package/src/runtime/routes/inbound-stages/background-dispatch.ts +87 -7
  645. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +156 -0
  646. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +22 -7
  647. package/src/runtime/routes/index.ts +36 -0
  648. package/src/runtime/routes/inference-profile-session-handler.ts +312 -0
  649. package/src/runtime/routes/inference-profile-session-reaper.ts +98 -0
  650. package/src/runtime/routes/inference-profile-session-routes.ts +146 -0
  651. package/src/runtime/routes/inference-provider-connection-routes.ts +317 -0
  652. package/src/runtime/routes/inference-send-routes.ts +115 -0
  653. package/src/runtime/routes/integrations/twilio.ts +1 -0
  654. package/src/runtime/routes/mcp-auth-routes.ts +283 -9
  655. package/src/runtime/routes/memory-item-routes.test.ts +3 -9
  656. package/src/runtime/routes/memory-item-routes.ts +5 -6
  657. package/src/runtime/routes/memory-v2-routes.ts +105 -404
  658. package/src/runtime/routes/notification-routes.ts +2 -0
  659. package/src/runtime/routes/oauth-apps.ts +112 -7
  660. package/src/runtime/routes/oauth-commands-routes.ts +1007 -0
  661. package/src/runtime/routes/oauth-connect-routes.ts +67 -5
  662. package/src/runtime/routes/oauth-providers.ts +298 -8
  663. package/src/runtime/routes/platform-routes.ts +336 -0
  664. package/src/runtime/routes/playground/inject-failures.ts +2 -1
  665. package/src/runtime/routes/playground/reset-circuit.ts +2 -1
  666. package/src/runtime/routes/playground/state.ts +2 -1
  667. package/src/runtime/routes/publish-routes.ts +221 -0
  668. package/src/runtime/routes/schedule-routes.ts +82 -0
  669. package/src/runtime/routes/sequence-routes.ts +291 -0
  670. package/src/runtime/routes/settings-routes.ts +2 -10
  671. package/src/runtime/routes/skills-routes.ts +31 -1
  672. package/src/runtime/routes/stt-routes.ts +240 -3
  673. package/src/runtime/routes/surface-action-routes.ts +43 -7
  674. package/src/runtime/routes/tts-routes.ts +67 -0
  675. package/src/runtime/routes/types.ts +32 -0
  676. package/src/runtime/routes/user-routes-cli.ts +243 -0
  677. package/src/runtime/routes/webhook-routes.ts +165 -0
  678. package/src/runtime/sync/resource-sync-events.ts +25 -0
  679. package/src/runtime/sync/sync-publisher.test.ts +105 -0
  680. package/src/runtime/sync/sync-publisher.ts +21 -0
  681. package/src/schedule/scheduler.ts +200 -123
  682. package/src/security/__tests__/provider-key-env-fallback.test.ts +12 -6
  683. package/src/security/secret-patterns.ts +3 -0
  684. package/src/sequence/engine.ts +38 -40
  685. package/src/skills/include-graph.ts +35 -13
  686. package/src/subagent/manager.ts +20 -15
  687. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +206 -0
  688. package/src/tools/browser/browser-execution.ts +15 -4
  689. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +174 -0
  690. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +16 -13
  691. package/src/tools/browser/cdp-client/extension-cdp-client.ts +24 -1
  692. package/src/tools/browser/cdp-client/factory.ts +66 -5
  693. package/src/tools/browser/runtime-check.ts +77 -0
  694. package/src/tools/document/document-tool.ts +20 -0
  695. package/src/tools/executor.ts +18 -2
  696. package/src/tools/memory/register.test.ts +10 -8
  697. package/src/tools/memory/register.ts +9 -1
  698. package/src/tools/network/__tests__/web-search.test.ts +156 -0
  699. package/src/tools/network/web-search.ts +280 -37
  700. package/src/tools/permission-checker.ts +28 -5
  701. package/src/tools/skills/load.ts +24 -20
  702. package/src/tools/subagent/spawn.ts +3 -3
  703. package/src/tools/terminal/shell.ts +44 -0
  704. package/src/tools/tool-name-aliases.ts +19 -0
  705. package/src/tools/types.ts +19 -1
  706. package/src/usage/attribution.ts +3 -2
  707. package/src/util/pricing.ts +86 -160
  708. package/src/watcher/__tests__/engine.test.ts +301 -0
  709. package/src/watcher/constants.ts +7 -0
  710. package/src/watcher/engine.ts +90 -90
  711. package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +6 -9
  712. package/src/workspace/migrations/054-seed-recall-callsite.ts +10 -1
  713. package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +28 -4
  714. package/src/workspace/migrations/067-release-notes-safe-storage-limits.ts +4 -62
  715. package/src/workspace/migrations/069-seed-onboarding-threads.ts +34 -0
  716. package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +31 -0
  717. package/src/workspace/migrations/071-remove-safe-storage-release-note.ts +111 -0
  718. package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +104 -0
  719. package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +93 -0
  720. package/src/workspace/migrations/074-drop-deprecated-secret-detection-keys.ts +117 -0
  721. package/src/workspace/migrations/075-memory-v2-bm25-b-default-reembed.ts +61 -0
  722. package/src/workspace/migrations/076-drop-services-inference-mode.ts +62 -0
  723. package/src/workspace/migrations/077-seed-memory-router-callsite.ts +89 -0
  724. package/src/workspace/migrations/078-release-notes-tavily-web-search.ts +66 -0
  725. package/src/workspace/migrations/079-home-feed-notification-only.ts +197 -0
  726. package/src/workspace/migrations/080-restrict-vercel-api-token-metadata.ts +182 -0
  727. package/src/workspace/migrations/081-backfill-bash-allowed-tools-for-injection-credentials.ts +160 -0
  728. package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +154 -0
  729. package/src/workspace/migrations/registry.ts +28 -0
  730. package/src/workspace/migrations/runner.ts +13 -2
  731. package/src/workspace/migrations/types.ts +13 -3
  732. package/src/workspace/provider-commit-message-generator.ts +3 -2
  733. package/src/__tests__/context-search-pkb-source.test.ts +0 -492
  734. package/src/__tests__/credentials-cli.test.ts +0 -1225
  735. package/src/__tests__/memory-admin-recall.test.ts +0 -213
  736. package/src/approvals/__tests__/guardian-feed-event.test.ts +0 -303
  737. package/src/cli/commands/__tests__/email-download.test.ts +0 -260
  738. package/src/cli/commands/__tests__/email-list.test.ts +0 -216
  739. package/src/cli/commands/__tests__/email-register.test.ts +0 -186
  740. package/src/cli/commands/__tests__/email-send.test.ts +0 -416
  741. package/src/cli/commands/__tests__/email-status.test.ts +0 -185
  742. package/src/cli/commands/__tests__/email-unregister.test.ts +0 -168
  743. package/src/cli/commands/__tests__/routes.test.ts +0 -562
  744. package/src/cli/commands/__tests__/stt-transcribe.test.ts +0 -454
  745. package/src/cli/commands/autonomy.ts +0 -365
  746. package/src/cli/commands/memory.ts +0 -424
  747. package/src/cli/commands/oauth/__tests__/connect.test.ts +0 -1201
  748. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +0 -686
  749. package/src/cli/commands/oauth/__tests__/mode.test.ts +0 -632
  750. package/src/cli/commands/oauth/__tests__/ping.test.ts +0 -631
  751. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +0 -573
  752. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +0 -330
  753. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +0 -521
  754. package/src/cli/commands/oauth/__tests__/status.test.ts +0 -551
  755. package/src/cli/commands/oauth/__tests__/token.test.ts +0 -420
  756. package/src/cli/lib/daemon-avatar-client.ts +0 -37
  757. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -87
  758. package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +0 -207
  759. package/src/daemon/__tests__/conversation-feed-event.test.ts +0 -304
  760. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +0 -233
  761. package/src/home/__tests__/assistant-feed-authoring.test.ts +0 -156
  762. package/src/home/__tests__/emit-feed-event.test.ts +0 -169
  763. package/src/home/__tests__/feed-population-integration.test.ts +0 -312
  764. package/src/home/__tests__/feed-scheduler.test.ts +0 -222
  765. package/src/home/__tests__/phase5-exit-criteria.test.ts +0 -229
  766. package/src/home/__tests__/platform-gmail-digest.test.ts +0 -222
  767. package/src/home/__tests__/rollup-producer.test.ts +0 -507
  768. package/src/home/assistant-feed-authoring.ts +0 -135
  769. package/src/home/emit-feed-event.ts +0 -169
  770. package/src/home/feed-scheduler.ts +0 -281
  771. package/src/home/platform-gmail-digest.ts +0 -163
  772. package/src/home/rewrite-command-preview.ts +0 -66
  773. package/src/home/rewrite-feed-title.ts +0 -58
  774. package/src/home/rollup-producer.ts +0 -426
  775. package/src/memory/admin.ts +0 -326
  776. package/src/memory/context-search/sources/pkb.ts +0 -477
  777. package/src/memory/graph/compaction.ts +0 -299
  778. /package/src/cli/{commands → lib}/cache-fs.ts +0 -0
@@ -0,0 +1,91 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Memory retrospective — periodic trigger check.
3
+ // ---------------------------------------------------------------------------
4
+ //
5
+ // Called from post-turn hooks (after each agent turn completes). Decides
6
+ // whether to enqueue a retrospective for this conversation based on:
7
+ //
8
+ // 1. Cooldown gate: never within `minCooldownMs` of the last attempt
9
+ // (success or failure). Prevents tight retry loops across trigger
10
+ // types.
11
+ // 2. Interval threshold: time since last attempt >= `timeThresholdMs`.
12
+ // 3. Message count threshold: new messages since `lastProcessedMessageId`
13
+ // >= `messageThreshold`.
14
+ //
15
+ // First-run case (no state row) skips the cooldown — `lastRunAt = 0` so the
16
+ // gap is effectively `Infinity`. The interval threshold trips immediately;
17
+ // the message-count threshold trips once enough messages accumulate.
18
+
19
+ import type { AssistantConfig } from "../config/types.js";
20
+ import { getLogger } from "../util/logger.js";
21
+ import { countMessagesAfter } from "./conversation-crud.js";
22
+ import { enqueueMemoryRetrospectiveIfEnabled } from "./memory-retrospective-enqueue.js";
23
+ import { getRetrospectiveState } from "./memory-retrospective-state.js";
24
+
25
+ const log = getLogger("memory-retrospective-trigger-check");
26
+
27
+ export type RetrospectiveTrigger = "interval" | "message_count";
28
+
29
+ /**
30
+ * Returns the trigger kind that fired, or `null` if no threshold tripped.
31
+ * Exported separately from `maybeEnqueueRetrospective` so tests can assert on
32
+ * the decision without observing side effects.
33
+ */
34
+ export function shouldEnqueueRetrospective(args: {
35
+ state: { lastProcessedMessageId: string; lastRunAt: number } | null;
36
+ newMessageCount: number;
37
+ now: number;
38
+ timeThresholdMs: number;
39
+ messageThreshold: number;
40
+ minCooldownMs: number;
41
+ }): RetrospectiveTrigger | null {
42
+ const {
43
+ state,
44
+ newMessageCount,
45
+ now,
46
+ timeThresholdMs,
47
+ messageThreshold,
48
+ minCooldownMs,
49
+ } = args;
50
+
51
+ if (state && now - state.lastRunAt < minCooldownMs) return null;
52
+
53
+ if (state && now - state.lastRunAt >= timeThresholdMs) return "interval";
54
+ if (!state) return "interval";
55
+
56
+ if (newMessageCount >= messageThreshold) return "message_count";
57
+ return null;
58
+ }
59
+
60
+ /**
61
+ * Post-turn hook entry point. Looks up state, counts new messages, evaluates
62
+ * thresholds, and enqueues if appropriate. Best-effort — any thrown error is
63
+ * caught and logged so the agent turn cleanup path doesn't fail.
64
+ */
65
+ export function maybeEnqueueRetrospective(
66
+ conversationId: string,
67
+ config: AssistantConfig,
68
+ ): void {
69
+ try {
70
+ const state = getRetrospectiveState(conversationId);
71
+ const newMessageCount = countMessagesAfter(
72
+ conversationId,
73
+ state?.lastProcessedMessageId ?? null,
74
+ );
75
+ if (newMessageCount === 0) return;
76
+
77
+ const trigger = shouldEnqueueRetrospective({
78
+ state,
79
+ newMessageCount,
80
+ now: Date.now(),
81
+ timeThresholdMs: config.memory.retrospective.timeThresholdMs,
82
+ messageThreshold: config.memory.retrospective.messageThreshold,
83
+ minCooldownMs: config.memory.retrospective.minCooldownMs,
84
+ });
85
+ if (!trigger) return;
86
+
87
+ enqueueMemoryRetrospectiveIfEnabled({ conversationId, trigger });
88
+ } catch (err) {
89
+ log.warn({ err, conversationId }, "trigger-check failed; skipping enqueue");
90
+ }
91
+ }
@@ -39,8 +39,43 @@ export interface MemoryV2ConceptRowRecord {
39
39
  */
40
40
  inRerankPool: boolean;
41
41
  spreadContribution: number;
42
- source: "prior_state" | "ann_top50" | "both";
43
- status: "in_context" | "injected" | "not_injected" | "page_missing";
42
+ /**
43
+ * Provenance of this concept row.
44
+ * - `prior_state` — carried over from prior turn's activation state.
45
+ * - `ann_top50` — entered via ANN top-K candidate pool.
46
+ * - `both` — present in both prior state and ANN pool.
47
+ * - `router` — selected by the Sonnet router (memory-v2 router
48
+ * mode). Router-mode rows zero out all activation values
49
+ * (`finalActivation`, `ownActivation`, `priorActivation`, channel
50
+ * similarities, rerank boosts, `spreadContribution`) because the
51
+ * router does not compute spreading-activation scores.
52
+ * - `carry_over` — router-mode row representing a slug carried over
53
+ * from `priorEverInjected` that the router did NOT re-pick on this
54
+ * turn. The cached attachment from a prior turn is still present
55
+ * on a prior user message; emitting `source: "router"` for these
56
+ * rows would overcount router selections in inspector queries.
57
+ * Same zeroed activation values as `router`.
58
+ */
59
+ source: "prior_state" | "ann_top50" | "both" | "router" | "carry_over";
60
+ /**
61
+ * Per-turn outcome for this slug:
62
+ * - `in_context` — already injected on a prior turn; cached attachment
63
+ * remains visible without re-rendering.
64
+ * - `injected` — freshly rendered into this turn's user message.
65
+ * - `not_injected`— a candidate that didn't make `slugsToRender`.
66
+ * - `page_missing`— would-have-been-injected, but `readPage` returned
67
+ * null (file vanished between selection and render — stale Qdrant
68
+ * or edge-index entry).
69
+ * - `corrupt` — would-have-been-injected, but `readPage` threw
70
+ * (e.g. malformed frontmatter). Other slugs in the same batch
71
+ * rendered normally.
72
+ */
73
+ status:
74
+ | "in_context"
75
+ | "injected"
76
+ | "not_injected"
77
+ | "page_missing"
78
+ | "corrupt";
44
79
  }
45
80
 
46
81
  export interface MemoryV2ConfigSnapshot {
@@ -57,7 +92,16 @@ export interface MemoryV2ConfigSnapshot {
57
92
  export interface RecordMemoryV2ActivationLogParams {
58
93
  conversationId: string;
59
94
  turn: number;
60
- mode: "context-load" | "per-turn";
95
+ /**
96
+ * Call-site mode: `context-load` for fresh / post-compaction loads,
97
+ * `per-turn` for normal append injections, `errored` when `injectMemoryV2Block`
98
+ * threw before completing — telemetry is still written so silent failures
99
+ * are observable in the database, with whatever `concepts` rows had been
100
+ * built so far (possibly empty). `router` indicates the Sonnet
101
+ * router selected the per-turn page set; router-mode rows carry zeroed
102
+ * activation values and `source: "router"` on every concept row.
103
+ */
104
+ mode: "context-load" | "per-turn" | "errored" | "router";
61
105
  concepts: MemoryV2ConceptRowRecord[];
62
106
  config: MemoryV2ConfigSnapshot;
63
107
  }
@@ -105,7 +149,7 @@ export function backfillMemoryV2ActivationMessageId(
105
149
  export interface MemoryV2ActivationLog {
106
150
  conversationId: string;
107
151
  turn: number;
108
- mode: "context-load" | "per-turn";
152
+ mode: "context-load" | "per-turn" | "errored" | "router";
109
153
  concepts: MemoryV2ConceptRowRecord[];
110
154
  config: MemoryV2ConfigSnapshot;
111
155
  }
@@ -126,7 +170,7 @@ export function getMemoryV2ActivationLogByMessageIds(
126
170
  return {
127
171
  conversationId: row.conversationId,
128
172
  turn: row.turn,
129
- mode: row.mode as "context-load" | "per-turn",
173
+ mode: row.mode as "context-load" | "per-turn" | "errored" | "router",
130
174
  concepts: JSON.parse(row.conceptsJson) as MemoryV2ConceptRowRecord[],
131
175
  config: JSON.parse(row.configJson) as MemoryV2ConfigSnapshot,
132
176
  };
@@ -52,6 +52,7 @@ const ZERO_COUNTS: ConceptFrequencyCounts = {
52
52
  in_context: 0,
53
53
  not_injected: 0,
54
54
  page_missing: 0,
55
+ corrupt: 0,
55
56
  };
56
57
 
57
58
  interface CountRow {
@@ -130,6 +131,9 @@ export async function getConceptFrequencySummary(
130
131
  case "page_missing":
131
132
  entry.counts.page_missing += row.count;
132
133
  break;
134
+ case "corrupt":
135
+ entry.counts.corrupt += row.count;
136
+ break;
133
137
  default:
134
138
  // Forward-compat: unknown status values are ignored, not summed into
135
139
  // totalEvaluations. The activation pipeline produces a closed enum.
@@ -121,7 +121,6 @@ export function extractMediaBlockMeta(
121
121
  }
122
122
  }
123
123
 
124
-
125
124
  function stableJson(value: unknown): string {
126
125
  try {
127
126
  return JSON.stringify(value);
@@ -129,3 +128,41 @@ function stableJson(value: unknown): string {
129
128
  return "<unserializable />";
130
129
  }
131
130
  }
131
+
132
+ /**
133
+ * Coerce stored message content into a single human-readable text string,
134
+ * dropping non-text blocks (images, tool calls, tool results, thinking,
135
+ * …). Used by call sites that want only the spoken text — sweep-model
136
+ * context, RAG backfill, bookmark previews. For richer renderings that
137
+ * include tool metadata, use {@link extractTextFromStoredMessageContent}
138
+ * instead.
139
+ *
140
+ * Handles the two on-disk shapes:
141
+ * - Modern rows: JSON-serialized `ContentBlock[]`
142
+ * - Legacy rows: plain string
143
+ *
144
+ * Parse failures fall back to returning the raw input trimmed (the
145
+ * legacy-string path).
146
+ */
147
+ export function stringifyMessageContent(stored: string): string {
148
+ let parsed: unknown;
149
+ try {
150
+ parsed = JSON.parse(stored);
151
+ } catch {
152
+ return stored.trim();
153
+ }
154
+ if (typeof parsed === "string") return parsed.trim();
155
+ if (!Array.isArray(parsed)) return "";
156
+ const parts: string[] = [];
157
+ for (const block of parsed) {
158
+ if (
159
+ block &&
160
+ typeof block === "object" &&
161
+ (block as { type?: string }).type === "text" &&
162
+ typeof (block as { text?: unknown }).text === "string"
163
+ ) {
164
+ parts.push((block as { text: string }).text);
165
+ }
166
+ }
167
+ return parts.join("\n").trim();
168
+ }
@@ -8,8 +8,13 @@ export function migrateAddConversationInferenceProfile(
8
8
  const columns = raw.query(`PRAGMA table_info(conversations)`).all() as Array<{
9
9
  name: string;
10
10
  }>;
11
+ // Skip if either the original camelCase column or the renamed snake_case
12
+ // column from migration 228 is already present. Without the snake_case
13
+ // check, this migration would re-add the camelCase column on every boot
14
+ // after 228 runs, leaving both columns permanently.
11
15
  const hasColumn = columns.some(
12
- (column) => column.name === "inferenceProfile",
16
+ (column) =>
17
+ column.name === "inferenceProfile" || column.name === "inference_profile",
13
18
  );
14
19
  if (hasColumn) {
15
20
  return;
@@ -6,19 +6,32 @@ import { tableHasColumn } from "./schema-introspection.js";
6
6
  * by migration 227) to `inference_profile` so it matches the snake_case
7
7
  * convention used by every other column on the table.
8
8
  *
9
- * Idempotent:
10
- * - camelCase column present, snake_case absent renames it.
11
- * - snake_case column already present no-op.
12
- * - neither column present no-op (shouldn't happen since 227 ran first,
13
- * but we guard for completeness).
9
+ * Idempotent and self-healing:
10
+ * - both columns present drop the camelCase one (heals instances that
11
+ * already booted twice with the original buggy migration 227, where 227
12
+ * re-added the camelCase column after this migration renamed it).
13
+ * - camelCase column present, snake_case absent → rename it.
14
+ * - snake_case column present, camelCase absent → no-op.
15
+ * - neither column present → no-op.
14
16
  */
15
17
  export function migrateRenameInferenceProfileSnakeCase(
16
18
  database: DrizzleDb,
17
19
  ): void {
18
- if (tableHasColumn(database, "conversations", "inference_profile")) {
20
+ const hasSnake = tableHasColumn(
21
+ database,
22
+ "conversations",
23
+ "inference_profile",
24
+ );
25
+ const hasCamel = tableHasColumn(
26
+ database,
27
+ "conversations",
28
+ "inferenceProfile",
29
+ );
30
+ if (hasSnake && hasCamel) {
31
+ database.run(`ALTER TABLE conversations DROP COLUMN inferenceProfile`);
19
32
  return;
20
33
  }
21
- if (!tableHasColumn(database, "conversations", "inferenceProfile")) {
34
+ if (!hasCamel) {
22
35
  return;
23
36
  }
24
37
  database.run(
@@ -615,7 +615,8 @@ function seedGuardianAndApprovalRows(raw: Database, now: number): void {
615
615
  created_at,
616
616
  updated_at
617
617
  ) VALUES
618
- ('call-standard-guardian', 'conv-standard', 'test-provider', '+15550100', '+15550101', 'initiated', ${now}, ${now});
618
+ ('call-standard-guardian', 'conv-standard', 'test-provider', '+15550100', '+15550101', 'initiated', ${now}, ${now}),
619
+ ('call-private-guardian', 'conv-private', 'test-provider', '+15550102', '+15550103', 'initiated', ${now}, ${now});
619
620
 
620
621
  INSERT INTO call_pending_questions (
621
622
  id,
@@ -708,6 +709,23 @@ function seedGuardianAndApprovalRows(raw: Database, now: number): void {
708
709
  ('scoped-grant-standard', 'request_id', 'canonical-request-standard', NULL, NULL, 'vellum', 'vellum', 'conv-standard', 'active', ${now + 60000}, ${now}, ${now}),
709
710
  ('scoped-grant-unscoped', 'tool_signature', NULL, 'test_tool', 'digest-123', 'vellum', 'vellum', NULL, 'active', ${now + 60000}, ${now}, ${now});
710
711
 
712
+ INSERT INTO scoped_approval_grants (
713
+ id,
714
+ scope_mode,
715
+ request_id,
716
+ tool_name,
717
+ input_digest,
718
+ request_channel,
719
+ decision_channel,
720
+ conversation_id,
721
+ call_session_id,
722
+ status,
723
+ expires_at,
724
+ created_at,
725
+ updated_at
726
+ ) VALUES
727
+ ('scoped-grant-private-call-only', 'tool_signature', NULL, 'test_tool', 'digest-456', 'vellum', 'vellum', NULL, 'call-private-guardian', 'active', ${now + 60000}, ${now}, ${now});
728
+
711
729
  INSERT INTO channel_guardian_approval_requests (
712
730
  id,
713
731
  run_id,
@@ -1034,6 +1052,13 @@ describe("migrateDeletePrivateConversations", () => {
1034
1052
  expect(
1035
1053
  countWhere(raw, "scoped_approval_grants", `id = 'scoped-grant-unscoped'`),
1036
1054
  ).toBe(1);
1055
+ expect(
1056
+ countWhere(
1057
+ raw,
1058
+ "scoped_approval_grants",
1059
+ `id = 'scoped-grant-private-call-only'`,
1060
+ ),
1061
+ ).toBe(0);
1037
1062
  expect(
1038
1063
  countWhere(
1039
1064
  raw,
@@ -1084,4 +1109,48 @@ describe("migrateDeletePrivateConversations", () => {
1084
1109
  ),
1085
1110
  ).toBe(1);
1086
1111
  });
1112
+
1113
+ test("removes orphan attachments left by prior runs that deleted private messages", () => {
1114
+ const db = createTestDb();
1115
+ const raw = getSqliteFrom(db);
1116
+ const now = Date.now();
1117
+
1118
+ bootstrapTables(raw);
1119
+ seedConversation(raw, "conv-standard", "standard");
1120
+ raw.exec(/*sql*/ `
1121
+ INSERT INTO attachments (
1122
+ id,
1123
+ original_filename,
1124
+ mime_type,
1125
+ size_bytes,
1126
+ kind,
1127
+ data_base64,
1128
+ created_at
1129
+ ) VALUES (
1130
+ 'orphan-private-attachment',
1131
+ 'leaked.txt',
1132
+ 'text/plain',
1133
+ 1,
1134
+ 'text',
1135
+ 'eA==',
1136
+ ${now}
1137
+ );
1138
+ `);
1139
+
1140
+ expect(
1141
+ countWhere(raw, "attachments", `id = 'orphan-private-attachment'`),
1142
+ ).toBe(1);
1143
+ expect(
1144
+ countWhere(raw, "attachments", `id = 'conv-standard-attachment'`),
1145
+ ).toBe(1);
1146
+
1147
+ migrateDeletePrivateConversations(db);
1148
+
1149
+ expect(
1150
+ countWhere(raw, "attachments", `id = 'orphan-private-attachment'`),
1151
+ ).toBe(0);
1152
+ expect(
1153
+ countWhere(raw, "attachments", `id = 'conv-standard-attachment'`),
1154
+ ).toBe(1);
1155
+ });
1087
1156
  });
@@ -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
+ }