@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,6 +1,41 @@
1
1
  import { type DrizzleDb, getSqliteFrom } from "../db-connection.js";
2
2
  import { withCrashRecovery } from "./validate-migration-state.js";
3
3
 
4
+ /**
5
+ * Reverse v23: add the "guardian_" prefix back to verification-related
6
+ * call_mode and event_type values.
7
+ */
8
+ export function downRenameGuardianVerificationValues(
9
+ database: DrizzleDb,
10
+ ): void {
11
+ const raw = getSqliteFrom(database);
12
+
13
+ // Rename call_mode values back
14
+ raw.exec(
15
+ /*sql*/ `UPDATE call_sessions SET call_mode = 'guardian_verification' WHERE call_mode = 'verification'`,
16
+ );
17
+
18
+ // Rename event_type values back
19
+ raw.exec(
20
+ /*sql*/ `UPDATE call_events SET event_type = 'guardian_voice_verification_started' WHERE event_type = 'voice_verification_started'`,
21
+ );
22
+ raw.exec(
23
+ /*sql*/ `UPDATE call_events SET event_type = 'guardian_voice_verification_succeeded' WHERE event_type = 'voice_verification_succeeded'`,
24
+ );
25
+ raw.exec(
26
+ /*sql*/ `UPDATE call_events SET event_type = 'guardian_voice_verification_failed' WHERE event_type = 'voice_verification_failed'`,
27
+ );
28
+ raw.exec(
29
+ /*sql*/ `UPDATE call_events SET event_type = 'outbound_guardian_voice_verification_started' WHERE event_type = 'outbound_voice_verification_started'`,
30
+ );
31
+ raw.exec(
32
+ /*sql*/ `UPDATE call_events SET event_type = 'outbound_guardian_voice_verification_succeeded' WHERE event_type = 'outbound_voice_verification_succeeded'`,
33
+ );
34
+ raw.exec(
35
+ /*sql*/ `UPDATE call_events SET event_type = 'outbound_guardian_voice_verification_failed' WHERE event_type = 'outbound_voice_verification_failed'`,
36
+ );
37
+ }
38
+
4
39
  /**
5
40
  * One-shot migration: rename persisted `guardian_verification` and
6
41
  * `guardian_voice_verification_*` / `outbound_guardian_voice_verification_*`
@@ -1,6 +1,142 @@
1
1
  import { type DrizzleDb, getSqliteFrom } from "../db-connection.js";
2
2
  import { withCrashRecovery } from "./validate-migration-state.js";
3
3
 
4
+ /**
5
+ * Reverse v24: rename "phone" channel values back to "voice" across all
6
+ * tables with channel text columns.
7
+ */
8
+ export function downRenameVoiceToPhone(database: DrizzleDb): void {
9
+ const raw = getSqliteFrom(database);
10
+
11
+ // contact_channels.type
12
+ raw.exec(
13
+ /*sql*/ `UPDATE contact_channels SET type = 'voice' WHERE type = 'phone'`,
14
+ );
15
+
16
+ // conversations.origin_channel
17
+ raw.exec(
18
+ /*sql*/ `UPDATE conversations SET origin_channel = 'voice' WHERE origin_channel = 'phone'`,
19
+ );
20
+
21
+ // conversations.origin_interface
22
+ raw.exec(
23
+ /*sql*/ `UPDATE conversations SET origin_interface = 'voice' WHERE origin_interface = 'phone'`,
24
+ );
25
+
26
+ // messages.metadata — reverse the JSON string replacement
27
+ raw.exec(
28
+ /*sql*/ `UPDATE messages SET metadata = REPLACE(metadata, '"phone"', '"voice"') WHERE metadata LIKE '%"phone"%'`,
29
+ );
30
+
31
+ // assistant_ingress_invites.source_channel
32
+ raw.exec(
33
+ /*sql*/ `UPDATE assistant_ingress_invites SET source_channel = 'voice' WHERE source_channel = 'phone'`,
34
+ );
35
+
36
+ // assistant_inbox_thread_state.source_channel
37
+ raw.exec(
38
+ /*sql*/ `UPDATE assistant_inbox_thread_state SET source_channel = 'voice' WHERE source_channel = 'phone'`,
39
+ );
40
+
41
+ // guardian_action_requests.source_channel
42
+ raw.exec(
43
+ /*sql*/ `UPDATE guardian_action_requests SET source_channel = 'voice' WHERE source_channel = 'phone'`,
44
+ );
45
+
46
+ // guardian_action_requests.answered_by_channel
47
+ raw.exec(
48
+ /*sql*/ `UPDATE guardian_action_requests SET answered_by_channel = 'voice' WHERE answered_by_channel = 'phone'`,
49
+ );
50
+
51
+ // channel_verification_sessions.channel (the forward migration ran after v21 rename)
52
+ raw.exec(
53
+ /*sql*/ `UPDATE channel_verification_sessions SET channel = 'voice' WHERE channel = 'phone'`,
54
+ );
55
+
56
+ // channel_guardian_approval_requests.channel
57
+ raw.exec(
58
+ /*sql*/ `UPDATE channel_guardian_approval_requests SET channel = 'voice' WHERE channel = 'phone'`,
59
+ );
60
+
61
+ // channel_guardian_rate_limits.channel
62
+ // Dedup: remove phone rows that would collide with existing voice rows
63
+ raw.exec(/*sql*/ `DELETE FROM channel_guardian_rate_limits WHERE channel = 'phone' AND EXISTS (
64
+ SELECT 1 FROM channel_guardian_rate_limits AS t2
65
+ WHERE t2.channel = 'voice'
66
+ AND t2.actor_external_user_id = channel_guardian_rate_limits.actor_external_user_id
67
+ AND t2.actor_chat_id = channel_guardian_rate_limits.actor_chat_id
68
+ )`);
69
+ raw.exec(
70
+ /*sql*/ `UPDATE channel_guardian_rate_limits SET channel = 'voice' WHERE channel = 'phone'`,
71
+ );
72
+
73
+ // notification_events.source_channel
74
+ raw.exec(
75
+ /*sql*/ `UPDATE notification_events SET source_channel = 'voice' WHERE source_channel = 'phone'`,
76
+ );
77
+
78
+ // notification_deliveries.channel
79
+ raw.exec(
80
+ /*sql*/ `UPDATE notification_deliveries SET channel = 'voice' WHERE channel = 'phone'`,
81
+ );
82
+
83
+ // external_conversation_bindings.source_channel
84
+ raw.exec(
85
+ /*sql*/ `UPDATE external_conversation_bindings SET source_channel = 'voice' WHERE source_channel = 'phone'`,
86
+ );
87
+
88
+ // channel_inbound_events.source_channel
89
+ raw.exec(
90
+ /*sql*/ `UPDATE channel_inbound_events SET source_channel = 'voice' WHERE source_channel = 'phone'`,
91
+ );
92
+
93
+ // conversation_attention_events.source_channel
94
+ raw.exec(
95
+ /*sql*/ `UPDATE conversation_attention_events SET source_channel = 'voice' WHERE source_channel = 'phone'`,
96
+ );
97
+
98
+ // conversation_assistant_attention_state.last_seen_source_channel
99
+ raw.exec(
100
+ /*sql*/ `UPDATE conversation_assistant_attention_state SET last_seen_source_channel = 'voice' WHERE last_seen_source_channel = 'phone'`,
101
+ );
102
+
103
+ // canonical_guardian_requests.source_channel
104
+ raw.exec(
105
+ /*sql*/ `UPDATE canonical_guardian_requests SET source_channel = 'voice' WHERE source_channel = 'phone'`,
106
+ );
107
+
108
+ // canonical_guardian_deliveries.destination_channel
109
+ raw.exec(
110
+ /*sql*/ `UPDATE canonical_guardian_deliveries SET destination_channel = 'voice' WHERE destination_channel = 'phone'`,
111
+ );
112
+
113
+ // guardian_action_deliveries.destination_channel
114
+ raw.exec(
115
+ /*sql*/ `UPDATE guardian_action_deliveries SET destination_channel = 'voice' WHERE destination_channel = 'phone'`,
116
+ );
117
+
118
+ // scoped_approval_grants: request_channel, decision_channel, execution_channel
119
+ raw.exec(
120
+ /*sql*/ `UPDATE scoped_approval_grants SET request_channel = 'voice' WHERE request_channel = 'phone'`,
121
+ );
122
+ raw.exec(
123
+ /*sql*/ `UPDATE scoped_approval_grants SET decision_channel = 'voice' WHERE decision_channel = 'phone'`,
124
+ );
125
+ raw.exec(
126
+ /*sql*/ `UPDATE scoped_approval_grants SET execution_channel = 'voice' WHERE execution_channel = 'phone'`,
127
+ );
128
+
129
+ // sequences.channel
130
+ raw.exec(
131
+ /*sql*/ `UPDATE sequences SET channel = 'voice' WHERE channel = 'phone'`,
132
+ );
133
+
134
+ // followups.channel
135
+ raw.exec(
136
+ /*sql*/ `UPDATE followups SET channel = 'voice' WHERE channel = 'phone'`,
137
+ );
138
+ }
139
+
4
140
  /**
5
141
  * One-shot migration: rename stored "voice" channel values to "phone" across
6
142
  * all tables that persist channel identifiers as text.
@@ -17,3 +17,35 @@ export function migrateDropAccountsTable(database: DrizzleDb): void {
17
17
  raw.exec(/*sql*/ `DROP TABLE IF EXISTS accounts`);
18
18
  });
19
19
  }
20
+
21
+ /**
22
+ * Reverse: recreate the accounts table with its original schema.
23
+ *
24
+ * Data is permanently lost — the table was dropped. This only restores the
25
+ * empty table structure so that earlier migrations referencing it can operate.
26
+ */
27
+ export function migrateDropAccountsTableDown(database: DrizzleDb): void {
28
+ const raw = getSqliteFrom(database);
29
+
30
+ raw.exec(/*sql*/ `
31
+ CREATE TABLE IF NOT EXISTS accounts (
32
+ id TEXT PRIMARY KEY,
33
+ service TEXT NOT NULL,
34
+ username TEXT,
35
+ email TEXT,
36
+ display_name TEXT,
37
+ status TEXT NOT NULL DEFAULT 'active',
38
+ credential_ref TEXT,
39
+ metadata_json TEXT,
40
+ created_at INTEGER NOT NULL,
41
+ updated_at INTEGER NOT NULL
42
+ )
43
+ `);
44
+
45
+ raw.exec(
46
+ /*sql*/ `CREATE INDEX IF NOT EXISTS idx_accounts_service ON accounts(service)`,
47
+ );
48
+ raw.exec(
49
+ /*sql*/ `CREATE INDEX IF NOT EXISTS idx_accounts_status ON accounts(status)`,
50
+ );
51
+ }
@@ -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
  /**
@@ -123,3 +124,15 @@ export function migrateRemindersToSchedules(database: DrizzleDb): void {
123
124
  }
124
125
  });
125
126
  }
127
+
128
+ /**
129
+ * Reverse: no-op.
130
+ *
131
+ * Cannot reliably identify which cron_jobs rows were migrated from reminders
132
+ * versus created natively as schedules. Rows share the same table and there
133
+ * is no origin marker. Deleting the wrong rows would destroy user-created
134
+ * schedules.
135
+ */
136
+ export function migrateRemindersToSchedulesDown(_database: DrizzleDb): void {
137
+ // No-op — see comment above.
138
+ }
@@ -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
  /**
@@ -12,3 +13,36 @@ export function migrateDropRemindersTable(database: DrizzleDb): void {
12
13
  raw.run("DROP TABLE IF EXISTS reminders");
13
14
  });
14
15
  }
16
+
17
+ /**
18
+ * Reverse: recreate the reminders table with its original schema.
19
+ *
20
+ * Data is permanently lost — the table was dropped. This only restores the
21
+ * empty table structure so that earlier migrations referencing it can operate.
22
+ * Includes the routing_intent and routing_hints_json columns added by
23
+ * migration 118.
24
+ */
25
+ export function migrateDropRemindersTableDown(database: DrizzleDb): void {
26
+ const raw = getSqliteFrom(database);
27
+
28
+ raw.exec(/*sql*/ `
29
+ CREATE TABLE IF NOT EXISTS reminders (
30
+ id TEXT PRIMARY KEY,
31
+ label TEXT NOT NULL,
32
+ message TEXT NOT NULL,
33
+ fire_at INTEGER NOT NULL,
34
+ mode TEXT NOT NULL,
35
+ status TEXT NOT NULL,
36
+ fired_at INTEGER,
37
+ conversation_id TEXT,
38
+ routing_intent TEXT NOT NULL DEFAULT 'all_channels',
39
+ routing_hints_json TEXT NOT NULL DEFAULT '{}',
40
+ created_at INTEGER NOT NULL,
41
+ updated_at INTEGER NOT NULL
42
+ )
43
+ `);
44
+
45
+ raw.exec(
46
+ /*sql*/ `CREATE INDEX IF NOT EXISTS idx_reminders_status_fire_at ON reminders(status, fire_at)`,
47
+ );
48
+ }
@@ -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
  /**
@@ -96,3 +97,70 @@ export function migrateOAuthAppsClientSecretPath(database: DrizzleDb): void {
96
97
  },
97
98
  );
98
99
  }
100
+
101
+ /**
102
+ * Reverse: drop the client_secret_credential_path column from oauth_apps.
103
+ *
104
+ * Rebuilds the table without the column (SQLite doesn't support DROP COLUMN
105
+ * on older versions). Idempotent — skips if the column doesn't exist.
106
+ */
107
+ export function migrateOAuthAppsClientSecretPathDown(
108
+ database: DrizzleDb,
109
+ ): void {
110
+ const raw = getSqliteFrom(database);
111
+
112
+ // Guard: table must exist
113
+ const tableExists = raw
114
+ .query(
115
+ `SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'oauth_apps'`,
116
+ )
117
+ .get();
118
+ if (!tableExists) return;
119
+
120
+ // Guard: if the column doesn't exist, nothing to do
121
+ const colInfo = raw
122
+ .query(
123
+ `SELECT 1 FROM pragma_table_info('oauth_apps') WHERE name = 'client_secret_credential_path'`,
124
+ )
125
+ .get();
126
+ if (!colInfo) return;
127
+
128
+ raw.exec("PRAGMA foreign_keys = OFF");
129
+ try {
130
+ raw.exec("BEGIN");
131
+
132
+ raw.exec(/*sql*/ `
133
+ CREATE TABLE oauth_apps_rollback (
134
+ id TEXT PRIMARY KEY,
135
+ provider_key TEXT NOT NULL REFERENCES oauth_providers(provider_key),
136
+ client_id TEXT NOT NULL,
137
+ created_at INTEGER NOT NULL,
138
+ updated_at INTEGER NOT NULL
139
+ )
140
+ `);
141
+
142
+ raw.exec(/*sql*/ `
143
+ INSERT INTO oauth_apps_rollback
144
+ SELECT id, provider_key, client_id, created_at, updated_at
145
+ FROM oauth_apps
146
+ `);
147
+
148
+ raw.exec(/*sql*/ `DROP TABLE oauth_apps`);
149
+ raw.exec(/*sql*/ `ALTER TABLE oauth_apps_rollback RENAME TO oauth_apps`);
150
+
151
+ raw.exec(
152
+ /*sql*/ `CREATE UNIQUE INDEX IF NOT EXISTS idx_oauth_apps_provider_client ON oauth_apps(provider_key, client_id)`,
153
+ );
154
+
155
+ raw.exec("COMMIT");
156
+ } catch (e) {
157
+ try {
158
+ raw.exec("ROLLBACK");
159
+ } catch {
160
+ /* no active transaction */
161
+ }
162
+ throw e;
163
+ } finally {
164
+ raw.exec("PRAGMA foreign_keys = ON");
165
+ }
166
+ }
@@ -281,3 +281,293 @@ function rebuildScopedApprovalGrants(raw: RawDb): void {
281
281
  raw.exec("PRAGMA foreign_keys = ON");
282
282
  }
283
283
  }
284
+
285
+ // ---------------------------------------------------------------------------
286
+ // Down functions
287
+ // ---------------------------------------------------------------------------
288
+
289
+ /**
290
+ * Reverse v29: convert epoch ms timestamps back to ISO 8601 text in guardian
291
+ * tables.
292
+ *
293
+ * Uses SQLite's datetime() to reconstruct ISO 8601 strings from the integer
294
+ * values. The millisecond component is appended manually since datetime()
295
+ * only returns second precision.
296
+ */
297
+ export function migrateGuardianTimestampsEpochMsDown(
298
+ database: DrizzleDb,
299
+ ): void {
300
+ const raw = getSqliteFrom(database);
301
+
302
+ // Convert canonical_guardian_requests timestamp columns back to ISO 8601
303
+ raw.exec(/*sql*/ `
304
+ UPDATE canonical_guardian_requests
305
+ SET created_at = strftime('%Y-%m-%dT%H:%M:%S', created_at / 1000, 'unixepoch') || '.' || printf('%03d', created_at % 1000) || 'Z',
306
+ updated_at = strftime('%Y-%m-%dT%H:%M:%S', updated_at / 1000, 'unixepoch') || '.' || printf('%03d', updated_at % 1000) || 'Z',
307
+ expires_at = CASE
308
+ WHEN expires_at IS NOT NULL
309
+ THEN strftime('%Y-%m-%dT%H:%M:%S', expires_at / 1000, 'unixepoch') || '.' || printf('%03d', expires_at % 1000) || 'Z'
310
+ ELSE NULL
311
+ END
312
+ WHERE typeof(created_at) = 'integer'
313
+ `);
314
+
315
+ // Convert canonical_guardian_deliveries timestamp columns back to ISO 8601
316
+ raw.exec(/*sql*/ `
317
+ UPDATE canonical_guardian_deliveries
318
+ SET created_at = strftime('%Y-%m-%dT%H:%M:%S', created_at / 1000, 'unixepoch') || '.' || printf('%03d', created_at % 1000) || 'Z',
319
+ updated_at = strftime('%Y-%m-%dT%H:%M:%S', updated_at / 1000, 'unixepoch') || '.' || printf('%03d', updated_at % 1000) || 'Z'
320
+ WHERE typeof(created_at) = 'integer'
321
+ `);
322
+
323
+ // Convert scoped_approval_grants timestamp columns back to ISO 8601
324
+ raw.exec(/*sql*/ `
325
+ UPDATE scoped_approval_grants
326
+ SET expires_at = strftime('%Y-%m-%dT%H:%M:%S', expires_at / 1000, 'unixepoch') || '.' || printf('%03d', expires_at % 1000) || 'Z',
327
+ created_at = strftime('%Y-%m-%dT%H:%M:%S', created_at / 1000, 'unixepoch') || '.' || printf('%03d', created_at % 1000) || 'Z',
328
+ updated_at = strftime('%Y-%m-%dT%H:%M:%S', updated_at / 1000, 'unixepoch') || '.' || printf('%03d', updated_at % 1000) || 'Z',
329
+ consumed_at = CASE
330
+ WHEN consumed_at IS NOT NULL
331
+ THEN strftime('%Y-%m-%dT%H:%M:%S', consumed_at / 1000, 'unixepoch') || '.' || printf('%03d', consumed_at % 1000) || 'Z'
332
+ ELSE NULL
333
+ END
334
+ WHERE typeof(created_at) = 'integer'
335
+ `);
336
+ }
337
+
338
+ /**
339
+ * Reverse v30: rebuild guardian tables with TEXT affinity on timestamp columns.
340
+ *
341
+ * Restores the original TEXT column declarations so that timestamp columns
342
+ * have TEXT affinity (the state before the INTEGER rebuild).
343
+ */
344
+ export function migrateGuardianTimestampsRebuildDown(
345
+ database: DrizzleDb,
346
+ ): void {
347
+ const raw = getSqliteFrom(database);
348
+
349
+ rebuildCanonicalGuardianRequestsToText(raw);
350
+ rebuildCanonicalGuardianDeliveriesToText(raw);
351
+ rebuildScopedApprovalGrantsToText(raw);
352
+ }
353
+
354
+ function hasTextAffinity(raw: RawDb, table: string, column: string): boolean {
355
+ const row = raw
356
+ .query(
357
+ `SELECT type FROM pragma_table_info('${table}') WHERE name = '${column}'`,
358
+ )
359
+ .get() as { type: string } | null;
360
+ if (!row) return true; // column doesn't exist — nothing to fix
361
+ return row.type.toUpperCase() === "TEXT";
362
+ }
363
+
364
+ function rebuildCanonicalGuardianRequestsToText(raw: RawDb): void {
365
+ if (hasTextAffinity(raw, "canonical_guardian_requests", "created_at")) return;
366
+
367
+ raw.exec("PRAGMA foreign_keys = OFF");
368
+ try {
369
+ raw.exec("BEGIN");
370
+
371
+ raw.exec(/*sql*/ `
372
+ CREATE TABLE canonical_guardian_requests_rb (
373
+ id TEXT PRIMARY KEY,
374
+ kind TEXT NOT NULL,
375
+ source_type TEXT NOT NULL,
376
+ source_channel TEXT,
377
+ conversation_id TEXT,
378
+ requester_external_user_id TEXT,
379
+ requester_chat_id TEXT,
380
+ guardian_external_user_id TEXT,
381
+ guardian_principal_id TEXT,
382
+ call_session_id TEXT,
383
+ pending_question_id TEXT,
384
+ question_text TEXT,
385
+ request_code TEXT,
386
+ tool_name TEXT,
387
+ input_digest TEXT,
388
+ status TEXT NOT NULL DEFAULT 'pending',
389
+ answer_text TEXT,
390
+ decided_by_external_user_id TEXT,
391
+ decided_by_principal_id TEXT,
392
+ followup_state TEXT,
393
+ expires_at TEXT,
394
+ created_at TEXT NOT NULL,
395
+ updated_at TEXT NOT NULL
396
+ )
397
+ `);
398
+
399
+ raw.exec(/*sql*/ `
400
+ INSERT INTO canonical_guardian_requests_rb
401
+ SELECT id, kind, source_type, source_channel, conversation_id,
402
+ requester_external_user_id, requester_chat_id,
403
+ guardian_external_user_id, guardian_principal_id,
404
+ call_session_id, pending_question_id, question_text,
405
+ request_code, tool_name, input_digest, status, answer_text,
406
+ decided_by_external_user_id, decided_by_principal_id,
407
+ followup_state, expires_at, created_at, updated_at
408
+ FROM canonical_guardian_requests
409
+ `);
410
+
411
+ raw.exec(/*sql*/ `DROP TABLE canonical_guardian_requests`);
412
+ raw.exec(
413
+ /*sql*/ `ALTER TABLE canonical_guardian_requests_rb RENAME TO canonical_guardian_requests`,
414
+ );
415
+
416
+ raw.exec(
417
+ /*sql*/ `CREATE INDEX IF NOT EXISTS idx_canonical_guardian_requests_status ON canonical_guardian_requests(status)`,
418
+ );
419
+ raw.exec(
420
+ /*sql*/ `CREATE INDEX IF NOT EXISTS idx_canonical_guardian_requests_guardian ON canonical_guardian_requests(guardian_external_user_id, status)`,
421
+ );
422
+ raw.exec(
423
+ /*sql*/ `CREATE INDEX IF NOT EXISTS idx_canonical_guardian_requests_conversation ON canonical_guardian_requests(conversation_id, status)`,
424
+ );
425
+ raw.exec(
426
+ /*sql*/ `CREATE INDEX IF NOT EXISTS idx_canonical_guardian_requests_source ON canonical_guardian_requests(source_type, status)`,
427
+ );
428
+ raw.exec(
429
+ /*sql*/ `CREATE INDEX IF NOT EXISTS idx_canonical_guardian_requests_kind ON canonical_guardian_requests(kind, status)`,
430
+ );
431
+ raw.exec(
432
+ /*sql*/ `CREATE INDEX IF NOT EXISTS idx_canonical_guardian_requests_request_code ON canonical_guardian_requests(request_code)`,
433
+ );
434
+
435
+ raw.exec("COMMIT");
436
+ } catch (e) {
437
+ try {
438
+ raw.exec("ROLLBACK");
439
+ } catch {
440
+ /* no active transaction */
441
+ }
442
+ throw e;
443
+ } finally {
444
+ raw.exec("PRAGMA foreign_keys = ON");
445
+ }
446
+ }
447
+
448
+ function rebuildCanonicalGuardianDeliveriesToText(raw: RawDb): void {
449
+ if (hasTextAffinity(raw, "canonical_guardian_deliveries", "created_at"))
450
+ return;
451
+
452
+ raw.exec("PRAGMA foreign_keys = OFF");
453
+ try {
454
+ raw.exec("BEGIN");
455
+
456
+ raw.exec(/*sql*/ `
457
+ CREATE TABLE canonical_guardian_deliveries_rb (
458
+ id TEXT PRIMARY KEY,
459
+ request_id TEXT NOT NULL REFERENCES canonical_guardian_requests(id) ON DELETE CASCADE,
460
+ destination_channel TEXT NOT NULL,
461
+ destination_conversation_id TEXT,
462
+ destination_chat_id TEXT,
463
+ destination_message_id TEXT,
464
+ status TEXT NOT NULL DEFAULT 'pending',
465
+ created_at TEXT NOT NULL,
466
+ updated_at TEXT NOT NULL
467
+ )
468
+ `);
469
+
470
+ raw.exec(/*sql*/ `
471
+ INSERT INTO canonical_guardian_deliveries_rb
472
+ SELECT id, request_id, destination_channel, destination_conversation_id,
473
+ destination_chat_id, destination_message_id, status,
474
+ created_at, updated_at
475
+ FROM canonical_guardian_deliveries
476
+ `);
477
+
478
+ raw.exec(/*sql*/ `DROP TABLE canonical_guardian_deliveries`);
479
+ raw.exec(
480
+ /*sql*/ `ALTER TABLE canonical_guardian_deliveries_rb RENAME TO canonical_guardian_deliveries`,
481
+ );
482
+
483
+ raw.exec(
484
+ /*sql*/ `CREATE INDEX IF NOT EXISTS idx_canonical_guardian_deliveries_request_id ON canonical_guardian_deliveries(request_id)`,
485
+ );
486
+ raw.exec(
487
+ /*sql*/ `CREATE INDEX IF NOT EXISTS idx_canonical_guardian_deliveries_status ON canonical_guardian_deliveries(status)`,
488
+ );
489
+ raw.exec(
490
+ /*sql*/ `CREATE INDEX IF NOT EXISTS idx_canonical_guardian_deliveries_destination ON canonical_guardian_deliveries(destination_channel, destination_chat_id)`,
491
+ );
492
+
493
+ raw.exec("COMMIT");
494
+ } catch (e) {
495
+ try {
496
+ raw.exec("ROLLBACK");
497
+ } catch {
498
+ /* no active transaction */
499
+ }
500
+ throw e;
501
+ } finally {
502
+ raw.exec("PRAGMA foreign_keys = ON");
503
+ }
504
+ }
505
+
506
+ function rebuildScopedApprovalGrantsToText(raw: RawDb): void {
507
+ if (hasTextAffinity(raw, "scoped_approval_grants", "created_at")) return;
508
+
509
+ raw.exec("PRAGMA foreign_keys = OFF");
510
+ try {
511
+ raw.exec("BEGIN");
512
+
513
+ raw.exec(/*sql*/ `
514
+ CREATE TABLE scoped_approval_grants_rb (
515
+ id TEXT PRIMARY KEY,
516
+ scope_mode TEXT NOT NULL,
517
+ request_id TEXT,
518
+ tool_name TEXT,
519
+ input_digest TEXT,
520
+ request_channel TEXT NOT NULL,
521
+ decision_channel TEXT NOT NULL,
522
+ execution_channel TEXT,
523
+ conversation_id TEXT,
524
+ call_session_id TEXT,
525
+ requester_external_user_id TEXT,
526
+ guardian_external_user_id TEXT,
527
+ status TEXT NOT NULL,
528
+ expires_at TEXT NOT NULL,
529
+ consumed_at TEXT,
530
+ consumed_by_request_id TEXT,
531
+ created_at TEXT NOT NULL,
532
+ updated_at TEXT NOT NULL
533
+ )
534
+ `);
535
+
536
+ raw.exec(/*sql*/ `
537
+ INSERT INTO scoped_approval_grants_rb
538
+ SELECT id, scope_mode, request_id, tool_name, input_digest,
539
+ request_channel, decision_channel, execution_channel,
540
+ conversation_id, call_session_id,
541
+ requester_external_user_id, guardian_external_user_id,
542
+ status, expires_at, consumed_at, consumed_by_request_id,
543
+ created_at, updated_at
544
+ FROM scoped_approval_grants
545
+ `);
546
+
547
+ raw.exec(/*sql*/ `DROP TABLE scoped_approval_grants`);
548
+ raw.exec(
549
+ /*sql*/ `ALTER TABLE scoped_approval_grants_rb RENAME TO scoped_approval_grants`,
550
+ );
551
+
552
+ raw.exec(
553
+ /*sql*/ `CREATE INDEX IF NOT EXISTS idx_scoped_grants_request_id ON scoped_approval_grants(request_id) WHERE request_id IS NOT NULL`,
554
+ );
555
+ raw.exec(
556
+ /*sql*/ `CREATE INDEX IF NOT EXISTS idx_scoped_grants_tool_sig ON scoped_approval_grants(tool_name, input_digest) WHERE tool_name IS NOT NULL`,
557
+ );
558
+ raw.exec(
559
+ /*sql*/ `CREATE INDEX IF NOT EXISTS idx_scoped_grants_status_expires ON scoped_approval_grants(status, expires_at)`,
560
+ );
561
+
562
+ raw.exec("COMMIT");
563
+ } catch (e) {
564
+ try {
565
+ raw.exec("ROLLBACK");
566
+ } catch {
567
+ /* no active transaction */
568
+ }
569
+ throw e;
570
+ } finally {
571
+ raw.exec("PRAGMA foreign_keys = ON");
572
+ }
573
+ }