@vellumai/assistant 0.5.5 → 0.5.7

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 (382) hide show
  1. package/.env.example +16 -2
  2. package/ARCHITECTURE.md +6 -75
  3. package/Dockerfile +4 -5
  4. package/README.md +0 -2
  5. package/bun.lock +0 -414
  6. package/docs/architecture/keychain-broker.md +45 -240
  7. package/docs/architecture/security.md +0 -17
  8. package/docs/credential-execution-service.md +2 -2
  9. package/node_modules/@vellumai/ces-contracts/package.json +1 -0
  10. package/node_modules/@vellumai/ces-contracts/src/rpc.ts +119 -0
  11. package/node_modules/@vellumai/credential-storage/package.json +1 -0
  12. package/node_modules/@vellumai/egress-proxy/package.json +1 -0
  13. package/package.json +2 -3
  14. package/src/__tests__/actor-token-service.test.ts +1 -2
  15. package/src/__tests__/assistant-feature-flags-integration.test.ts +30 -29
  16. package/src/__tests__/browser-skill-endstate.test.ts +6 -5
  17. package/src/__tests__/btw-routes.test.ts +0 -39
  18. package/src/__tests__/call-domain.test.ts +0 -128
  19. package/src/__tests__/ces-rpc-credential-backend.test.ts +199 -0
  20. package/src/__tests__/channel-approval-routes.test.ts +0 -5
  21. package/src/__tests__/channel-readiness-service.test.ts +1 -60
  22. package/src/__tests__/checker.test.ts +4 -2
  23. package/src/__tests__/cli-command-risk-guard.test.ts +112 -0
  24. package/src/__tests__/config-schema-cmd.test.ts +0 -1
  25. package/src/__tests__/config-schema.test.ts +3 -3
  26. package/src/__tests__/context-window-manager.test.ts +78 -0
  27. package/src/__tests__/conversation-attention-telegram.test.ts +0 -5
  28. package/src/__tests__/conversation-init.benchmark.test.ts +0 -2
  29. package/src/__tests__/conversation-skill-tools.test.ts +0 -54
  30. package/src/__tests__/conversation-title-service.test.ts +117 -1
  31. package/src/__tests__/credential-execution-feature-gates.test.ts +28 -14
  32. package/src/__tests__/credential-execution-managed-contract.test.ts +33 -18
  33. package/src/__tests__/credential-security-e2e.test.ts +0 -66
  34. package/src/__tests__/credential-security-invariants.test.ts +4 -45
  35. package/src/__tests__/credentials-cli.test.ts +78 -0
  36. package/src/__tests__/db-migration-rollback.test.ts +2015 -1
  37. package/src/__tests__/docker-signing-key-bootstrap.test.ts +98 -0
  38. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +6 -4
  39. package/src/__tests__/guardian-routing-state.test.ts +0 -5
  40. package/src/__tests__/host-shell-tool.test.ts +6 -7
  41. package/src/__tests__/http-user-message-parity.test.ts +3 -103
  42. package/src/__tests__/inbound-invite-redemption.test.ts +0 -4
  43. package/src/__tests__/inline-skill-load-permissions.test.ts +6 -8
  44. package/src/__tests__/intent-routing.test.ts +0 -13
  45. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +178 -0
  46. package/src/__tests__/keychain-broker-client.test.ts +161 -22
  47. package/src/__tests__/memory-jobs-worker-backoff.test.ts +150 -0
  48. package/src/__tests__/memory-regressions.test.ts +8 -30
  49. package/src/__tests__/migration-export-http.test.ts +2 -2
  50. package/src/__tests__/migration-import-commit-http.test.ts +2 -2
  51. package/src/__tests__/migration-import-preflight-http.test.ts +2 -2
  52. package/src/__tests__/migration-validate-http.test.ts +2 -2
  53. package/src/__tests__/non-member-access-request.test.ts +0 -5
  54. package/src/__tests__/notification-decision-fallback.test.ts +4 -0
  55. package/src/__tests__/notification-decision-identity.test.ts +4 -0
  56. package/src/__tests__/permission-types.test.ts +1 -0
  57. package/src/__tests__/provider-managed-proxy-integration.test.ts +5 -6
  58. package/src/__tests__/qdrant-manager.test.ts +28 -2
  59. package/src/__tests__/registry.test.ts +0 -6
  60. package/src/__tests__/require-fresh-approval.test.ts +4 -0
  61. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -4
  62. package/src/__tests__/secret-routes-managed-proxy.test.ts +0 -4
  63. package/src/__tests__/secure-keys.test.ts +83 -263
  64. package/src/__tests__/shell-identity.test.ts +96 -6
  65. package/src/__tests__/skill-feature-flags-integration.test.ts +22 -14
  66. package/src/__tests__/skill-feature-flags.test.ts +46 -45
  67. package/src/__tests__/skill-load-feature-flag.test.ts +7 -10
  68. package/src/__tests__/skill-load-inline-command.test.ts +8 -12
  69. package/src/__tests__/skill-load-inline-includes.test.ts +6 -10
  70. package/src/__tests__/skill-load-tool.test.ts +0 -2
  71. package/src/__tests__/skill-projection-feature-flag.test.ts +33 -29
  72. package/src/__tests__/skills.test.ts +0 -2
  73. package/src/__tests__/slack-inbound-verification.test.ts +0 -4
  74. package/src/__tests__/suggestion-routes.test.ts +1 -32
  75. package/src/__tests__/system-prompt.test.ts +0 -1
  76. package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -0
  77. package/src/__tests__/tool-executor-shell-integration.test.ts +5 -3
  78. package/src/__tests__/tool-executor.test.ts +4 -0
  79. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +0 -5
  80. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -4
  81. package/src/__tests__/update-bulletin.test.ts +0 -2
  82. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +6 -9
  83. package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -6
  84. package/src/__tests__/workspace-migration-015-migrate-credentials-to-keychain.test.ts +252 -0
  85. package/src/__tests__/workspace-migration-016-migrate-credentials-from-keychain.test.ts +218 -0
  86. package/src/__tests__/workspace-migration-down-functions.test.ts +1009 -0
  87. package/src/__tests__/workspace-migrations-runner.test.ts +114 -0
  88. package/src/calls/audio-store.test.ts +97 -0
  89. package/src/calls/audio-store.ts +205 -0
  90. package/src/calls/call-controller.ts +85 -7
  91. package/src/calls/call-domain.ts +3 -0
  92. package/src/calls/call-store.ts +10 -3
  93. package/src/calls/fish-audio-client.ts +117 -0
  94. package/src/calls/relay-server.ts +27 -0
  95. package/src/calls/twilio-routes.ts +2 -1
  96. package/src/calls/types.ts +1 -0
  97. package/src/calls/voice-ingress-preflight.ts +0 -42
  98. package/src/calls/voice-quality.ts +26 -5
  99. package/src/calls/voice-session-bridge.ts +6 -12
  100. package/src/cli/commands/config.ts +1 -4
  101. package/src/cli/commands/conversations.ts +0 -18
  102. package/src/cli/commands/credentials.ts +34 -4
  103. package/src/cli/commands/oauth/index.ts +7 -0
  104. package/src/cli/commands/oauth/platform.ts +179 -0
  105. package/src/cli/commands/platform.ts +3 -3
  106. package/src/config/assistant-feature-flags.ts +186 -5
  107. package/src/config/bundled-skills/messaging/SKILL.md +5 -5
  108. package/src/config/bundled-skills/phone-calls/TOOLS.json +4 -0
  109. package/src/config/bundled-skills/settings/TOOLS.json +2 -2
  110. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +42 -0
  111. package/src/config/bundled-tool-registry.ts +1 -11
  112. package/src/config/env-registry.ts +1 -1
  113. package/src/config/env.ts +16 -16
  114. package/src/config/feature-flag-registry.json +48 -16
  115. package/src/config/loader.ts +98 -31
  116. package/src/config/schema.ts +4 -25
  117. package/src/config/schemas/calls.ts +13 -0
  118. package/src/config/schemas/fish-audio.ts +39 -0
  119. package/src/config/schemas/memory.ts +0 -4
  120. package/src/config/schemas/platform.ts +1 -1
  121. package/src/config/schemas/security.ts +4 -4
  122. package/src/config/types.ts +0 -1
  123. package/src/contacts/contact-store.ts +39 -0
  124. package/src/contacts/types.ts +2 -0
  125. package/src/context/window-manager.ts +53 -2
  126. package/src/credential-execution/approval-bridge.ts +1 -0
  127. package/src/credential-execution/executable-discovery.ts +28 -4
  128. package/src/credential-execution/feature-gates.ts +16 -0
  129. package/src/credential-execution/process-manager.ts +38 -0
  130. package/src/daemon/assistant-attachments.ts +9 -0
  131. package/src/daemon/config-watcher.ts +6 -4
  132. package/src/daemon/conversation-agent-loop.ts +0 -60
  133. package/src/daemon/conversation-memory.ts +0 -117
  134. package/src/daemon/conversation-runtime-assembly.ts +0 -2
  135. package/src/daemon/conversation-tool-setup.ts +0 -105
  136. package/src/daemon/conversation.ts +10 -1
  137. package/src/daemon/handlers/config-vercel.ts +92 -0
  138. package/src/daemon/handlers/conversations.ts +0 -11
  139. package/src/daemon/handlers/skills.ts +2 -15
  140. package/src/daemon/install-symlink.ts +195 -0
  141. package/src/daemon/lifecycle.ts +229 -96
  142. package/src/daemon/message-types/conversations.ts +3 -4
  143. package/src/daemon/message-types/diagnostics.ts +3 -22
  144. package/src/daemon/message-types/messages.ts +0 -2
  145. package/src/daemon/message-types/upgrades.ts +8 -0
  146. package/src/daemon/server.ts +30 -92
  147. package/src/events/domain-events.ts +2 -1
  148. package/src/followups/followup-store.ts +5 -2
  149. package/src/inbound/platform-callback-registration.ts +3 -3
  150. package/src/instrument.ts +8 -5
  151. package/src/memory/conversation-crud.ts +0 -236
  152. package/src/memory/conversation-title-service.ts +76 -11
  153. package/src/memory/db-init.ts +15 -11
  154. package/src/memory/indexer.ts +15 -106
  155. package/src/memory/items-extractor.ts +15 -1
  156. package/src/memory/job-handlers/conversation-starters.ts +4 -1
  157. package/src/memory/job-handlers/embedding.ts +0 -79
  158. package/src/memory/job-utils.ts +1 -1
  159. package/src/memory/jobs-store.ts +30 -13
  160. package/src/memory/jobs-worker.ts +31 -27
  161. package/src/memory/migrations/001-job-deferrals.ts +19 -0
  162. package/src/memory/migrations/004-entity-relation-dedup.ts +10 -0
  163. package/src/memory/migrations/005-fingerprint-scope-unique.ts +76 -0
  164. package/src/memory/migrations/006-scope-salted-fingerprints.ts +50 -0
  165. package/src/memory/migrations/007-assistant-id-to-self.ts +10 -0
  166. package/src/memory/migrations/008-remove-assistant-id-columns.ts +34 -0
  167. package/src/memory/migrations/009-llm-usage-events-drop-assistant-id.ts +26 -0
  168. package/src/memory/migrations/014-backfill-inbox-thread-state.ts +10 -0
  169. package/src/memory/migrations/015-drop-active-search-index.ts +17 -0
  170. package/src/memory/migrations/019-notification-tables-schema-migration.ts +12 -0
  171. package/src/memory/migrations/020-rename-macos-ios-channel-to-vellum.ts +121 -0
  172. package/src/memory/migrations/024-embedding-vector-blob.ts +74 -0
  173. package/src/memory/migrations/026a-embeddings-nullable-vector-json.ts +82 -0
  174. package/src/memory/migrations/036-normalize-phone-identities.ts +11 -0
  175. package/src/memory/migrations/116-messages-fts.ts +106 -1
  176. package/src/memory/migrations/126-backfill-guardian-principal-id.ts +52 -0
  177. package/src/memory/migrations/127-guardian-principal-id-not-null.ts +77 -0
  178. package/src/memory/migrations/134-contacts-notes-column.ts +13 -0
  179. package/src/memory/migrations/135-backfill-contact-interaction-stats.ts +20 -0
  180. package/src/memory/migrations/136-drop-assistant-id-columns.ts +52 -0
  181. package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +13 -0
  182. package/src/memory/migrations/141-rename-verification-table.ts +54 -0
  183. package/src/memory/migrations/142-rename-verification-session-id-column.ts +25 -0
  184. package/src/memory/migrations/143-rename-guardian-verification-values.ts +35 -0
  185. package/src/memory/migrations/144-rename-voice-to-phone.ts +136 -0
  186. package/src/memory/migrations/145-drop-accounts-table.ts +32 -0
  187. package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +14 -1
  188. package/src/memory/migrations/148-drop-reminders-table.ts +35 -1
  189. package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +69 -1
  190. package/src/memory/migrations/162-guardian-timestamps-epoch-ms.ts +290 -0
  191. package/src/memory/migrations/169-rename-gmail-provider-key-to-google.ts +51 -1
  192. package/src/memory/migrations/174-rename-thread-starters-table.ts +47 -1
  193. package/src/memory/migrations/176-drop-capability-card-state.ts +13 -0
  194. package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +16 -0
  195. package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +28 -1
  196. package/src/memory/migrations/189-drop-simplified-memory.ts +42 -0
  197. package/src/memory/migrations/190-call-session-skip-disclosure.ts +15 -0
  198. package/src/memory/migrations/191-backfill-audio-attachment-mime-types.ts +64 -0
  199. package/src/memory/migrations/192-contacts-user-file-column.ts +15 -0
  200. package/src/memory/migrations/index.ts +5 -3
  201. package/src/memory/migrations/registry.ts +90 -0
  202. package/src/memory/migrations/validate-migration-state.ts +137 -11
  203. package/src/memory/qdrant-circuit-breaker.ts +9 -0
  204. package/src/memory/qdrant-client.ts +4 -6
  205. package/src/memory/qdrant-manager.ts +64 -7
  206. package/src/memory/schema/calls.ts +1 -0
  207. package/src/memory/schema/contacts.ts +1 -0
  208. package/src/memory/schema/conversations.ts +0 -3
  209. package/src/memory/schema/index.ts +0 -2
  210. package/src/messaging/draft-store.ts +2 -2
  211. package/src/notifications/decision-engine.ts +4 -1
  212. package/src/oauth/connection-resolver.ts +6 -4
  213. package/src/permissions/checker.ts +0 -38
  214. package/src/permissions/defaults.ts +3 -3
  215. package/src/permissions/shell-identity.ts +76 -22
  216. package/src/permissions/trust-client.ts +2 -13
  217. package/src/permissions/trust-store.ts +8 -3
  218. package/src/permissions/types.ts +4 -2
  219. package/src/platform/client.ts +35 -7
  220. package/src/prompts/persona-resolver.ts +138 -0
  221. package/src/prompts/system-prompt.ts +36 -4
  222. package/src/prompts/templates/users/default.md +1 -0
  223. package/src/providers/registry.ts +27 -40
  224. package/src/runtime/auth/__tests__/credential-service.test.ts +0 -1
  225. package/src/runtime/auth/__tests__/external-assistant-id.test.ts +13 -68
  226. package/src/runtime/auth/external-assistant-id.ts +13 -59
  227. package/src/runtime/auth/route-policy.ts +29 -1
  228. package/src/runtime/auth/token-service.ts +53 -15
  229. package/src/runtime/channel-readiness-service.ts +1 -16
  230. package/src/runtime/http-server.ts +29 -2
  231. package/src/runtime/middleware/error-handler.ts +1 -9
  232. package/src/runtime/routes/audio-routes.ts +40 -0
  233. package/src/runtime/routes/btw-routes.ts +0 -17
  234. package/src/runtime/routes/conversation-management-routes.ts +0 -36
  235. package/src/runtime/routes/conversation-query-routes.ts +106 -2
  236. package/src/runtime/routes/conversation-routes.ts +4 -43
  237. package/src/runtime/routes/diagnostics-routes.ts +1 -477
  238. package/src/runtime/routes/identity-routes.ts +18 -29
  239. package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +4 -33
  240. package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +1 -1
  241. package/src/runtime/routes/integrations/vercel.ts +89 -0
  242. package/src/runtime/routes/log-export-routes.ts +5 -0
  243. package/src/runtime/routes/memory-item-routes.test.ts +221 -3
  244. package/src/runtime/routes/memory-item-routes.ts +144 -4
  245. package/src/runtime/routes/migration-rollback-routes.ts +209 -0
  246. package/src/runtime/routes/migration-routes.ts +17 -1
  247. package/src/runtime/routes/notification-routes.ts +58 -0
  248. package/src/runtime/routes/schedule-routes.ts +65 -0
  249. package/src/runtime/routes/settings-routes.ts +41 -1
  250. package/src/runtime/routes/tts-routes.ts +86 -0
  251. package/src/runtime/routes/upgrade-broadcast-routes.ts +175 -0
  252. package/src/runtime/routes/workspace-commit-routes.ts +62 -0
  253. package/src/runtime/routes/workspace-routes.test.ts +22 -1
  254. package/src/runtime/routes/workspace-routes.ts +1 -1
  255. package/src/runtime/routes/workspace-utils.ts +86 -2
  256. package/src/schedule/schedule-store.ts +0 -21
  257. package/src/security/ces-credential-client.ts +59 -22
  258. package/src/security/ces-rpc-credential-backend.ts +85 -0
  259. package/src/security/credential-backend.ts +12 -88
  260. package/src/security/keychain-broker-client.ts +10 -2
  261. package/src/security/secure-keys.ts +94 -113
  262. package/src/skills/catalog-install.ts +13 -7
  263. package/src/skills/inline-command-render.ts +5 -1
  264. package/src/skills/inline-command-runner.ts +30 -2
  265. package/src/telemetry/usage-telemetry-reporter.ts +4 -2
  266. package/src/tools/calls/call-start.ts +1 -0
  267. package/src/tools/executor.ts +0 -4
  268. package/src/tools/memory/handlers.ts +1 -129
  269. package/src/tools/network/script-proxy/session-manager.ts +19 -4
  270. package/src/tools/network/web-fetch.ts +3 -1
  271. package/src/tools/permission-checker.ts +18 -0
  272. package/src/tools/skills/execute.ts +1 -1
  273. package/src/tools/skills/load.ts +9 -2
  274. package/src/tools/types.ts +0 -8
  275. package/src/util/errors.ts +0 -12
  276. package/src/util/platform.ts +8 -55
  277. package/src/util/xml.ts +8 -0
  278. package/src/workspace/git-service.ts +5 -2
  279. package/src/workspace/heartbeat-service.ts +5 -24
  280. package/src/workspace/migrations/001-avatar-rename.ts +15 -0
  281. package/src/workspace/migrations/003-seed-device-id.ts +17 -1
  282. package/src/workspace/migrations/004-extract-collect-usage-data.ts +33 -0
  283. package/src/workspace/migrations/005-add-send-diagnostics.ts +3 -0
  284. package/src/workspace/migrations/006-services-config.ts +49 -0
  285. package/src/workspace/migrations/007-web-search-provider-rename.ts +27 -0
  286. package/src/workspace/migrations/008-voice-timeout-and-max-steps.ts +3 -0
  287. package/src/workspace/migrations/009-backfill-conversation-disk-view.ts +4 -0
  288. package/src/workspace/migrations/010-app-dir-rename.ts +78 -0
  289. package/src/workspace/migrations/011-backfill-installation-id.ts +11 -0
  290. package/src/workspace/migrations/012-rename-conversation-disk-view-dirs.ts +44 -0
  291. package/src/workspace/migrations/013-repair-conversation-disk-view.ts +5 -0
  292. package/src/workspace/migrations/015-migrate-credentials-to-keychain.ts +153 -0
  293. package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +156 -0
  294. package/src/workspace/migrations/016-migrate-credentials-from-keychain.ts +150 -0
  295. package/src/workspace/migrations/017-seed-persona-dirs.ts +95 -0
  296. package/src/workspace/migrations/migrate-to-workspace-volume.ts +23 -1
  297. package/src/workspace/migrations/registry.ts +8 -0
  298. package/src/workspace/migrations/runner.ts +106 -2
  299. package/src/workspace/migrations/types.ts +4 -0
  300. package/src/__tests__/archive-recall.test.ts +0 -560
  301. package/src/__tests__/claude-code-skill-regression.test.ts +0 -206
  302. package/src/__tests__/claude-code-tool-profiles.test.ts +0 -99
  303. package/src/__tests__/conversation-memory-dirty-tail.test.ts +0 -150
  304. package/src/__tests__/conversation-switch-memory-reduction.test.ts +0 -474
  305. package/src/__tests__/db-memory-archive-migration.test.ts +0 -372
  306. package/src/__tests__/db-memory-brief-state-migration.test.ts +0 -213
  307. package/src/__tests__/db-memory-reducer-checkpoints.test.ts +0 -273
  308. package/src/__tests__/diagnostics-export.test.ts +0 -288
  309. package/src/__tests__/local-gateway-health.test.ts +0 -209
  310. package/src/__tests__/memory-brief-open-loops.test.ts +0 -530
  311. package/src/__tests__/memory-brief-time.test.ts +0 -285
  312. package/src/__tests__/memory-brief-wrapper.test.ts +0 -311
  313. package/src/__tests__/memory-chunk-archive.test.ts +0 -400
  314. package/src/__tests__/memory-chunk-dual-write.test.ts +0 -453
  315. package/src/__tests__/memory-episode-archive.test.ts +0 -370
  316. package/src/__tests__/memory-episode-dual-write.test.ts +0 -626
  317. package/src/__tests__/memory-observation-archive.test.ts +0 -375
  318. package/src/__tests__/memory-observation-dual-write.test.ts +0 -318
  319. package/src/__tests__/memory-reducer-job.test.ts +0 -538
  320. package/src/__tests__/memory-reducer-scheduling.test.ts +0 -473
  321. package/src/__tests__/memory-reducer-store.test.ts +0 -728
  322. package/src/__tests__/memory-reducer-types.test.ts +0 -707
  323. package/src/__tests__/memory-reducer.test.ts +0 -704
  324. package/src/__tests__/memory-simplified-config.test.ts +0 -281
  325. package/src/__tests__/secret-ingress-handler.test.ts +0 -120
  326. package/src/__tests__/simplified-memory-e2e.test.ts +0 -666
  327. package/src/__tests__/simplified-memory-runtime.test.ts +0 -616
  328. package/src/__tests__/swarm-conversation-integration.test.ts +0 -358
  329. package/src/__tests__/swarm-dag-pathological.test.ts +0 -547
  330. package/src/__tests__/swarm-orchestrator.test.ts +0 -463
  331. package/src/__tests__/swarm-plan-validator.test.ts +0 -384
  332. package/src/__tests__/swarm-recursion.test.ts +0 -197
  333. package/src/__tests__/swarm-router-planner.test.ts +0 -234
  334. package/src/__tests__/swarm-tool.test.ts +0 -185
  335. package/src/__tests__/swarm-worker-backend.test.ts +0 -144
  336. package/src/__tests__/swarm-worker-runner.test.ts +0 -288
  337. package/src/commands/__tests__/cc-command-registry.test.ts +0 -396
  338. package/src/commands/cc-command-registry.ts +0 -248
  339. package/src/config/bundled-skills/claude-code/SKILL.md +0 -53
  340. package/src/config/bundled-skills/claude-code/TOOLS.json +0 -47
  341. package/src/config/bundled-skills/claude-code/tools/claude-code.ts +0 -12
  342. package/src/config/bundled-skills/orchestration/SKILL.md +0 -33
  343. package/src/config/bundled-skills/orchestration/TOOLS.json +0 -35
  344. package/src/config/bundled-skills/orchestration/tools/swarm-delegate.ts +0 -12
  345. package/src/config/schemas/memory-simplified.ts +0 -101
  346. package/src/config/schemas/swarm.ts +0 -82
  347. package/src/logfire.ts +0 -135
  348. package/src/memory/archive-recall.ts +0 -516
  349. package/src/memory/archive-store.ts +0 -400
  350. package/src/memory/brief-formatting.ts +0 -33
  351. package/src/memory/brief-open-loops.ts +0 -266
  352. package/src/memory/brief-time.ts +0 -162
  353. package/src/memory/brief.ts +0 -75
  354. package/src/memory/job-handlers/backfill-simplified-memory.ts +0 -462
  355. package/src/memory/job-handlers/reduce-conversation-memory.ts +0 -229
  356. package/src/memory/migrations/185-memory-brief-state.ts +0 -52
  357. package/src/memory/migrations/186-memory-archive.ts +0 -109
  358. package/src/memory/migrations/187-memory-reducer-checkpoints.ts +0 -19
  359. package/src/memory/reducer-scheduler.ts +0 -242
  360. package/src/memory/reducer-store.ts +0 -271
  361. package/src/memory/reducer-types.ts +0 -106
  362. package/src/memory/reducer.ts +0 -467
  363. package/src/memory/schema/memory-archive.ts +0 -121
  364. package/src/memory/schema/memory-brief.ts +0 -55
  365. package/src/runtime/local-gateway-health.ts +0 -275
  366. package/src/security/secret-ingress.ts +0 -68
  367. package/src/swarm/backend-claude-code.ts +0 -225
  368. package/src/swarm/checkpoint.ts +0 -137
  369. package/src/swarm/graph-utils.ts +0 -53
  370. package/src/swarm/index.ts +0 -55
  371. package/src/swarm/limits.ts +0 -66
  372. package/src/swarm/orchestrator.ts +0 -424
  373. package/src/swarm/plan-validator.ts +0 -117
  374. package/src/swarm/router-planner.ts +0 -162
  375. package/src/swarm/router-prompts.ts +0 -39
  376. package/src/swarm/synthesizer.ts +0 -81
  377. package/src/swarm/types.ts +0 -72
  378. package/src/swarm/worker-backend.ts +0 -131
  379. package/src/swarm/worker-prompts.ts +0 -80
  380. package/src/swarm/worker-runner.ts +0 -170
  381. package/src/tools/claude-code/claude-code.ts +0 -610
  382. package/src/tools/swarm/delegate.ts +0 -205
@@ -1,4 +1,5 @@
1
- import { type DrizzleDb, getSqliteFrom } from "../db-connection.js";
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+ import { getSqliteFrom } from "../db-connection.js";
2
3
  import { withCrashRecovery } from "./validate-migration-state.js";
3
4
 
4
5
  /**
@@ -62,3 +63,52 @@ export function migrateRenameGmailProviderKeyToGoogle(
62
63
  },
63
64
  );
64
65
  }
66
+
67
+ /**
68
+ * Reverse: rename "integration:google" back to "integration:gmail" across
69
+ * OAuth tables.
70
+ *
71
+ * Mirrors the forward migration logic but in the opposite direction. If
72
+ * `integration:gmail` already exists (shouldn't normally happen on rollback),
73
+ * deletes the google rows to avoid duplicates.
74
+ */
75
+ export function migrateRenameGmailProviderKeyToGoogleDown(
76
+ database: DrizzleDb,
77
+ ): void {
78
+ const raw = getSqliteFrom(database);
79
+
80
+ raw.exec("PRAGMA foreign_keys = OFF");
81
+ try {
82
+ const gmailExists = raw
83
+ .prepare(
84
+ /*sql*/ `SELECT 1 FROM oauth_providers WHERE provider_key = 'integration:gmail'`,
85
+ )
86
+ .get();
87
+
88
+ if (gmailExists) {
89
+ // Old gmail rows already exist — delete the google ones to avoid duplication.
90
+ raw.exec(
91
+ /*sql*/ `DELETE FROM oauth_connections WHERE provider_key = 'integration:google'`,
92
+ );
93
+ raw.exec(
94
+ /*sql*/ `DELETE FROM oauth_apps WHERE provider_key = 'integration:google'`,
95
+ );
96
+ raw.exec(
97
+ /*sql*/ `DELETE FROM oauth_providers WHERE provider_key = 'integration:google'`,
98
+ );
99
+ } else {
100
+ // Rename google back to gmail — children first, then parent.
101
+ raw.exec(
102
+ /*sql*/ `UPDATE oauth_connections SET provider_key = 'integration:gmail' WHERE provider_key = 'integration:google'`,
103
+ );
104
+ raw.exec(
105
+ /*sql*/ `UPDATE oauth_apps SET provider_key = 'integration:gmail' WHERE provider_key = 'integration:google'`,
106
+ );
107
+ raw.exec(
108
+ /*sql*/ `UPDATE oauth_providers SET provider_key = 'integration:gmail' WHERE provider_key = 'integration:google'`,
109
+ );
110
+ }
111
+ } finally {
112
+ raw.exec("PRAGMA foreign_keys = ON");
113
+ }
114
+ }
@@ -1,4 +1,5 @@
1
- import { type DrizzleDb, getSqliteFrom } from "../db-connection.js";
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+ import { getSqliteFrom } from "../db-connection.js";
2
3
  import { withCrashRecovery } from "./validate-migration-state.js";
3
4
 
4
5
  /**
@@ -51,3 +52,48 @@ export function migrateRenameThreadStartersTable(database: DrizzleDb): void {
51
52
  },
52
53
  );
53
54
  }
55
+
56
+ /**
57
+ * Reverse: rename conversation_starters back to thread_starters and recreate
58
+ * old index names.
59
+ *
60
+ * Idempotent — skips if the old table already exists or the new table is
61
+ * absent.
62
+ */
63
+ export function migrateRenameThreadStartersTableDown(
64
+ database: DrizzleDb,
65
+ ): void {
66
+ const raw = getSqliteFrom(database);
67
+
68
+ // Guard: new table must exist
69
+ const newTableExists = raw
70
+ .query(
71
+ `SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'conversation_starters'`,
72
+ )
73
+ .get();
74
+ if (!newTableExists) return;
75
+
76
+ // Guard: old table must not already exist
77
+ const oldTableExists = raw
78
+ .query(
79
+ `SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'thread_starters'`,
80
+ )
81
+ .get();
82
+ if (oldTableExists) return;
83
+
84
+ // Rename the table back
85
+ raw.exec(
86
+ /*sql*/ `ALTER TABLE conversation_starters RENAME TO thread_starters`,
87
+ );
88
+
89
+ // Drop new indexes and recreate with old names
90
+ raw.exec(/*sql*/ `DROP INDEX IF EXISTS idx_conversation_starters_batch`);
91
+ raw.exec(
92
+ /*sql*/ `CREATE INDEX IF NOT EXISTS idx_thread_starters_batch ON thread_starters(generation_batch, created_at)`,
93
+ );
94
+
95
+ raw.exec(/*sql*/ `DROP INDEX IF EXISTS idx_conversation_starters_card_type`);
96
+ raw.exec(
97
+ /*sql*/ `CREATE INDEX IF NOT EXISTS idx_thread_starters_card_type ON thread_starters(card_type, scope_id)`,
98
+ );
99
+ }
@@ -34,3 +34,16 @@ export function migrateDropCapabilityCardState(database: DrizzleDb): void {
34
34
  raw.exec(/*sql*/ `DROP TABLE IF EXISTS capability_card_categories`);
35
35
  });
36
36
  }
37
+
38
+ /**
39
+ * Reverse: no-op.
40
+ *
41
+ * The forward migration deleted rows (card-type conversation starters,
42
+ * generate_capability_cards jobs, capability_cards checkpoints) and dropped
43
+ * the capability_card_categories table. The deleted data cannot be restored
44
+ * — it was discarded as dead state after the capability card feature was
45
+ * removed.
46
+ */
47
+ export function migrateDropCapabilityCardStateDown(_database: DrizzleDb): void {
48
+ // No-op — see comment above.
49
+ }
@@ -64,3 +64,19 @@ export function migrateBackfillInlineAttachmentsToDisk(
64
64
  },
65
65
  );
66
66
  }
67
+
68
+ /**
69
+ * Reverse: no-op.
70
+ *
71
+ * The forward migration moved attachment data from inline base64 in the
72
+ * database to on-disk files and cleared the dataBase64 column. The original
73
+ * base64 data has been deleted from the DB, and re-reading it from disk
74
+ * back into the database would be unreliable (file paths may have changed,
75
+ * disk files may have been cleaned up). The on-disk files remain intact
76
+ * and functional.
77
+ */
78
+ export function migrateBackfillInlineAttachmentsToDiskDown(
79
+ _database: DrizzleDb,
80
+ ): void {
81
+ // No-op — see comment above.
82
+ }
@@ -1,4 +1,5 @@
1
- import { type DrizzleDb, getSqliteFrom } from "../db-connection.js";
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+ import { getSqliteFrom } from "../db-connection.js";
2
3
  import { withCrashRecovery } from "./validate-migration-state.js";
3
4
 
4
5
  /**
@@ -44,3 +45,29 @@ export function migrateRenameThreadStartersCheckpoints(
44
45
  },
45
46
  );
46
47
  }
48
+
49
+ /**
50
+ * Reverse: rename checkpoint keys from "conversation_starters:" back to
51
+ * "thread_starters:" prefix.
52
+ *
53
+ * Mirrors the forward migration but in reverse. Handles collisions the same
54
+ * way — if an old-prefix key already exists, the new-prefix key is dropped.
55
+ */
56
+ export function migrateRenameThreadStartersCheckpointsDown(
57
+ database: DrizzleDb,
58
+ ): void {
59
+ const raw = getSqliteFrom(database);
60
+
61
+ // 1. Delete conversation_starters: keys where a corresponding
62
+ // thread_starters: key already exists.
63
+ raw.exec(/*sql*/ `DELETE FROM memory_checkpoints
64
+ WHERE key LIKE 'conversation_starters:%'
65
+ AND replace(key, 'conversation_starters:', 'thread_starters:') IN (
66
+ SELECT key FROM memory_checkpoints WHERE key LIKE 'thread_starters:%'
67
+ )`);
68
+
69
+ // 2. Rename remaining keys back to the old prefix.
70
+ raw.exec(
71
+ /*sql*/ `UPDATE memory_checkpoints SET key = replace(key, 'conversation_starters:', 'thread_starters:') WHERE key LIKE 'conversation_starters:%'`,
72
+ );
73
+ }
@@ -0,0 +1,42 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+ import { getSqliteFrom } from "../db-connection.js";
3
+
4
+ /**
5
+ * Drop simplified-memory tables and reducer checkpoint columns added by
6
+ * the simplified-memory-v1 plan, reverting to the legacy item/tier/XML
7
+ * memory system.
8
+ */
9
+ export function migrateDropSimplifiedMemory(database: DrizzleDb): void {
10
+ const raw = getSqliteFrom(database);
11
+
12
+ // Drop simplified-memory tables (idempotent — IF EXISTS).
13
+ raw.exec(`DROP TABLE IF EXISTS time_contexts`);
14
+ raw.exec(`DROP TABLE IF EXISTS open_loops`);
15
+ raw.exec(`DROP TABLE IF EXISTS memory_observations`);
16
+ raw.exec(`DROP TABLE IF EXISTS memory_chunks`);
17
+ raw.exec(`DROP TABLE IF EXISTS memory_episodes`);
18
+
19
+ // Remove reducer checkpoint columns from conversations.
20
+ // SQLite doesn't support DROP COLUMN before 3.35.0, but Bun's built-in
21
+ // SQLite is >= 3.38, so this is safe.
22
+ for (const col of [
23
+ "memory_reduced_through_message_id",
24
+ "memory_dirty_tail_since_message_id",
25
+ "memory_last_reduced_at",
26
+ ]) {
27
+ try {
28
+ raw.exec(`ALTER TABLE conversations DROP COLUMN ${col}`);
29
+ } catch {
30
+ // Column doesn't exist — already cleaned up.
31
+ }
32
+ }
33
+
34
+ // Remove embedding rows for archive target types that no longer exist.
35
+ try {
36
+ raw.exec(
37
+ `DELETE FROM memory_embeddings WHERE target_type IN ('observation', 'chunk', 'episode')`,
38
+ );
39
+ } catch {
40
+ // Column doesn't exist — table was never migrated to include target_type.
41
+ }
42
+ }
@@ -0,0 +1,15 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+
3
+ /**
4
+ * Add skip_disclosure column to call_sessions so outbound calls can
5
+ * skip the disclosure announcement on a per-call basis.
6
+ */
7
+ export function migrateCallSessionSkipDisclosure(database: DrizzleDb): void {
8
+ try {
9
+ database.run(
10
+ /*sql*/ `ALTER TABLE call_sessions ADD COLUMN skip_disclosure INTEGER NOT NULL DEFAULT 0`,
11
+ );
12
+ } catch {
13
+ /* already exists */
14
+ }
15
+ }
@@ -0,0 +1,64 @@
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
+ /**
6
+ * Backfill MIME types for audio attachments that were stored with
7
+ * "application/octet-stream" because the EXTENSION_MIME_MAP was
8
+ * missing audio format entries.
9
+ *
10
+ * Updates mime_type based on the file extension in original_filename.
11
+ */
12
+
13
+ const AUDIO_EXT_MIME: Record<string, string> = {
14
+ mp3: "audio/mpeg",
15
+ wav: "audio/wav",
16
+ ogg: "audio/ogg",
17
+ flac: "audio/flac",
18
+ aac: "audio/aac",
19
+ m4a: "audio/x-m4a",
20
+ opus: "audio/opus",
21
+ };
22
+
23
+ export function migrateBackfillAudioAttachmentMimeTypes(
24
+ database: DrizzleDb,
25
+ ): void {
26
+ withCrashRecovery(
27
+ database,
28
+ "migration_backfill_audio_attachment_mime_types_v1",
29
+ () => {
30
+ const raw = getSqliteFrom(database);
31
+
32
+ for (const [ext, mime] of Object.entries(AUDIO_EXT_MIME)) {
33
+ const pattern = `%.${ext}`;
34
+ const result = raw
35
+ .query(
36
+ `UPDATE attachments
37
+ SET mime_type = ?, kind = 'document'
38
+ WHERE lower(original_filename) LIKE ?
39
+ AND mime_type = 'application/octet-stream'`,
40
+ )
41
+ .run(mime, pattern);
42
+
43
+ if ((result as { changes?: number }).changes) {
44
+ console.log(
45
+ `Backfilled ${(result as { changes: number }).changes} .${ext} attachments → ${mime}`,
46
+ );
47
+ }
48
+ }
49
+ },
50
+ );
51
+ }
52
+
53
+ /**
54
+ * Reverse: no-op.
55
+ *
56
+ * The forward migration corrected incorrect MIME types (application/octet-stream)
57
+ * to their proper audio/* values. Restoring the wrong MIME types would break
58
+ * audio playback and file handling. The corrected values are the desired state.
59
+ */
60
+ export function migrateBackfillAudioAttachmentMimeTypesDown(
61
+ _database: DrizzleDb,
62
+ ): void {
63
+ // No-op — see comment above.
64
+ }
@@ -0,0 +1,15 @@
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
+ export function migrateContactsUserFileColumn(database: DrizzleDb): void {
6
+ withCrashRecovery(database, "migration_contacts_user_file_column_v1", () => {
7
+ const raw = getSqliteFrom(database);
8
+
9
+ try {
10
+ raw.exec(/*sql*/ `ALTER TABLE contacts ADD COLUMN user_file TEXT`);
11
+ } catch {
12
+ /* already exists */
13
+ }
14
+ });
15
+ }
@@ -126,10 +126,11 @@ export { migrateRenameThreadStartersCheckpoints } from "./181-rename-thread-star
126
126
  export { migrateOAuthProvidersDisplayMetadata } from "./182-oauth-providers-display-metadata.js";
127
127
  export { migrateConversationForkLineage } from "./183-add-conversation-fork-lineage.js";
128
128
  export { migrateLlmRequestLogProvider } from "./184-llm-request-log-provider.js";
129
- export { migrateMemoryBriefState } from "./185-memory-brief-state.js";
130
- export { migrateMemoryArchiveTables } from "./186-memory-archive.js";
131
- export { migrateMemoryReducerCheckpoints } from "./187-memory-reducer-checkpoints.js";
132
129
  export { migrateScheduleQuietFlag } from "./188-schedule-quiet-flag.js";
130
+ export { migrateDropSimplifiedMemory } from "./189-drop-simplified-memory.js";
131
+ export { migrateCallSessionSkipDisclosure } from "./190-call-session-skip-disclosure.js";
132
+ export { migrateBackfillAudioAttachmentMimeTypes } from "./191-backfill-audio-attachment-mime-types.js";
133
+ export { migrateContactsUserFileColumn } from "./192-contacts-user-file-column.js";
133
134
  export {
134
135
  MIGRATION_REGISTRY,
135
136
  type MigrationRegistryEntry,
@@ -137,6 +138,7 @@ export {
137
138
  } from "./registry.js";
138
139
  export {
139
140
  recoverCrashedMigrations,
141
+ rollbackMemoryMigration,
140
142
  validateMigrationState,
141
143
  withCrashRecovery,
142
144
  } from "./validate-migration-state.js";
@@ -1,3 +1,43 @@
1
+ import type { DrizzleDb } from "../db-connection.js";
2
+ import { downJobDeferrals } from "./001-job-deferrals.js";
3
+ import { downMemoryEntityRelationDedup } from "./004-entity-relation-dedup.js";
4
+ import { downMemoryItemsFingerprintScopeUnique } from "./005-fingerprint-scope-unique.js";
5
+ import { downMemoryItemsScopeSaltedFingerprints } from "./006-scope-salted-fingerprints.js";
6
+ import { downAssistantIdToSelf } from "./007-assistant-id-to-self.js";
7
+ import { downRemoveAssistantIdColumns } from "./008-remove-assistant-id-columns.js";
8
+ import { downLlmUsageEventsDropAssistantId } from "./009-llm-usage-events-drop-assistant-id.js";
9
+ import { downBackfillInboxThreadState } from "./014-backfill-inbox-thread-state.js";
10
+ import { downDropActiveSearchIndex } from "./015-drop-active-search-index.js";
11
+ import { downNotificationTablesSchema } from "./019-notification-tables-schema-migration.js";
12
+ import { downRenameChannelToVellum } from "./020-rename-macos-ios-channel-to-vellum.js";
13
+ import { downEmbeddingVectorBlob } from "./024-embedding-vector-blob.js";
14
+ import { downEmbeddingsNullableVectorJson } from "./026a-embeddings-nullable-vector-json.js";
15
+ import { downNormalizePhoneIdentities } from "./036-normalize-phone-identities.js";
16
+ import { downBackfillGuardianPrincipalId } from "./126-backfill-guardian-principal-id.js";
17
+ import { downGuardianPrincipalIdNotNull } from "./127-guardian-principal-id-not-null.js";
18
+ import { downContactsNotesColumn } from "./134-contacts-notes-column.js";
19
+ import { downBackfillContactInteractionStats } from "./135-backfill-contact-interaction-stats.js";
20
+ import { downDropAssistantIdColumns } from "./136-drop-assistant-id-columns.js";
21
+ import { downBackfillUsageCacheAccounting } from "./140-backfill-usage-cache-accounting.js";
22
+ import { downRenameVerificationTable } from "./141-rename-verification-table.js";
23
+ import { downRenameVerificationSessionIdColumn } from "./142-rename-verification-session-id-column.js";
24
+ import { downRenameGuardianVerificationValues } from "./143-rename-guardian-verification-values.js";
25
+ import { downRenameVoiceToPhone } from "./144-rename-voice-to-phone.js";
26
+ import { migrateDropAccountsTableDown } from "./145-drop-accounts-table.js";
27
+ import { migrateRemindersToSchedulesDown } from "./147-migrate-reminders-to-schedules.js";
28
+ import { migrateDropRemindersTableDown } from "./148-drop-reminders-table.js";
29
+ import { migrateOAuthAppsClientSecretPathDown } from "./150-oauth-apps-client-secret-path.js";
30
+ import {
31
+ migrateGuardianTimestampsEpochMsDown,
32
+ migrateGuardianTimestampsRebuildDown,
33
+ } from "./162-guardian-timestamps-epoch-ms.js";
34
+ import { migrateRenameGmailProviderKeyToGoogleDown } from "./169-rename-gmail-provider-key-to-google.js";
35
+ import { migrateRenameThreadStartersTableDown } from "./174-rename-thread-starters-table.js";
36
+ import { migrateDropCapabilityCardStateDown } from "./176-drop-capability-card-state.js";
37
+ import { migrateBackfillInlineAttachmentsToDiskDown } from "./180-backfill-inline-attachments-to-disk.js";
38
+ import { migrateRenameThreadStartersCheckpointsDown } from "./181-rename-thread-starters-checkpoints.js";
39
+ import { migrateBackfillAudioAttachmentMimeTypesDown } from "./191-backfill-audio-attachment-mime-types.js";
40
+
1
41
  export interface MigrationRegistryEntry {
2
42
  /** The checkpoint key written to memory_checkpoints on completion. */
3
43
  key: string;
@@ -7,6 +47,8 @@ export interface MigrationRegistryEntry {
7
47
  dependsOn?: string[];
8
48
  /** Human-readable description for diagnostics and future authorship guidance. */
9
49
  description: string;
50
+ /** Reverse the migration. Must be idempotent — safe to re-run. */
51
+ down: (database: DrizzleDb) => void;
10
52
  }
11
53
 
12
54
  // ---------------------------------------------------------------------------
@@ -26,18 +68,21 @@ export const MIGRATION_REGISTRY: MigrationRegistryEntry[] = [
26
68
  version: 1,
27
69
  description:
28
70
  "Reconcile legacy deferral history from attempts column into deferrals column",
71
+ down: downJobDeferrals,
29
72
  },
30
73
  {
31
74
  key: "migration_memory_entity_relations_dedup_v1",
32
75
  version: 2,
33
76
  description:
34
77
  "Deduplicate entity relation edges before enforcing the (source, target, relation) unique index",
78
+ down: downMemoryEntityRelationDedup,
35
79
  },
36
80
  {
37
81
  key: "migration_memory_items_fingerprint_scope_unique_v1",
38
82
  version: 3,
39
83
  description:
40
84
  "Replace column-level UNIQUE on fingerprint with compound (fingerprint, scope_id) unique index",
85
+ down: downMemoryItemsFingerprintScopeUnique,
41
86
  },
42
87
  {
43
88
  key: "migration_memory_items_scope_salted_fingerprints_v1",
@@ -45,12 +90,14 @@ export const MIGRATION_REGISTRY: MigrationRegistryEntry[] = [
45
90
  dependsOn: ["migration_memory_items_fingerprint_scope_unique_v1"],
46
91
  description:
47
92
  "Recompute memory item fingerprints to include scope_id prefix after schema change",
93
+ down: downMemoryItemsScopeSaltedFingerprints,
48
94
  },
49
95
  {
50
96
  key: "migration_normalize_assistant_id_to_self_v1",
51
97
  version: 5,
52
98
  description:
53
99
  'Normalize all assistant_id values in scoped tables to the implicit "self" single-tenant identity',
100
+ down: downAssistantIdToSelf,
54
101
  },
55
102
  {
56
103
  key: "migration_remove_assistant_id_columns_v1",
@@ -58,6 +105,7 @@ export const MIGRATION_REGISTRY: MigrationRegistryEntry[] = [
58
105
  dependsOn: ["migration_normalize_assistant_id_to_self_v1"],
59
106
  description:
60
107
  "Rebuild four tables to drop the assistant_id column after normalization",
108
+ down: downRemoveAssistantIdColumns,
61
109
  },
62
110
  {
63
111
  key: "migration_remove_assistant_id_lue_v1",
@@ -65,36 +113,42 @@ export const MIGRATION_REGISTRY: MigrationRegistryEntry[] = [
65
113
  dependsOn: ["migration_normalize_assistant_id_to_self_v1"],
66
114
  description:
67
115
  "Remove assistant_id column from llm_usage_events (separate checkpoint from the four-table migration)",
116
+ down: downLlmUsageEventsDropAssistantId,
68
117
  },
69
118
  {
70
119
  key: "backfill_inbox_thread_state_from_bindings",
71
120
  version: 8,
72
121
  description:
73
122
  "Seed assistant_inbox_thread_state from external_conversation_bindings",
123
+ down: downBackfillInboxThreadState,
74
124
  },
75
125
  {
76
126
  key: "drop_active_search_index_v1",
77
127
  version: 9,
78
128
  description:
79
129
  "Drop old idx_memory_items_active_search so it can be recreated with updated covering columns",
130
+ down: downDropActiveSearchIndex,
80
131
  },
81
132
  {
82
133
  key: "migration_notification_tables_schema_v1",
83
134
  version: 10,
84
135
  description:
85
136
  "Drop legacy enum-based notification tables so they can be recreated with the new signal-contract schema",
137
+ down: downNotificationTablesSchema,
86
138
  },
87
139
  {
88
140
  key: "migration_rename_macos_ios_channel_to_vellum_v1",
89
141
  version: 11,
90
142
  description:
91
143
  "Rename macos and ios channel identifiers to vellum across all tables",
144
+ down: downRenameChannelToVellum,
92
145
  },
93
146
  {
94
147
  key: "migration_embedding_vector_blob_v1",
95
148
  version: 12,
96
149
  description:
97
150
  "Add vector_blob BLOB column to memory_embeddings and backfill from vector_json for compact binary storage",
151
+ down: downEmbeddingVectorBlob,
98
152
  },
99
153
  {
100
154
  key: "migration_embeddings_nullable_vector_json_v1",
@@ -102,18 +156,21 @@ export const MIGRATION_REGISTRY: MigrationRegistryEntry[] = [
102
156
  dependsOn: ["migration_embedding_vector_blob_v1"],
103
157
  description:
104
158
  "Rebuild memory_embeddings to make vector_json nullable (pre-100 DBs had NOT NULL)",
159
+ down: downEmbeddingsNullableVectorJson,
105
160
  },
106
161
  {
107
162
  key: "migration_normalize_phone_identities_v1",
108
163
  version: 14,
109
164
  description:
110
165
  "Normalize phone-like identity fields to E.164 format across guardian bindings, verification challenges, canonical requests, ingress members, and rate limits",
166
+ down: downNormalizePhoneIdentities,
111
167
  },
112
168
  {
113
169
  key: "migration_backfill_guardian_principal_id_v3",
114
170
  version: 15,
115
171
  description:
116
172
  "Backfill guardianPrincipalId for existing channel_guardian_bindings and canonical_guardian_requests rows, expire unresolvable pending requests",
173
+ down: downBackfillGuardianPrincipalId,
117
174
  },
118
175
  {
119
176
  key: "migration_guardian_principal_id_not_null_v1",
@@ -121,18 +178,21 @@ export const MIGRATION_REGISTRY: MigrationRegistryEntry[] = [
121
178
  dependsOn: ["migration_backfill_guardian_principal_id_v3"],
122
179
  description:
123
180
  "Enforce NOT NULL on channel_guardian_bindings.guardian_principal_id after backfill",
181
+ down: downGuardianPrincipalIdNotNull,
124
182
  },
125
183
  {
126
184
  key: "migration_contacts_notes_column_v1",
127
185
  version: 17,
128
186
  description:
129
187
  "Consolidate relationship/importance/response_expectation/preferred_tone into a single notes TEXT column, then drop the legacy columns",
188
+ down: downContactsNotesColumn,
130
189
  },
131
190
  {
132
191
  key: "backfill_contact_interaction_stats",
133
192
  version: 18,
134
193
  description:
135
194
  "Backfill contacts.last_interaction from the max lastSeenAt across each contact's channels",
195
+ down: downBackfillContactInteractionStats,
136
196
  },
137
197
  {
138
198
  key: "migration_drop_assistant_id_columns_v1",
@@ -140,48 +200,56 @@ export const MIGRATION_REGISTRY: MigrationRegistryEntry[] = [
140
200
  dependsOn: ["migration_normalize_assistant_id_to_self_v1"],
141
201
  description:
142
202
  "Drop assistant_id columns from all 16 daemon tables after normalization to single-tenant identity",
203
+ down: downDropAssistantIdColumns,
143
204
  },
144
205
  {
145
206
  key: "migration_backfill_usage_cache_accounting_v1",
146
207
  version: 20,
147
208
  description:
148
209
  "Backfill historical Anthropic llm_usage_events rows from llm_request_logs with cache-aware pricing",
210
+ down: downBackfillUsageCacheAccounting,
149
211
  },
150
212
  {
151
213
  key: "migration_rename_verification_table_v1",
152
214
  version: 21,
153
215
  description:
154
216
  "Rename channel_guardian_verification_challenges table to channel_verification_sessions and update indexes",
217
+ down: downRenameVerificationTable,
155
218
  },
156
219
  {
157
220
  key: "migration_rename_verification_session_id_column_v1",
158
221
  version: 22,
159
222
  description:
160
223
  "Rename guardian_verification_session_id column in call_sessions to verification_session_id",
224
+ down: downRenameVerificationSessionIdColumn,
161
225
  },
162
226
  {
163
227
  key: "migration_rename_guardian_verification_values_v1",
164
228
  version: 23,
165
229
  description:
166
230
  "Rename persisted guardian_verification call_mode and guardian_voice_verification_* event_type values to drop the guardian_ prefix",
231
+ down: downRenameGuardianVerificationValues,
167
232
  },
168
233
  {
169
234
  key: "migration_rename_voice_to_phone_v1",
170
235
  version: 24,
171
236
  description:
172
237
  'Rename stored "voice" channel values to "phone" across all tables with channel text columns',
238
+ down: downRenameVoiceToPhone,
173
239
  },
174
240
  {
175
241
  key: "migration_drop_accounts_table_v1",
176
242
  version: 25,
177
243
  description:
178
244
  "Drop the unused legacy accounts table and its leftover indexes after account_manage removal",
245
+ down: migrateDropAccountsTableDown,
179
246
  },
180
247
  {
181
248
  key: "migration_reminders_to_schedules_v1",
182
249
  version: 26,
183
250
  description:
184
251
  "Copy all existing reminders into cron_jobs as one-shot schedules with correct status and field mapping",
252
+ down: migrateRemindersToSchedulesDown,
185
253
  },
186
254
  {
187
255
  key: "migration_drop_reminders_table_v1",
@@ -189,18 +257,21 @@ export const MIGRATION_REGISTRY: MigrationRegistryEntry[] = [
189
257
  dependsOn: ["migration_reminders_to_schedules_v1"],
190
258
  description:
191
259
  "Drop the legacy reminders table and its index after data migration to cron_jobs",
260
+ down: migrateDropRemindersTableDown,
192
261
  },
193
262
  {
194
263
  key: "migration_oauth_apps_client_secret_path_v1",
195
264
  version: 28,
196
265
  description:
197
266
  "Add client_secret_credential_path column to oauth_apps and backfill existing rows with convention-based paths",
267
+ down: migrateOAuthAppsClientSecretPathDown,
198
268
  },
199
269
  {
200
270
  key: "migration_guardian_timestamps_epoch_ms_v1",
201
271
  version: 29,
202
272
  description:
203
273
  "Convert guardian table timestamps from ISO 8601 text to epoch ms integers for consistency with all other tables",
274
+ down: migrateGuardianTimestampsEpochMsDown,
204
275
  },
205
276
  {
206
277
  key: "migration_guardian_timestamps_rebuild_v1",
@@ -208,18 +279,21 @@ export const MIGRATION_REGISTRY: MigrationRegistryEntry[] = [
208
279
  dependsOn: ["migration_guardian_timestamps_epoch_ms_v1"],
209
280
  description:
210
281
  "Rebuild guardian tables so timestamp columns have INTEGER affinity instead of TEXT",
282
+ down: migrateGuardianTimestampsRebuildDown,
211
283
  },
212
284
  {
213
285
  key: "migration_rename_gmail_provider_key_to_google_v1",
214
286
  version: 31,
215
287
  description:
216
288
  "Rename integration:gmail provider key to integration:google across oauth_providers, oauth_apps, and oauth_connections",
289
+ down: migrateRenameGmailProviderKeyToGoogleDown,
217
290
  },
218
291
  {
219
292
  key: "migration_rename_thread_starters_table_v1",
220
293
  version: 32,
221
294
  description:
222
295
  "Rename thread_starters table to conversation_starters and recreate indexes with new names",
296
+ down: migrateRenameThreadStartersTableDown,
223
297
  },
224
298
  {
225
299
  key: "migration_drop_capability_card_state_v1",
@@ -227,12 +301,14 @@ export const MIGRATION_REGISTRY: MigrationRegistryEntry[] = [
227
301
  dependsOn: ["migration_rename_thread_starters_table_v1"],
228
302
  description:
229
303
  "Remove deleted capability-card rows, jobs, checkpoints, and category state",
304
+ down: migrateDropCapabilityCardStateDown,
230
305
  },
231
306
  {
232
307
  key: "migration_backfill_inline_attachments_v1",
233
308
  version: 34,
234
309
  description:
235
310
  "Backfill existing inline base64 attachments to on-disk storage and clear dataBase64",
311
+ down: migrateBackfillInlineAttachmentsToDiskDown,
236
312
  },
237
313
  {
238
314
  key: "migration_rename_thread_starters_checkpoints_v1",
@@ -240,12 +316,26 @@ export const MIGRATION_REGISTRY: MigrationRegistryEntry[] = [
240
316
  dependsOn: ["migration_rename_thread_starters_table_v1"],
241
317
  description:
242
318
  "Rename checkpoint keys from thread_starters: to conversation_starters: prefix so renamed code paths find existing generation state",
319
+ down: migrateRenameThreadStartersCheckpointsDown,
320
+ },
321
+ {
322
+ key: "migration_backfill_audio_attachment_mime_types_v1",
323
+ version: 36,
324
+ description:
325
+ "Backfill correct MIME types for audio attachments stored as application/octet-stream due to missing extension map entries",
326
+ down: migrateBackfillAudioAttachmentMimeTypesDown,
243
327
  },
244
328
  ];
245
329
 
330
+ export function getMaxMigrationVersion(): number {
331
+ return Math.max(...MIGRATION_REGISTRY.map((e) => e.version));
332
+ }
333
+
246
334
  export interface MigrationValidationResult {
247
335
  /** Keys of migrations whose checkpoint has value 'started' — started but never completed. */
248
336
  crashed: string[];
249
337
  /** Pairs where a completed migration's declared prerequisite is missing from checkpoints. */
250
338
  dependencyViolations: Array<{ migration: string; missingDependency: string }>;
339
+ /** Checkpoint keys present in the database but absent from the migration registry — likely from a newer version. */
340
+ unknownCheckpoints: string[];
251
341
  }