@vellumai/assistant 0.3.5 → 0.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (487) hide show
  1. package/README.md +51 -0
  2. package/eslint.config.mjs +31 -0
  3. package/package.json +1 -1
  4. package/scripts/ipc/check-swift-decoder-drift.ts +4 -1
  5. package/scripts/ipc/generate-swift.ts +18 -2
  6. package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +338 -1
  7. package/src/__tests__/approval-conversation-turn.test.ts +214 -0
  8. package/src/__tests__/browser-manager.test.ts +1 -0
  9. package/src/__tests__/call-conversation-messages.test.ts +130 -0
  10. package/src/__tests__/call-orchestrator.test.ts +752 -271
  11. package/src/__tests__/call-pointer-messages.test.ts +148 -0
  12. package/src/__tests__/call-recovery.test.ts +3 -0
  13. package/src/__tests__/call-routes-http.test.ts +5 -0
  14. package/src/__tests__/call-store.test.ts +3 -0
  15. package/src/__tests__/channel-approval-routes.test.ts +1260 -85
  16. package/src/__tests__/channel-approval.test.ts +37 -0
  17. package/src/__tests__/channel-approvals.test.ts +4 -65
  18. package/src/__tests__/channel-guardian.test.ts +556 -0
  19. package/src/__tests__/channel-readiness-service.test.ts +74 -7
  20. package/src/__tests__/checker.test.ts +14 -7
  21. package/src/__tests__/clarification-resolver.test.ts +44 -24
  22. package/src/__tests__/commit-message-enrichment-service.test.ts +9 -4
  23. package/src/__tests__/computer-use-session-working-dir.test.ts +8 -0
  24. package/src/__tests__/config-schema.test.ts +12 -7
  25. package/src/__tests__/context-window-manager.test.ts +30 -2
  26. package/src/__tests__/contradiction-checker.test.ts +20 -5
  27. package/src/__tests__/credential-security-invariants.test.ts +6 -2
  28. package/src/__tests__/db-migration-rollback.test.ts +752 -0
  29. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +2 -0
  30. package/src/__tests__/fuzzy-match-property.test.ts +5 -5
  31. package/src/__tests__/guardian-action-store.test.ts +123 -0
  32. package/src/__tests__/guardian-action-sweep.test.ts +277 -0
  33. package/src/__tests__/guardian-dispatch.test.ts +389 -0
  34. package/src/__tests__/guardian-question-copy.test.ts +47 -0
  35. package/src/__tests__/handlers-telegram-config.test.ts +4 -2
  36. package/src/__tests__/handlers-twilio-config.test.ts +126 -0
  37. package/src/__tests__/intent-routing.test.ts +2 -0
  38. package/src/__tests__/ipc-snapshot.test.ts +228 -1
  39. package/src/__tests__/memory-upsert-concurrency.test.ts +828 -0
  40. package/src/__tests__/model-intents.test.ts +96 -0
  41. package/src/__tests__/no-direct-anthropic-sdk-imports.test.ts +42 -0
  42. package/src/__tests__/oauth2-gateway-transport.test.ts +130 -0
  43. package/src/__tests__/onboarding-starter-tasks.test.ts +2 -0
  44. package/src/__tests__/provider-commit-message-generator.test.ts +89 -13
  45. package/src/__tests__/provider-error-scenarios.test.ts +621 -0
  46. package/src/__tests__/provider-fail-open-selection.test.ts +119 -0
  47. package/src/__tests__/qdrant-manager.test.ts +27 -20
  48. package/src/__tests__/relay-server.test.ts +779 -40
  49. package/src/__tests__/run-orchestrator-assistant-events.test.ts +2 -0
  50. package/src/__tests__/run-orchestrator.test.ts +20 -4
  51. package/src/__tests__/runtime-runs-http.test.ts +17 -1
  52. package/src/__tests__/runtime-runs.test.ts +16 -0
  53. package/src/__tests__/schedule-store.test.ts +18 -4
  54. package/src/__tests__/scheduler-recurrence.test.ts +13 -4
  55. package/src/__tests__/session-abort-tool-results.test.ts +6 -0
  56. package/src/__tests__/session-agent-loop.test.ts +857 -0
  57. package/src/__tests__/session-conflict-gate.test.ts +6 -0
  58. package/src/__tests__/session-pre-run-repair.test.ts +6 -0
  59. package/src/__tests__/session-profile-injection.test.ts +6 -0
  60. package/src/__tests__/session-provider-retry-repair.test.ts +6 -0
  61. package/src/__tests__/session-queue.test.ts +6 -0
  62. package/src/__tests__/session-runtime-assembly.test.ts +237 -13
  63. package/src/__tests__/session-slash-known.test.ts +6 -0
  64. package/src/__tests__/session-slash-queue.test.ts +6 -0
  65. package/src/__tests__/session-slash-unknown.test.ts +6 -0
  66. package/src/__tests__/session-surfaces-task-progress.test.ts +2 -0
  67. package/src/__tests__/session-tool-setup-app-refresh.test.ts +1 -0
  68. package/src/__tests__/session-tool-setup-memory-scope.test.ts +1 -0
  69. package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +1 -0
  70. package/src/__tests__/session-workspace-injection.test.ts +6 -0
  71. package/src/__tests__/session-workspace-tool-tracking.test.ts +6 -0
  72. package/src/__tests__/skills.test.ts +2 -0
  73. package/src/__tests__/sms-messaging-provider.test.ts +2 -1
  74. package/src/__tests__/starter-task-flow.test.ts +2 -0
  75. package/src/__tests__/swarm-dag-pathological.test.ts +535 -0
  76. package/src/__tests__/system-prompt.test.ts +2 -0
  77. package/src/__tests__/task-management-tools.test.ts +2 -2
  78. package/src/__tests__/task-runner.test.ts +14 -4
  79. package/src/__tests__/terminal-tools.test.ts +25 -19
  80. package/src/__tests__/tool-execution-abort-cleanup.test.ts +545 -0
  81. package/src/__tests__/tool-executor-shell-integration.test.ts +11 -11
  82. package/src/__tests__/tool-executor.test.ts +23 -24
  83. package/src/__tests__/trust-store.test.ts +3 -3
  84. package/src/__tests__/twilio-rest.test.ts +29 -0
  85. package/src/__tests__/twilio-routes-elevenlabs.test.ts +3 -0
  86. package/src/__tests__/twilio-routes-twiml.test.ts +11 -0
  87. package/src/__tests__/twilio-routes.test.ts +141 -21
  88. package/src/__tests__/user-reference.test.ts +2 -0
  89. package/src/__tests__/voice-quality.test.ts +222 -0
  90. package/src/__tests__/web-search.test.ts +45 -29
  91. package/src/agent/loop.ts +1 -1
  92. package/src/agent-heartbeat/agent-heartbeat-service.ts +2 -10
  93. package/src/amazon/client.ts +1418 -0
  94. package/src/amazon/request-extractor.ts +135 -0
  95. package/src/amazon/session.ts +109 -0
  96. package/src/autonomy/autonomy-store.ts +5 -5
  97. package/src/browser-extension-relay/client.ts +124 -0
  98. package/src/browser-extension-relay/protocol.ts +63 -0
  99. package/src/browser-extension-relay/server.ts +177 -0
  100. package/src/bundler/app-bundler.ts +3 -3
  101. package/src/bundler/bundle-signer.ts +1 -1
  102. package/src/bundler/signature-verifier.ts +1 -1
  103. package/src/calls/call-conversation-messages.ts +33 -0
  104. package/src/calls/call-domain.ts +106 -5
  105. package/src/calls/call-orchestrator.ts +252 -54
  106. package/src/calls/call-pointer-messages.ts +53 -0
  107. package/src/calls/call-recovery.ts +3 -8
  108. package/src/calls/call-store.ts +69 -87
  109. package/src/calls/elevenlabs-config.ts +3 -2
  110. package/src/calls/guardian-action-sweep.ts +105 -0
  111. package/src/calls/guardian-dispatch.ts +203 -0
  112. package/src/calls/guardian-question-copy.ts +133 -0
  113. package/src/calls/relay-server.ts +466 -8
  114. package/src/calls/speaker-identification.ts +1 -1
  115. package/src/calls/twilio-config.ts +7 -5
  116. package/src/calls/twilio-provider.ts +6 -4
  117. package/src/calls/twilio-rest.ts +40 -15
  118. package/src/calls/twilio-routes.ts +60 -45
  119. package/src/calls/types.ts +3 -1
  120. package/src/channels/types.ts +25 -0
  121. package/src/cli/amazon.ts +815 -0
  122. package/src/cli/config-commands.ts +2 -2
  123. package/src/cli/core-commands.ts +4 -3
  124. package/src/cli/influencer.ts +244 -0
  125. package/src/cli/map.ts +89 -6
  126. package/src/cli.ts +1 -1
  127. package/src/config/agent-schema.ts +171 -0
  128. package/src/config/bundled-skills/amazon/SKILL.md +127 -0
  129. package/src/config/bundled-skills/amazon/icon.svg +13 -0
  130. package/src/config/bundled-skills/api-mapping/SKILL.md +78 -0
  131. package/src/config/bundled-skills/browser/SKILL.md +1 -0
  132. package/src/config/bundled-skills/browser/TOOLS.json +17 -0
  133. package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +25 -0
  134. package/src/config/bundled-skills/doordash/SKILL.md +51 -51
  135. package/src/config/bundled-skills/email-setup/SKILL.md +14 -5
  136. package/src/config/bundled-skills/google-oauth-setup/SKILL.md +183 -0
  137. package/src/config/bundled-skills/influencer/SKILL.md +144 -0
  138. package/src/config/bundled-skills/macos-automation/icon.svg +12 -0
  139. package/src/config/bundled-skills/media-processing/SKILL.md +72 -95
  140. package/src/config/bundled-skills/media-processing/TOOLS.json +57 -147
  141. package/src/config/bundled-skills/media-processing/__tests__/concurrency-pool.test.ts +77 -0
  142. package/src/config/bundled-skills/media-processing/__tests__/cost-tracker.test.ts +69 -0
  143. package/src/config/bundled-skills/media-processing/__tests__/preprocess.test.ts +303 -0
  144. package/src/config/bundled-skills/media-processing/services/concurrency-pool.ts +55 -0
  145. package/src/config/bundled-skills/media-processing/services/cost-tracker.ts +86 -0
  146. package/src/config/bundled-skills/media-processing/services/gemini-map.ts +339 -0
  147. package/src/config/bundled-skills/media-processing/services/preprocess.ts +551 -0
  148. package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +7 -9
  149. package/src/config/bundled-skills/media-processing/services/reduce.ts +197 -0
  150. package/src/config/bundled-skills/media-processing/tools/analyze-keyframes.ts +88 -253
  151. package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +22 -153
  152. package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +2 -2
  153. package/src/config/bundled-skills/media-processing/tools/media-diagnostics.ts +28 -51
  154. package/src/config/bundled-skills/media-processing/tools/query-media-events.ts +35 -270
  155. package/src/config/bundled-skills/messaging/SKILL.md +12 -2
  156. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +4 -7
  157. package/src/config/bundled-skills/messaging/tools/messaging-reply.ts +2 -1
  158. package/src/config/bundled-skills/phone-calls/SKILL.md +86 -21
  159. package/src/config/bundled-skills/twitter/icon.svg +14 -0
  160. package/src/config/bundled-tool-registry.ts +310 -0
  161. package/src/config/calls-schema.ts +181 -0
  162. package/src/config/core-schema.ts +309 -0
  163. package/src/config/defaults.ts +27 -3
  164. package/src/config/env-registry.ts +169 -0
  165. package/src/config/env.ts +175 -0
  166. package/src/config/loader.ts +6 -6
  167. package/src/config/memory-schema.ts +528 -0
  168. package/src/config/sandbox-schema.ts +55 -0
  169. package/src/config/schema.ts +157 -1138
  170. package/src/config/skill-state.ts +1 -1
  171. package/src/config/skills-schema.ts +32 -0
  172. package/src/config/skills.ts +35 -24
  173. package/src/config/system-prompt.ts +107 -56
  174. package/src/config/templates/SOUL.md +1 -1
  175. package/src/config/types.ts +1 -0
  176. package/src/config/user-reference.ts +4 -9
  177. package/src/config/vellum-skills/catalog.json +0 -7
  178. package/src/config/vellum-skills/chatgpt-import/tools/chatgpt-import.ts +5 -1
  179. package/src/config/vellum-skills/slack-oauth-setup/SKILL.md +1 -0
  180. package/src/config/vellum-skills/sms-setup/SKILL.md +112 -14
  181. package/src/context/window-manager.ts +27 -7
  182. package/src/daemon/approval-generators.ts +186 -0
  183. package/src/daemon/approved-devices-store.ts +140 -0
  184. package/src/daemon/assistant-attachments.ts +1 -1
  185. package/src/daemon/classifier.ts +35 -32
  186. package/src/daemon/config-watcher.ts +1 -1
  187. package/src/daemon/daemon-control.ts +254 -0
  188. package/src/daemon/handlers/apps.ts +2 -3
  189. package/src/daemon/handlers/config-channels.ts +158 -0
  190. package/src/daemon/handlers/config-inbox.ts +540 -0
  191. package/src/daemon/handlers/config-ingress.ts +231 -0
  192. package/src/daemon/handlers/config-integrations.ts +258 -0
  193. package/src/daemon/handlers/config-model.ts +143 -0
  194. package/src/daemon/handlers/config-parental.ts +163 -0
  195. package/src/daemon/handlers/config-scheduling.ts +172 -0
  196. package/src/daemon/handlers/config-slack.ts +92 -0
  197. package/src/daemon/handlers/config-telegram.ts +301 -0
  198. package/src/daemon/handlers/config-tools.ts +177 -0
  199. package/src/daemon/handlers/config-trust.ts +104 -0
  200. package/src/daemon/handlers/config-twilio.ts +1080 -0
  201. package/src/daemon/handlers/config.ts +53 -2463
  202. package/src/daemon/handlers/diagnostics.ts +1 -1
  203. package/src/daemon/handlers/dictation.ts +4 -6
  204. package/src/daemon/handlers/documents.ts +18 -32
  205. package/src/daemon/handlers/index.ts +9 -0
  206. package/src/daemon/handlers/misc.ts +3 -5
  207. package/src/daemon/handlers/pairing.ts +98 -0
  208. package/src/daemon/handlers/sessions.ts +74 -5
  209. package/src/daemon/handlers/shared.ts +3 -1
  210. package/src/daemon/handlers/skills.ts +1 -1
  211. package/src/daemon/handlers/twitter-auth.ts +2 -0
  212. package/src/daemon/handlers/work-items.ts +2 -2
  213. package/src/daemon/handlers/workspace-files.ts +4 -3
  214. package/src/daemon/install-cli-launchers.ts +113 -0
  215. package/src/daemon/ipc-contract/apps.ts +356 -0
  216. package/src/daemon/ipc-contract/browser.ts +74 -0
  217. package/src/daemon/ipc-contract/computer-use.ts +151 -0
  218. package/src/daemon/ipc-contract/diagnostics.ts +56 -0
  219. package/src/daemon/ipc-contract/documents.ts +74 -0
  220. package/src/daemon/ipc-contract/inbox.ts +209 -0
  221. package/src/daemon/ipc-contract/integrations.ts +284 -0
  222. package/src/daemon/ipc-contract/memory.ts +48 -0
  223. package/src/daemon/ipc-contract/messages.ts +211 -0
  224. package/src/daemon/ipc-contract/pairing.ts +45 -0
  225. package/src/daemon/ipc-contract/parental-control.ts +95 -0
  226. package/src/daemon/ipc-contract/schedules.ts +97 -0
  227. package/src/daemon/ipc-contract/sessions.ts +321 -0
  228. package/src/daemon/ipc-contract/shared.ts +42 -0
  229. package/src/daemon/ipc-contract/skills.ts +120 -0
  230. package/src/daemon/ipc-contract/subagents.ts +58 -0
  231. package/src/daemon/ipc-contract/surfaces.ts +250 -0
  232. package/src/daemon/ipc-contract/trust.ts +60 -0
  233. package/src/daemon/ipc-contract/work-items.ts +225 -0
  234. package/src/daemon/ipc-contract/workspace.ts +113 -0
  235. package/src/daemon/ipc-contract-inventory.json +62 -0
  236. package/src/daemon/ipc-contract-inventory.ts +55 -29
  237. package/src/daemon/ipc-contract.ts +227 -2527
  238. package/src/daemon/ipc-protocol.ts +1 -1
  239. package/src/daemon/ipc-validate.ts +7 -0
  240. package/src/daemon/lifecycle.ts +97 -379
  241. package/src/daemon/pairing-store.ts +177 -0
  242. package/src/daemon/providers-setup.ts +43 -0
  243. package/src/daemon/ride-shotgun-handler.ts +67 -2
  244. package/src/daemon/server.ts +60 -44
  245. package/src/daemon/session-agent-loop-handlers.ts +421 -0
  246. package/src/daemon/session-agent-loop.ts +113 -275
  247. package/src/daemon/session-dynamic-profile.ts +1 -1
  248. package/src/daemon/session-history.ts +1 -1
  249. package/src/daemon/session-media-retry.ts +1 -1
  250. package/src/daemon/session-messaging.ts +37 -2
  251. package/src/daemon/session-notifiers.ts +5 -25
  252. package/src/daemon/session-process.ts +99 -59
  253. package/src/daemon/session-queue-manager.ts +98 -4
  254. package/src/daemon/session-runtime-assembly.ts +149 -15
  255. package/src/daemon/session-surfaces.ts +26 -4
  256. package/src/daemon/session-tool-setup.ts +28 -30
  257. package/src/daemon/session-workspace.ts +1 -1
  258. package/src/daemon/session.ts +24 -1
  259. package/src/daemon/shutdown-handlers.ts +122 -0
  260. package/src/daemon/trace-emitter.ts +1 -1
  261. package/src/daemon/watch-handler.ts +36 -33
  262. package/src/doordash/cart-queries.ts +787 -0
  263. package/src/doordash/client.ts +144 -127
  264. package/src/doordash/order-queries.ts +85 -0
  265. package/src/doordash/queries.ts +10 -1308
  266. package/src/doordash/search-queries.ts +203 -0
  267. package/src/doordash/session.ts +3 -2
  268. package/src/doordash/store-queries.ts +246 -0
  269. package/src/doordash/types.ts +367 -0
  270. package/src/email/providers/agentmail.ts +2 -1
  271. package/src/email/providers/index.ts +3 -2
  272. package/src/email/service.ts +3 -2
  273. package/src/errors.ts +43 -0
  274. package/src/home-base/prebuilt/seed.ts +1 -1
  275. package/src/hooks/cli.ts +6 -5
  276. package/src/hooks/config.ts +6 -8
  277. package/src/hooks/discovery.ts +6 -5
  278. package/src/hooks/manager.ts +4 -3
  279. package/src/hooks/runner.ts +2 -2
  280. package/src/hooks/templates.ts +5 -5
  281. package/src/inbound/public-ingress-urls.ts +3 -1
  282. package/src/index.ts +4 -2
  283. package/src/influencer/client.ts +1104 -0
  284. package/src/instrument.ts +4 -3
  285. package/src/logfire.ts +4 -3
  286. package/src/memory/admin.ts +25 -35
  287. package/src/memory/attachments-store.ts +4 -7
  288. package/src/memory/channel-delivery-store.ts +30 -1
  289. package/src/memory/channel-guardian-store.ts +200 -1
  290. package/src/memory/clarification-resolver.ts +37 -33
  291. package/src/memory/conflict-store.ts +67 -61
  292. package/src/memory/contradiction-checker.ts +141 -117
  293. package/src/memory/conversation-store.ts +335 -51
  294. package/src/memory/db-connection.ts +27 -4
  295. package/src/memory/db-init.ts +121 -4
  296. package/src/memory/db.ts +14 -1
  297. package/src/memory/embedding-backend.ts +27 -5
  298. package/src/memory/embedding-ollama.ts +2 -1
  299. package/src/memory/entity-extractor.ts +38 -35
  300. package/src/memory/guardian-action-store.ts +430 -0
  301. package/src/memory/inbox-escalation-projection.ts +59 -0
  302. package/src/memory/inbox-thread-store.ts +218 -0
  303. package/src/memory/ingress-invite-store.ts +338 -0
  304. package/src/memory/ingress-member-store.ts +350 -0
  305. package/src/memory/items-extractor.ts +91 -97
  306. package/src/memory/job-handlers/index-maintenance.ts +3 -3
  307. package/src/memory/job-handlers/media-processing.ts +11 -42
  308. package/src/memory/job-handlers/summarization.ts +32 -26
  309. package/src/memory/job-utils.ts +3 -10
  310. package/src/memory/jobs-store.ts +6 -9
  311. package/src/memory/jobs-worker.ts +51 -36
  312. package/src/memory/migrations/001-job-deferrals.ts +45 -0
  313. package/src/memory/migrations/002-tool-invocations-fk.ts +43 -0
  314. package/src/memory/migrations/003-memory-fts-backfill.ts +24 -0
  315. package/src/memory/migrations/004-entity-relation-dedup.ts +87 -0
  316. package/src/memory/migrations/005-fingerprint-scope-unique.ts +80 -0
  317. package/src/memory/migrations/006-scope-salted-fingerprints.ts +62 -0
  318. package/src/memory/migrations/007-assistant-id-to-self.ts +254 -0
  319. package/src/memory/migrations/008-remove-assistant-id-columns.ts +208 -0
  320. package/src/memory/migrations/009-llm-usage-events-drop-assistant-id.ts +83 -0
  321. package/src/memory/migrations/010-ext-conv-bindings-channel-chat-unique.ts +56 -0
  322. package/src/memory/migrations/011-call-sessions-provider-sid-dedup.ts +63 -0
  323. package/src/memory/migrations/012-call-sessions-add-initiated-from.ts +19 -0
  324. package/src/memory/migrations/013-guardian-action-tables.ts +68 -0
  325. package/src/memory/migrations/014-backfill-inbox-thread-state.ts +76 -0
  326. package/src/memory/migrations/015-drop-active-search-index.ts +27 -0
  327. package/src/memory/migrations/016-memory-segments-indexes.ts +11 -0
  328. package/src/memory/migrations/017-memory-items-indexes.ts +12 -0
  329. package/src/memory/migrations/018-remaining-table-indexes.ts +13 -0
  330. package/src/memory/migrations/index.ts +24 -0
  331. package/src/memory/migrations/registry.ts +79 -0
  332. package/src/memory/migrations/validate-migration-state.ts +69 -0
  333. package/src/memory/qdrant-manager.ts +49 -8
  334. package/src/memory/query-builder.ts +1 -1
  335. package/src/memory/raw-query.ts +119 -0
  336. package/src/memory/recall-cache.ts +4 -1
  337. package/src/memory/retriever.ts +163 -47
  338. package/src/memory/schema-migration.ts +25 -984
  339. package/src/memory/schema.ts +130 -7
  340. package/src/memory/search/entity.ts +10 -19
  341. package/src/memory/search/lexical.ts +81 -52
  342. package/src/memory/search/ranking.ts +21 -22
  343. package/src/memory/search/semantic.ts +157 -19
  344. package/src/memory/shared-app-links-store.ts +4 -5
  345. package/src/memory/validation.ts +19 -0
  346. package/src/messaging/draft-store.ts +5 -6
  347. package/src/messaging/providers/sms/adapter.ts +3 -6
  348. package/src/messaging/providers/telegram-bot/adapter.ts +2 -5
  349. package/src/messaging/providers/whatsapp/adapter.ts +136 -0
  350. package/src/messaging/providers/whatsapp/client.ts +67 -0
  351. package/src/messaging/style-analyzer.ts +5 -4
  352. package/src/messaging/thread-summarizer.ts +61 -69
  353. package/src/messaging/triage-engine.ts +62 -71
  354. package/src/migrations/config-merge.ts +53 -0
  355. package/src/migrations/data-layout.ts +68 -0
  356. package/src/migrations/data-merge.ts +33 -0
  357. package/src/migrations/hooks-merge.ts +90 -0
  358. package/src/migrations/index.ts +6 -0
  359. package/src/migrations/log.ts +23 -0
  360. package/src/migrations/skills-merge.ts +33 -0
  361. package/src/migrations/workspace-layout.ts +79 -0
  362. package/src/permissions/checker.ts +126 -11
  363. package/src/permissions/prompter.ts +14 -0
  364. package/src/permissions/shell-identity.ts +31 -1
  365. package/src/permissions/trust-store.ts +21 -1
  366. package/src/providers/anthropic/client.ts +4 -4
  367. package/src/providers/failover.ts +2 -2
  368. package/src/providers/model-intents.ts +70 -0
  369. package/src/providers/ollama/client.ts +2 -1
  370. package/src/providers/provider-send-message.ts +176 -0
  371. package/src/providers/registry.ts +71 -30
  372. package/src/providers/retry.ts +35 -1
  373. package/src/providers/types.ts +12 -1
  374. package/src/runtime/approval-conversation-turn.ts +97 -0
  375. package/src/runtime/approval-message-composer.ts +115 -5
  376. package/src/runtime/assistant-event-hub.ts +3 -1
  377. package/src/runtime/channel-approval-parser.ts +36 -2
  378. package/src/runtime/channel-approvals.ts +0 -21
  379. package/src/runtime/channel-guardian-service.ts +48 -7
  380. package/src/runtime/channel-readiness-service.ts +160 -34
  381. package/src/runtime/channel-readiness-types.ts +10 -4
  382. package/src/runtime/channel-retry-sweep.ts +184 -0
  383. package/src/runtime/guardian-context-resolver.ts +108 -0
  384. package/src/runtime/http-server.ts +289 -745
  385. package/src/runtime/http-types.ts +56 -3
  386. package/src/runtime/middleware/auth.ts +116 -0
  387. package/src/runtime/middleware/error-handler.ts +33 -0
  388. package/src/runtime/middleware/twilio-validation.ts +127 -0
  389. package/src/runtime/routes/app-routes.ts +1 -1
  390. package/src/runtime/routes/call-routes.ts +49 -6
  391. package/src/runtime/routes/channel-delivery-routes.ts +170 -0
  392. package/src/runtime/routes/channel-guardian-routes.ts +1191 -0
  393. package/src/runtime/routes/channel-inbound-routes.ts +1152 -0
  394. package/src/runtime/routes/channel-route-shared.ts +144 -0
  395. package/src/runtime/routes/channel-routes.ts +32 -1634
  396. package/src/runtime/routes/conversation-routes.ts +50 -7
  397. package/src/runtime/routes/events-routes.ts +2 -2
  398. package/src/runtime/routes/identity-routes.ts +126 -0
  399. package/src/runtime/routes/pairing-routes.ts +144 -0
  400. package/src/runtime/routes/run-routes.ts +15 -1
  401. package/src/runtime/run-orchestrator.ts +52 -34
  402. package/src/schedule/schedule-store.ts +36 -32
  403. package/src/schedule/scheduler.ts +3 -3
  404. package/src/security/encrypted-store.ts +5 -7
  405. package/src/security/oauth2.ts +45 -15
  406. package/src/security/parental-control-store.ts +183 -0
  407. package/src/security/secret-allowlist.ts +4 -3
  408. package/src/security/secret-scanner.ts +5 -5
  409. package/src/security/secure-keys.ts +1 -1
  410. package/src/security/token-manager.ts +3 -2
  411. package/src/services/vercel-deploy.ts +6 -2
  412. package/src/skills/tool-manifest.ts +3 -3
  413. package/src/skills/vellum-catalog-remote.ts +75 -16
  414. package/src/slack/slack-webhook.ts +2 -1
  415. package/src/swarm/orchestrator.ts +92 -1
  416. package/src/swarm/router-planner.ts +6 -9
  417. package/src/swarm/worker-prompts.ts +9 -12
  418. package/src/tasks/task-compiler.ts +19 -28
  419. package/src/tasks/task-runner.ts +1 -1
  420. package/src/tools/assets/search.ts +15 -14
  421. package/src/tools/browser/__tests__/auth-detector.test.ts +1 -0
  422. package/src/tools/browser/auto-navigate.ts +1 -0
  423. package/src/tools/browser/browser-execution.ts +13 -1
  424. package/src/tools/browser/browser-manager.ts +119 -4
  425. package/src/tools/browser/network-recorder.ts +5 -0
  426. package/src/tools/credentials/broker.ts +11 -2
  427. package/src/tools/credentials/metadata-store.ts +18 -14
  428. package/src/tools/credentials/post-connect-hooks.ts +61 -0
  429. package/src/tools/credentials/vault.ts +49 -23
  430. package/src/tools/executor.ts +80 -18
  431. package/src/tools/host-terminal/cli-discover.ts +1 -1
  432. package/src/tools/network/script-proxy/http-forwarder.ts +1 -1
  433. package/src/tools/network/script-proxy/mitm-handler.ts +1 -1
  434. package/src/tools/network/script-proxy/server.ts +1 -1
  435. package/src/tools/network/script-proxy/session-manager.ts +6 -5
  436. package/src/tools/network/web-fetch.ts +18 -2
  437. package/src/tools/network/web-search.ts +7 -3
  438. package/src/tools/reminder/reminder-store.ts +14 -15
  439. package/src/tools/schedule/create.ts +1 -0
  440. package/src/tools/schedule/list.ts +2 -1
  441. package/src/tools/shared/filesystem/file-ops-service.ts +5 -7
  442. package/src/tools/skills/skill-script-runner.ts +24 -9
  443. package/src/tools/skills/skill-tool-factory.ts +1 -0
  444. package/src/tools/tasks/work-item-enqueue.ts +2 -2
  445. package/src/tools/terminal/evaluate-typescript.ts +21 -12
  446. package/src/tools/terminal/parser.ts +50 -0
  447. package/src/tools/watcher/delete.ts +6 -0
  448. package/src/tools/weather/service.ts +1 -1
  449. package/src/twitter/client.ts +190 -24
  450. package/src/twitter/session.ts +4 -3
  451. package/src/util/clipboard.ts +1 -1
  452. package/src/util/errors.ts +65 -8
  453. package/src/util/fs.ts +40 -0
  454. package/src/util/json.ts +10 -0
  455. package/src/util/log-redact.ts +189 -0
  456. package/src/util/logger.ts +25 -18
  457. package/src/util/object.ts +3 -0
  458. package/src/util/platform.ts +72 -365
  459. package/src/util/pricing.ts +1 -1
  460. package/src/util/promise-guard.ts +1 -1
  461. package/src/util/retry.ts +19 -0
  462. package/src/util/row-mapper.ts +79 -0
  463. package/src/util/silently.ts +21 -0
  464. package/src/watcher/engine.ts +5 -1
  465. package/src/watcher/provider-types.ts +20 -0
  466. package/src/watcher/providers/github.ts +156 -0
  467. package/src/watcher/providers/gmail.ts +1 -0
  468. package/src/watcher/providers/google-calendar.ts +1 -0
  469. package/src/watcher/providers/linear.ts +460 -0
  470. package/src/watcher/providers/slack.ts +1 -0
  471. package/src/work-items/work-item-runner.ts +1 -1
  472. package/src/workspace/git-service.ts +1 -1
  473. package/src/workspace/provider-commit-message-generator.ts +51 -22
  474. package/src/__tests__/call-bridge.test.ts +0 -517
  475. package/src/__tests__/session-process-bridge.test.ts +0 -244
  476. package/src/calls/call-bridge.ts +0 -168
  477. package/src/config/bundled-skills/media-processing/services/capability-registry.ts +0 -137
  478. package/src/config/bundled-skills/media-processing/services/event-detection-service.ts +0 -280
  479. package/src/config/bundled-skills/media-processing/services/feedback-aggregation.ts +0 -144
  480. package/src/config/bundled-skills/media-processing/services/feedback-store.ts +0 -136
  481. package/src/config/bundled-skills/media-processing/services/retrieval-service.ts +0 -95
  482. package/src/config/bundled-skills/media-processing/services/timeline-service.ts +0 -267
  483. package/src/config/bundled-skills/media-processing/tools/detect-events.ts +0 -110
  484. package/src/config/bundled-skills/media-processing/tools/recalibrate.ts +0 -235
  485. package/src/config/bundled-skills/media-processing/tools/select-tracking-profile.ts +0 -142
  486. package/src/config/bundled-skills/media-processing/tools/submit-feedback.ts +0 -150
  487. package/src/config/vellum-skills/google-oauth-setup/SKILL.md +0 -199
@@ -0,0 +1,79 @@
1
+ export interface MigrationRegistryEntry {
2
+ /** The checkpoint key written to memory_checkpoints on completion. */
3
+ key: string;
4
+ /** Monotonic version number used for ordering assertions. */
5
+ version: number;
6
+ /** Keys of other migrations that must complete before this one runs. */
7
+ dependsOn?: string[];
8
+ /** Human-readable description for diagnostics and future authorship guidance. */
9
+ description: string;
10
+ }
11
+
12
+ // ---------------------------------------------------------------------------
13
+ // Central registry of all checkpoint-based one-shot migrations. Each entry
14
+ // carries a monotonic version number (for documentation / ordering assertions)
15
+ // and an optional list of prerequisite checkpoint keys that must already be
16
+ // completed before this migration runs.
17
+ //
18
+ // Migrations that use pure DDL guards (CREATE TABLE IF NOT EXISTS, index
19
+ // presence checks, ALTER TABLE ADD COLUMN try/catch) are inherently idempotent
20
+ // and do not need entries here — they are safe to re-run on every startup.
21
+ // ---------------------------------------------------------------------------
22
+
23
+ export const MIGRATION_REGISTRY: MigrationRegistryEntry[] = [
24
+ {
25
+ key: 'migration_job_deferrals',
26
+ version: 1,
27
+ description: 'Reconcile legacy deferral history from attempts column into deferrals column',
28
+ },
29
+ {
30
+ key: 'migration_memory_entity_relations_dedup_v1',
31
+ version: 2,
32
+ description: 'Deduplicate entity relation edges before enforcing the (source, target, relation) unique index',
33
+ },
34
+ {
35
+ key: 'migration_memory_items_fingerprint_scope_unique_v1',
36
+ version: 3,
37
+ description: 'Replace column-level UNIQUE on fingerprint with compound (fingerprint, scope_id) unique index',
38
+ },
39
+ {
40
+ key: 'migration_memory_items_scope_salted_fingerprints_v1',
41
+ version: 4,
42
+ dependsOn: ['migration_memory_items_fingerprint_scope_unique_v1'],
43
+ description: 'Recompute memory item fingerprints to include scope_id prefix after schema change',
44
+ },
45
+ {
46
+ key: 'migration_normalize_assistant_id_to_self_v1',
47
+ version: 5,
48
+ description: 'Normalize all assistant_id values in scoped tables to the implicit "self" single-tenant identity',
49
+ },
50
+ {
51
+ key: 'migration_remove_assistant_id_columns_v1',
52
+ version: 6,
53
+ dependsOn: ['migration_normalize_assistant_id_to_self_v1'],
54
+ description: 'Rebuild four tables to drop the assistant_id column after normalization',
55
+ },
56
+ {
57
+ key: 'migration_remove_assistant_id_lue_v1',
58
+ version: 7,
59
+ dependsOn: ['migration_normalize_assistant_id_to_self_v1'],
60
+ description: 'Remove assistant_id column from llm_usage_events (separate checkpoint from the four-table migration)',
61
+ },
62
+ {
63
+ key: 'backfill_inbox_thread_state_from_bindings',
64
+ version: 8,
65
+ description: 'Seed assistant_inbox_thread_state from external_conversation_bindings',
66
+ },
67
+ {
68
+ key: 'drop_active_search_index_v1',
69
+ version: 9,
70
+ description: 'Drop old idx_memory_items_active_search so it can be recreated with updated covering columns',
71
+ },
72
+ ];
73
+
74
+ export interface MigrationValidationResult {
75
+ /** Keys of migrations whose checkpoint has value 'started' — started but never completed. */
76
+ crashed: string[];
77
+ /** Pairs where a completed migration's declared prerequisite is missing from checkpoints. */
78
+ dependencyViolations: Array<{ migration: string; missingDependency: string }>;
79
+ }
@@ -0,0 +1,69 @@
1
+ import { getSqliteFrom, type DrizzleDb } from '../db-connection.js';
2
+ import { getLogger } from '../../util/logger.js';
3
+ import { MIGRATION_REGISTRY, type MigrationValidationResult } from './registry.js';
4
+
5
+ const log = getLogger('memory-db');
6
+
7
+ /**
8
+ * Validate the applied migration state against the registry at startup.
9
+ *
10
+ * Logs warnings when a migration started but never completed (crash detected),
11
+ * and logs errors when a migration was applied but a declared prerequisite is
12
+ * missing from the checkpoints table (dependency ordering violation).
13
+ *
14
+ * Returns structured diagnostic data so callers (e.g. tests) can assert on the
15
+ * specific issues detected without having to re-query the DB or inspect logs.
16
+ *
17
+ * Call this AFTER all DDL and migration functions have run so that the final
18
+ * state is inspected.
19
+ */
20
+ export function validateMigrationState(database: DrizzleDb): MigrationValidationResult {
21
+ const raw = getSqliteFrom(database);
22
+
23
+ let rows: Array<{ key: string; value: string }>;
24
+ try {
25
+ rows = raw.query(`SELECT key, value FROM memory_checkpoints`).all() as Array<{ key: string; value: string }>;
26
+ } catch {
27
+ // memory_checkpoints may not exist on a very old database; skip.
28
+ return { crashed: [], dependencyViolations: [] };
29
+ }
30
+
31
+ // Detect crashed migrations: a checkpoint value of 'started' means the
32
+ // migration wrote its start marker but never reached the completion INSERT.
33
+ // The migration will re-run on the next startup (its own idempotency guard
34
+ // will determine safety), but we surface a warning for visibility.
35
+ const crashed = rows.filter((r) => r.value === 'started').map((r) => r.key);
36
+ if (crashed.length > 0) {
37
+ log.warn(
38
+ { crashed },
39
+ 'Crashed migrations detected — these migrations started but never completed; they will re-run on next startup',
40
+ );
41
+ }
42
+
43
+ // Only rows whose value is NOT 'started' represent truly completed migrations.
44
+ // In-progress/crashed checkpoints (value = 'started') must not count as applied
45
+ // dependencies — the migration never finished, so its postconditions are unmet.
46
+ const completed = new Set(rows.filter((r) => r.value !== 'started').map((r) => r.key));
47
+
48
+ const dependencyViolations: Array<{ migration: string; missingDependency: string }> = [];
49
+
50
+ // Validate dependency ordering.
51
+ for (const entry of MIGRATION_REGISTRY) {
52
+ if (!entry.dependsOn || entry.dependsOn.length === 0) continue;
53
+ // Only check entries that have been completed — unapplied or in-progress
54
+ // migrations have not had a chance to violate their prerequisites yet.
55
+ if (!completed.has(entry.key)) continue;
56
+
57
+ for (const dep of entry.dependsOn) {
58
+ if (!completed.has(dep)) {
59
+ log.error(
60
+ { migration: entry.key, missingDependency: dep, version: entry.version },
61
+ 'Migration dependency violation: this migration is marked complete but its declared prerequisite has no checkpoint — database schema may be inconsistent',
62
+ );
63
+ dependencyViolations.push({ migration: entry.key, missingDependency: dep });
64
+ }
65
+ }
66
+ }
67
+
68
+ return { crashed, dependencyViolations };
69
+ }
@@ -1,9 +1,11 @@
1
1
  import { existsSync, readFileSync, writeFileSync, unlinkSync, mkdirSync, chmodSync } from 'node:fs';
2
2
  import { join, dirname } from 'node:path';
3
3
  import { arch, platform } from 'node:os';
4
+ import { createHash } from 'node:crypto';
4
5
  import type { Subprocess } from 'bun';
5
6
  import { getLogger } from '../util/logger.js';
6
7
  import { getDataDir } from '../util/platform.js';
8
+ import { getQdrantUrlEnv } from '../config/env.js';
7
9
 
8
10
  const log = getLogger('qdrant-manager');
9
11
 
@@ -15,6 +17,12 @@ const SHUTDOWN_GRACE_MS = 5_000;
15
17
  export interface QdrantManagerConfig {
16
18
  url: string;
17
19
  storagePath?: string;
20
+ /** Override readyz poll interval (ms). Default: 200 */
21
+ readyzPollIntervalMs?: number;
22
+ /** Override readyz timeout (ms). Default: 30 000 */
23
+ readyzTimeoutMs?: number;
24
+ /** Override SIGTERM→SIGKILL grace period (ms). Default: 5 000 */
25
+ shutdownGraceMs?: number;
18
26
  }
19
27
 
20
28
  /**
@@ -36,6 +44,9 @@ export class QdrantManager {
36
44
  private readonly storagePath: string;
37
45
  private readonly pidPath: string;
38
46
  private readonly isExternal: boolean;
47
+ private readonly readyzPollIntervalMs: number;
48
+ private readonly readyzTimeoutMs: number;
49
+ private readonly shutdownGraceMs: number;
39
50
 
40
51
  constructor(config: QdrantManagerConfig) {
41
52
  this.url = config.url;
@@ -45,8 +56,12 @@ export class QdrantManager {
45
56
  this.storagePath = config.storagePath ?? join(getDataDir(), 'qdrant');
46
57
  this.pidPath = join(getDataDir(), 'qdrant', 'qdrant.pid');
47
58
 
59
+ this.readyzPollIntervalMs = config.readyzPollIntervalMs ?? READYZ_POLL_INTERVAL_MS;
60
+ this.readyzTimeoutMs = config.readyzTimeoutMs ?? READYZ_TIMEOUT_MS;
61
+ this.shutdownGraceMs = config.shutdownGraceMs ?? SHUTDOWN_GRACE_MS;
62
+
48
63
  // External mode only if QDRANT_URL is explicitly set
49
- this.isExternal = Boolean(process.env.QDRANT_URL?.trim());
64
+ this.isExternal = Boolean(getQdrantUrlEnv());
50
65
  }
51
66
 
52
67
  async start(): Promise<void> {
@@ -107,7 +122,7 @@ export class QdrantManager {
107
122
  // Wait for graceful shutdown
108
123
  const graceful = await Promise.race([
109
124
  this.process.exited.then(() => true),
110
- new Promise<false>((resolve) => setTimeout(() => resolve(false), SHUTDOWN_GRACE_MS)),
125
+ new Promise<false>((resolve) => setTimeout(() => resolve(false), this.shutdownGraceMs)),
111
126
  ]);
112
127
 
113
128
  if (!graceful) {
@@ -146,16 +161,42 @@ export class QdrantManager {
146
161
  }
147
162
 
148
163
  const filename = `qdrant-${target}.tar.gz`;
149
- const url = `https://github.com/qdrant/qdrant/releases/download/v${QDRANT_VERSION}/${filename}`;
164
+ const baseUrl = `https://github.com/qdrant/qdrant/releases/download/v${QDRANT_VERSION}`;
165
+ const url = `${baseUrl}/${filename}`;
166
+ const checksumUrl = `${baseUrl}/${filename}.sha256`;
167
+
150
168
  log.info({ url, binaryPath }, 'Downloading Qdrant binary');
151
169
 
152
- const response = await fetch(url);
170
+ // Fetch the tarball and its SHA-256 checksum in parallel
171
+ const [response, checksumResponse] = await Promise.all([
172
+ fetch(url),
173
+ fetch(checksumUrl),
174
+ ]);
175
+
153
176
  if (!response.ok) {
154
177
  throw new Error(`Failed to download Qdrant: ${response.status} ${response.statusText} from ${url}`);
155
178
  }
156
179
 
157
180
  const tarball = await response.arrayBuffer();
158
181
 
182
+ // Verify SHA-256 integrity if the checksum file is available
183
+ if (checksumResponse.ok) {
184
+ const checksumText = (await checksumResponse.text()).trim();
185
+ // Checksum files contain "<hex> <filename>" or just "<hex>"
186
+ const expectedHash = checksumText.split(/\s+/)[0].toLowerCase();
187
+ const actualHash = createHash('sha256').update(Buffer.from(tarball)).digest('hex');
188
+
189
+ if (actualHash !== expectedHash) {
190
+ throw new Error(
191
+ `Qdrant binary checksum mismatch! ` +
192
+ `expected=${expectedHash} actual=${actualHash} url=${url}`,
193
+ );
194
+ }
195
+ log.info({ hash: actualHash }, 'Qdrant binary checksum verified');
196
+ } else {
197
+ log.warn({ checksumUrl, status: checksumResponse.status }, 'Could not fetch Qdrant checksum — skipping integrity check');
198
+ }
199
+
159
200
  // Extract the qdrant binary from the tarball
160
201
  const binDir = dirname(binaryPath);
161
202
  mkdirSync(binDir, { recursive: true });
@@ -185,16 +226,16 @@ export class QdrantManager {
185
226
 
186
227
  private async waitForReady(): Promise<void> {
187
228
  const start = Date.now();
188
- while (Date.now() - start < READYZ_TIMEOUT_MS) {
229
+ while (Date.now() - start < this.readyzTimeoutMs) {
189
230
  try {
190
231
  const res = await fetch(`${this.url}/readyz`);
191
232
  if (res.ok) return;
192
233
  } catch {
193
234
  // Not ready yet
194
235
  }
195
- await Bun.sleep(READYZ_POLL_INTERVAL_MS);
236
+ await Bun.sleep(this.readyzPollIntervalMs);
196
237
  }
197
- throw new Error(`Qdrant did not become ready within ${READYZ_TIMEOUT_MS}ms at ${this.url}`);
238
+ throw new Error(`Qdrant did not become ready within ${this.readyzTimeoutMs}ms at ${this.url}`);
198
239
  }
199
240
 
200
241
  private getBinaryPath(): string {
@@ -203,7 +244,7 @@ export class QdrantManager {
203
244
 
204
245
  private cleanupStaleProcess(): void {
205
246
  const pid = this.readPid();
206
- if (pid === null) return;
247
+ if (pid == null) return;
207
248
 
208
249
  try {
209
250
  process.kill(pid, 0); // Check if process exists
@@ -23,7 +23,7 @@ export function buildMemoryQuery(
23
23
  const requestText = clampSection(userRequest.trim(), maxUserRequestChars);
24
24
  const sessionSummary = messages
25
25
  .map((message) => getSummaryFromContextMessage(message))
26
- .find((summary): summary is string => summary !== null);
26
+ .find((summary): summary is string => summary != null);
27
27
 
28
28
  const content = requestText.length > 0 ? requestText : '(empty)';
29
29
 
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Type-safe wrappers for raw SQL queries against bun:sqlite.
3
+ *
4
+ * ## When to use raw SQL vs Drizzle ORM
5
+ *
6
+ * **Default to Drizzle** for all standard CRUD operations. Use raw SQL only when
7
+ * Drizzle cannot express the query or when a raw API is required:
8
+ *
9
+ * - **FTS5 operations**: MATCH operator, bm25() ranking, virtual table
10
+ * INSERT/DELETE. Drizzle has no FTS5 support.
11
+ *
12
+ * - **Schema migrations**: DDL statements (CREATE TABLE, ALTER TABLE, DROP TABLE),
13
+ * PRAGMA control, and transaction-wrapped table rebuilds. These are structural
14
+ * operations outside Drizzle's query-building scope.
15
+ *
16
+ * - **Affected-row checks after Drizzle .run()**: Drizzle's bun:sqlite adapter
17
+ * returns void from .run(), so checking changes() requires the raw client.
18
+ * Use `rawChanges()` for this.
19
+ *
20
+ * - **INSERT OR IGNORE / ON CONFLICT**: SQLite-specific upsert syntax that
21
+ * Drizzle's bun:sqlite adapter doesn't fully support.
22
+ *
23
+ * - **Atomic in-place updates**: Expressions like `SET count = count + 1` can
24
+ * use Drizzle's `sql` template, but raw SQL is acceptable when simpler.
25
+ *
26
+ * - **Bulk deletes across virtual tables**: Operations like clearing
27
+ * memory_segment_fts that reference virtual tables not modeled in Drizzle.
28
+ *
29
+ * For everything else — selects, inserts, updates, deletes, joins, aggregations,
30
+ * filtering, ordering, pagination — use Drizzle.
31
+ */
32
+
33
+ import type { Database, SQLQueryBindings } from 'bun:sqlite';
34
+ import { getSqlite, type DrizzleDb, getSqliteFrom } from './db-connection.js';
35
+
36
+ type SqlParam = SQLQueryBindings;
37
+
38
+ // ---------------------------------------------------------------------------
39
+ // Typed query helpers (global Drizzle instance)
40
+ // ---------------------------------------------------------------------------
41
+
42
+ /** Execute a raw SQL query and return a single typed row, or null if no match. */
43
+ export function rawGet<T>(sql: string, ...params: SqlParam[]): T | null {
44
+ return (getSqlite().query(sql).get(...params) as T) ?? null;
45
+ }
46
+
47
+ /** Execute a raw SQL query and return all matching rows with type safety. */
48
+ export function rawAll<T>(sql: string, ...params: SqlParam[]): T[] {
49
+ return getSqlite().query(sql).all(...params) as T[];
50
+ }
51
+
52
+ /**
53
+ * Execute a raw SQL statement (INSERT/UPDATE/DELETE) and return the number
54
+ * of affected rows.
55
+ */
56
+ export function rawRun(sql: string, ...params: SqlParam[]): number {
57
+ getSqlite().query(sql).run(...params);
58
+ return rawChanges();
59
+ }
60
+
61
+ /** Execute batch SQL (multiple statements, no bindings). */
62
+ export function rawExec(sql: string): void {
63
+ getSqlite().exec(sql);
64
+ }
65
+
66
+ /**
67
+ * Return the number of rows affected by the most recent INSERT/UPDATE/DELETE.
68
+ *
69
+ * Useful after a Drizzle `.run()` call, since Drizzle's bun:sqlite adapter
70
+ * returns void and discards the changes count.
71
+ */
72
+ export function rawChanges(): number {
73
+ return (getSqlite().query('SELECT changes() AS c').get() as { c: number }).c;
74
+ }
75
+
76
+ // ---------------------------------------------------------------------------
77
+ // Typed query helpers (explicit Drizzle instance)
78
+ //
79
+ // Used by migrations and tests that receive the Drizzle instance as a
80
+ // parameter rather than using the global singleton.
81
+ // ---------------------------------------------------------------------------
82
+
83
+ /** Execute a raw SQL query against a specific Drizzle instance and return a single typed row. */
84
+ export function rawGetFrom<T>(db: DrizzleDb, sql: string, ...params: SqlParam[]): T | null {
85
+ return (getSqliteFrom(db).query(sql).get(...params) as T) ?? null;
86
+ }
87
+
88
+ /** Execute a raw SQL query against a specific Drizzle instance and return all matching rows. */
89
+ export function rawAllFrom<T>(db: DrizzleDb, sql: string, ...params: SqlParam[]): T[] {
90
+ return getSqliteFrom(db).query(sql).all(...params) as T[];
91
+ }
92
+
93
+ /**
94
+ * Execute a raw SQL statement against a specific Drizzle instance and return
95
+ * affected row count.
96
+ */
97
+ export function rawRunFrom(db: DrizzleDb, sql: string, ...params: SqlParam[]): number {
98
+ const sqlite = getSqliteFrom(db);
99
+ sqlite.query(sql).run(...params);
100
+ return (sqlite.query('SELECT changes() AS c').get() as { c: number }).c;
101
+ }
102
+
103
+ /** Execute batch SQL against a specific Drizzle instance. */
104
+ export function rawExecFrom(db: DrizzleDb, sql: string): void {
105
+ getSqliteFrom(db).exec(sql);
106
+ }
107
+
108
+ /**
109
+ * Create a prepared statement from the raw SQLite client.
110
+ * Useful when you need to execute the same parameterized query in a loop.
111
+ */
112
+ export function rawPrepare(sql: string): ReturnType<Database['prepare']> {
113
+ return getSqlite().prepare(sql);
114
+ }
115
+
116
+ /** Create a prepared statement from a specific Drizzle instance. */
117
+ export function rawPrepareFrom(db: DrizzleDb, sql: string): ReturnType<Database['prepare']> {
118
+ return getSqliteFrom(db).prepare(sql);
119
+ }
@@ -68,11 +68,14 @@ export function getCachedRecall(
68
68
  _cache.delete(key);
69
69
  return undefined;
70
70
  }
71
+ // Move to end of Map iteration order so it's treated as most-recently-used
72
+ _cache.delete(key);
73
+ _cache.set(key, entry);
71
74
  return entry.result;
72
75
  }
73
76
 
74
77
  /**
75
- * Store a recall result in the cache. Evicts oldest entries when full.
78
+ * Store a recall result in the cache. Evicts least-recently-used entries when full.
76
79
  *
77
80
  * When `snapshotVersion` is provided, the entry is only stored if the
78
81
  * snapshot still matches the current global version — this prevents a