vellum 0.2.14 → 0.3.2

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 (1060) hide show
  1. package/bin/vellum.js +2 -0
  2. package/package.json +6 -65
  3. package/.dockerignore +0 -27
  4. package/.env.example +0 -22
  5. package/Dockerfile +0 -99
  6. package/Dockerfile.sandbox +0 -5
  7. package/README.md +0 -201
  8. package/bun.lock +0 -1743
  9. package/bunfig.toml +0 -2
  10. package/docs/skills.md +0 -158
  11. package/drizzle/0000_dizzy_maggott.sql +0 -301
  12. package/drizzle/meta/0000_snapshot.json +0 -1999
  13. package/drizzle/meta/_journal.json +0 -13
  14. package/drizzle.config.ts +0 -7
  15. package/eslint.config.mjs +0 -17
  16. package/hook-templates/debug-prompt-logger/hook.json +0 -7
  17. package/hook-templates/debug-prompt-logger/run.sh +0 -68
  18. package/knip.json +0 -9
  19. package/scripts/capture-x-graphql.ts +0 -545
  20. package/scripts/ipc/check-contract-inventory.ts +0 -104
  21. package/scripts/ipc/check-swift-decoder-drift.ts +0 -164
  22. package/scripts/ipc/generate-swift.ts +0 -492
  23. package/scripts/test-filesystem-tools.sh +0 -48
  24. package/scripts/test.sh +0 -127
  25. package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +0 -2526
  26. package/src/__tests__/account-registry.test.ts +0 -245
  27. package/src/__tests__/active-skill-tools.test.ts +0 -378
  28. package/src/__tests__/agent-heartbeat-service.test.ts +0 -250
  29. package/src/__tests__/agent-loop-thinking.test.ts +0 -81
  30. package/src/__tests__/agent-loop.test.ts +0 -1135
  31. package/src/__tests__/anthropic-provider.test.ts +0 -778
  32. package/src/__tests__/app-builder-tool-scripts.test.ts +0 -290
  33. package/src/__tests__/app-bundler.test.ts +0 -292
  34. package/src/__tests__/app-executors.test.ts +0 -613
  35. package/src/__tests__/app-git-history.test.ts +0 -176
  36. package/src/__tests__/app-git-service.test.ts +0 -169
  37. package/src/__tests__/app-open-proxy.test.ts +0 -62
  38. package/src/__tests__/asset-materialize-tool.test.ts +0 -452
  39. package/src/__tests__/asset-search-tool.test.ts +0 -477
  40. package/src/__tests__/assistant-attachment-directive.test.ts +0 -401
  41. package/src/__tests__/assistant-attachments.test.ts +0 -437
  42. package/src/__tests__/assistant-event-hub.test.ts +0 -226
  43. package/src/__tests__/assistant-event.test.ts +0 -123
  44. package/src/__tests__/assistant-events-sse-hardening.test.ts +0 -315
  45. package/src/__tests__/attachments-store.test.ts +0 -476
  46. package/src/__tests__/attachments.test.ts +0 -134
  47. package/src/__tests__/audit-log-rotation.test.ts +0 -154
  48. package/src/__tests__/browser-fill-credential.test.ts +0 -309
  49. package/src/__tests__/browser-manager.test.ts +0 -203
  50. package/src/__tests__/browser-runtime-check.test.ts +0 -55
  51. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +0 -68
  52. package/src/__tests__/browser-skill-endstate.test.ts +0 -195
  53. package/src/__tests__/bundle-scanner.test.ts +0 -313
  54. package/src/__tests__/call-bridge.test.ts +0 -517
  55. package/src/__tests__/call-constants.test.ts +0 -40
  56. package/src/__tests__/call-domain.test.ts +0 -163
  57. package/src/__tests__/call-orchestrator.test.ts +0 -625
  58. package/src/__tests__/call-recovery.test.ts +0 -518
  59. package/src/__tests__/call-routes-http.test.ts +0 -699
  60. package/src/__tests__/call-state-machine.test.ts +0 -143
  61. package/src/__tests__/call-state.test.ts +0 -174
  62. package/src/__tests__/call-store.test.ts +0 -691
  63. package/src/__tests__/channel-approval-routes.test.ts +0 -438
  64. package/src/__tests__/channel-approval.test.ts +0 -266
  65. package/src/__tests__/channel-approvals.test.ts +0 -393
  66. package/src/__tests__/channel-delivery-store.test.ts +0 -447
  67. package/src/__tests__/checker.test.ts +0 -3519
  68. package/src/__tests__/clarification-resolver.test.ts +0 -159
  69. package/src/__tests__/classifier.test.ts +0 -67
  70. package/src/__tests__/claude-code-skill-regression.test.ts +0 -127
  71. package/src/__tests__/claude-code-tool-profiles.test.ts +0 -88
  72. package/src/__tests__/cli-discover.test.ts +0 -85
  73. package/src/__tests__/cli.test.ts +0 -26
  74. package/src/__tests__/clipboard.test.ts +0 -80
  75. package/src/__tests__/commit-guarantee.test.ts +0 -335
  76. package/src/__tests__/commit-message-enrichment-service.test.ts +0 -550
  77. package/src/__tests__/compaction.benchmark.test.ts +0 -176
  78. package/src/__tests__/computer-use-session-compaction.test.ts +0 -132
  79. package/src/__tests__/computer-use-session-lifecycle.test.ts +0 -293
  80. package/src/__tests__/computer-use-session-working-dir.test.ts +0 -117
  81. package/src/__tests__/computer-use-skill-baseline.test.ts +0 -74
  82. package/src/__tests__/computer-use-skill-endstate.test.ts +0 -89
  83. package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +0 -217
  84. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +0 -107
  85. package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +0 -54
  86. package/src/__tests__/computer-use-tools.test.ts +0 -250
  87. package/src/__tests__/config-schema.test.ts +0 -1462
  88. package/src/__tests__/conflict-intent-tokenization.test.ts +0 -141
  89. package/src/__tests__/conflict-policy.test.ts +0 -121
  90. package/src/__tests__/conflict-store.test.ts +0 -332
  91. package/src/__tests__/connection-policy.test.ts +0 -102
  92. package/src/__tests__/contacts-tools.test.ts +0 -331
  93. package/src/__tests__/context-memory-e2e.test.ts +0 -434
  94. package/src/__tests__/context-token-estimator.test.ts +0 -135
  95. package/src/__tests__/context-window-manager.test.ts +0 -376
  96. package/src/__tests__/contradiction-checker.test.ts +0 -314
  97. package/src/__tests__/conversation-store.test.ts +0 -612
  98. package/src/__tests__/credential-broker-browser-fill.test.ts +0 -517
  99. package/src/__tests__/credential-broker-server-use.test.ts +0 -554
  100. package/src/__tests__/credential-broker.test.ts +0 -167
  101. package/src/__tests__/credential-host-pattern-match.test.ts +0 -104
  102. package/src/__tests__/credential-metadata-store.test.ts +0 -779
  103. package/src/__tests__/credential-policy-validate.test.ts +0 -121
  104. package/src/__tests__/credential-resolve.test.ts +0 -328
  105. package/src/__tests__/credential-security-e2e.test.ts +0 -352
  106. package/src/__tests__/credential-security-invariants.test.ts +0 -583
  107. package/src/__tests__/credential-selection.test.ts +0 -354
  108. package/src/__tests__/credential-vault-unit.test.ts +0 -780
  109. package/src/__tests__/credential-vault.test.ts +0 -852
  110. package/src/__tests__/daemon-assistant-events.test.ts +0 -164
  111. package/src/__tests__/daemon-server-session-init.test.ts +0 -522
  112. package/src/__tests__/date-context.test.ts +0 -373
  113. package/src/__tests__/db-schedule-syntax-migration.test.ts +0 -129
  114. package/src/__tests__/delete-managed-skill-tool.test.ts +0 -97
  115. package/src/__tests__/diff.test.ts +0 -121
  116. package/src/__tests__/domain-normalize.test.ts +0 -112
  117. package/src/__tests__/domain-policy.test.ts +0 -124
  118. package/src/__tests__/doordash-client.test.ts +0 -186
  119. package/src/__tests__/doordash-session.test.ts +0 -152
  120. package/src/__tests__/dynamic-page-surface.test.ts +0 -91
  121. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -132
  122. package/src/__tests__/edit-engine.test.ts +0 -180
  123. package/src/__tests__/elevenlabs-client.test.ts +0 -271
  124. package/src/__tests__/email-cli.test.ts +0 -283
  125. package/src/__tests__/encrypted-store.test.ts +0 -332
  126. package/src/__tests__/entity-extractor.test.ts +0 -190
  127. package/src/__tests__/ephemeral-permissions.test.ts +0 -362
  128. package/src/__tests__/evaluate-typescript-tool.test.ts +0 -286
  129. package/src/__tests__/event-bus.test.ts +0 -222
  130. package/src/__tests__/file-edit-tool.test.ts +0 -122
  131. package/src/__tests__/file-ops-service.test.ts +0 -330
  132. package/src/__tests__/file-read-tool.test.ts +0 -75
  133. package/src/__tests__/file-write-tool.test.ts +0 -113
  134. package/src/__tests__/filesystem-tools.test.ts +0 -579
  135. package/src/__tests__/fixtures/credential-security-fixtures.ts +0 -181
  136. package/src/__tests__/fixtures/media-reuse-fixtures.ts +0 -126
  137. package/src/__tests__/fixtures/mock-signup-server.ts +0 -387
  138. package/src/__tests__/fixtures/proxy-fixtures.ts +0 -147
  139. package/src/__tests__/followup-tools.test.ts +0 -303
  140. package/src/__tests__/forbidden-legacy-symbols.test.ts +0 -71
  141. package/src/__tests__/fuzzy-match-property.test.ts +0 -216
  142. package/src/__tests__/fuzzy-match.test.ts +0 -138
  143. package/src/__tests__/gateway-only-enforcement.test.ts +0 -546
  144. package/src/__tests__/gemini-image-service.test.ts +0 -261
  145. package/src/__tests__/gemini-provider.test.ts +0 -651
  146. package/src/__tests__/get-weather.test.ts +0 -318
  147. package/src/__tests__/gmail-integration.test.ts +0 -73
  148. package/src/__tests__/handlers-add-trust-rule-metadata.test.ts +0 -202
  149. package/src/__tests__/handlers-cu-observation-blob.test.ts +0 -352
  150. package/src/__tests__/handlers-ipc-blob-probe.test.ts +0 -191
  151. package/src/__tests__/handlers-slack-config.test.ts +0 -200
  152. package/src/__tests__/handlers-task-submit-slash.test.ts +0 -38
  153. package/src/__tests__/handlers-telegram-config.test.ts +0 -855
  154. package/src/__tests__/handlers-twitter-config.test.ts +0 -858
  155. package/src/__tests__/headless-browser-interactions.test.ts +0 -536
  156. package/src/__tests__/headless-browser-navigate.test.ts +0 -211
  157. package/src/__tests__/headless-browser-read-tools.test.ts +0 -261
  158. package/src/__tests__/headless-browser-snapshot.test.ts +0 -185
  159. package/src/__tests__/history-repair-observability.test.ts +0 -56
  160. package/src/__tests__/history-repair.test.ts +0 -510
  161. package/src/__tests__/home-base-bootstrap.test.ts +0 -82
  162. package/src/__tests__/hooks-blocking.test.ts +0 -128
  163. package/src/__tests__/hooks-cli.test.ts +0 -144
  164. package/src/__tests__/hooks-config.test.ts +0 -93
  165. package/src/__tests__/hooks-discovery.test.ts +0 -199
  166. package/src/__tests__/hooks-integration.test.ts +0 -189
  167. package/src/__tests__/hooks-manager.test.ts +0 -187
  168. package/src/__tests__/hooks-runner.test.ts +0 -182
  169. package/src/__tests__/hooks-settings.test.ts +0 -154
  170. package/src/__tests__/hooks-templates.test.ts +0 -137
  171. package/src/__tests__/hooks-ts-runner.test.ts +0 -125
  172. package/src/__tests__/hooks-watch.test.ts +0 -100
  173. package/src/__tests__/host-file-edit-tool.test.ts +0 -228
  174. package/src/__tests__/host-file-read-tool.test.ts +0 -123
  175. package/src/__tests__/host-file-write-tool.test.ts +0 -136
  176. package/src/__tests__/host-shell-tool.test.ts +0 -562
  177. package/src/__tests__/ingress-reconcile.test.ts +0 -581
  178. package/src/__tests__/ingress-url-consistency.test.ts +0 -214
  179. package/src/__tests__/intent-routing.test.ts +0 -259
  180. package/src/__tests__/ipc-blob-store.test.ts +0 -315
  181. package/src/__tests__/ipc-contract-inventory.test.ts +0 -54
  182. package/src/__tests__/ipc-contract.test.ts +0 -74
  183. package/src/__tests__/ipc-protocol.test.ts +0 -113
  184. package/src/__tests__/ipc-roundtrip.benchmark.test.ts +0 -237
  185. package/src/__tests__/ipc-snapshot.test.ts +0 -1757
  186. package/src/__tests__/ipc-validate.test.ts +0 -407
  187. package/src/__tests__/key-migration.test.ts +0 -206
  188. package/src/__tests__/keychain.test.ts +0 -258
  189. package/src/__tests__/llm-usage-store.test.ts +0 -221
  190. package/src/__tests__/managed-skill-lifecycle.test.ts +0 -257
  191. package/src/__tests__/managed-store.test.ts +0 -608
  192. package/src/__tests__/media-generate-image.test.ts +0 -238
  193. package/src/__tests__/media-reuse-story.e2e.test.ts +0 -676
  194. package/src/__tests__/media-visibility-policy.test.ts +0 -141
  195. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +0 -235
  196. package/src/__tests__/memory-lifecycle-e2e.test.ts +0 -481
  197. package/src/__tests__/memory-query-builder.test.ts +0 -59
  198. package/src/__tests__/memory-recall-quality.test.ts +0 -846
  199. package/src/__tests__/memory-regressions.experimental.test.ts +0 -538
  200. package/src/__tests__/memory-regressions.test.ts +0 -4435
  201. package/src/__tests__/memory-retrieval-budget.test.ts +0 -49
  202. package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -430
  203. package/src/__tests__/migration-cli-flows.test.ts +0 -169
  204. package/src/__tests__/migration-ordering.test.ts +0 -249
  205. package/src/__tests__/mock-signup-server.test.ts +0 -528
  206. package/src/__tests__/oauth-callback-registry.test.ts +0 -92
  207. package/src/__tests__/oauth2-gateway-transport.test.ts +0 -285
  208. package/src/__tests__/onboarding-starter-tasks.test.ts +0 -176
  209. package/src/__tests__/onboarding-template-contract.test.ts +0 -58
  210. package/src/__tests__/openai-provider.test.ts +0 -753
  211. package/src/__tests__/parallel-tool.benchmark.test.ts +0 -294
  212. package/src/__tests__/parser.test.ts +0 -472
  213. package/src/__tests__/path-classifier.test.ts +0 -73
  214. package/src/__tests__/path-policy.test.ts +0 -435
  215. package/src/__tests__/platform-move-helper.test.ts +0 -99
  216. package/src/__tests__/platform-socket-path.test.ts +0 -52
  217. package/src/__tests__/platform-workspace-migration.test.ts +0 -1000
  218. package/src/__tests__/platform.test.ts +0 -131
  219. package/src/__tests__/playbook-execution.test.ts +0 -502
  220. package/src/__tests__/playbook-tools.test.ts +0 -340
  221. package/src/__tests__/prebuilt-home-base-seed.test.ts +0 -75
  222. package/src/__tests__/pricing.test.ts +0 -256
  223. package/src/__tests__/profile-compiler.test.ts +0 -374
  224. package/src/__tests__/provider-commit-message-generator.test.ts +0 -342
  225. package/src/__tests__/provider-registry-ollama.test.ts +0 -16
  226. package/src/__tests__/provider-streaming.benchmark.test.ts +0 -773
  227. package/src/__tests__/proxy-approval-callback.test.ts +0 -601
  228. package/src/__tests__/public-ingress-urls.test.ts +0 -256
  229. package/src/__tests__/qdrant-manager.test.ts +0 -267
  230. package/src/__tests__/ratelimit.test.ts +0 -297
  231. package/src/__tests__/recurrence-engine-rruleset.test.ts +0 -175
  232. package/src/__tests__/recurrence-engine.test.ts +0 -78
  233. package/src/__tests__/recurrence-types.test.ts +0 -79
  234. package/src/__tests__/registry.test.ts +0 -494
  235. package/src/__tests__/relay-server.test.ts +0 -688
  236. package/src/__tests__/reminder-store.test.ts +0 -223
  237. package/src/__tests__/reminder.test.ts +0 -229
  238. package/src/__tests__/request-file-tool.test.ts +0 -158
  239. package/src/__tests__/run-orchestrator-assistant-events.test.ts +0 -222
  240. package/src/__tests__/run-orchestrator.test.ts +0 -200
  241. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -189
  242. package/src/__tests__/runtime-events-sse-parity.test.ts +0 -343
  243. package/src/__tests__/runtime-events-sse.test.ts +0 -162
  244. package/src/__tests__/runtime-runs-http.test.ts +0 -433
  245. package/src/__tests__/runtime-runs.test.ts +0 -249
  246. package/src/__tests__/sandbox-diagnostics.test.ts +0 -408
  247. package/src/__tests__/sandbox-host-parity.test.ts +0 -950
  248. package/src/__tests__/scaffold-managed-skill-tool.test.ts +0 -253
  249. package/src/__tests__/schedule-store.test.ts +0 -484
  250. package/src/__tests__/schedule-tools.test.ts +0 -783
  251. package/src/__tests__/scheduler-recurrence.test.ts +0 -430
  252. package/src/__tests__/script-proxy-certs.test.ts +0 -90
  253. package/src/__tests__/script-proxy-connect-tunnel.test.ts +0 -177
  254. package/src/__tests__/script-proxy-decision-trace.test.ts +0 -156
  255. package/src/__tests__/script-proxy-http-forwarder.test.ts +0 -281
  256. package/src/__tests__/script-proxy-injection-runtime.test.ts +0 -401
  257. package/src/__tests__/script-proxy-mitm-handler.test.ts +0 -407
  258. package/src/__tests__/script-proxy-policy-runtime.test.ts +0 -287
  259. package/src/__tests__/script-proxy-policy.test.ts +0 -310
  260. package/src/__tests__/script-proxy-rewrite-specificity.test.ts +0 -135
  261. package/src/__tests__/script-proxy-router.test.ts +0 -180
  262. package/src/__tests__/script-proxy-session-manager.test.ts +0 -382
  263. package/src/__tests__/script-proxy-session-runtime.test.ts +0 -113
  264. package/src/__tests__/secret-allowlist.test.ts +0 -230
  265. package/src/__tests__/secret-ingress-handler.test.ts +0 -110
  266. package/src/__tests__/secret-onetime-send.test.ts +0 -130
  267. package/src/__tests__/secret-prompt-log-hygiene.test.ts +0 -106
  268. package/src/__tests__/secret-response-routing.test.ts +0 -93
  269. package/src/__tests__/secret-scanner-executor.test.ts +0 -348
  270. package/src/__tests__/secret-scanner.test.ts +0 -900
  271. package/src/__tests__/secure-keys.test.ts +0 -323
  272. package/src/__tests__/server-history-render.test.ts +0 -431
  273. package/src/__tests__/session-abort-tool-results.test.ts +0 -240
  274. package/src/__tests__/session-conflict-gate.test.ts +0 -1136
  275. package/src/__tests__/session-error.test.ts +0 -369
  276. package/src/__tests__/session-evictor.test.ts +0 -188
  277. package/src/__tests__/session-init.benchmark.test.ts +0 -465
  278. package/src/__tests__/session-load-history-repair.test.ts +0 -222
  279. package/src/__tests__/session-pre-run-repair.test.ts +0 -213
  280. package/src/__tests__/session-process-bridge.test.ts +0 -242
  281. package/src/__tests__/session-profile-injection.test.ts +0 -444
  282. package/src/__tests__/session-provider-retry-repair.test.ts +0 -306
  283. package/src/__tests__/session-queue.test.ts +0 -1535
  284. package/src/__tests__/session-runtime-assembly.test.ts +0 -476
  285. package/src/__tests__/session-runtime-workspace.test.ts +0 -183
  286. package/src/__tests__/session-skill-tools.test.ts +0 -2431
  287. package/src/__tests__/session-slash-known.test.ts +0 -368
  288. package/src/__tests__/session-slash-queue.test.ts +0 -288
  289. package/src/__tests__/session-slash-unknown.test.ts +0 -271
  290. package/src/__tests__/session-surfaces-task-progress.test.ts +0 -104
  291. package/src/__tests__/session-tool-setup-app-refresh.test.ts +0 -473
  292. package/src/__tests__/session-tool-setup-memory-scope.test.ts +0 -140
  293. package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +0 -140
  294. package/src/__tests__/session-undo.test.ts +0 -75
  295. package/src/__tests__/session-workspace-cache-state.test.ts +0 -246
  296. package/src/__tests__/session-workspace-injection.test.ts +0 -327
  297. package/src/__tests__/session-workspace-tool-tracking.test.ts +0 -240
  298. package/src/__tests__/shared-filesystem-errors.test.ts +0 -78
  299. package/src/__tests__/shell-credential-ref.test.ts +0 -187
  300. package/src/__tests__/shell-identity.test.ts +0 -256
  301. package/src/__tests__/shell-parser-fuzz.test.ts +0 -544
  302. package/src/__tests__/shell-parser-property.test.ts +0 -433
  303. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -272
  304. package/src/__tests__/signup-e2e.test.ts +0 -353
  305. package/src/__tests__/size-guard.test.ts +0 -117
  306. package/src/__tests__/skill-include-graph.test.ts +0 -303
  307. package/src/__tests__/skill-load-tool.test.ts +0 -409
  308. package/src/__tests__/skill-projection.benchmark.test.ts +0 -338
  309. package/src/__tests__/skill-script-runner-host.test.ts +0 -489
  310. package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -349
  311. package/src/__tests__/skill-script-runner.test.ts +0 -159
  312. package/src/__tests__/skill-tool-factory.test.ts +0 -252
  313. package/src/__tests__/skill-tool-manifest.test.ts +0 -658
  314. package/src/__tests__/skill-version-hash.test.ts +0 -182
  315. package/src/__tests__/skills.test.ts +0 -680
  316. package/src/__tests__/slash-commands-catalog.test.ts +0 -86
  317. package/src/__tests__/slash-commands-parser.test.ts +0 -119
  318. package/src/__tests__/slash-commands-resolver.test.ts +0 -193
  319. package/src/__tests__/slash-commands-rewrite.test.ts +0 -39
  320. package/src/__tests__/speaker-identification.test.ts +0 -52
  321. package/src/__tests__/starter-bundle.test.ts +0 -136
  322. package/src/__tests__/starter-task-flow.test.ts +0 -143
  323. package/src/__tests__/subagent-manager-notify.test.ts +0 -404
  324. package/src/__tests__/subagent-tools.test.ts +0 -801
  325. package/src/__tests__/subagent-types.test.ts +0 -78
  326. package/src/__tests__/swarm-orchestrator.test.ts +0 -428
  327. package/src/__tests__/swarm-plan-validator.test.ts +0 -330
  328. package/src/__tests__/swarm-recursion.test.ts +0 -165
  329. package/src/__tests__/swarm-router-planner.test.ts +0 -208
  330. package/src/__tests__/swarm-session-integration.test.ts +0 -274
  331. package/src/__tests__/swarm-tool.test.ts +0 -145
  332. package/src/__tests__/swarm-worker-backend.test.ts +0 -129
  333. package/src/__tests__/swarm-worker-runner.test.ts +0 -272
  334. package/src/__tests__/system-prompt.test.ts +0 -439
  335. package/src/__tests__/task-compiler.test.ts +0 -284
  336. package/src/__tests__/task-management-tools.test.ts +0 -936
  337. package/src/__tests__/task-runner.test.ts +0 -216
  338. package/src/__tests__/task-scheduler.test.ts +0 -217
  339. package/src/__tests__/task-tools.test.ts +0 -595
  340. package/src/__tests__/terminal-sandbox-docker.test.ts +0 -1064
  341. package/src/__tests__/terminal-sandbox.integration.test.ts +0 -178
  342. package/src/__tests__/terminal-sandbox.test.ts +0 -202
  343. package/src/__tests__/terminal-tools.test.ts +0 -840
  344. package/src/__tests__/test-support/browser-skill-harness.ts +0 -90
  345. package/src/__tests__/test-support/computer-use-skill-harness.ts +0 -45
  346. package/src/__tests__/tool-audit-listener.test.ts +0 -113
  347. package/src/__tests__/tool-domain-event-publisher.test.ts +0 -253
  348. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -500
  349. package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -516
  350. package/src/__tests__/tool-executor-redaction.test.ts +0 -289
  351. package/src/__tests__/tool-executor-shell-integration.test.ts +0 -301
  352. package/src/__tests__/tool-executor.test.ts +0 -1989
  353. package/src/__tests__/tool-metrics-listener.test.ts +0 -225
  354. package/src/__tests__/tool-notification-listener.test.ts +0 -49
  355. package/src/__tests__/tool-permission-simulate-handler.test.ts +0 -336
  356. package/src/__tests__/tool-policy.test.ts +0 -54
  357. package/src/__tests__/tool-profiling-listener.test.ts +0 -268
  358. package/src/__tests__/tool-result-truncation.test.ts +0 -217
  359. package/src/__tests__/tool-trace-listener.test.ts +0 -226
  360. package/src/__tests__/top-level-renderer.test.ts +0 -121
  361. package/src/__tests__/top-level-scanner.test.ts +0 -141
  362. package/src/__tests__/trace-emitter.test.ts +0 -173
  363. package/src/__tests__/trust-store.test.ts +0 -1605
  364. package/src/__tests__/turn-commit.test.ts +0 -554
  365. package/src/__tests__/twilio-provider.test.ts +0 -329
  366. package/src/__tests__/twilio-routes-elevenlabs.test.ts +0 -375
  367. package/src/__tests__/twilio-routes-twiml.test.ts +0 -127
  368. package/src/__tests__/twilio-routes.test.ts +0 -577
  369. package/src/__tests__/twitter-auth-handler.test.ts +0 -667
  370. package/src/__tests__/twitter-cli-error-shaping.test.ts +0 -208
  371. package/src/__tests__/twitter-cli-routing.test.ts +0 -252
  372. package/src/__tests__/twitter-oauth-client.test.ts +0 -209
  373. package/src/__tests__/url-safety.test.ts +0 -418
  374. package/src/__tests__/view-image-tool.test.ts +0 -217
  375. package/src/__tests__/weather-skill-regression.test.ts +0 -225
  376. package/src/__tests__/web-fetch.test.ts +0 -869
  377. package/src/__tests__/web-search.test.ts +0 -584
  378. package/src/__tests__/workspace-git-service.test.ts +0 -1153
  379. package/src/__tests__/workspace-heartbeat-service.test.ts +0 -486
  380. package/src/__tests__/workspace-lifecycle.test.ts +0 -292
  381. package/src/__tests__/workspace-policy.test.ts +0 -213
  382. package/src/agent/attachments.ts +0 -35
  383. package/src/agent/loop.ts +0 -500
  384. package/src/agent/message-types.ts +0 -17
  385. package/src/agent-heartbeat/agent-heartbeat-service.ts +0 -155
  386. package/src/autonomy/autonomy-resolver.ts +0 -60
  387. package/src/autonomy/autonomy-store.ts +0 -122
  388. package/src/autonomy/disposition-mapper.ts +0 -31
  389. package/src/autonomy/index.ts +0 -11
  390. package/src/autonomy/types.ts +0 -39
  391. package/src/bundler/app-bundler.ts +0 -295
  392. package/src/bundler/bundle-scanner.ts +0 -535
  393. package/src/bundler/bundle-signer.ts +0 -124
  394. package/src/bundler/manifest.ts +0 -21
  395. package/src/bundler/signature-verifier.ts +0 -184
  396. package/src/calls/call-bridge.ts +0 -168
  397. package/src/calls/call-constants.ts +0 -48
  398. package/src/calls/call-domain.ts +0 -430
  399. package/src/calls/call-orchestrator.ts +0 -498
  400. package/src/calls/call-recovery.ts +0 -207
  401. package/src/calls/call-state-machine.ts +0 -68
  402. package/src/calls/call-state.ts +0 -87
  403. package/src/calls/call-store.ts +0 -422
  404. package/src/calls/elevenlabs-client.ts +0 -97
  405. package/src/calls/elevenlabs-config.ts +0 -31
  406. package/src/calls/relay-server.ts +0 -390
  407. package/src/calls/speaker-identification.ts +0 -213
  408. package/src/calls/twilio-config.ts +0 -45
  409. package/src/calls/twilio-provider.ts +0 -269
  410. package/src/calls/twilio-routes.ts +0 -311
  411. package/src/calls/types.ts +0 -39
  412. package/src/calls/voice-provider.ts +0 -14
  413. package/src/calls/voice-quality.ts +0 -114
  414. package/src/cli/autonomy.ts +0 -188
  415. package/src/cli/config-commands.ts +0 -334
  416. package/src/cli/contacts.ts +0 -149
  417. package/src/cli/core-commands.ts +0 -784
  418. package/src/cli/doordash.ts +0 -1055
  419. package/src/cli/email-guardrails.ts +0 -200
  420. package/src/cli/email.ts +0 -405
  421. package/src/cli/ipc-client.ts +0 -82
  422. package/src/cli/main-screen.tsx +0 -53
  423. package/src/cli/map.ts +0 -270
  424. package/src/cli/twitter.ts +0 -754
  425. package/src/cli.ts +0 -918
  426. package/src/commands/__tests__/cc-command-registry.test.ts +0 -319
  427. package/src/commands/cc-command-registry.ts +0 -209
  428. package/src/config/bundled-skills/.gitkeep +0 -0
  429. package/src/config/bundled-skills/agentmail/SKILL.md +0 -128
  430. package/src/config/bundled-skills/agentmail/icon.svg +0 -21
  431. package/src/config/bundled-skills/app-builder/SKILL.md +0 -1404
  432. package/src/config/bundled-skills/app-builder/TOOLS.json +0 -279
  433. package/src/config/bundled-skills/app-builder/icon.svg +0 -9
  434. package/src/config/bundled-skills/app-builder/tools/app-create.ts +0 -15
  435. package/src/config/bundled-skills/app-builder/tools/app-delete.ts +0 -10
  436. package/src/config/bundled-skills/app-builder/tools/app-file-edit.ts +0 -11
  437. package/src/config/bundled-skills/app-builder/tools/app-file-list.ts +0 -10
  438. package/src/config/bundled-skills/app-builder/tools/app-file-read.ts +0 -18
  439. package/src/config/bundled-skills/app-builder/tools/app-file-write.ts +0 -11
  440. package/src/config/bundled-skills/app-builder/tools/app-list.ts +0 -10
  441. package/src/config/bundled-skills/app-builder/tools/app-query.ts +0 -10
  442. package/src/config/bundled-skills/app-builder/tools/app-update.ts +0 -20
  443. package/src/config/bundled-skills/browser/SKILL.md +0 -28
  444. package/src/config/bundled-skills/browser/TOOLS.json +0 -234
  445. package/src/config/bundled-skills/browser/tools/browser-click.ts +0 -9
  446. package/src/config/bundled-skills/browser/tools/browser-close.ts +0 -9
  447. package/src/config/bundled-skills/browser/tools/browser-extract.ts +0 -9
  448. package/src/config/bundled-skills/browser/tools/browser-fill-credential.ts +0 -9
  449. package/src/config/bundled-skills/browser/tools/browser-navigate.ts +0 -9
  450. package/src/config/bundled-skills/browser/tools/browser-press-key.ts +0 -9
  451. package/src/config/bundled-skills/browser/tools/browser-screenshot.ts +0 -9
  452. package/src/config/bundled-skills/browser/tools/browser-snapshot.ts +0 -9
  453. package/src/config/bundled-skills/browser/tools/browser-type.ts +0 -9
  454. package/src/config/bundled-skills/browser/tools/browser-wait-for.ts +0 -9
  455. package/src/config/bundled-skills/claude-code/SKILL.md +0 -50
  456. package/src/config/bundled-skills/claude-code/TOOLS.json +0 -40
  457. package/src/config/bundled-skills/claude-code/tools/claude-code.ts +0 -9
  458. package/src/config/bundled-skills/computer-use/SKILL.md +0 -17
  459. package/src/config/bundled-skills/computer-use/TOOLS.json +0 -326
  460. package/src/config/bundled-skills/computer-use/tools/computer-use-click.ts +0 -9
  461. package/src/config/bundled-skills/computer-use/tools/computer-use-done.ts +0 -9
  462. package/src/config/bundled-skills/computer-use/tools/computer-use-double-click.ts +0 -9
  463. package/src/config/bundled-skills/computer-use/tools/computer-use-drag.ts +0 -9
  464. package/src/config/bundled-skills/computer-use/tools/computer-use-key.ts +0 -9
  465. package/src/config/bundled-skills/computer-use/tools/computer-use-open-app.ts +0 -9
  466. package/src/config/bundled-skills/computer-use/tools/computer-use-request-control.ts +0 -9
  467. package/src/config/bundled-skills/computer-use/tools/computer-use-respond.ts +0 -9
  468. package/src/config/bundled-skills/computer-use/tools/computer-use-right-click.ts +0 -9
  469. package/src/config/bundled-skills/computer-use/tools/computer-use-run-applescript.ts +0 -9
  470. package/src/config/bundled-skills/computer-use/tools/computer-use-scroll.ts +0 -9
  471. package/src/config/bundled-skills/computer-use/tools/computer-use-type-text.ts +0 -9
  472. package/src/config/bundled-skills/computer-use/tools/computer-use-wait.ts +0 -9
  473. package/src/config/bundled-skills/contacts/SKILL.md +0 -39
  474. package/src/config/bundled-skills/contacts/TOOLS.json +0 -122
  475. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +0 -57
  476. package/src/config/bundled-skills/contacts/tools/contact-search.ts +0 -60
  477. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -66
  478. package/src/config/bundled-skills/document/SKILL.md +0 -26
  479. package/src/config/bundled-skills/document/TOOLS.json +0 -53
  480. package/src/config/bundled-skills/document/tools/document-create.ts +0 -9
  481. package/src/config/bundled-skills/document/tools/document-update.ts +0 -9
  482. package/src/config/bundled-skills/doordash/SKILL.md +0 -163
  483. package/src/config/bundled-skills/followups/SKILL.md +0 -32
  484. package/src/config/bundled-skills/followups/TOOLS.json +0 -100
  485. package/src/config/bundled-skills/followups/icon.svg +0 -24
  486. package/src/config/bundled-skills/followups/tools/followup-create.ts +0 -9
  487. package/src/config/bundled-skills/followups/tools/followup-list.ts +0 -9
  488. package/src/config/bundled-skills/followups/tools/followup-resolve.ts +0 -9
  489. package/src/config/bundled-skills/google-calendar/SKILL.md +0 -51
  490. package/src/config/bundled-skills/google-calendar/TOOLS.json +0 -108
  491. package/src/config/bundled-skills/google-calendar/calendar-client.ts +0 -165
  492. package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +0 -21
  493. package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +0 -42
  494. package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +0 -13
  495. package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +0 -30
  496. package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +0 -41
  497. package/src/config/bundled-skills/google-calendar/tools/shared.ts +0 -18
  498. package/src/config/bundled-skills/google-calendar/types.ts +0 -97
  499. package/src/config/bundled-skills/image-studio/SKILL.md +0 -32
  500. package/src/config/bundled-skills/image-studio/TOOLS.json +0 -42
  501. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +0 -115
  502. package/src/config/bundled-skills/macos-automation/SKILL.md +0 -66
  503. package/src/config/bundled-skills/messaging/SKILL.md +0 -145
  504. package/src/config/bundled-skills/messaging/TOOLS.json +0 -357
  505. package/src/config/bundled-skills/messaging/tools/gmail-archive.ts +0 -23
  506. package/src/config/bundled-skills/messaging/tools/gmail-batch-archive.ts +0 -23
  507. package/src/config/bundled-skills/messaging/tools/gmail-batch-label.ts +0 -25
  508. package/src/config/bundled-skills/messaging/tools/gmail-draft.ts +0 -26
  509. package/src/config/bundled-skills/messaging/tools/gmail-label.ts +0 -25
  510. package/src/config/bundled-skills/messaging/tools/gmail-trash.ts +0 -23
  511. package/src/config/bundled-skills/messaging/tools/gmail-unsubscribe.ts +0 -84
  512. package/src/config/bundled-skills/messaging/tools/messaging-analyze-activity.ts +0 -18
  513. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +0 -125
  514. package/src/config/bundled-skills/messaging/tools/messaging-auth-test.ts +0 -16
  515. package/src/config/bundled-skills/messaging/tools/messaging-draft.ts +0 -49
  516. package/src/config/bundled-skills/messaging/tools/messaging-list-conversations.ts +0 -21
  517. package/src/config/bundled-skills/messaging/tools/messaging-mark-read.ts +0 -25
  518. package/src/config/bundled-skills/messaging/tools/messaging-read.ts +0 -28
  519. package/src/config/bundled-skills/messaging/tools/messaging-reply.ts +0 -32
  520. package/src/config/bundled-skills/messaging/tools/messaging-search.ts +0 -22
  521. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -31
  522. package/src/config/bundled-skills/messaging/tools/shared.ts +0 -76
  523. package/src/config/bundled-skills/messaging/tools/slack-add-reaction.ts +0 -25
  524. package/src/config/bundled-skills/messaging/tools/slack-leave-channel.ts +0 -23
  525. package/src/config/bundled-skills/phone-calls/SKILL.md +0 -522
  526. package/src/config/bundled-skills/playbooks/SKILL.md +0 -31
  527. package/src/config/bundled-skills/playbooks/TOOLS.json +0 -126
  528. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +0 -98
  529. package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +0 -54
  530. package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +0 -76
  531. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +0 -113
  532. package/src/config/bundled-skills/public-ingress/SKILL.md +0 -200
  533. package/src/config/bundled-skills/reminder/SKILL.md +0 -20
  534. package/src/config/bundled-skills/reminder/TOOLS.json +0 -67
  535. package/src/config/bundled-skills/reminder/tools/reminder-cancel.ts +0 -9
  536. package/src/config/bundled-skills/reminder/tools/reminder-create.ts +0 -9
  537. package/src/config/bundled-skills/reminder/tools/reminder-list.ts +0 -9
  538. package/src/config/bundled-skills/schedule/SKILL.md +0 -74
  539. package/src/config/bundled-skills/schedule/TOOLS.json +0 -135
  540. package/src/config/bundled-skills/schedule/tools/schedule-create.ts +0 -9
  541. package/src/config/bundled-skills/schedule/tools/schedule-delete.ts +0 -9
  542. package/src/config/bundled-skills/schedule/tools/schedule-list.ts +0 -9
  543. package/src/config/bundled-skills/schedule/tools/schedule-update.ts +0 -9
  544. package/src/config/bundled-skills/self-upgrade/SKILL.md +0 -68
  545. package/src/config/bundled-skills/start-the-day/SKILL.md +0 -70
  546. package/src/config/bundled-skills/start-the-day/icon.svg +0 -13
  547. package/src/config/bundled-skills/subagent/SKILL.md +0 -25
  548. package/src/config/bundled-skills/subagent/TOOLS.json +0 -107
  549. package/src/config/bundled-skills/subagent/tools/subagent-abort.ts +0 -9
  550. package/src/config/bundled-skills/subagent/tools/subagent-message.ts +0 -9
  551. package/src/config/bundled-skills/subagent/tools/subagent-read.ts +0 -9
  552. package/src/config/bundled-skills/subagent/tools/subagent-spawn.ts +0 -9
  553. package/src/config/bundled-skills/subagent/tools/subagent-status.ts +0 -9
  554. package/src/config/bundled-skills/tasks/SKILL.md +0 -28
  555. package/src/config/bundled-skills/tasks/TOOLS.json +0 -281
  556. package/src/config/bundled-skills/tasks/tools/task-delete.ts +0 -9
  557. package/src/config/bundled-skills/tasks/tools/task-list-add.ts +0 -9
  558. package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +0 -9
  559. package/src/config/bundled-skills/tasks/tools/task-list-show.ts +0 -9
  560. package/src/config/bundled-skills/tasks/tools/task-list-update.ts +0 -9
  561. package/src/config/bundled-skills/tasks/tools/task-list.ts +0 -9
  562. package/src/config/bundled-skills/tasks/tools/task-queue-run.ts +0 -9
  563. package/src/config/bundled-skills/tasks/tools/task-run.ts +0 -9
  564. package/src/config/bundled-skills/tasks/tools/task-save.ts +0 -9
  565. package/src/config/bundled-skills/transcribe/SKILL.md +0 -25
  566. package/src/config/bundled-skills/transcribe/TOOLS.json +0 -32
  567. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +0 -370
  568. package/src/config/bundled-skills/twitter/SKILL.md +0 -220
  569. package/src/config/bundled-skills/watcher/SKILL.md +0 -27
  570. package/src/config/bundled-skills/watcher/TOOLS.json +0 -147
  571. package/src/config/bundled-skills/watcher/tools/watcher-create.ts +0 -9
  572. package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +0 -9
  573. package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +0 -9
  574. package/src/config/bundled-skills/watcher/tools/watcher-list.ts +0 -9
  575. package/src/config/bundled-skills/watcher/tools/watcher-update.ts +0 -9
  576. package/src/config/bundled-skills/weather/SKILL.md +0 -37
  577. package/src/config/bundled-skills/weather/TOOLS.json +0 -32
  578. package/src/config/bundled-skills/weather/icon.svg +0 -24
  579. package/src/config/bundled-skills/weather/tools/get-weather.ts +0 -9
  580. package/src/config/computer-use-prompt.ts +0 -97
  581. package/src/config/defaults.ts +0 -258
  582. package/src/config/loader.ts +0 -339
  583. package/src/config/schema.ts +0 -1415
  584. package/src/config/skill-state.ts +0 -95
  585. package/src/config/skills.ts +0 -972
  586. package/src/config/system-prompt.ts +0 -675
  587. package/src/config/templates/BOOTSTRAP.md +0 -70
  588. package/src/config/templates/IDENTITY.md +0 -25
  589. package/src/config/templates/LOOKS.md +0 -25
  590. package/src/config/templates/SOUL.md +0 -37
  591. package/src/config/templates/USER.md +0 -19
  592. package/src/config/types.ts +0 -41
  593. package/src/config/vellum-skills/deploy-fullstack-vercel/SKILL.md +0 -179
  594. package/src/config/vellum-skills/document-writer/SKILL.md +0 -195
  595. package/src/config/vellum-skills/google-oauth-setup/SKILL.md +0 -199
  596. package/src/config/vellum-skills/slack-oauth-setup/SKILL.md +0 -153
  597. package/src/config/vellum-skills/telegram-setup/SKILL.md +0 -97
  598. package/src/contacts/contact-store.ts +0 -410
  599. package/src/contacts/index.ts +0 -11
  600. package/src/contacts/types.ts +0 -28
  601. package/src/context/token-estimator.ts +0 -108
  602. package/src/context/tool-result-truncation.ts +0 -128
  603. package/src/context/window-manager.ts +0 -531
  604. package/src/daemon/assistant-attachments.ts +0 -691
  605. package/src/daemon/classifier.ts +0 -110
  606. package/src/daemon/computer-use-session.ts +0 -903
  607. package/src/daemon/connection-policy.ts +0 -41
  608. package/src/daemon/date-context.ts +0 -136
  609. package/src/daemon/handlers/apps.ts +0 -530
  610. package/src/daemon/handlers/browser.ts +0 -54
  611. package/src/daemon/handlers/computer-use.ts +0 -187
  612. package/src/daemon/handlers/config.ts +0 -1226
  613. package/src/daemon/handlers/diagnostics.ts +0 -338
  614. package/src/daemon/handlers/documents.ts +0 -173
  615. package/src/daemon/handlers/home-base.ts +0 -78
  616. package/src/daemon/handlers/identity.ts +0 -127
  617. package/src/daemon/handlers/index.ts +0 -129
  618. package/src/daemon/handlers/misc.ts +0 -331
  619. package/src/daemon/handlers/open-bundle-handler.ts +0 -80
  620. package/src/daemon/handlers/publish.ts +0 -187
  621. package/src/daemon/handlers/sessions.ts +0 -555
  622. package/src/daemon/handlers/shared.ts +0 -570
  623. package/src/daemon/handlers/signing.ts +0 -37
  624. package/src/daemon/handlers/skills.ts +0 -486
  625. package/src/daemon/handlers/subagents.ts +0 -210
  626. package/src/daemon/handlers/twitter-auth.ts +0 -198
  627. package/src/daemon/handlers/work-items.ts +0 -632
  628. package/src/daemon/handlers/workspace-files.ts +0 -75
  629. package/src/daemon/handlers.ts +0 -17
  630. package/src/daemon/history-repair.ts +0 -214
  631. package/src/daemon/ipc-blob-store.ts +0 -231
  632. package/src/daemon/ipc-contract-inventory.json +0 -491
  633. package/src/daemon/ipc-contract-inventory.ts +0 -126
  634. package/src/daemon/ipc-contract.ts +0 -2510
  635. package/src/daemon/ipc-protocol.ts +0 -75
  636. package/src/daemon/ipc-validate.ts +0 -188
  637. package/src/daemon/lifecycle.ts +0 -582
  638. package/src/daemon/main.ts +0 -21
  639. package/src/daemon/media-visibility-policy.ts +0 -57
  640. package/src/daemon/ride-shotgun-handler.ts +0 -309
  641. package/src/daemon/server.ts +0 -1213
  642. package/src/daemon/session-agent-loop.ts +0 -922
  643. package/src/daemon/session-attachments.ts +0 -196
  644. package/src/daemon/session-conflict-gate.ts +0 -184
  645. package/src/daemon/session-dynamic-profile.ts +0 -63
  646. package/src/daemon/session-error.ts +0 -290
  647. package/src/daemon/session-evictor.ts +0 -196
  648. package/src/daemon/session-history.ts +0 -437
  649. package/src/daemon/session-lifecycle.ts +0 -147
  650. package/src/daemon/session-media-retry.ts +0 -147
  651. package/src/daemon/session-memory.ts +0 -212
  652. package/src/daemon/session-messaging.ts +0 -145
  653. package/src/daemon/session-notifiers.ts +0 -193
  654. package/src/daemon/session-process.ts +0 -323
  655. package/src/daemon/session-queue-manager.ts +0 -82
  656. package/src/daemon/session-runtime-assembly.ts +0 -447
  657. package/src/daemon/session-skill-tools.ts +0 -356
  658. package/src/daemon/session-slash.ts +0 -305
  659. package/src/daemon/session-surfaces.ts +0 -702
  660. package/src/daemon/session-tool-setup.ts +0 -523
  661. package/src/daemon/session-usage.ts +0 -72
  662. package/src/daemon/session-workspace.ts +0 -19
  663. package/src/daemon/session.ts +0 -400
  664. package/src/daemon/tls-certs.ts +0 -189
  665. package/src/daemon/trace-emitter.ts +0 -82
  666. package/src/daemon/video-thumbnail.ts +0 -62
  667. package/src/daemon/watch-handler.ts +0 -274
  668. package/src/doordash/client.ts +0 -999
  669. package/src/doordash/queries.ts +0 -1311
  670. package/src/doordash/query-extractor.ts +0 -93
  671. package/src/doordash/session.ts +0 -82
  672. package/src/email/provider.ts +0 -117
  673. package/src/email/providers/agentmail.ts +0 -317
  674. package/src/email/providers/index.ts +0 -58
  675. package/src/email/service.ts +0 -303
  676. package/src/email/types.ts +0 -126
  677. package/src/events/bus.ts +0 -157
  678. package/src/events/domain-events.ts +0 -83
  679. package/src/events/index.ts +0 -18
  680. package/src/events/tool-audit-listener.ts +0 -80
  681. package/src/events/tool-domain-event-publisher.ts +0 -111
  682. package/src/events/tool-metrics-listener.ts +0 -159
  683. package/src/events/tool-notification-listener.ts +0 -17
  684. package/src/events/tool-profiling-listener.ts +0 -158
  685. package/src/events/tool-trace-listener.ts +0 -75
  686. package/src/export/formatter.ts +0 -98
  687. package/src/followups/followup-store.ts +0 -168
  688. package/src/followups/index.ts +0 -10
  689. package/src/followups/types.ts +0 -29
  690. package/src/gallery/default-gallery.ts +0 -795
  691. package/src/gallery/gallery-manifest.ts +0 -24
  692. package/src/home-base/app-link-store.ts +0 -82
  693. package/src/home-base/bootstrap.ts +0 -68
  694. package/src/home-base/prebuilt/index.html +0 -662
  695. package/src/home-base/prebuilt/seed-metadata.json +0 -21
  696. package/src/home-base/prebuilt/seed.ts +0 -112
  697. package/src/home-base/prebuilt-home-base-updater.ts +0 -30
  698. package/src/hooks/cli.ts +0 -163
  699. package/src/hooks/config.ts +0 -88
  700. package/src/hooks/discovery.ts +0 -110
  701. package/src/hooks/manager.ts +0 -124
  702. package/src/hooks/runner.ts +0 -123
  703. package/src/hooks/templates.ts +0 -52
  704. package/src/hooks/types.ts +0 -72
  705. package/src/inbound/public-ingress-urls.ts +0 -123
  706. package/src/index.ts +0 -75
  707. package/src/instrument.ts +0 -60
  708. package/src/logfire.ts +0 -99
  709. package/src/media/gemini-image-service.ts +0 -136
  710. package/src/memory/account-store.ts +0 -108
  711. package/src/memory/admin.ts +0 -211
  712. package/src/memory/app-git-service.ts +0 -295
  713. package/src/memory/app-store.ts +0 -577
  714. package/src/memory/attachments-store.ts +0 -397
  715. package/src/memory/channel-delivery-store.ts +0 -353
  716. package/src/memory/checkpoints.ts +0 -52
  717. package/src/memory/clarification-resolver.ts +0 -298
  718. package/src/memory/conflict-intent.ts +0 -157
  719. package/src/memory/conflict-policy.ts +0 -73
  720. package/src/memory/conflict-store.ts +0 -350
  721. package/src/memory/contradiction-checker.ts +0 -358
  722. package/src/memory/conversation-key-store.ts +0 -122
  723. package/src/memory/conversation-store.ts +0 -470
  724. package/src/memory/db.ts +0 -1906
  725. package/src/memory/embedding-backend.ts +0 -229
  726. package/src/memory/embedding-gemini.ts +0 -52
  727. package/src/memory/embedding-local.ts +0 -65
  728. package/src/memory/embedding-ollama.ts +0 -55
  729. package/src/memory/embedding-openai.ts +0 -25
  730. package/src/memory/entity-extractor.ts +0 -474
  731. package/src/memory/external-conversation-store.ts +0 -234
  732. package/src/memory/fingerprint.ts +0 -20
  733. package/src/memory/indexer.ts +0 -156
  734. package/src/memory/items-extractor.ts +0 -461
  735. package/src/memory/job-handlers/backfill.ts +0 -139
  736. package/src/memory/job-handlers/cleanup.ts +0 -58
  737. package/src/memory/job-handlers/conflict.ts +0 -141
  738. package/src/memory/job-handlers/embedding.ts +0 -61
  739. package/src/memory/job-handlers/extraction.ts +0 -123
  740. package/src/memory/job-handlers/index-maintenance.ts +0 -54
  741. package/src/memory/job-handlers/summarization.ts +0 -286
  742. package/src/memory/job-utils.ts +0 -170
  743. package/src/memory/jobs-store.ts +0 -401
  744. package/src/memory/jobs-worker.ts +0 -313
  745. package/src/memory/llm-request-log-store.ts +0 -45
  746. package/src/memory/llm-usage-store.ts +0 -60
  747. package/src/memory/message-content.ts +0 -54
  748. package/src/memory/profile-compiler.ts +0 -160
  749. package/src/memory/published-pages-store.ts +0 -137
  750. package/src/memory/qdrant-client.ts +0 -366
  751. package/src/memory/qdrant-manager.ts +0 -242
  752. package/src/memory/query-builder.ts +0 -45
  753. package/src/memory/retrieval-budget.ts +0 -30
  754. package/src/memory/retriever.ts +0 -653
  755. package/src/memory/runs-store.ts +0 -302
  756. package/src/memory/schema.ts +0 -608
  757. package/src/memory/search/entity.ts +0 -298
  758. package/src/memory/search/formatting.ts +0 -207
  759. package/src/memory/search/lexical.ts +0 -227
  760. package/src/memory/search/ranking.ts +0 -401
  761. package/src/memory/search/semantic.ts +0 -121
  762. package/src/memory/search/types.ts +0 -137
  763. package/src/memory/segmenter.ts +0 -68
  764. package/src/memory/shared-app-links-store.ts +0 -138
  765. package/src/memory/tool-usage-store.ts +0 -62
  766. package/src/messaging/activity-analyzer.ts +0 -76
  767. package/src/messaging/draft-store.ts +0 -88
  768. package/src/messaging/index.ts +0 -3
  769. package/src/messaging/provider-types.ts +0 -80
  770. package/src/messaging/provider.ts +0 -52
  771. package/src/messaging/providers/gmail/adapter.ts +0 -193
  772. package/src/messaging/providers/gmail/client.ts +0 -204
  773. package/src/messaging/providers/gmail/types.ts +0 -90
  774. package/src/messaging/providers/slack/adapter.ts +0 -202
  775. package/src/messaging/providers/slack/client.ts +0 -198
  776. package/src/messaging/providers/slack/types.ts +0 -119
  777. package/src/messaging/providers/telegram-bot/adapter.ts +0 -162
  778. package/src/messaging/providers/telegram-bot/client.ts +0 -104
  779. package/src/messaging/providers/telegram-bot/types.ts +0 -15
  780. package/src/messaging/registry.ts +0 -35
  781. package/src/messaging/style-analyzer.ts +0 -159
  782. package/src/messaging/thread-summarizer.ts +0 -306
  783. package/src/messaging/triage-engine.ts +0 -323
  784. package/src/messaging/types.ts +0 -55
  785. package/src/permissions/checker.ts +0 -640
  786. package/src/permissions/defaults.ts +0 -254
  787. package/src/permissions/prompter.ts +0 -98
  788. package/src/permissions/secret-prompter.ts +0 -114
  789. package/src/permissions/shell-identity.ts +0 -227
  790. package/src/permissions/trust-store.ts +0 -607
  791. package/src/permissions/types.ts +0 -43
  792. package/src/permissions/workspace-policy.ts +0 -114
  793. package/src/playbooks/index.ts +0 -2
  794. package/src/playbooks/playbook-compiler.ts +0 -90
  795. package/src/playbooks/types.ts +0 -55
  796. package/src/providers/anthropic/client.ts +0 -751
  797. package/src/providers/failover.ts +0 -129
  798. package/src/providers/fireworks/client.ts +0 -20
  799. package/src/providers/gemini/client.ts +0 -285
  800. package/src/providers/ollama/client.ts +0 -30
  801. package/src/providers/openai/client.ts +0 -337
  802. package/src/providers/openrouter/client.ts +0 -20
  803. package/src/providers/ratelimit.ts +0 -93
  804. package/src/providers/registry.ts +0 -146
  805. package/src/providers/retry.ts +0 -81
  806. package/src/providers/stream-timeout.ts +0 -38
  807. package/src/providers/types.ts +0 -109
  808. package/src/runtime/assistant-event-hub.ts +0 -157
  809. package/src/runtime/assistant-event.ts +0 -82
  810. package/src/runtime/channel-approval-parser.ts +0 -60
  811. package/src/runtime/channel-approval-types.ts +0 -71
  812. package/src/runtime/channel-approvals.ts +0 -145
  813. package/src/runtime/gateway-client.ts +0 -58
  814. package/src/runtime/http-server.ts +0 -1076
  815. package/src/runtime/http-types.ts +0 -66
  816. package/src/runtime/routes/app-routes.ts +0 -174
  817. package/src/runtime/routes/attachment-routes.ts +0 -133
  818. package/src/runtime/routes/call-routes.ts +0 -190
  819. package/src/runtime/routes/channel-routes.ts +0 -662
  820. package/src/runtime/routes/conversation-routes.ts +0 -352
  821. package/src/runtime/routes/events-routes.ts +0 -148
  822. package/src/runtime/routes/run-routes.ts +0 -257
  823. package/src/runtime/routes/secret-routes.ts +0 -76
  824. package/src/runtime/run-orchestrator.ts +0 -293
  825. package/src/schedule/recurrence-engine.ts +0 -162
  826. package/src/schedule/recurrence-types.ts +0 -67
  827. package/src/schedule/schedule-store.ts +0 -506
  828. package/src/schedule/scheduler.ts +0 -171
  829. package/src/security/encrypted-store.ts +0 -238
  830. package/src/security/keychain.ts +0 -252
  831. package/src/security/oauth-callback-registry.ts +0 -66
  832. package/src/security/oauth2.ts +0 -274
  833. package/src/security/redaction.ts +0 -89
  834. package/src/security/secret-allowlist.ts +0 -164
  835. package/src/security/secret-ingress.ts +0 -57
  836. package/src/security/secret-scanner.ts +0 -550
  837. package/src/security/secure-keys.ts +0 -180
  838. package/src/security/token-manager.ts +0 -141
  839. package/src/services/published-app-updater.ts +0 -69
  840. package/src/services/vercel-deploy.ts +0 -73
  841. package/src/skills/active-skill-tools.ts +0 -81
  842. package/src/skills/clawhub.ts +0 -414
  843. package/src/skills/include-graph.ts +0 -146
  844. package/src/skills/managed-store.ts +0 -233
  845. package/src/skills/path-classifier.ts +0 -128
  846. package/src/skills/slash-commands.ts +0 -174
  847. package/src/skills/tool-manifest.ts +0 -165
  848. package/src/skills/version-hash.ts +0 -110
  849. package/src/slack/slack-webhook.ts +0 -61
  850. package/src/subagent/index.ts +0 -19
  851. package/src/subagent/manager.ts +0 -511
  852. package/src/subagent/types.ts +0 -69
  853. package/src/swarm/backend-claude-code.ts +0 -145
  854. package/src/swarm/index.ts +0 -44
  855. package/src/swarm/limits.ts +0 -37
  856. package/src/swarm/orchestrator.ts +0 -279
  857. package/src/swarm/plan-validator.ts +0 -151
  858. package/src/swarm/router-planner.ts +0 -100
  859. package/src/swarm/router-prompts.ts +0 -36
  860. package/src/swarm/synthesizer.ts +0 -62
  861. package/src/swarm/types.ts +0 -62
  862. package/src/swarm/worker-backend.ts +0 -121
  863. package/src/swarm/worker-prompts.ts +0 -79
  864. package/src/swarm/worker-runner.ts +0 -164
  865. package/src/tasks/SPEC.md +0 -139
  866. package/src/tasks/candidate-store.ts +0 -86
  867. package/src/tasks/ephemeral-permissions.ts +0 -48
  868. package/src/tasks/task-compiler.ts +0 -199
  869. package/src/tasks/task-runner.ts +0 -90
  870. package/src/tasks/task-scheduler.ts +0 -21
  871. package/src/tasks/task-store.ts +0 -127
  872. package/src/tasks/tool-sanitizer.ts +0 -36
  873. package/src/tools/apps/definitions.ts +0 -59
  874. package/src/tools/apps/executors.ts +0 -313
  875. package/src/tools/apps/open-proxy.ts +0 -43
  876. package/src/tools/apps/registry.ts +0 -16
  877. package/src/tools/assets/materialize.ts +0 -218
  878. package/src/tools/assets/search.ts +0 -361
  879. package/src/tools/browser/__tests__/auth-cache.test.ts +0 -219
  880. package/src/tools/browser/__tests__/auth-detector.test.ts +0 -362
  881. package/src/tools/browser/__tests__/jit-auth.test.ts +0 -189
  882. package/src/tools/browser/api-map.ts +0 -293
  883. package/src/tools/browser/auth-cache.ts +0 -149
  884. package/src/tools/browser/auth-detector.ts +0 -347
  885. package/src/tools/browser/auto-navigate.ts +0 -270
  886. package/src/tools/browser/browser-execution.ts +0 -980
  887. package/src/tools/browser/browser-handoff.ts +0 -79
  888. package/src/tools/browser/browser-manager.ts +0 -715
  889. package/src/tools/browser/browser-screencast.ts +0 -217
  890. package/src/tools/browser/headless-browser.ts +0 -450
  891. package/src/tools/browser/jit-auth.ts +0 -51
  892. package/src/tools/browser/network-recorder.ts +0 -349
  893. package/src/tools/browser/network-recording-types.ts +0 -49
  894. package/src/tools/browser/recording-store.ts +0 -49
  895. package/src/tools/browser/runtime-check.ts +0 -43
  896. package/src/tools/browser/x-auto-navigate.ts +0 -207
  897. package/src/tools/calls/call-end.ts +0 -67
  898. package/src/tools/calls/call-start.ts +0 -81
  899. package/src/tools/calls/call-status.ts +0 -81
  900. package/src/tools/claude-code/claude-code.ts +0 -428
  901. package/src/tools/computer-use/definitions.ts +0 -443
  902. package/src/tools/computer-use/registry.ts +0 -22
  903. package/src/tools/computer-use/request-computer-control.ts +0 -53
  904. package/src/tools/computer-use/skill-proxy-bridge.ts +0 -28
  905. package/src/tools/credentials/account-registry.ts +0 -127
  906. package/src/tools/credentials/broker-types.ts +0 -107
  907. package/src/tools/credentials/broker.ts +0 -372
  908. package/src/tools/credentials/domain-policy.ts +0 -51
  909. package/src/tools/credentials/host-pattern-match.ts +0 -60
  910. package/src/tools/credentials/metadata-store.ts +0 -335
  911. package/src/tools/credentials/policy-types.ts +0 -52
  912. package/src/tools/credentials/policy-validate.ts +0 -80
  913. package/src/tools/credentials/resolve.ts +0 -122
  914. package/src/tools/credentials/selection.ts +0 -159
  915. package/src/tools/credentials/tool-policy.ts +0 -25
  916. package/src/tools/credentials/vault.ts +0 -657
  917. package/src/tools/document/document-tool.ts +0 -92
  918. package/src/tools/document/editor-template.ts +0 -237
  919. package/src/tools/execution-target.ts +0 -21
  920. package/src/tools/execution-timeout.ts +0 -49
  921. package/src/tools/executor.ts +0 -815
  922. package/src/tools/filesystem/edit.ts +0 -127
  923. package/src/tools/filesystem/fuzzy-match.ts +0 -202
  924. package/src/tools/filesystem/read.ts +0 -71
  925. package/src/tools/filesystem/view-image.ts +0 -199
  926. package/src/tools/filesystem/write.ts +0 -79
  927. package/src/tools/followups/followup_create.ts +0 -76
  928. package/src/tools/followups/followup_list.ts +0 -60
  929. package/src/tools/followups/followup_resolve.ts +0 -56
  930. package/src/tools/host-filesystem/edit.ts +0 -125
  931. package/src/tools/host-filesystem/read.ts +0 -80
  932. package/src/tools/host-filesystem/write.ts +0 -76
  933. package/src/tools/host-terminal/cli-discover.ts +0 -180
  934. package/src/tools/host-terminal/host-shell.ts +0 -191
  935. package/src/tools/memory/definitions.ts +0 -69
  936. package/src/tools/memory/handlers.ts +0 -246
  937. package/src/tools/memory/register.ts +0 -66
  938. package/src/tools/network/__tests__/web-search.test.ts +0 -427
  939. package/src/tools/network/domain-normalize.ts +0 -85
  940. package/src/tools/network/script-proxy/__tests__/logging.test.ts +0 -248
  941. package/src/tools/network/script-proxy/__tests__/policy.test.ts +0 -234
  942. package/src/tools/network/script-proxy/__tests__/router.test.ts +0 -76
  943. package/src/tools/network/script-proxy/certs.ts +0 -237
  944. package/src/tools/network/script-proxy/connect-tunnel.ts +0 -82
  945. package/src/tools/network/script-proxy/http-forwarder.ts +0 -151
  946. package/src/tools/network/script-proxy/index.ts +0 -28
  947. package/src/tools/network/script-proxy/logging.ts +0 -196
  948. package/src/tools/network/script-proxy/mitm-handler.ts +0 -269
  949. package/src/tools/network/script-proxy/policy.ts +0 -152
  950. package/src/tools/network/script-proxy/router.ts +0 -60
  951. package/src/tools/network/script-proxy/server.ts +0 -136
  952. package/src/tools/network/script-proxy/session-manager.ts +0 -534
  953. package/src/tools/network/script-proxy/types.ts +0 -125
  954. package/src/tools/network/url-safety.ts +0 -227
  955. package/src/tools/network/web-fetch.ts +0 -713
  956. package/src/tools/network/web-search.ts +0 -296
  957. package/src/tools/policy-context.ts +0 -29
  958. package/src/tools/registry.ts +0 -295
  959. package/src/tools/reminder/reminder-store.ts +0 -148
  960. package/src/tools/reminder/reminder.ts +0 -80
  961. package/src/tools/schedule/create.ts +0 -81
  962. package/src/tools/schedule/delete.ts +0 -28
  963. package/src/tools/schedule/list.ts +0 -69
  964. package/src/tools/schedule/update.ts +0 -97
  965. package/src/tools/shared/filesystem/edit-engine.ts +0 -56
  966. package/src/tools/shared/filesystem/errors.ts +0 -85
  967. package/src/tools/shared/filesystem/file-ops-service.ts +0 -215
  968. package/src/tools/shared/filesystem/format-diff.ts +0 -35
  969. package/src/tools/shared/filesystem/path-policy.ts +0 -125
  970. package/src/tools/shared/filesystem/size-guard.ts +0 -41
  971. package/src/tools/shared/filesystem/types.ts +0 -80
  972. package/src/tools/shared/shell-output.ts +0 -52
  973. package/src/tools/skills/delete-managed.ts +0 -60
  974. package/src/tools/skills/load.ts +0 -139
  975. package/src/tools/skills/sandbox-runner.ts +0 -279
  976. package/src/tools/skills/scaffold-managed.ts +0 -150
  977. package/src/tools/skills/script-contract.ts +0 -6
  978. package/src/tools/skills/skill-script-runner.ts +0 -86
  979. package/src/tools/skills/skill-tool-factory.ts +0 -64
  980. package/src/tools/skills/vellum-catalog.ts +0 -217
  981. package/src/tools/subagent/abort.ts +0 -33
  982. package/src/tools/subagent/message.ts +0 -39
  983. package/src/tools/subagent/read.ts +0 -67
  984. package/src/tools/subagent/spawn.ts +0 -46
  985. package/src/tools/subagent/status.ts +0 -45
  986. package/src/tools/swarm/delegate.ts +0 -183
  987. package/src/tools/system/request-permission.ts +0 -98
  988. package/src/tools/system/version.ts +0 -43
  989. package/src/tools/tasks/index.ts +0 -27
  990. package/src/tools/tasks/task-delete.ts +0 -82
  991. package/src/tools/tasks/task-list.ts +0 -44
  992. package/src/tools/tasks/task-run.ts +0 -97
  993. package/src/tools/tasks/task-save.ts +0 -47
  994. package/src/tools/tasks/work-item-enqueue.ts +0 -234
  995. package/src/tools/tasks/work-item-list.ts +0 -55
  996. package/src/tools/tasks/work-item-remove.ts +0 -60
  997. package/src/tools/tasks/work-item-run.ts +0 -78
  998. package/src/tools/tasks/work-item-update.ts +0 -114
  999. package/src/tools/terminal/backends/docker.ts +0 -372
  1000. package/src/tools/terminal/backends/native.ts +0 -190
  1001. package/src/tools/terminal/backends/types.ts +0 -26
  1002. package/src/tools/terminal/evaluate-typescript.ts +0 -275
  1003. package/src/tools/terminal/parser.ts +0 -413
  1004. package/src/tools/terminal/safe-env.ts +0 -37
  1005. package/src/tools/terminal/sandbox-diagnostics.ts +0 -149
  1006. package/src/tools/terminal/sandbox.ts +0 -44
  1007. package/src/tools/terminal/shell.ts +0 -257
  1008. package/src/tools/tool-manifest.ts +0 -198
  1009. package/src/tools/types.ts +0 -176
  1010. package/src/tools/ui-surface/definitions.ts +0 -244
  1011. package/src/tools/ui-surface/registry.ts +0 -14
  1012. package/src/tools/watch/screen-watch.ts +0 -130
  1013. package/src/tools/watch/watch-state.ts +0 -119
  1014. package/src/tools/watcher/create.ts +0 -64
  1015. package/src/tools/watcher/delete.ts +0 -27
  1016. package/src/tools/watcher/digest.ts +0 -50
  1017. package/src/tools/watcher/list.ts +0 -60
  1018. package/src/tools/watcher/update.ts +0 -56
  1019. package/src/tools/weather/service.ts +0 -551
  1020. package/src/twitter/client.ts +0 -690
  1021. package/src/twitter/oauth-client.ts +0 -102
  1022. package/src/twitter/router.ts +0 -101
  1023. package/src/twitter/session.ts +0 -91
  1024. package/src/usage/actors.ts +0 -24
  1025. package/src/usage/types.ts +0 -37
  1026. package/src/util/clipboard.ts +0 -33
  1027. package/src/util/content-id.ts +0 -16
  1028. package/src/util/debounce.ts +0 -88
  1029. package/src/util/diff.ts +0 -181
  1030. package/src/util/errors.ts +0 -129
  1031. package/src/util/logger.ts +0 -243
  1032. package/src/util/network-info.ts +0 -47
  1033. package/src/util/platform.ts +0 -632
  1034. package/src/util/pricing.ts +0 -150
  1035. package/src/util/promise-guard.ts +0 -37
  1036. package/src/util/retry.ts +0 -98
  1037. package/src/util/spinner.ts +0 -51
  1038. package/src/util/time.ts +0 -16
  1039. package/src/util/truncate.ts +0 -6
  1040. package/src/util/xml.ts +0 -4
  1041. package/src/version.ts +0 -3
  1042. package/src/watcher/constants.ts +0 -11
  1043. package/src/watcher/engine.ts +0 -199
  1044. package/src/watcher/provider-registry.ts +0 -15
  1045. package/src/watcher/provider-types.ts +0 -48
  1046. package/src/watcher/providers/gmail.ts +0 -198
  1047. package/src/watcher/providers/google-calendar.ts +0 -228
  1048. package/src/watcher/providers/slack.ts +0 -129
  1049. package/src/watcher/watcher-store.ts +0 -419
  1050. package/src/work-items/work-item-runner.ts +0 -171
  1051. package/src/work-items/work-item-store.ts +0 -325
  1052. package/src/workspace/commit-message-enrichment-service.ts +0 -284
  1053. package/src/workspace/commit-message-provider.ts +0 -95
  1054. package/src/workspace/git-service.ts +0 -857
  1055. package/src/workspace/heartbeat-service.ts +0 -345
  1056. package/src/workspace/provider-commit-message-generator.ts +0 -285
  1057. package/src/workspace/top-level-renderer.ts +0 -19
  1058. package/src/workspace/top-level-scanner.ts +0 -41
  1059. package/src/workspace/turn-commit.ts +0 -175
  1060. package/tsconfig.json +0 -21
package/src/memory/db.ts DELETED
@@ -1,1906 +0,0 @@
1
- import { Database } from 'bun:sqlite';
2
- import { drizzle } from 'drizzle-orm/bun-sqlite';
3
- import { computeMemoryFingerprint } from './fingerprint.js';
4
- import * as schema from './schema.js';
5
- import { getDbPath, ensureDataDir, migrateToDataLayout, migrateToWorkspaceLayout } from '../util/platform.js';
6
- import { getLogger } from '../util/logger.js';
7
-
8
- const log = getLogger('memory-db');
9
-
10
- let db: ReturnType<typeof drizzle<typeof schema>> | null = null;
11
-
12
- export function getDb() {
13
- if (!db) {
14
- migrateToDataLayout();
15
- migrateToWorkspaceLayout();
16
- ensureDataDir();
17
- const sqlite = new Database(getDbPath());
18
- sqlite.exec('PRAGMA journal_mode=WAL');
19
- sqlite.exec('PRAGMA foreign_keys = ON');
20
- db = drizzle(sqlite, { schema });
21
- }
22
- return db;
23
- }
24
-
25
- /** Reset the db singleton. Used by tests to ensure isolation between test files. */
26
- export function resetDb(): void {
27
- if (db) {
28
- const raw = (db as unknown as { $client: Database }).$client;
29
- raw.close();
30
- db = null;
31
- }
32
- }
33
-
34
- export function initializeDb(): void {
35
- const database = getDb();
36
-
37
- database.run(/*sql*/ `
38
- CREATE TABLE IF NOT EXISTS conversations (
39
- id TEXT PRIMARY KEY,
40
- title TEXT,
41
- created_at INTEGER NOT NULL,
42
- updated_at INTEGER NOT NULL,
43
- total_input_tokens INTEGER NOT NULL DEFAULT 0,
44
- total_output_tokens INTEGER NOT NULL DEFAULT 0,
45
- total_estimated_cost REAL NOT NULL DEFAULT 0,
46
- context_summary TEXT,
47
- context_compacted_message_count INTEGER NOT NULL DEFAULT 0,
48
- context_compacted_at INTEGER
49
- )
50
- `);
51
-
52
- database.run(/*sql*/ `
53
- CREATE TABLE IF NOT EXISTS messages (
54
- id TEXT PRIMARY KEY,
55
- conversation_id TEXT NOT NULL REFERENCES conversations(id),
56
- role TEXT NOT NULL,
57
- content TEXT NOT NULL,
58
- created_at INTEGER NOT NULL
59
- )
60
- `);
61
-
62
- database.run(/*sql*/ `
63
- CREATE TABLE IF NOT EXISTS tool_invocations (
64
- id TEXT PRIMARY KEY,
65
- conversation_id TEXT NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
66
- tool_name TEXT NOT NULL,
67
- input TEXT NOT NULL,
68
- result TEXT NOT NULL,
69
- decision TEXT NOT NULL,
70
- risk_level TEXT NOT NULL,
71
- duration_ms INTEGER NOT NULL,
72
- created_at INTEGER NOT NULL
73
- )
74
- `);
75
-
76
- database.run(/*sql*/ `
77
- CREATE TABLE IF NOT EXISTS memory_segments (
78
- id TEXT PRIMARY KEY,
79
- message_id TEXT NOT NULL REFERENCES messages(id) ON DELETE CASCADE,
80
- conversation_id TEXT NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
81
- role TEXT NOT NULL,
82
- segment_index INTEGER NOT NULL,
83
- text TEXT NOT NULL,
84
- token_estimate INTEGER NOT NULL,
85
- created_at INTEGER NOT NULL,
86
- updated_at INTEGER NOT NULL
87
- )
88
- `);
89
-
90
- database.run(/*sql*/ `
91
- CREATE TABLE IF NOT EXISTS memory_items (
92
- id TEXT PRIMARY KEY,
93
- kind TEXT NOT NULL,
94
- subject TEXT NOT NULL,
95
- statement TEXT NOT NULL,
96
- status TEXT NOT NULL,
97
- confidence REAL NOT NULL,
98
- fingerprint TEXT NOT NULL,
99
- first_seen_at INTEGER NOT NULL,
100
- last_seen_at INTEGER NOT NULL,
101
- last_used_at INTEGER
102
- )
103
- `);
104
-
105
- database.run(/*sql*/ `
106
- CREATE TABLE IF NOT EXISTS memory_item_sources (
107
- memory_item_id TEXT NOT NULL REFERENCES memory_items(id) ON DELETE CASCADE,
108
- message_id TEXT NOT NULL REFERENCES messages(id) ON DELETE CASCADE,
109
- evidence TEXT,
110
- created_at INTEGER NOT NULL,
111
- PRIMARY KEY (memory_item_id, message_id)
112
- )
113
- `);
114
-
115
- database.run(/*sql*/ `
116
- CREATE TABLE IF NOT EXISTS memory_item_conflicts (
117
- id TEXT PRIMARY KEY,
118
- scope_id TEXT NOT NULL DEFAULT 'default',
119
- existing_item_id TEXT NOT NULL REFERENCES memory_items(id) ON DELETE CASCADE,
120
- candidate_item_id TEXT NOT NULL REFERENCES memory_items(id) ON DELETE CASCADE,
121
- relationship TEXT NOT NULL,
122
- status TEXT NOT NULL,
123
- clarification_question TEXT,
124
- resolution_note TEXT,
125
- last_asked_at INTEGER,
126
- resolved_at INTEGER,
127
- created_at INTEGER NOT NULL,
128
- updated_at INTEGER NOT NULL
129
- )
130
- `);
131
-
132
- database.run(/*sql*/ `
133
- CREATE TABLE IF NOT EXISTS memory_summaries (
134
- id TEXT PRIMARY KEY,
135
- scope TEXT NOT NULL,
136
- scope_key TEXT NOT NULL,
137
- summary TEXT NOT NULL,
138
- token_estimate INTEGER NOT NULL,
139
- start_at INTEGER NOT NULL,
140
- end_at INTEGER NOT NULL,
141
- created_at INTEGER NOT NULL,
142
- updated_at INTEGER NOT NULL,
143
- UNIQUE (scope, scope_key)
144
- )
145
- `);
146
-
147
- database.run(/*sql*/ `
148
- CREATE TABLE IF NOT EXISTS memory_embeddings (
149
- id TEXT PRIMARY KEY,
150
- target_type TEXT NOT NULL,
151
- target_id TEXT NOT NULL,
152
- provider TEXT NOT NULL,
153
- model TEXT NOT NULL,
154
- dimensions INTEGER NOT NULL,
155
- vector_json TEXT NOT NULL,
156
- created_at INTEGER NOT NULL,
157
- updated_at INTEGER NOT NULL,
158
- UNIQUE (target_type, target_id, provider, model)
159
- )
160
- `);
161
-
162
- database.run(/*sql*/ `
163
- CREATE TABLE IF NOT EXISTS memory_jobs (
164
- id TEXT PRIMARY KEY,
165
- type TEXT NOT NULL,
166
- payload TEXT NOT NULL,
167
- status TEXT NOT NULL,
168
- attempts INTEGER NOT NULL DEFAULT 0,
169
- run_after INTEGER NOT NULL,
170
- last_error TEXT,
171
- created_at INTEGER NOT NULL,
172
- updated_at INTEGER NOT NULL
173
- )
174
- `);
175
-
176
- database.run(/*sql*/ `
177
- CREATE TABLE IF NOT EXISTS memory_checkpoints (
178
- key TEXT PRIMARY KEY,
179
- value TEXT NOT NULL,
180
- updated_at INTEGER NOT NULL
181
- )
182
- `);
183
-
184
- database.run(/*sql*/ `
185
- CREATE TABLE IF NOT EXISTS attachments (
186
- id TEXT PRIMARY KEY,
187
- original_filename TEXT NOT NULL,
188
- mime_type TEXT NOT NULL,
189
- size_bytes INTEGER NOT NULL,
190
- kind TEXT NOT NULL,
191
- data_base64 TEXT NOT NULL,
192
- created_at INTEGER NOT NULL
193
- )
194
- `);
195
-
196
- database.run(/*sql*/ `
197
- CREATE TABLE IF NOT EXISTS message_attachments (
198
- id TEXT PRIMARY KEY,
199
- message_id TEXT NOT NULL REFERENCES messages(id) ON DELETE CASCADE,
200
- attachment_id TEXT NOT NULL REFERENCES attachments(id) ON DELETE CASCADE,
201
- position INTEGER NOT NULL DEFAULT 0,
202
- created_at INTEGER NOT NULL
203
- )
204
- `);
205
-
206
- database.run(/*sql*/ `
207
- CREATE TABLE IF NOT EXISTS message_surfaces (
208
- id TEXT PRIMARY KEY,
209
- message_id TEXT NOT NULL REFERENCES messages(id) ON DELETE CASCADE,
210
- surface_id TEXT NOT NULL,
211
- surface_type TEXT NOT NULL,
212
- title TEXT,
213
- data TEXT NOT NULL,
214
- actions TEXT,
215
- surface_message TEXT,
216
- display TEXT,
217
- position INTEGER NOT NULL DEFAULT 0,
218
- created_at INTEGER NOT NULL
219
- )
220
- `);
221
-
222
- database.run(/*sql*/ `
223
- CREATE TABLE IF NOT EXISTS channel_inbound_events (
224
- id TEXT PRIMARY KEY,
225
- source_channel TEXT NOT NULL,
226
- external_chat_id TEXT NOT NULL,
227
- external_message_id TEXT NOT NULL,
228
- conversation_id TEXT NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
229
- message_id TEXT REFERENCES messages(id) ON DELETE CASCADE,
230
- delivery_status TEXT NOT NULL DEFAULT 'pending',
231
- created_at INTEGER NOT NULL,
232
- updated_at INTEGER NOT NULL,
233
- UNIQUE (source_channel, external_chat_id, external_message_id)
234
- )
235
- `);
236
-
237
- database.run(/*sql*/ `
238
- CREATE TABLE IF NOT EXISTS message_runs (
239
- id TEXT PRIMARY KEY,
240
- conversation_id TEXT NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
241
- message_id TEXT REFERENCES messages(id) ON DELETE CASCADE,
242
- status TEXT NOT NULL DEFAULT 'running',
243
- pending_confirmation TEXT,
244
- pending_secret TEXT,
245
- input_tokens INTEGER NOT NULL DEFAULT 0,
246
- output_tokens INTEGER NOT NULL DEFAULT 0,
247
- estimated_cost REAL NOT NULL DEFAULT 0,
248
- error TEXT,
249
- created_at INTEGER NOT NULL,
250
- updated_at INTEGER NOT NULL
251
- )
252
- `);
253
-
254
- try { database.run(/*sql*/ `ALTER TABLE message_runs ADD COLUMN pending_secret TEXT`); } catch (e) { log.debug({ err: e }, 'ALTER TABLE message_runs ADD COLUMN pending_secret (likely already exists)'); }
255
-
256
- database.run(/*sql*/ `
257
- CREATE TABLE IF NOT EXISTS reminders (
258
- id TEXT PRIMARY KEY,
259
- label TEXT NOT NULL,
260
- message TEXT NOT NULL,
261
- fire_at INTEGER NOT NULL,
262
- mode TEXT NOT NULL,
263
- status TEXT NOT NULL,
264
- fired_at INTEGER,
265
- conversation_id TEXT,
266
- created_at INTEGER NOT NULL,
267
- updated_at INTEGER NOT NULL
268
- )
269
- `);
270
-
271
- database.run(/*sql*/ `
272
- CREATE TABLE IF NOT EXISTS cron_jobs (
273
- id TEXT PRIMARY KEY,
274
- name TEXT NOT NULL,
275
- enabled INTEGER NOT NULL DEFAULT 1,
276
- cron_expression TEXT NOT NULL,
277
- schedule_syntax TEXT NOT NULL DEFAULT 'cron',
278
- timezone TEXT,
279
- message TEXT NOT NULL,
280
- next_run_at INTEGER NOT NULL,
281
- last_run_at INTEGER,
282
- last_status TEXT,
283
- retry_count INTEGER NOT NULL DEFAULT 0,
284
- created_by TEXT NOT NULL,
285
- created_at INTEGER NOT NULL,
286
- updated_at INTEGER NOT NULL
287
- )
288
- `);
289
-
290
- database.run(/*sql*/ `
291
- CREATE TABLE IF NOT EXISTS cron_runs (
292
- id TEXT PRIMARY KEY,
293
- job_id TEXT NOT NULL REFERENCES cron_jobs(id) ON DELETE CASCADE,
294
- status TEXT NOT NULL,
295
- started_at INTEGER NOT NULL,
296
- finished_at INTEGER,
297
- duration_ms INTEGER,
298
- output TEXT,
299
- error TEXT,
300
- conversation_id TEXT,
301
- created_at INTEGER NOT NULL
302
- )
303
- `);
304
-
305
- database.run(/*sql*/ `
306
- CREATE TABLE IF NOT EXISTS accounts (
307
- id TEXT PRIMARY KEY,
308
- service TEXT NOT NULL,
309
- username TEXT,
310
- email TEXT,
311
- display_name TEXT,
312
- status TEXT NOT NULL DEFAULT 'active',
313
- credential_ref TEXT,
314
- metadata_json TEXT,
315
- created_at INTEGER NOT NULL,
316
- updated_at INTEGER NOT NULL
317
- )
318
- `);
319
-
320
- database.run(/*sql*/ `
321
- CREATE TABLE IF NOT EXISTS documents (
322
- surface_id TEXT PRIMARY KEY,
323
- conversation_id TEXT NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
324
- title TEXT NOT NULL,
325
- content TEXT NOT NULL,
326
- word_count INTEGER NOT NULL DEFAULT 0,
327
- created_at INTEGER NOT NULL,
328
- updated_at INTEGER NOT NULL
329
- )
330
- `);
331
-
332
- database.run(/*sql*/ `
333
- CREATE TABLE IF NOT EXISTS published_pages (
334
- id TEXT PRIMARY KEY,
335
- deployment_id TEXT NOT NULL UNIQUE,
336
- public_url TEXT NOT NULL,
337
- page_title TEXT,
338
- html_hash TEXT NOT NULL,
339
- published_at INTEGER NOT NULL,
340
- status TEXT NOT NULL DEFAULT 'active'
341
- )
342
- `);
343
-
344
- try { database.run(/*sql*/ `ALTER TABLE published_pages ADD COLUMN app_id TEXT`); } catch (e) { log.debug({ err: e }, 'ALTER TABLE published_pages ADD COLUMN app_id (likely already exists)'); }
345
- try { database.run(/*sql*/ `ALTER TABLE published_pages ADD COLUMN project_slug TEXT`); } catch (e) { log.debug({ err: e }, 'ALTER TABLE published_pages ADD COLUMN project_slug (likely already exists)'); }
346
-
347
- database.run(/*sql*/ `
348
- CREATE TABLE IF NOT EXISTS shared_app_links (
349
- id TEXT PRIMARY KEY,
350
- share_token TEXT NOT NULL UNIQUE,
351
- bundle_data BLOB NOT NULL,
352
- bundle_size_bytes INTEGER NOT NULL,
353
- manifest_json TEXT NOT NULL,
354
- download_count INTEGER NOT NULL DEFAULT 0,
355
- created_at INTEGER NOT NULL,
356
- expires_at INTEGER
357
- )
358
- `);
359
-
360
- database.run(/*sql*/ `
361
- CREATE TABLE IF NOT EXISTS home_base_app_links (
362
- id TEXT PRIMARY KEY,
363
- app_id TEXT NOT NULL,
364
- source TEXT NOT NULL,
365
- created_at INTEGER NOT NULL,
366
- updated_at INTEGER NOT NULL
367
- )
368
- `);
369
-
370
- // ── Watchers ─────────────────────────────────────────────────────────
371
-
372
- database.run(/*sql*/ `
373
- CREATE TABLE IF NOT EXISTS watchers (
374
- id TEXT PRIMARY KEY,
375
- name TEXT NOT NULL,
376
- provider_id TEXT NOT NULL,
377
- enabled INTEGER NOT NULL DEFAULT 1,
378
- poll_interval_ms INTEGER NOT NULL DEFAULT 60000,
379
- action_prompt TEXT NOT NULL,
380
- watermark TEXT,
381
- conversation_id TEXT,
382
- status TEXT NOT NULL DEFAULT 'idle',
383
- consecutive_errors INTEGER NOT NULL DEFAULT 0,
384
- last_error TEXT,
385
- last_poll_at INTEGER,
386
- next_poll_at INTEGER NOT NULL,
387
- config_json TEXT,
388
- credential_service TEXT NOT NULL,
389
- created_at INTEGER NOT NULL,
390
- updated_at INTEGER NOT NULL
391
- )
392
- `);
393
-
394
- database.run(/*sql*/ `
395
- CREATE TABLE IF NOT EXISTS watcher_events (
396
- id TEXT PRIMARY KEY,
397
- watcher_id TEXT NOT NULL REFERENCES watchers(id) ON DELETE CASCADE,
398
- external_id TEXT NOT NULL,
399
- event_type TEXT NOT NULL,
400
- summary TEXT NOT NULL,
401
- payload_json TEXT NOT NULL,
402
- disposition TEXT NOT NULL DEFAULT 'pending',
403
- llm_action TEXT,
404
- processed_at INTEGER,
405
- created_at INTEGER NOT NULL,
406
- UNIQUE (watcher_id, external_id)
407
- )
408
- `);
409
-
410
- database.run(/*sql*/ `
411
- CREATE TABLE IF NOT EXISTS llm_request_logs (
412
- id TEXT PRIMARY KEY,
413
- conversation_id TEXT NOT NULL,
414
- request_payload TEXT NOT NULL,
415
- response_payload TEXT NOT NULL,
416
- created_at INTEGER NOT NULL
417
- )
418
- `);
419
-
420
- database.run(/*sql*/ `
421
- CREATE TABLE IF NOT EXISTS llm_usage_events (
422
- id TEXT PRIMARY KEY,
423
- created_at INTEGER NOT NULL,
424
- conversation_id TEXT,
425
- run_id TEXT,
426
- request_id TEXT,
427
- actor TEXT NOT NULL,
428
- provider TEXT NOT NULL,
429
- model TEXT NOT NULL,
430
- input_tokens INTEGER NOT NULL,
431
- output_tokens INTEGER NOT NULL,
432
- cache_creation_input_tokens INTEGER,
433
- cache_read_input_tokens INTEGER,
434
- estimated_cost_usd REAL,
435
- pricing_status TEXT NOT NULL,
436
- metadata_json TEXT
437
- )
438
- `);
439
-
440
- database.run(/*sql*/ `
441
- CREATE TABLE IF NOT EXISTS memory_entities (
442
- id TEXT PRIMARY KEY,
443
- name TEXT NOT NULL,
444
- type TEXT NOT NULL,
445
- aliases TEXT,
446
- description TEXT,
447
- first_seen_at INTEGER NOT NULL,
448
- last_seen_at INTEGER NOT NULL,
449
- mention_count INTEGER NOT NULL DEFAULT 1
450
- )
451
- `);
452
-
453
- database.run(/*sql*/ `
454
- CREATE TABLE IF NOT EXISTS memory_entity_relations (
455
- id TEXT PRIMARY KEY,
456
- source_entity_id TEXT NOT NULL,
457
- target_entity_id TEXT NOT NULL,
458
- relation TEXT NOT NULL,
459
- evidence TEXT,
460
- first_seen_at INTEGER NOT NULL,
461
- last_seen_at INTEGER NOT NULL
462
- )
463
- `);
464
-
465
- database.run(/*sql*/ `
466
- CREATE TABLE IF NOT EXISTS memory_item_entities (
467
- memory_item_id TEXT NOT NULL,
468
- entity_id TEXT NOT NULL,
469
- PRIMARY KEY (memory_item_id, entity_id)
470
- )
471
- `);
472
-
473
- // FTS table for lexical retrieval over memory_segments.text.
474
- database.run(/*sql*/ `
475
- CREATE VIRTUAL TABLE IF NOT EXISTS memory_segment_fts USING fts5(
476
- segment_id UNINDEXED,
477
- text
478
- )
479
- `);
480
-
481
- database.run(/*sql*/ `
482
- CREATE TRIGGER IF NOT EXISTS memory_segments_ai
483
- AFTER INSERT ON memory_segments
484
- BEGIN
485
- INSERT INTO memory_segment_fts(segment_id, text) VALUES (new.id, new.text);
486
- END
487
- `);
488
-
489
- database.run(/*sql*/ `
490
- CREATE TRIGGER IF NOT EXISTS memory_segments_ad
491
- AFTER DELETE ON memory_segments
492
- BEGIN
493
- DELETE FROM memory_segment_fts WHERE segment_id = old.id;
494
- END
495
- `);
496
-
497
- database.run(/*sql*/ `
498
- CREATE TRIGGER IF NOT EXISTS memory_segments_au
499
- AFTER UPDATE ON memory_segments
500
- BEGIN
501
- DELETE FROM memory_segment_fts WHERE segment_id = old.id;
502
- INSERT INTO memory_segment_fts(segment_id, text) VALUES (new.id, new.text);
503
- END
504
- `);
505
-
506
- database.run(/*sql*/ `
507
- CREATE TABLE IF NOT EXISTS conversation_keys (
508
- id TEXT PRIMARY KEY,
509
- conversation_key TEXT NOT NULL UNIQUE,
510
- conversation_id TEXT NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
511
- created_at INTEGER NOT NULL
512
- )
513
- `);
514
-
515
- // Migrations — ALTER TABLE ADD COLUMN throws if column already exists
516
- try { database.run(/*sql*/ `ALTER TABLE conversations ADD COLUMN total_input_tokens INTEGER NOT NULL DEFAULT 0`); } catch { /* already exists */ }
517
- try { database.run(/*sql*/ `ALTER TABLE conversations ADD COLUMN total_output_tokens INTEGER NOT NULL DEFAULT 0`); } catch { /* already exists */ }
518
- try { database.run(/*sql*/ `ALTER TABLE conversations ADD COLUMN total_estimated_cost REAL NOT NULL DEFAULT 0`); } catch { /* already exists */ }
519
- try { database.run(/*sql*/ `ALTER TABLE conversations ADD COLUMN context_summary TEXT`); } catch { /* already exists */ }
520
- try { database.run(/*sql*/ `ALTER TABLE conversations ADD COLUMN context_compacted_message_count INTEGER NOT NULL DEFAULT 0`); } catch { /* already exists */ }
521
- try { database.run(/*sql*/ `ALTER TABLE conversations ADD COLUMN context_compacted_at INTEGER`); } catch { /* already exists */ }
522
- try { database.run(/*sql*/ `ALTER TABLE memory_items ADD COLUMN importance REAL`); } catch { /* already exists */ }
523
- try { database.run(/*sql*/ `ALTER TABLE memory_items ADD COLUMN access_count INTEGER NOT NULL DEFAULT 0`); } catch { /* already exists */ }
524
- try { database.run(/*sql*/ `ALTER TABLE memory_summaries ADD COLUMN version INTEGER NOT NULL DEFAULT 1`); } catch { /* already exists */ }
525
- try { database.run(/*sql*/ `ALTER TABLE memory_items ADD COLUMN valid_from INTEGER`); } catch { /* already exists */ }
526
- try { database.run(/*sql*/ `ALTER TABLE memory_items ADD COLUMN invalid_at INTEGER`); } catch { /* already exists */ }
527
- try { database.run(/*sql*/ `ALTER TABLE memory_items ADD COLUMN verification_state TEXT NOT NULL DEFAULT 'assistant_inferred'`); } catch { /* already exists */ }
528
- try { database.run(/*sql*/ `ALTER TABLE memory_jobs ADD COLUMN deferrals INTEGER NOT NULL DEFAULT 0`); } catch { /* already exists */ }
529
- try { database.run(/*sql*/ `ALTER TABLE memory_segments ADD COLUMN scope_id TEXT NOT NULL DEFAULT 'default'`); } catch { /* already exists */ }
530
- try { database.run(/*sql*/ `ALTER TABLE memory_items ADD COLUMN scope_id TEXT NOT NULL DEFAULT 'default'`); } catch { /* already exists */ }
531
- try { database.run(/*sql*/ `ALTER TABLE memory_summaries ADD COLUMN scope_id TEXT NOT NULL DEFAULT 'default'`); } catch { /* already exists */ }
532
- try { database.run(/*sql*/ `ALTER TABLE memory_segments ADD COLUMN content_hash TEXT`); } catch { /* already exists */ }
533
- try { database.run(/*sql*/ `ALTER TABLE channel_inbound_events ADD COLUMN source_message_id TEXT`); } catch { /* already exists */ }
534
- try { database.run(/*sql*/ `ALTER TABLE attachments ADD COLUMN content_hash TEXT`); } catch { /* already exists */ }
535
- try { database.run(/*sql*/ `ALTER TABLE channel_inbound_events ADD COLUMN processing_status TEXT NOT NULL DEFAULT 'pending'`); } catch { /* already exists */ }
536
- try { database.run(/*sql*/ `ALTER TABLE channel_inbound_events ADD COLUMN processing_attempts INTEGER NOT NULL DEFAULT 0`); } catch { /* already exists */ }
537
- try { database.run(/*sql*/ `ALTER TABLE channel_inbound_events ADD COLUMN last_processing_error TEXT`); } catch { /* already exists */ }
538
- try { database.run(/*sql*/ `ALTER TABLE channel_inbound_events ADD COLUMN retry_after INTEGER`); } catch { /* already exists */ }
539
- try { database.run(/*sql*/ `ALTER TABLE channel_inbound_events ADD COLUMN raw_payload TEXT`); } catch { /* already exists */ }
540
- try { database.run(/*sql*/ `ALTER TABLE conversations ADD COLUMN thread_type TEXT NOT NULL DEFAULT 'standard'`); } catch { /* already exists */ }
541
- try { database.run(/*sql*/ `ALTER TABLE conversations ADD COLUMN memory_scope_id TEXT NOT NULL DEFAULT 'default'`); } catch { /* already exists */ }
542
- try { database.run(/*sql*/ `ALTER TABLE attachments ADD COLUMN thumbnail_base64 TEXT`); } catch { /* already exists */ }
543
- try { database.run(/*sql*/ `ALTER TABLE cron_jobs ADD COLUMN schedule_syntax TEXT NOT NULL DEFAULT 'cron'`); } catch { /* already exists */ }
544
- try { database.run(/*sql*/ `ALTER TABLE messages ADD COLUMN metadata TEXT`); } catch { /* already exists */ }
545
-
546
- migrateJobDeferrals(database);
547
- migrateToolInvocationsFk(database);
548
- migrateMemoryEntityRelationDedup(database);
549
- migrateMemoryItemsFingerprintScopeUnique(database);
550
- migrateMemoryItemsScopeSaltedFingerprints(database);
551
- migrateAssistantIdToSelf(database);
552
- migrateRemoveAssistantIdColumns(database);
553
- migrateLlmUsageEventsDropAssistantId(database);
554
-
555
- // Indexes for query performance on large datasets
556
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_llm_request_logs_conv_created ON llm_request_logs(conversation_id, created_at)`);
557
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_messages_conversation_id ON messages(conversation_id)`);
558
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_tool_invocations_conversation_id ON tool_invocations(conversation_id)`);
559
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_conversations_updated_at ON conversations(updated_at)`);
560
- database.run(/*sql*/ `CREATE UNIQUE INDEX IF NOT EXISTS idx_memory_segments_message_segment ON memory_segments(message_id, segment_index)`);
561
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_memory_segments_conversation_created ON memory_segments(conversation_id, created_at DESC)`);
562
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_memory_item_sources_message_id ON memory_item_sources(message_id)`);
563
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_memory_item_conflicts_status_created ON memory_item_conflicts(status, created_at)`);
564
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_memory_item_conflicts_status_resolved_at ON memory_item_conflicts(status, resolved_at)`);
565
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_memory_item_conflicts_scope_status ON memory_item_conflicts(scope_id, status)`);
566
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_memory_item_conflicts_existing_item_id ON memory_item_conflicts(existing_item_id)`);
567
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_memory_item_conflicts_candidate_item_id ON memory_item_conflicts(candidate_item_id)`);
568
- database.run(/*sql*/ `
569
- CREATE UNIQUE INDEX IF NOT EXISTS idx_memory_item_conflicts_pending_pair_unique
570
- ON memory_item_conflicts(scope_id, existing_item_id, candidate_item_id)
571
- WHERE status = 'pending_clarification'
572
- `);
573
- database.run(/*sql*/ `CREATE UNIQUE INDEX IF NOT EXISTS idx_memory_items_fingerprint_scope ON memory_items(fingerprint, scope_id)`);
574
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_memory_items_kind_status ON memory_items(kind, status)`);
575
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_memory_items_status_invalid_at ON memory_items(status, invalid_at)`);
576
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_memory_items_scope_status_kind ON memory_items(scope_id, status, kind)`);
577
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_memory_items_last_seen_at ON memory_items(last_seen_at)`);
578
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_memory_embeddings_target ON memory_embeddings(target_type, target_id)`);
579
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_memory_embeddings_provider_model ON memory_embeddings(provider, model)`);
580
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_memory_jobs_status_run_after ON memory_jobs(status, run_after)`);
581
- database.run(/*sql*/ `
582
- CREATE INDEX IF NOT EXISTS idx_memory_jobs_conflict_resolve_dedupe
583
- ON memory_jobs(
584
- type,
585
- status,
586
- json_extract(payload, '$.messageId'),
587
- COALESCE(json_extract(payload, '$.scopeId'), 'default')
588
- )
589
- `);
590
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_memory_summaries_scope_time ON memory_summaries(scope, end_at DESC)`);
591
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_memory_segments_scope_id ON memory_segments(scope_id)`);
592
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_memory_items_scope_id ON memory_items(scope_id)`);
593
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_memory_summaries_scope_id ON memory_summaries(scope_id)`);
594
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_conversation_keys_key ON conversation_keys(conversation_key)`);
595
- // Deduplicate before creating unique index — existing DBs may have duplicate content_hash values.
596
- // Re-point message_attachments to the survivor (MIN rowid per content_hash), then delete dupes.
597
- {
598
- const raw = (database as unknown as { $client: Database }).$client;
599
- raw.exec(/*sql*/ `
600
- UPDATE message_attachments
601
- SET attachment_id = (
602
- SELECT a_survivor.id
603
- FROM attachments a_survivor
604
- WHERE a_survivor.content_hash = (
605
- SELECT a_dup.content_hash FROM attachments a_dup
606
- WHERE a_dup.id = message_attachments.attachment_id
607
- )
608
- ORDER BY a_survivor.rowid
609
- LIMIT 1
610
- )
611
- WHERE attachment_id IN (
612
- SELECT id FROM attachments
613
- WHERE content_hash IS NOT NULL
614
- AND rowid NOT IN (
615
- SELECT MIN(rowid) FROM attachments
616
- WHERE content_hash IS NOT NULL
617
- GROUP BY content_hash
618
- )
619
- )
620
- `);
621
- raw.exec(/*sql*/ `
622
- DELETE FROM attachments
623
- WHERE content_hash IS NOT NULL
624
- AND rowid NOT IN (
625
- SELECT MIN(rowid) FROM attachments
626
- WHERE content_hash IS NOT NULL
627
- GROUP BY content_hash
628
- )
629
- `);
630
- }
631
- database.run(/*sql*/ `CREATE UNIQUE INDEX IF NOT EXISTS idx_attachments_content_dedup ON attachments(content_hash) WHERE content_hash IS NOT NULL`);
632
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_message_attachments_message_id ON message_attachments(message_id)`);
633
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_message_attachments_attachment_id ON message_attachments(attachment_id)`);
634
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_channel_inbound_events_lookup ON channel_inbound_events(source_channel, external_chat_id, external_message_id)`);
635
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_channel_inbound_events_conversation ON channel_inbound_events(conversation_id)`);
636
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_channel_inbound_events_source_msg ON channel_inbound_events(source_channel, external_chat_id, source_message_id)`);
637
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_channel_inbound_events_processing_retry ON channel_inbound_events(processing_status, retry_after)`);
638
-
639
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_message_runs_status ON message_runs(status)`);
640
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_message_runs_conversation ON message_runs(conversation_id)`);
641
-
642
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_reminders_status_fire_at ON reminders(status, fire_at)`);
643
-
644
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_cron_jobs_enabled_next_run ON cron_jobs(enabled, next_run_at)`);
645
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_cron_jobs_syntax_enabled_next_run ON cron_jobs(schedule_syntax, enabled, next_run_at)`);
646
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_cron_runs_job_id ON cron_runs(job_id)`);
647
-
648
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_accounts_service ON accounts(service)`);
649
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_accounts_status ON accounts(status)`);
650
-
651
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_llm_usage_events_created_at ON llm_usage_events(created_at)`);
652
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_llm_usage_events_provider ON llm_usage_events(provider)`);
653
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_llm_usage_events_model ON llm_usage_events(model)`);
654
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_llm_usage_events_actor ON llm_usage_events(actor)`);
655
-
656
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_shared_app_links_share_token ON shared_app_links(share_token)`);
657
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_home_base_app_links_app_id ON home_base_app_links(app_id)`);
658
-
659
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_published_pages_html_hash ON published_pages(html_hash)`);
660
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_published_pages_status ON published_pages(status)`);
661
-
662
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_watchers_enabled_next_poll ON watchers(enabled, next_poll_at)`);
663
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_watchers_status ON watchers(status)`);
664
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_watcher_events_watcher_id ON watcher_events(watcher_id)`);
665
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_watcher_events_disposition ON watcher_events(disposition)`);
666
-
667
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_memory_entities_name ON memory_entities(name)`);
668
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_memory_entities_type ON memory_entities(type)`);
669
- database.run(/*sql*/ `CREATE UNIQUE INDEX IF NOT EXISTS idx_memory_entity_relations_unique_edge ON memory_entity_relations(source_entity_id, target_entity_id, relation)`);
670
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_memory_entity_relations_source ON memory_entity_relations(source_entity_id)`);
671
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_memory_entity_relations_target ON memory_entity_relations(target_entity_id)`);
672
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_memory_item_entities_memory_item ON memory_item_entities(memory_item_id)`);
673
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_memory_item_entities_entity ON memory_item_entities(entity_id)`);
674
-
675
- // ── Contacts ────────────────────────────────────────────────────────
676
-
677
- database.run(/*sql*/ `
678
- CREATE TABLE IF NOT EXISTS contacts (
679
- id TEXT PRIMARY KEY,
680
- display_name TEXT NOT NULL,
681
- relationship TEXT,
682
- importance REAL NOT NULL DEFAULT 0.5,
683
- response_expectation TEXT,
684
- preferred_tone TEXT,
685
- last_interaction INTEGER,
686
- interaction_count INTEGER NOT NULL DEFAULT 0,
687
- created_at INTEGER NOT NULL,
688
- updated_at INTEGER NOT NULL
689
- )
690
- `);
691
-
692
- database.run(/*sql*/ `
693
- CREATE TABLE IF NOT EXISTS contact_channels (
694
- id TEXT PRIMARY KEY,
695
- contact_id TEXT NOT NULL REFERENCES contacts(id) ON DELETE CASCADE,
696
- type TEXT NOT NULL,
697
- address TEXT NOT NULL,
698
- is_primary INTEGER NOT NULL DEFAULT 0,
699
- created_at INTEGER NOT NULL
700
- )
701
- `);
702
-
703
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_contacts_display_name ON contacts(display_name)`);
704
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_contacts_importance ON contacts(importance DESC)`);
705
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_contacts_last_interaction ON contacts(last_interaction DESC)`);
706
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_contact_channels_contact_id ON contact_channels(contact_id)`);
707
- database.run(/*sql*/ `CREATE UNIQUE INDEX IF NOT EXISTS idx_contact_channels_type_address ON contact_channels(type, address)`);
708
-
709
- // ── Triage Results ─────────────────────────────────────────────────
710
-
711
- database.run(/*sql*/ `
712
- CREATE TABLE IF NOT EXISTS triage_results (
713
- id TEXT PRIMARY KEY,
714
- channel TEXT NOT NULL,
715
- sender TEXT NOT NULL,
716
- category TEXT NOT NULL,
717
- confidence REAL NOT NULL,
718
- suggested_action TEXT NOT NULL,
719
- matched_playbook_ids TEXT,
720
- message_id TEXT,
721
- created_at INTEGER NOT NULL
722
- )
723
- `);
724
-
725
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_triage_results_channel ON triage_results(channel)`);
726
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_triage_results_category ON triage_results(category)`);
727
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_triage_results_sender ON triage_results(sender)`);
728
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_triage_results_created_at ON triage_results(created_at DESC)`);
729
-
730
- // ── Call Sessions (outgoing AI phone calls) ────────────────────────
731
-
732
- database.run(/*sql*/ `
733
- CREATE TABLE IF NOT EXISTS call_sessions (
734
- id TEXT PRIMARY KEY,
735
- conversation_id TEXT NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
736
- provider TEXT NOT NULL,
737
- provider_call_sid TEXT,
738
- from_number TEXT NOT NULL,
739
- to_number TEXT NOT NULL,
740
- task TEXT,
741
- status TEXT NOT NULL DEFAULT 'initiated',
742
- started_at INTEGER,
743
- ended_at INTEGER,
744
- last_error TEXT,
745
- created_at INTEGER NOT NULL,
746
- updated_at INTEGER NOT NULL
747
- )
748
- `);
749
-
750
- database.run(/*sql*/ `
751
- CREATE TABLE IF NOT EXISTS call_events (
752
- id TEXT PRIMARY KEY,
753
- call_session_id TEXT NOT NULL REFERENCES call_sessions(id) ON DELETE CASCADE,
754
- event_type TEXT NOT NULL,
755
- payload_json TEXT NOT NULL DEFAULT '{}',
756
- created_at INTEGER NOT NULL
757
- )
758
- `);
759
-
760
- database.run(/*sql*/ `
761
- CREATE TABLE IF NOT EXISTS call_pending_questions (
762
- id TEXT PRIMARY KEY,
763
- call_session_id TEXT NOT NULL REFERENCES call_sessions(id) ON DELETE CASCADE,
764
- question_text TEXT NOT NULL,
765
- status TEXT NOT NULL DEFAULT 'pending',
766
- asked_at INTEGER NOT NULL,
767
- answered_at INTEGER,
768
- answer_text TEXT
769
- )
770
- `);
771
-
772
- database.run(/*sql*/ `
773
- CREATE TABLE IF NOT EXISTS processed_callbacks (
774
- id TEXT PRIMARY KEY,
775
- dedupe_key TEXT NOT NULL UNIQUE,
776
- call_session_id TEXT NOT NULL REFERENCES call_sessions(id) ON DELETE CASCADE,
777
- created_at INTEGER NOT NULL
778
- )
779
- `);
780
-
781
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_call_sessions_conversation_id ON call_sessions(conversation_id)`);
782
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_call_sessions_provider_call_sid ON call_sessions(provider_call_sid)`);
783
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_call_sessions_status ON call_sessions(status)`);
784
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_call_events_call_session_id ON call_events(call_session_id)`);
785
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_call_pending_questions_call_session_id ON call_pending_questions(call_session_id)`);
786
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_call_pending_questions_status ON call_pending_questions(status)`);
787
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_processed_callbacks_dedupe_key ON processed_callbacks(dedupe_key)`);
788
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_processed_callbacks_call_session_id ON processed_callbacks(call_session_id)`);
789
-
790
- // Add claim ownership token to prevent cross-handler claim interference
791
- try { database.run(/*sql*/ `ALTER TABLE processed_callbacks ADD COLUMN claim_id TEXT`); } catch { /* already exists */ }
792
-
793
- // Caller identity persistence for auditability
794
- try { database.run(/*sql*/ `ALTER TABLE call_sessions ADD COLUMN caller_identity_mode TEXT`); } catch { /* already exists */ }
795
- try { database.run(/*sql*/ `ALTER TABLE call_sessions ADD COLUMN caller_identity_source TEXT`); } catch { /* already exists */ }
796
-
797
- // Unique constraint: at most one non-null provider_call_sid per (provider, provider_call_sid).
798
- // On upgraded databases that pre-date this constraint, duplicate rows may exist; deduplicate
799
- // them first to avoid a UNIQUE constraint failure that would prevent startup.
800
- migrateCallSessionsProviderSidDedup(database);
801
- database.run(/*sql*/ `CREATE UNIQUE INDEX IF NOT EXISTS idx_call_sessions_provider_sid_unique ON call_sessions(provider, provider_call_sid) WHERE provider_call_sid IS NOT NULL`);
802
-
803
- // ── Follow-ups ─────────────────────────────────────────────────────
804
-
805
- database.run(/*sql*/ `
806
- CREATE TABLE IF NOT EXISTS followups (
807
- id TEXT PRIMARY KEY,
808
- channel TEXT NOT NULL,
809
- thread_id TEXT NOT NULL,
810
- contact_id TEXT REFERENCES contacts(id) ON DELETE SET NULL,
811
- sent_at INTEGER NOT NULL,
812
- expected_response_by INTEGER,
813
- status TEXT NOT NULL DEFAULT 'pending',
814
- reminder_cron_id TEXT,
815
- created_at INTEGER NOT NULL,
816
- updated_at INTEGER NOT NULL
817
- )
818
- `);
819
-
820
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_followups_status ON followups(status)`);
821
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_followups_channel ON followups(channel)`);
822
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_followups_contact_id ON followups(contact_id)`);
823
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_followups_channel_thread ON followups(channel, thread_id)`);
824
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_followups_status_expected ON followups(status, expected_response_by)`);
825
-
826
- // ── Tasks ─────────────────────────────────────────────────────────
827
-
828
- database.run(/*sql*/ `
829
- CREATE TABLE IF NOT EXISTS tasks (
830
- id TEXT PRIMARY KEY,
831
- title TEXT NOT NULL,
832
- template TEXT NOT NULL,
833
- input_schema TEXT,
834
- context_flags TEXT,
835
- required_tools TEXT,
836
- created_from_conversation_id TEXT,
837
- status TEXT NOT NULL DEFAULT 'active',
838
- created_at INTEGER NOT NULL,
839
- updated_at INTEGER NOT NULL
840
- )
841
- `);
842
-
843
- database.run(/*sql*/ `
844
- CREATE TABLE IF NOT EXISTS task_runs (
845
- id TEXT PRIMARY KEY,
846
- task_id TEXT NOT NULL REFERENCES tasks(id),
847
- conversation_id TEXT,
848
- status TEXT NOT NULL DEFAULT 'pending',
849
- started_at INTEGER,
850
- finished_at INTEGER,
851
- error TEXT,
852
- principal_id TEXT,
853
- memory_scope_id TEXT,
854
- created_at INTEGER NOT NULL
855
- )
856
- `);
857
-
858
- database.run(/*sql*/ `
859
- CREATE TABLE IF NOT EXISTS task_candidates (
860
- id TEXT PRIMARY KEY,
861
- source_conversation_id TEXT NOT NULL,
862
- compiled_template TEXT NOT NULL,
863
- confidence REAL,
864
- required_tools TEXT,
865
- created_at INTEGER NOT NULL,
866
- promoted_task_id TEXT
867
- )
868
- `);
869
-
870
- // ── Work Items (Tasks) ──────────────────────────────────────────────
871
-
872
- database.run(/*sql*/ `
873
- CREATE TABLE IF NOT EXISTS work_items (
874
- id TEXT PRIMARY KEY,
875
- task_id TEXT NOT NULL REFERENCES tasks(id),
876
- title TEXT NOT NULL,
877
- notes TEXT,
878
- status TEXT NOT NULL DEFAULT 'queued',
879
- priority_tier INTEGER NOT NULL DEFAULT 1,
880
- sort_index INTEGER,
881
- last_run_id TEXT,
882
- last_run_conversation_id TEXT,
883
- last_run_status TEXT,
884
- source_type TEXT,
885
- source_id TEXT,
886
- created_at INTEGER NOT NULL,
887
- updated_at INTEGER NOT NULL
888
- )
889
- `);
890
-
891
- // Work item run contract snapshot
892
- try { database.run(/*sql*/ `ALTER TABLE work_items ADD COLUMN required_tools TEXT`); } catch (e) { log.debug({ err: e }, 'ALTER TABLE work_items ADD COLUMN required_tools (likely already exists)'); }
893
-
894
- // Work item permission preflight columns
895
- try { database.run(/*sql*/ `ALTER TABLE work_items ADD COLUMN approved_tools TEXT`); } catch (e) { log.debug({ err: e }, 'ALTER TABLE work_items ADD COLUMN approved_tools (likely already exists)'); }
896
- try { database.run(/*sql*/ `ALTER TABLE work_items ADD COLUMN approval_status TEXT DEFAULT 'none'`); } catch (e) { log.debug({ err: e }, 'ALTER TABLE work_items ADD COLUMN approval_status (likely already exists)'); }
897
-
898
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_work_items_status ON work_items(status)`);
899
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_work_items_task_id ON work_items(task_id)`);
900
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_work_items_priority_sort ON work_items(priority_tier, sort_index)`);
901
-
902
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status)`);
903
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_task_runs_task_id ON task_runs(task_id)`);
904
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_task_runs_status ON task_runs(status)`);
905
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_task_candidates_promoted ON task_candidates(promoted_task_id)`);
906
-
907
- // ── External Conversation Bindings ──────────────────────────────────
908
-
909
- database.run(/*sql*/ `
910
- CREATE TABLE IF NOT EXISTS external_conversation_bindings (
911
- conversation_id TEXT PRIMARY KEY REFERENCES conversations(id) ON DELETE CASCADE,
912
- source_channel TEXT NOT NULL,
913
- external_chat_id TEXT NOT NULL,
914
- external_user_id TEXT,
915
- display_name TEXT,
916
- username TEXT,
917
- created_at INTEGER NOT NULL,
918
- updated_at INTEGER NOT NULL,
919
- last_inbound_at INTEGER,
920
- last_outbound_at INTEGER
921
- )
922
- `);
923
-
924
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_ext_conv_bindings_channel_chat ON external_conversation_bindings(source_channel, external_chat_id)`);
925
- database.run(/*sql*/ `CREATE INDEX IF NOT EXISTS idx_ext_conv_bindings_channel ON external_conversation_bindings(source_channel)`);
926
-
927
- migrateExtConvBindingsChannelChatUnique(database);
928
-
929
- migrateMemoryFtsBackfill(database);
930
- }
931
-
932
- /**
933
- * One-shot migration: reconcile old deferral history into the new `deferrals` column.
934
- *
935
- * Before the `deferrals` column was added, `deferMemoryJob` incremented `attempts`.
936
- * After the column is added with DEFAULT 0, those legacy jobs still carry the old
937
- * attempt count (which was really a deferral count) while `deferrals` is 0. This
938
- * moves the attempt count into `deferrals` and resets `attempts` to 0.
939
- *
940
- * This migration MUST run only once. On subsequent startups, post-migration jobs
941
- * that genuinely failed via `failMemoryJob` (attempts > 0, deferrals = 0, non-null
942
- * last_error) must NOT be touched — resetting their attempts would let them bypass
943
- * the configured maxAttempts budget across restarts.
944
- *
945
- * We use a `memory_checkpoints` row to ensure the migration runs exactly once.
946
- */
947
- function migrateJobDeferrals(database: ReturnType<typeof drizzle<typeof schema>>): void {
948
- const raw = (database as unknown as { $client: Database }).$client;
949
- const checkpoint = raw.query(
950
- `SELECT 1 FROM memory_checkpoints WHERE key = 'migration_job_deferrals'`
951
- ).get();
952
- if (checkpoint) return;
953
-
954
- try {
955
- raw.exec(/*sql*/ `
956
- BEGIN;
957
- UPDATE memory_jobs
958
- SET deferrals = attempts,
959
- attempts = 0,
960
- last_error = NULL,
961
- updated_at = ${Date.now()}
962
- WHERE status = 'pending'
963
- AND attempts > 0
964
- AND deferrals = 0
965
- AND type IN ('embed_segment', 'embed_item', 'embed_summary');
966
- INSERT OR IGNORE INTO memory_checkpoints (key, value, updated_at)
967
- VALUES ('migration_job_deferrals', '1', ${Date.now()});
968
- COMMIT;
969
- `);
970
- } catch (e) {
971
- try { raw.exec('ROLLBACK'); } catch { /* no active transaction */ }
972
- throw e;
973
- }
974
- }
975
-
976
- /**
977
- * Migrate existing tool_invocations table to add FK constraint with ON DELETE CASCADE.
978
- * SQLite doesn't support ALTER TABLE ADD CONSTRAINT, so we rebuild the table.
979
- * This is idempotent: it checks whether the FK already exists before migrating.
980
- */
981
- function migrateToolInvocationsFk(database: ReturnType<typeof drizzle<typeof schema>>): void {
982
- const raw = (database as unknown as { $client: Database }).$client;
983
- const row = raw.query(`SELECT sql FROM sqlite_master WHERE type='table' AND name='tool_invocations'`).get() as { sql: string } | null;
984
- if (!row) return; // table doesn't exist yet (will be created above)
985
-
986
- // If the DDL already contains REFERENCES, the FK is in place
987
- if (row.sql.includes('REFERENCES')) return;
988
-
989
- raw.exec('PRAGMA foreign_keys = OFF');
990
- try {
991
- raw.exec(/*sql*/ `
992
- BEGIN;
993
- CREATE TABLE tool_invocations_new (
994
- id TEXT PRIMARY KEY,
995
- conversation_id TEXT NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
996
- tool_name TEXT NOT NULL,
997
- input TEXT NOT NULL,
998
- result TEXT NOT NULL,
999
- decision TEXT NOT NULL,
1000
- risk_level TEXT NOT NULL,
1001
- duration_ms INTEGER NOT NULL,
1002
- created_at INTEGER NOT NULL
1003
- );
1004
- INSERT INTO tool_invocations_new SELECT t.* FROM tool_invocations t
1005
- WHERE EXISTS (SELECT 1 FROM conversations c WHERE c.id = t.conversation_id);
1006
- DROP TABLE tool_invocations;
1007
- ALTER TABLE tool_invocations_new RENAME TO tool_invocations;
1008
- COMMIT;
1009
- `);
1010
- } catch (e) {
1011
- try { raw.exec('ROLLBACK'); } catch { /* no active transaction */ }
1012
- throw e;
1013
- } finally {
1014
- raw.exec('PRAGMA foreign_keys = ON');
1015
- }
1016
- }
1017
-
1018
- /**
1019
- * Backfill FTS rows for existing memory_segments records when upgrading from a
1020
- * version that may not have had trigger-managed FTS.
1021
- */
1022
- function migrateMemoryFtsBackfill(database: ReturnType<typeof drizzle<typeof schema>>): void {
1023
- const raw = (database as unknown as { $client: Database }).$client;
1024
- const ftsCountRow = raw.query(`SELECT COUNT(*) AS c FROM memory_segment_fts`).get() as { c: number } | null;
1025
- const ftsCount = ftsCountRow?.c ?? 0;
1026
- if (ftsCount > 0) return;
1027
-
1028
- raw.exec(/*sql*/ `
1029
- INSERT INTO memory_segment_fts(segment_id, text)
1030
- SELECT id, text FROM memory_segments
1031
- `);
1032
- }
1033
-
1034
- /**
1035
- * One-shot migration: merge duplicate relation edges so uniqueness can be
1036
- * enforced on (source_entity_id, target_entity_id, relation).
1037
- */
1038
- function migrateMemoryEntityRelationDedup(database: ReturnType<typeof drizzle<typeof schema>>): void {
1039
- const raw = (database as unknown as { $client: Database }).$client;
1040
- const checkpointKey = 'migration_memory_entity_relations_dedup_v1';
1041
- const checkpoint = raw.query(
1042
- `SELECT 1 FROM memory_checkpoints WHERE key = ?`,
1043
- ).get(checkpointKey);
1044
- if (checkpoint) return;
1045
-
1046
- try {
1047
- raw.exec('BEGIN');
1048
-
1049
- raw.exec(/*sql*/ `
1050
- CREATE TEMP TABLE memory_entity_relation_merge AS
1051
- WITH ranked AS (
1052
- SELECT
1053
- source_entity_id,
1054
- target_entity_id,
1055
- relation,
1056
- first_seen_at,
1057
- last_seen_at,
1058
- evidence,
1059
- ROW_NUMBER() OVER (
1060
- PARTITION BY source_entity_id, target_entity_id, relation
1061
- ORDER BY last_seen_at DESC, first_seen_at DESC, id DESC
1062
- ) AS rank_latest
1063
- FROM memory_entity_relations
1064
- )
1065
- SELECT
1066
- source_entity_id,
1067
- target_entity_id,
1068
- relation,
1069
- MIN(first_seen_at) AS merged_first_seen_at,
1070
- MAX(last_seen_at) AS merged_last_seen_at,
1071
- MAX(CASE WHEN rank_latest = 1 THEN evidence ELSE NULL END) AS merged_evidence
1072
- FROM ranked
1073
- GROUP BY source_entity_id, target_entity_id, relation
1074
- `);
1075
-
1076
- raw.exec(/*sql*/ `DELETE FROM memory_entity_relations`);
1077
-
1078
- raw.exec(/*sql*/ `
1079
- INSERT INTO memory_entity_relations (
1080
- id,
1081
- source_entity_id,
1082
- target_entity_id,
1083
- relation,
1084
- evidence,
1085
- first_seen_at,
1086
- last_seen_at
1087
- )
1088
- SELECT
1089
- lower(hex(randomblob(16))),
1090
- source_entity_id,
1091
- target_entity_id,
1092
- relation,
1093
- merged_evidence,
1094
- merged_first_seen_at,
1095
- merged_last_seen_at
1096
- FROM memory_entity_relation_merge
1097
- `);
1098
-
1099
- raw.exec(/*sql*/ `DROP TABLE memory_entity_relation_merge`);
1100
-
1101
- raw.query(
1102
- `INSERT OR IGNORE INTO memory_checkpoints (key, value, updated_at) VALUES (?, '1', ?)`,
1103
- ).run(checkpointKey, Date.now());
1104
-
1105
- raw.exec('COMMIT');
1106
- } catch (e) {
1107
- try { raw.exec('ROLLBACK'); } catch { /* no active transaction */ }
1108
- throw e;
1109
- }
1110
- }
1111
-
1112
- /**
1113
- * Migrate from a column-level UNIQUE on fingerprint to a compound unique
1114
- * index on (fingerprint, scope_id) so that the same item can exist in
1115
- * different scopes independently.
1116
- */
1117
- function migrateMemoryItemsFingerprintScopeUnique(database: ReturnType<typeof drizzle<typeof schema>>): void {
1118
- const raw = (database as unknown as { $client: Database }).$client;
1119
- const checkpointKey = 'migration_memory_items_fingerprint_scope_unique_v1';
1120
- const checkpoint = raw.query(
1121
- `SELECT 1 FROM memory_checkpoints WHERE key = ?`,
1122
- ).get(checkpointKey);
1123
- if (checkpoint) return;
1124
-
1125
- // Check if the old column-level UNIQUE constraint still exists by inspecting
1126
- // the CREATE TABLE DDL for the word UNIQUE (the PK also creates an autoindex,
1127
- // so we cannot rely on sqlite_autoindex_* presence alone).
1128
- const tableDdl = raw.query(
1129
- `SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'memory_items'`,
1130
- ).get() as { sql: string } | null;
1131
- if (!tableDdl || !tableDdl.sql.match(/fingerprint\s+TEXT\s+NOT\s+NULL\s+UNIQUE/i)) {
1132
- // No column-level UNIQUE on fingerprint — either fresh DB or already migrated.
1133
- raw.query(
1134
- `INSERT OR IGNORE INTO memory_checkpoints (key, value, updated_at) VALUES (?, '1', ?)`,
1135
- ).run(checkpointKey, Date.now());
1136
- return;
1137
- }
1138
-
1139
- // Rebuild the table without the column-level UNIQUE constraint.
1140
- raw.exec('PRAGMA foreign_keys = OFF');
1141
- try {
1142
- raw.exec('BEGIN');
1143
-
1144
- // Create new table without UNIQUE on fingerprint — all other columns
1145
- // match the latest schema (including migration-added columns).
1146
- raw.exec(/*sql*/ `
1147
- CREATE TABLE memory_items_new (
1148
- id TEXT PRIMARY KEY,
1149
- kind TEXT NOT NULL,
1150
- subject TEXT NOT NULL,
1151
- statement TEXT NOT NULL,
1152
- status TEXT NOT NULL,
1153
- confidence REAL NOT NULL,
1154
- fingerprint TEXT NOT NULL,
1155
- first_seen_at INTEGER NOT NULL,
1156
- last_seen_at INTEGER NOT NULL,
1157
- last_used_at INTEGER,
1158
- importance REAL,
1159
- access_count INTEGER NOT NULL DEFAULT 0,
1160
- valid_from INTEGER,
1161
- invalid_at INTEGER,
1162
- verification_state TEXT NOT NULL DEFAULT 'assistant_inferred',
1163
- scope_id TEXT NOT NULL DEFAULT 'default'
1164
- )
1165
- `);
1166
-
1167
- raw.exec(/*sql*/ `
1168
- INSERT INTO memory_items_new
1169
- SELECT id, kind, subject, statement, status, confidence, fingerprint,
1170
- first_seen_at, last_seen_at, last_used_at, importance, access_count,
1171
- valid_from, invalid_at, verification_state, scope_id
1172
- FROM memory_items
1173
- `);
1174
-
1175
- raw.exec(/*sql*/ `DROP TABLE memory_items`);
1176
- raw.exec(/*sql*/ `ALTER TABLE memory_items_new RENAME TO memory_items`);
1177
-
1178
- raw.query(
1179
- `INSERT OR IGNORE INTO memory_checkpoints (key, value, updated_at) VALUES (?, '1', ?)`,
1180
- ).run(checkpointKey, Date.now());
1181
-
1182
- raw.exec('COMMIT');
1183
- } catch (e) {
1184
- try { raw.exec('ROLLBACK'); } catch { /* no active transaction */ }
1185
- throw e;
1186
- } finally {
1187
- raw.exec('PRAGMA foreign_keys = ON');
1188
- }
1189
- }
1190
-
1191
- /**
1192
- * One-shot migration: recompute fingerprints for existing memory items to
1193
- * include the scope_id prefix introduced in the scope-salted fingerprint PR.
1194
- *
1195
- * Old format: sha256(`${kind}|${subject.toLowerCase()}|${statement.toLowerCase()}`)
1196
- * New format: sha256(`${scopeId}|${kind}|${subject.toLowerCase()}|${statement.toLowerCase()}`)
1197
- *
1198
- * Without this migration, pre-upgrade items would never match on re-extraction,
1199
- * causing duplicates and broken deduplication.
1200
- */
1201
- function migrateMemoryItemsScopeSaltedFingerprints(database: ReturnType<typeof drizzle<typeof schema>>): void {
1202
- const raw = (database as unknown as { $client: Database }).$client;
1203
- const checkpointKey = 'migration_memory_items_scope_salted_fingerprints_v1';
1204
- const checkpoint = raw.query(
1205
- `SELECT 1 FROM memory_checkpoints WHERE key = ?`,
1206
- ).get(checkpointKey);
1207
- if (checkpoint) return;
1208
-
1209
- interface ItemRow {
1210
- id: string;
1211
- kind: string;
1212
- subject: string;
1213
- statement: string;
1214
- scope_id: string;
1215
- }
1216
-
1217
- const items = raw.query(
1218
- `SELECT id, kind, subject, statement, scope_id FROM memory_items`,
1219
- ).all() as ItemRow[];
1220
-
1221
- if (items.length === 0) {
1222
- raw.query(
1223
- `INSERT OR IGNORE INTO memory_checkpoints (key, value, updated_at) VALUES (?, '1', ?)`,
1224
- ).run(checkpointKey, Date.now());
1225
- return;
1226
- }
1227
-
1228
- try {
1229
- raw.exec('BEGIN');
1230
-
1231
- const updateStmt = raw.prepare(
1232
- `UPDATE memory_items SET fingerprint = ? WHERE id = ?`,
1233
- );
1234
-
1235
- for (const item of items) {
1236
- const fingerprint = computeMemoryFingerprint(item.scope_id, item.kind, item.subject, item.statement);
1237
- updateStmt.run(fingerprint, item.id);
1238
- }
1239
-
1240
- raw.query(
1241
- `INSERT OR IGNORE INTO memory_checkpoints (key, value, updated_at) VALUES (?, '1', ?)`,
1242
- ).run(checkpointKey, Date.now());
1243
-
1244
- raw.exec('COMMIT');
1245
- } catch (e) {
1246
- try { raw.exec('ROLLBACK'); } catch { /* no active transaction */ }
1247
- throw e;
1248
- }
1249
- }
1250
-
1251
- /**
1252
- * One-shot migration: normalize all assistant_id values in assistant-scoped tables
1253
- * to "self" so they are visible after the daemon switched to the implicit single-tenant
1254
- * identity.
1255
- *
1256
- * Before this change, rows were keyed by the real assistantId string passed via the
1257
- * HTTP route. After the route change, all lookups use the constant "self". Without this
1258
- * migration an upgraded daemon would see empty history / attachment lists for existing
1259
- * data that was stored under the old assistantId.
1260
- *
1261
- * Affected tables:
1262
- * - conversation_keys UNIQUE (assistant_id, conversation_key)
1263
- * - attachments UNIQUE (assistant_id, content_hash) WHERE content_hash IS NOT NULL
1264
- * - channel_inbound_events UNIQUE (assistant_id, source_channel, external_chat_id, external_message_id)
1265
- * - message_runs no unique constraint on assistant_id
1266
- *
1267
- * Data-safety guarantees:
1268
- * - conversation_keys: when a key exists under both 'self' and a real assistantId, the
1269
- * 'self' row is updated to point to the real-assistantId conversation (which holds the
1270
- * historical message thread). The 'self' conversation may be orphaned but is not deleted.
1271
- * - attachments: message_attachments links are remapped to the surviving attachment before
1272
- * any duplicate row is deleted, so no message loses its attachment metadata.
1273
- * - channel_inbound_events: only delivery-tracking metadata, not user content; dedup
1274
- * keeps one row per unique (channel, chat, message) tuple.
1275
- * - All conversations and messages remain untouched — only assistant_id index columns
1276
- * and key-lookup rows are modified.
1277
- */
1278
- function migrateAssistantIdToSelf(database: ReturnType<typeof drizzle<typeof schema>>): void {
1279
- const raw = (database as unknown as { $client: Database }).$client;
1280
- const checkpointKey = 'migration_normalize_assistant_id_to_self_v1';
1281
- const checkpoint = raw.query(
1282
- `SELECT 1 FROM memory_checkpoints WHERE key = ?`,
1283
- ).get(checkpointKey);
1284
- if (checkpoint) return;
1285
-
1286
- // On fresh installs the tables are created without assistant_id (PR 7+). Skip the
1287
- // migration if NONE of the four affected tables have the column — pre-seed the
1288
- // checkpoint so subsequent startups are also skipped. Checking all four (not just
1289
- // conversation_keys) avoids a false negative on very old installs where
1290
- // conversation_keys may not exist yet but other tables still carry assistant_id data.
1291
- const affectedTables = ['conversation_keys', 'attachments', 'channel_inbound_events', 'message_runs'];
1292
- const anyHasAssistantId = affectedTables.some((tbl) => {
1293
- const ddl = raw.query(
1294
- `SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?`,
1295
- ).get(tbl) as { sql: string } | null;
1296
- return ddl?.sql.includes('assistant_id') ?? false;
1297
- });
1298
- if (!anyHasAssistantId) {
1299
- raw.query(
1300
- `INSERT OR IGNORE INTO memory_checkpoints (key, value, updated_at) VALUES (?, '1', ?)`,
1301
- ).run(checkpointKey, Date.now());
1302
- return;
1303
- }
1304
-
1305
- // Helper: returns true if the given table's current DDL contains 'assistant_id'.
1306
- const tableHasAssistantId = (tbl: string): boolean => {
1307
- const ddl = raw.query(
1308
- `SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?`,
1309
- ).get(tbl) as { sql: string } | null;
1310
- return ddl?.sql.includes('assistant_id') ?? false;
1311
- };
1312
-
1313
- try {
1314
- raw.exec('BEGIN');
1315
-
1316
- // Each section is guarded so that SQL referencing assistant_id is only executed
1317
- // when the column still exists in that table. This handles mixed-schema states
1318
- // (e.g., very old installs where some tables may already lack the column).
1319
-
1320
- // conversation_keys: UNIQUE (assistant_id, conversation_key)
1321
- if (tableHasAssistantId('conversation_keys')) {
1322
- // Step 1: Among non-self rows, keep only one per conversation_key so the
1323
- // bulk UPDATE cannot hit a (non-self-A, key) + (non-self-B, key) collision.
1324
- raw.exec(/*sql*/ `
1325
- DELETE FROM conversation_keys
1326
- WHERE assistant_id != 'self'
1327
- AND rowid NOT IN (
1328
- SELECT MIN(rowid) FROM conversation_keys
1329
- WHERE assistant_id != 'self'
1330
- GROUP BY conversation_key
1331
- )
1332
- `);
1333
- // Step 2: For 'self' rows that have a non-self counterpart with the same
1334
- // conversation_key, update the 'self' row to use the non-self row's
1335
- // conversation_id. This preserves the historical conversation (which
1336
- // has the message history from before the route change) rather than
1337
- // discarding it in favour of a potentially-empty 'self' conversation.
1338
- raw.exec(/*sql*/ `
1339
- UPDATE conversation_keys
1340
- SET conversation_id = (
1341
- SELECT ck_ns.conversation_id
1342
- FROM conversation_keys ck_ns
1343
- WHERE ck_ns.assistant_id != 'self'
1344
- AND ck_ns.conversation_key = conversation_keys.conversation_key
1345
- ORDER BY ck_ns.rowid
1346
- LIMIT 1
1347
- )
1348
- WHERE assistant_id = 'self'
1349
- AND EXISTS (
1350
- SELECT 1 FROM conversation_keys ck_ns
1351
- WHERE ck_ns.assistant_id != 'self'
1352
- AND ck_ns.conversation_key = conversation_keys.conversation_key
1353
- )
1354
- `);
1355
- // Step 3: Delete the now-redundant non-self rows (their conversation_ids
1356
- // have been preserved in the 'self' rows above).
1357
- raw.exec(/*sql*/ `
1358
- DELETE FROM conversation_keys
1359
- WHERE assistant_id != 'self'
1360
- AND EXISTS (
1361
- SELECT 1 FROM conversation_keys ck2
1362
- WHERE ck2.assistant_id = 'self'
1363
- AND ck2.conversation_key = conversation_keys.conversation_key
1364
- )
1365
- `);
1366
- // Step 4: Remaining non-self rows have no 'self' counterpart — safe to bulk-update.
1367
- raw.exec(/*sql*/ `
1368
- UPDATE conversation_keys SET assistant_id = 'self' WHERE assistant_id != 'self'
1369
- `);
1370
- }
1371
-
1372
- // attachments: UNIQUE (assistant_id, content_hash) WHERE content_hash IS NOT NULL
1373
- //
1374
- // message_attachments rows reference attachment IDs with ON DELETE CASCADE, so we
1375
- // must remap links to the surviving row BEFORE deleting duplicates to avoid
1376
- // silently dropping attachment metadata from messages.
1377
- if (tableHasAssistantId('attachments')) {
1378
- // Step 1: Remap message_attachments from non-self duplicates to their survivor
1379
- // (MIN rowid per content_hash group), then delete the duplicates.
1380
- raw.exec(/*sql*/ `
1381
- UPDATE message_attachments
1382
- SET attachment_id = (
1383
- SELECT a_survivor.id
1384
- FROM attachments a_survivor
1385
- WHERE a_survivor.assistant_id != 'self'
1386
- AND a_survivor.content_hash = (
1387
- SELECT a_dup.content_hash FROM attachments a_dup
1388
- WHERE a_dup.id = message_attachments.attachment_id
1389
- )
1390
- ORDER BY a_survivor.rowid
1391
- LIMIT 1
1392
- )
1393
- WHERE attachment_id IN (
1394
- SELECT id FROM attachments
1395
- WHERE assistant_id != 'self'
1396
- AND content_hash IS NOT NULL
1397
- AND rowid NOT IN (
1398
- SELECT MIN(rowid) FROM attachments
1399
- WHERE assistant_id != 'self' AND content_hash IS NOT NULL
1400
- GROUP BY content_hash
1401
- )
1402
- )
1403
- `);
1404
- raw.exec(/*sql*/ `
1405
- DELETE FROM attachments
1406
- WHERE assistant_id != 'self'
1407
- AND content_hash IS NOT NULL
1408
- AND rowid NOT IN (
1409
- SELECT MIN(rowid) FROM attachments
1410
- WHERE assistant_id != 'self'
1411
- AND content_hash IS NOT NULL
1412
- GROUP BY content_hash
1413
- )
1414
- `);
1415
- // Step 2: Remap message_attachments from non-self rows conflicting with a 'self'
1416
- // row to the 'self' row, then delete the now-unlinked non-self rows.
1417
- raw.exec(/*sql*/ `
1418
- UPDATE message_attachments
1419
- SET attachment_id = (
1420
- SELECT a_self.id
1421
- FROM attachments a_self
1422
- WHERE a_self.assistant_id = 'self'
1423
- AND a_self.content_hash = (
1424
- SELECT a_ns.content_hash FROM attachments a_ns
1425
- WHERE a_ns.id = message_attachments.attachment_id
1426
- )
1427
- LIMIT 1
1428
- )
1429
- WHERE attachment_id IN (
1430
- SELECT id FROM attachments
1431
- WHERE assistant_id != 'self'
1432
- AND content_hash IS NOT NULL
1433
- AND EXISTS (
1434
- SELECT 1 FROM attachments a2
1435
- WHERE a2.assistant_id = 'self'
1436
- AND a2.content_hash = attachments.content_hash
1437
- )
1438
- )
1439
- `);
1440
- raw.exec(/*sql*/ `
1441
- DELETE FROM attachments
1442
- WHERE assistant_id != 'self'
1443
- AND content_hash IS NOT NULL
1444
- AND EXISTS (
1445
- SELECT 1 FROM attachments a2
1446
- WHERE a2.assistant_id = 'self'
1447
- AND a2.content_hash = attachments.content_hash
1448
- )
1449
- `);
1450
- // Step 3: Bulk-update remaining non-self rows.
1451
- raw.exec(/*sql*/ `
1452
- UPDATE attachments SET assistant_id = 'self' WHERE assistant_id != 'self'
1453
- `);
1454
- }
1455
-
1456
- // channel_inbound_events: UNIQUE (assistant_id, source_channel, external_chat_id, external_message_id)
1457
- if (tableHasAssistantId('channel_inbound_events')) {
1458
- // Step 1: Dedup non-self rows sharing the same (source_channel, external_chat_id, external_message_id).
1459
- raw.exec(/*sql*/ `
1460
- DELETE FROM channel_inbound_events
1461
- WHERE assistant_id != 'self'
1462
- AND rowid NOT IN (
1463
- SELECT MIN(rowid) FROM channel_inbound_events
1464
- WHERE assistant_id != 'self'
1465
- GROUP BY source_channel, external_chat_id, external_message_id
1466
- )
1467
- `);
1468
- // Step 2: Delete non-self rows conflicting with existing 'self' rows.
1469
- raw.exec(/*sql*/ `
1470
- DELETE FROM channel_inbound_events
1471
- WHERE assistant_id != 'self'
1472
- AND EXISTS (
1473
- SELECT 1 FROM channel_inbound_events e2
1474
- WHERE e2.assistant_id = 'self'
1475
- AND e2.source_channel = channel_inbound_events.source_channel
1476
- AND e2.external_chat_id = channel_inbound_events.external_chat_id
1477
- AND e2.external_message_id = channel_inbound_events.external_message_id
1478
- )
1479
- `);
1480
- // Step 3: Bulk-update remaining non-self rows.
1481
- raw.exec(/*sql*/ `
1482
- UPDATE channel_inbound_events SET assistant_id = 'self' WHERE assistant_id != 'self'
1483
- `);
1484
- }
1485
-
1486
- // message_runs: no unique constraint on assistant_id — simple bulk update
1487
- if (tableHasAssistantId('message_runs')) {
1488
- raw.exec(/*sql*/ `
1489
- UPDATE message_runs SET assistant_id = 'self' WHERE assistant_id != 'self'
1490
- `);
1491
- }
1492
-
1493
- raw.query(
1494
- `INSERT OR IGNORE INTO memory_checkpoints (key, value, updated_at) VALUES (?, '1', ?)`,
1495
- ).run(checkpointKey, Date.now());
1496
-
1497
- raw.exec('COMMIT');
1498
- } catch (e) {
1499
- try { raw.exec('ROLLBACK'); } catch { /* no active transaction */ }
1500
- throw e;
1501
- }
1502
- }
1503
-
1504
- /**
1505
- * One-shot migration: rebuild tables that previously stored assistant_id to remove
1506
- * that column now that all rows are keyed to the implicit single-tenant identity ("self").
1507
- *
1508
- * Must run AFTER migrateAssistantIdToSelf (which normalises all values to "self")
1509
- * so there are no constraint violations when recreating the tables without the
1510
- * assistant_id dimension.
1511
- *
1512
- * Each table section is guarded by a DDL check so this is safe on fresh installs
1513
- * where the column was never created in the first place.
1514
- *
1515
- * Tables rebuilt:
1516
- * - conversation_keys UNIQUE (conversation_key)
1517
- * - attachments no structural unique; content-dedup index updated
1518
- * - channel_inbound_events UNIQUE (source_channel, external_chat_id, external_message_id)
1519
- * - message_runs no unique constraint on assistant_id
1520
- * - llm_usage_events nullable column with no constraint
1521
- */
1522
- function migrateRemoveAssistantIdColumns(database: ReturnType<typeof drizzle<typeof schema>>): void {
1523
- const raw = (database as unknown as { $client: Database }).$client;
1524
- const checkpointKey = 'migration_remove_assistant_id_columns_v1';
1525
- const checkpoint = raw.query(
1526
- `SELECT 1 FROM memory_checkpoints WHERE key = ?`,
1527
- ).get(checkpointKey);
1528
- if (checkpoint) return;
1529
-
1530
- raw.exec('PRAGMA foreign_keys = OFF');
1531
- try {
1532
- raw.exec('BEGIN');
1533
-
1534
- // --- conversation_keys ---
1535
- const ckDdl = raw.query(
1536
- `SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'conversation_keys'`,
1537
- ).get() as { sql: string } | null;
1538
- if (ckDdl?.sql.includes('assistant_id')) {
1539
- raw.exec(/*sql*/ `
1540
- CREATE TABLE conversation_keys_new (
1541
- id TEXT PRIMARY KEY,
1542
- conversation_key TEXT NOT NULL UNIQUE,
1543
- conversation_id TEXT NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
1544
- created_at INTEGER NOT NULL
1545
- )
1546
- `);
1547
- raw.exec(/*sql*/ `
1548
- INSERT INTO conversation_keys_new (id, conversation_key, conversation_id, created_at)
1549
- SELECT id, conversation_key, conversation_id, created_at FROM conversation_keys
1550
- `);
1551
- raw.exec(/*sql*/ `DROP TABLE conversation_keys`);
1552
- raw.exec(/*sql*/ `ALTER TABLE conversation_keys_new RENAME TO conversation_keys`);
1553
- }
1554
-
1555
- // --- attachments ---
1556
- const attDdl = raw.query(
1557
- `SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'attachments'`,
1558
- ).get() as { sql: string } | null;
1559
- if (attDdl?.sql.includes('assistant_id')) {
1560
- raw.exec(/*sql*/ `
1561
- CREATE TABLE attachments_new (
1562
- id TEXT PRIMARY KEY,
1563
- original_filename TEXT NOT NULL,
1564
- mime_type TEXT NOT NULL,
1565
- size_bytes INTEGER NOT NULL,
1566
- kind TEXT NOT NULL,
1567
- data_base64 TEXT NOT NULL,
1568
- content_hash TEXT,
1569
- thumbnail_base64 TEXT,
1570
- created_at INTEGER NOT NULL
1571
- )
1572
- `);
1573
- raw.exec(/*sql*/ `
1574
- INSERT INTO attachments_new (id, original_filename, mime_type, size_bytes, kind, data_base64, content_hash, thumbnail_base64, created_at)
1575
- SELECT id, original_filename, mime_type, size_bytes, kind, data_base64, content_hash, thumbnail_base64, created_at FROM attachments
1576
- `);
1577
- raw.exec(/*sql*/ `DROP TABLE attachments`);
1578
- raw.exec(/*sql*/ `ALTER TABLE attachments_new RENAME TO attachments`);
1579
- }
1580
-
1581
- // --- channel_inbound_events ---
1582
- const cieDdl = raw.query(
1583
- `SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'channel_inbound_events'`,
1584
- ).get() as { sql: string } | null;
1585
- if (cieDdl?.sql.includes('assistant_id')) {
1586
- raw.exec(/*sql*/ `
1587
- CREATE TABLE channel_inbound_events_new (
1588
- id TEXT PRIMARY KEY,
1589
- source_channel TEXT NOT NULL,
1590
- external_chat_id TEXT NOT NULL,
1591
- external_message_id TEXT NOT NULL,
1592
- source_message_id TEXT,
1593
- conversation_id TEXT NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
1594
- message_id TEXT REFERENCES messages(id) ON DELETE CASCADE,
1595
- delivery_status TEXT NOT NULL DEFAULT 'pending',
1596
- processing_status TEXT NOT NULL DEFAULT 'pending',
1597
- processing_attempts INTEGER NOT NULL DEFAULT 0,
1598
- last_processing_error TEXT,
1599
- retry_after INTEGER,
1600
- raw_payload TEXT,
1601
- created_at INTEGER NOT NULL,
1602
- updated_at INTEGER NOT NULL,
1603
- UNIQUE (source_channel, external_chat_id, external_message_id)
1604
- )
1605
- `);
1606
- raw.exec(/*sql*/ `
1607
- INSERT INTO channel_inbound_events_new (
1608
- id, source_channel, external_chat_id, external_message_id, source_message_id,
1609
- conversation_id, message_id, delivery_status, processing_status,
1610
- processing_attempts, last_processing_error, retry_after, raw_payload,
1611
- created_at, updated_at
1612
- )
1613
- SELECT
1614
- id, source_channel, external_chat_id, external_message_id, source_message_id,
1615
- conversation_id, message_id, delivery_status, processing_status,
1616
- processing_attempts, last_processing_error, retry_after, raw_payload,
1617
- created_at, updated_at
1618
- FROM channel_inbound_events
1619
- `);
1620
- raw.exec(/*sql*/ `DROP TABLE channel_inbound_events`);
1621
- raw.exec(/*sql*/ `ALTER TABLE channel_inbound_events_new RENAME TO channel_inbound_events`);
1622
- }
1623
-
1624
- // --- message_runs ---
1625
- const mrDdl = raw.query(
1626
- `SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'message_runs'`,
1627
- ).get() as { sql: string } | null;
1628
- if (mrDdl?.sql.includes('assistant_id')) {
1629
- raw.exec(/*sql*/ `
1630
- CREATE TABLE message_runs_new (
1631
- id TEXT PRIMARY KEY,
1632
- conversation_id TEXT NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
1633
- message_id TEXT REFERENCES messages(id) ON DELETE CASCADE,
1634
- status TEXT NOT NULL DEFAULT 'running',
1635
- pending_confirmation TEXT,
1636
- input_tokens INTEGER NOT NULL DEFAULT 0,
1637
- output_tokens INTEGER NOT NULL DEFAULT 0,
1638
- estimated_cost REAL NOT NULL DEFAULT 0,
1639
- error TEXT,
1640
- created_at INTEGER NOT NULL,
1641
- updated_at INTEGER NOT NULL
1642
- )
1643
- `);
1644
- raw.exec(/*sql*/ `
1645
- INSERT INTO message_runs_new (
1646
- id, conversation_id, message_id, status, pending_confirmation,
1647
- input_tokens, output_tokens, estimated_cost, error, created_at, updated_at
1648
- )
1649
- SELECT
1650
- id, conversation_id, message_id, status, pending_confirmation,
1651
- input_tokens, output_tokens, estimated_cost, error, created_at, updated_at
1652
- FROM message_runs
1653
- `);
1654
- raw.exec(/*sql*/ `DROP TABLE message_runs`);
1655
- raw.exec(/*sql*/ `ALTER TABLE message_runs_new RENAME TO message_runs`);
1656
- }
1657
-
1658
- // --- llm_usage_events ---
1659
- const lueDdl = raw.query(
1660
- `SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'llm_usage_events'`,
1661
- ).get() as { sql: string } | null;
1662
- if (lueDdl?.sql.includes('assistant_id')) {
1663
- raw.exec(/*sql*/ `
1664
- CREATE TABLE llm_usage_events_new (
1665
- id TEXT PRIMARY KEY,
1666
- created_at INTEGER NOT NULL,
1667
- conversation_id TEXT,
1668
- run_id TEXT,
1669
- request_id TEXT,
1670
- actor TEXT NOT NULL,
1671
- provider TEXT NOT NULL,
1672
- model TEXT NOT NULL,
1673
- input_tokens INTEGER NOT NULL,
1674
- output_tokens INTEGER NOT NULL,
1675
- cache_creation_input_tokens INTEGER,
1676
- cache_read_input_tokens INTEGER,
1677
- estimated_cost_usd REAL,
1678
- pricing_status TEXT NOT NULL,
1679
- metadata_json TEXT
1680
- )
1681
- `);
1682
- raw.exec(/*sql*/ `
1683
- INSERT INTO llm_usage_events_new (
1684
- id, created_at, conversation_id, run_id, request_id, actor, provider, model,
1685
- input_tokens, output_tokens, cache_creation_input_tokens, cache_read_input_tokens,
1686
- estimated_cost_usd, pricing_status, metadata_json
1687
- )
1688
- SELECT
1689
- id, created_at, conversation_id, run_id, request_id, actor, provider, model,
1690
- input_tokens, output_tokens, cache_creation_input_tokens, cache_read_input_tokens,
1691
- estimated_cost_usd, pricing_status, metadata_json
1692
- FROM llm_usage_events
1693
- `);
1694
- raw.exec(/*sql*/ `DROP TABLE llm_usage_events`);
1695
- raw.exec(/*sql*/ `ALTER TABLE llm_usage_events_new RENAME TO llm_usage_events`);
1696
- }
1697
-
1698
- raw.query(
1699
- `INSERT OR IGNORE INTO memory_checkpoints (key, value, updated_at) VALUES (?, '1', ?)`,
1700
- ).run(checkpointKey, Date.now());
1701
-
1702
- raw.exec('COMMIT');
1703
- } catch (e) {
1704
- try { raw.exec('ROLLBACK'); } catch { /* no active transaction */ }
1705
- throw e;
1706
- } finally {
1707
- raw.exec('PRAGMA foreign_keys = ON');
1708
- }
1709
- }
1710
-
1711
- /**
1712
- * One-shot migration: rebuild llm_usage_events to drop the assistant_id column.
1713
- *
1714
- * This is a SEPARATE migration from migrateRemoveAssistantIdColumns so that installs
1715
- * where the 4-table version of that migration already ran (checkpoint already set)
1716
- * still get the llm_usage_events column removed. Without a separate checkpoint key,
1717
- * those installs would skip the llm_usage_events rebuild entirely.
1718
- *
1719
- * Safe on fresh installs (DDL guard exits early) and idempotent via checkpoint.
1720
- */
1721
- function migrateLlmUsageEventsDropAssistantId(database: ReturnType<typeof drizzle<typeof schema>>): void {
1722
- const raw = (database as unknown as { $client: Database }).$client;
1723
- const checkpointKey = 'migration_remove_assistant_id_lue_v1';
1724
- const checkpoint = raw.query(
1725
- `SELECT 1 FROM memory_checkpoints WHERE key = ?`,
1726
- ).get(checkpointKey);
1727
- if (checkpoint) return;
1728
-
1729
- // DDL guard: if the column was already removed (fresh install or migrateRemoveAssistantIdColumns
1730
- // ran with the llm_usage_events block), just record the checkpoint and exit.
1731
- const lueDdl = raw.query(
1732
- `SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'llm_usage_events'`,
1733
- ).get() as { sql: string } | null;
1734
-
1735
- if (!lueDdl?.sql.includes('assistant_id')) {
1736
- raw.query(
1737
- `INSERT OR IGNORE INTO memory_checkpoints (key, value, updated_at) VALUES (?, '1', ?)`,
1738
- ).run(checkpointKey, Date.now());
1739
- return;
1740
- }
1741
-
1742
- raw.exec('PRAGMA foreign_keys = OFF');
1743
- try {
1744
- raw.exec('BEGIN');
1745
-
1746
- raw.exec(/*sql*/ `
1747
- CREATE TABLE llm_usage_events_new (
1748
- id TEXT PRIMARY KEY,
1749
- created_at INTEGER NOT NULL,
1750
- conversation_id TEXT,
1751
- run_id TEXT,
1752
- request_id TEXT,
1753
- actor TEXT NOT NULL,
1754
- provider TEXT NOT NULL,
1755
- model TEXT NOT NULL,
1756
- input_tokens INTEGER NOT NULL,
1757
- output_tokens INTEGER NOT NULL,
1758
- cache_creation_input_tokens INTEGER,
1759
- cache_read_input_tokens INTEGER,
1760
- estimated_cost_usd REAL,
1761
- pricing_status TEXT NOT NULL,
1762
- metadata_json TEXT
1763
- )
1764
- `);
1765
- raw.exec(/*sql*/ `
1766
- INSERT INTO llm_usage_events_new (
1767
- id, created_at, conversation_id, run_id, request_id, actor, provider, model,
1768
- input_tokens, output_tokens, cache_creation_input_tokens, cache_read_input_tokens,
1769
- estimated_cost_usd, pricing_status, metadata_json
1770
- )
1771
- SELECT
1772
- id, created_at, conversation_id, run_id, request_id, actor, provider, model,
1773
- input_tokens, output_tokens, cache_creation_input_tokens, cache_read_input_tokens,
1774
- estimated_cost_usd, pricing_status, metadata_json
1775
- FROM llm_usage_events
1776
- `);
1777
- raw.exec(/*sql*/ `DROP TABLE llm_usage_events`);
1778
- raw.exec(/*sql*/ `ALTER TABLE llm_usage_events_new RENAME TO llm_usage_events`);
1779
-
1780
- raw.query(
1781
- `INSERT OR IGNORE INTO memory_checkpoints (key, value, updated_at) VALUES (?, '1', ?)`,
1782
- ).run(checkpointKey, Date.now());
1783
-
1784
- raw.exec('COMMIT');
1785
- } catch (e) {
1786
- try { raw.exec('ROLLBACK'); } catch { /* no active transaction */ }
1787
- throw e;
1788
- } finally {
1789
- raw.exec('PRAGMA foreign_keys = ON');
1790
- }
1791
- }
1792
-
1793
- /**
1794
- * One-shot migration: deduplicate external_conversation_bindings rows that
1795
- * share the same (source_channel, external_chat_id), then create a unique
1796
- * index to enforce the invariant at DB level.
1797
- *
1798
- * For each duplicate group, the binding with the newest updatedAt (then
1799
- * createdAt) is kept; older duplicates are deleted.
1800
- */
1801
- function migrateExtConvBindingsChannelChatUnique(database: ReturnType<typeof drizzle<typeof schema>>): void {
1802
- const raw = (database as unknown as { $client: Database }).$client;
1803
-
1804
- // If the unique index already exists, nothing to do.
1805
- const idxExists = raw.query(
1806
- `SELECT 1 FROM sqlite_master WHERE type = 'index' AND name = 'idx_ext_conv_bindings_channel_chat_unique'`,
1807
- ).get();
1808
- if (idxExists) return;
1809
-
1810
- // Check if the table exists (first boot edge case).
1811
- const tableExists = raw.query(
1812
- `SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'external_conversation_bindings'`,
1813
- ).get();
1814
- if (!tableExists) return;
1815
-
1816
- // Remove duplicates: keep the row with the newest updatedAt, then createdAt.
1817
- // Since conversation_id is the PK (rowid alias), we use it for ordering ties.
1818
- try {
1819
- raw.exec('BEGIN');
1820
-
1821
- raw.exec(/*sql*/ `
1822
- DELETE FROM external_conversation_bindings
1823
- WHERE rowid NOT IN (
1824
- SELECT rowid FROM (
1825
- SELECT rowid,
1826
- ROW_NUMBER() OVER (
1827
- PARTITION BY source_channel, external_chat_id
1828
- ORDER BY updated_at DESC, created_at DESC, rowid DESC
1829
- ) AS rn
1830
- FROM external_conversation_bindings
1831
- )
1832
- WHERE rn = 1
1833
- )
1834
- `);
1835
-
1836
- raw.exec(/*sql*/ `
1837
- CREATE UNIQUE INDEX IF NOT EXISTS idx_ext_conv_bindings_channel_chat_unique
1838
- ON external_conversation_bindings(source_channel, external_chat_id)
1839
- `);
1840
-
1841
- raw.exec('COMMIT');
1842
- } catch (e) {
1843
- try { raw.exec('ROLLBACK'); } catch { /* no active transaction */ }
1844
- throw e;
1845
- }
1846
- }
1847
-
1848
- /**
1849
- * One-shot migration: remove duplicate (provider, provider_call_sid) rows from
1850
- * call_sessions so that the unique index can be created safely on upgraded databases
1851
- * that pre-date the constraint.
1852
- *
1853
- * For each set of duplicates, the most recently updated row is kept.
1854
- */
1855
- function migrateCallSessionsProviderSidDedup(database: ReturnType<typeof drizzle<typeof schema>>): void {
1856
- const raw = (database as unknown as { $client: Database }).$client;
1857
-
1858
- // Quick check: if the unique index already exists, no dedup is needed.
1859
- const idxExists = raw.query(
1860
- `SELECT 1 FROM sqlite_master WHERE type = 'index' AND name = 'idx_call_sessions_provider_sid_unique'`,
1861
- ).get();
1862
- if (idxExists) return;
1863
-
1864
- // Check if the table even exists yet (first boot).
1865
- const tableExists = raw.query(
1866
- `SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'call_sessions'`,
1867
- ).get();
1868
- if (!tableExists) return;
1869
-
1870
- // Count duplicates before doing any work.
1871
- const dupCount = raw.query(/*sql*/ `
1872
- SELECT COUNT(*) AS c FROM (
1873
- SELECT provider, provider_call_sid
1874
- FROM call_sessions
1875
- WHERE provider_call_sid IS NOT NULL
1876
- GROUP BY provider, provider_call_sid
1877
- HAVING COUNT(*) > 1
1878
- )
1879
- `).get() as { c: number } | null;
1880
-
1881
- if (!dupCount || dupCount.c === 0) return;
1882
-
1883
- log.warn({ duplicateGroups: dupCount.c }, 'Deduplicating call_sessions with duplicate provider_call_sid before creating unique index');
1884
-
1885
- try {
1886
- raw.exec('BEGIN');
1887
-
1888
- // Keep the most recently updated row per (provider, provider_call_sid);
1889
- // delete the rest.
1890
- raw.exec(/*sql*/ `
1891
- DELETE FROM call_sessions
1892
- WHERE provider_call_sid IS NOT NULL
1893
- AND rowid NOT IN (
1894
- SELECT MAX(rowid) FROM call_sessions
1895
- WHERE provider_call_sid IS NOT NULL
1896
- GROUP BY provider, provider_call_sid
1897
- )
1898
- `);
1899
-
1900
- raw.exec('COMMIT');
1901
- } catch (e) {
1902
- try { raw.exec('ROLLBACK'); } catch { /* no active transaction */ }
1903
- throw e;
1904
- }
1905
- }
1906
-