@vellumai/assistant 0.7.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (666) hide show
  1. package/ARCHITECTURE.md +6 -7
  2. package/Dockerfile +1 -0
  3. package/README.md +2 -2
  4. package/__tests__/permissions/gateway-threshold-reader.test.ts +79 -139
  5. package/bun.lock +3 -0
  6. package/docs/architecture/security.md +18 -16
  7. package/knip.json +1 -0
  8. package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +1 -5
  9. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -5
  10. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -16
  11. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +1 -9
  12. package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +12 -12
  13. package/node_modules/@vellumai/slack-text/bun.lock +24 -0
  14. package/node_modules/@vellumai/slack-text/package.json +18 -0
  15. package/node_modules/@vellumai/slack-text/src/index.test.ts +153 -0
  16. package/node_modules/@vellumai/slack-text/src/index.ts +235 -0
  17. package/node_modules/@vellumai/slack-text/tsconfig.json +20 -0
  18. package/openapi.yaml +294 -107
  19. package/package.json +4 -2
  20. package/scripts/generate-openapi.ts +16 -111
  21. package/src/__tests__/agent-wake-override-profile.test.ts +23 -1
  22. package/src/__tests__/anthropic-provider.test.ts +56 -13
  23. package/src/__tests__/app-conversation-ids-backfill.test.ts +278 -0
  24. package/src/__tests__/app-conversation-ids.test.ts +151 -0
  25. package/src/__tests__/approval-cascade.test.ts +0 -15
  26. package/src/__tests__/approval-routes-http.test.ts +6 -17
  27. package/src/__tests__/assistant-event-hub.test.ts +126 -77
  28. package/src/__tests__/assistant-event.test.ts +0 -5
  29. package/src/__tests__/assistant-events-sse-hardening.test.ts +37 -15
  30. package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -29
  31. package/src/__tests__/background-shell-host-bash.test.ts +34 -43
  32. package/src/__tests__/call-controller.test.ts +1 -1
  33. package/src/__tests__/call-site-routing-provider.test.ts +193 -0
  34. package/src/__tests__/channel-approval-routes.test.ts +10 -296
  35. package/src/__tests__/channel-approvals.test.ts +25 -17
  36. package/src/__tests__/channel-guardian.test.ts +100 -146
  37. package/src/__tests__/checker.test.ts +20 -34
  38. package/src/__tests__/compact-event-conversation-id-guard.test.ts +50 -0
  39. package/src/__tests__/compaction-events.test.ts +2 -0
  40. package/src/__tests__/config-schema.test.ts +6 -48
  41. package/src/__tests__/config-watcher.test.ts +12 -0
  42. package/src/__tests__/connection-policy.test.ts +1 -52
  43. package/src/__tests__/contacts-write.test.ts +2 -64
  44. package/src/__tests__/context-image-dimensions.test.ts +1 -1
  45. package/src/__tests__/context-search-memory-source.test.ts +120 -1
  46. package/src/__tests__/context-search-memory-v2-source.test.ts +383 -0
  47. package/src/__tests__/context-search-pkb-source.test.ts +49 -0
  48. package/src/__tests__/context-search-workspace-source.test.ts +9 -22
  49. package/src/__tests__/context-window-manager.test.ts +46 -0
  50. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
  51. package/src/__tests__/conversation-agent-loop-overflow.test.ts +102 -29
  52. package/src/__tests__/conversation-agent-loop.test.ts +980 -13
  53. package/src/__tests__/conversation-analysis-routes.test.ts +12 -10
  54. package/src/__tests__/conversation-attention-telegram.test.ts +11 -3
  55. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -291
  56. package/src/__tests__/conversation-history-web-search.test.ts +4 -3
  57. package/src/__tests__/conversation-inference-profile-route.test.ts +12 -23
  58. package/src/__tests__/conversation-lifecycle.test.ts +4 -4
  59. package/src/__tests__/conversation-process-callsite.test.ts +79 -2
  60. package/src/__tests__/conversation-queue.test.ts +3 -8
  61. package/src/__tests__/conversation-routes-disk-view.test.ts +1 -161
  62. package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -32
  63. package/src/__tests__/conversation-routes-slash-commands.test.ts +75 -66
  64. package/src/__tests__/conversation-runtime-assembly.test.ts +257 -3
  65. package/src/__tests__/conversation-slash-commands.test.ts +24 -4
  66. package/src/__tests__/conversation-slash-queue.test.ts +2 -0
  67. package/src/__tests__/conversation-speed-override.test.ts +0 -3
  68. package/src/__tests__/conversation-starter-routes.test.ts +79 -2
  69. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -5
  70. package/src/__tests__/conversation-surfaces-standalone.test.ts +18 -14
  71. package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -2
  72. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +8 -46
  73. package/src/__tests__/conversation-usage.test.ts +253 -3
  74. package/src/__tests__/credential-execution-shell-lockdown.test.ts +0 -39
  75. package/src/__tests__/credential-health-service.test.ts +68 -0
  76. package/src/__tests__/credential-security-e2e.test.ts +4 -3
  77. package/src/__tests__/credential-security-invariants.test.ts +1 -5
  78. package/src/__tests__/credential-token-resolver.test.ts +180 -0
  79. package/src/__tests__/cu-unified-flow.test.ts +33 -16
  80. package/src/__tests__/daemon-assistant-events.test.ts +34 -21
  81. package/src/__tests__/daemon-credential-client.test.ts +4 -1
  82. package/src/__tests__/db-connection-isolation.test.ts +125 -0
  83. package/src/__tests__/db-migration-rollback.test.ts +101 -0
  84. package/src/__tests__/db-slack-compaction-watermark-migration.test.ts +169 -0
  85. package/src/__tests__/deterministic-verification-control-plane.test.ts +7 -80
  86. package/src/__tests__/document-conversations.test.ts +332 -0
  87. package/src/__tests__/embedding-managed-proxy-selection.test.ts +2 -2
  88. package/src/__tests__/emit-event-signal.test.ts +4 -6
  89. package/src/__tests__/events-client-registration.test.ts +193 -49
  90. package/src/__tests__/filing-service.test.ts +58 -7
  91. package/src/__tests__/first-greeting.test.ts +156 -150
  92. package/src/__tests__/fixtures/mock-chrome-extension.ts +108 -66
  93. package/src/__tests__/get-skill-detail-audit.test.ts +3 -8
  94. package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
  95. package/src/__tests__/guardian-dispatch.test.ts +1 -1
  96. package/src/__tests__/guardian-grant-minting.test.ts +7 -2
  97. package/src/__tests__/guardian-routing-invariants.test.ts +7 -2
  98. package/src/__tests__/guardian-routing-state.test.ts +1 -1
  99. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +32 -11
  100. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -83
  101. package/src/__tests__/headless-browser-mode.test.ts +4 -9
  102. package/src/__tests__/headless-browser-navigate.test.ts +21 -20
  103. package/src/__tests__/heartbeat-service.test.ts +289 -7
  104. package/src/__tests__/helpers/channel-test-adapter.ts +2 -2
  105. package/src/__tests__/helpers/create-guardian-binding.ts +91 -0
  106. package/src/__tests__/host-bash-proxy.test.ts +46 -122
  107. package/src/__tests__/host-browser-e2e-cloud.test.ts +36 -497
  108. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +26 -96
  109. package/src/__tests__/host-browser-proxy.test.ts +111 -185
  110. package/src/__tests__/host-browser-routes.test.ts +45 -75
  111. package/src/__tests__/host-browser-ws-events-e2e.test.ts +26 -30
  112. package/src/__tests__/host-cu-proxy.test.ts +56 -111
  113. package/src/__tests__/host-file-proxy.test.ts +44 -98
  114. package/src/__tests__/host-file-read-tool.test.ts +42 -21
  115. package/src/__tests__/host-shell-tool.test.ts +33 -68
  116. package/src/__tests__/host-transfer-pending-interactions.test.ts +2 -18
  117. package/src/__tests__/host-transfer-proxy.test.ts +43 -53
  118. package/src/__tests__/http-user-message-parity.test.ts +0 -6
  119. package/src/__tests__/inbound-slack-persistence.test.ts +31 -0
  120. package/src/__tests__/injector-chain.test.ts +10 -5
  121. package/src/__tests__/injector-pkb-v2-silenced.test.ts +124 -0
  122. package/src/__tests__/inline-command-runner.test.ts +0 -66
  123. package/src/__tests__/inline-skill-load-permissions.test.ts +0 -2
  124. package/src/__tests__/install-skill-routing.test.ts +1 -13
  125. package/src/__tests__/llm-callsite-catalog.test.ts +34 -0
  126. package/src/__tests__/llm-catalog-parity.test.ts +90 -0
  127. package/src/__tests__/llm-context-resolution.test.ts +180 -0
  128. package/src/__tests__/llm-resolver.test.ts +80 -12
  129. package/src/__tests__/llm-usage-store.test.ts +269 -4
  130. package/src/__tests__/log-export-routes.test.ts +89 -0
  131. package/src/__tests__/managed-profile-guard.test.ts +225 -0
  132. package/src/__tests__/managed-skill-lifecycle.test.ts +0 -10
  133. package/src/__tests__/manual-token-reconciliation.test.ts +334 -0
  134. package/src/__tests__/memory-v2-static-injector.test.ts +95 -0
  135. package/src/__tests__/migration-cross-version-compatibility.test.ts +197 -291
  136. package/src/__tests__/migration-export-http.test.ts +33 -26
  137. package/src/__tests__/migration-export-streaming.test.ts +18 -10
  138. package/src/__tests__/migration-export-to-gcs.test.ts +49 -9
  139. package/src/__tests__/migration-import-commit-http.test.ts +66 -21
  140. package/src/__tests__/migration-import-from-gcs.test.ts +50 -9
  141. package/src/__tests__/migration-import-from-url.test.ts +20 -6
  142. package/src/__tests__/migration-import-preflight-http.test.ts +95 -95
  143. package/src/__tests__/migration-parity-persistence.test.ts +62 -25
  144. package/src/__tests__/migration-transport.test.ts +115 -23
  145. package/src/__tests__/migration-validate-http.test.ts +105 -80
  146. package/src/__tests__/migration-wizard.test.ts +133 -27
  147. package/src/__tests__/non-member-access-request.test.ts +1 -1
  148. package/src/__tests__/notification-guardian-path.test.ts +1 -1
  149. package/src/__tests__/oauth-store.test.ts +19 -0
  150. package/src/__tests__/platform-bash-auto-approve.test.ts +21 -12
  151. package/src/__tests__/prechat-onboarding-contract.test.ts +31 -7
  152. package/src/__tests__/pricing.test.ts +68 -4
  153. package/src/__tests__/process-message-background-slack.test.ts +331 -0
  154. package/src/__tests__/provider-managed-proxy-integration.test.ts +153 -17
  155. package/src/__tests__/provider-send-message-override-profile.test.ts +50 -0
  156. package/src/__tests__/provider-usage-tracking.test.ts +208 -0
  157. package/src/__tests__/reaction-persistence.test.ts +9 -6
  158. package/src/__tests__/rebind-secrets-screen.test.ts +53 -16
  159. package/src/__tests__/recording-handler.test.ts +64 -81
  160. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +4 -3
  161. package/src/__tests__/relay-server.test.ts +18 -13
  162. package/src/__tests__/require-fresh-approval.test.ts +13 -22
  163. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
  164. package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
  165. package/src/__tests__/runtime-events-sse.test.ts +3 -12
  166. package/src/__tests__/search-skills-unified.test.ts +9 -15
  167. package/src/__tests__/secret-ingress-cli.test.ts +2 -5
  168. package/src/__tests__/secret-ingress-http.test.ts +0 -4
  169. package/src/__tests__/secret-onetime-send.test.ts +4 -2
  170. package/src/__tests__/secret-prompt-log-hygiene.test.ts +24 -7
  171. package/src/__tests__/secret-prompter-channel-fallback.test.ts +42 -47
  172. package/src/__tests__/secret-response-routing.test.ts +29 -15
  173. package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -1
  174. package/src/__tests__/secret-scanner.test.ts +2 -545
  175. package/src/__tests__/send-endpoint-busy.test.ts +9 -24
  176. package/src/__tests__/settings-routes.test.ts +1 -1
  177. package/src/__tests__/shell-credential-ref.test.ts +0 -8
  178. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -56
  179. package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -11
  180. package/src/__tests__/skill-tool-factory.test.ts +97 -0
  181. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -30
  182. package/src/__tests__/skills-files-catalog-fallback.test.ts +11 -17
  183. package/src/__tests__/slack-inbound-verification.test.ts +1 -62
  184. package/src/__tests__/subagent-fork-notifications.test.ts +57 -47
  185. package/src/__tests__/subagent-manager-notify.test.ts +70 -70
  186. package/src/__tests__/subagent-notify-parent.test.ts +80 -83
  187. package/src/__tests__/system-prompt.test.ts +115 -13
  188. package/src/__tests__/terminal-tools.test.ts +0 -89
  189. package/src/__tests__/thread-backfill.test.ts +945 -31
  190. package/src/__tests__/tool-domain-event-publisher.test.ts +0 -36
  191. package/src/__tests__/tool-execute-pipeline.test.ts +0 -6
  192. package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -16
  193. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +9 -19
  194. package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -7
  195. package/src/__tests__/tool-executor.test.ts +12 -19
  196. package/src/__tests__/tool-metrics-listener.test.ts +0 -35
  197. package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
  198. package/src/__tests__/tool-trace-listener.test.ts +0 -17
  199. package/src/__tests__/transfer-progress-screen.test.ts +63 -26
  200. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -149
  201. package/src/__tests__/trusted-contact-multichannel.test.ts +2 -4
  202. package/src/__tests__/trusted-contact-verification.test.ts +1 -1
  203. package/src/__tests__/tts-catalog-parity.test.ts +16 -5
  204. package/src/__tests__/usage-attribution.test.ts +247 -0
  205. package/src/__tests__/usage-cli.test.ts +143 -0
  206. package/src/__tests__/usage-grouped-buckets.test.ts +155 -0
  207. package/src/__tests__/usage-routes.test.ts +150 -0
  208. package/src/__tests__/validation-results-screen.test.ts +39 -16
  209. package/src/__tests__/vbundle-pax-and-symlink.test.ts +12 -3
  210. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +49 -137
  211. package/src/__tests__/verification-control-plane-policy.test.ts +4 -7
  212. package/src/__tests__/voice-session-bridge.test.ts +5 -5
  213. package/src/__tests__/workspace-migration-062-drop-memory-v2-edges-json.test.ts +103 -0
  214. package/src/__tests__/workspace-migration-063-release-notes-dynamic-model-context.test.ts +77 -0
  215. package/src/__tests__/workspace-migration-064-unwind-main-agent-opus-seed.test.ts +225 -0
  216. package/src/__tests__/workspace-migration-memory-v2-init.test.ts +8 -30
  217. package/src/acp/index.ts +0 -15
  218. package/src/acp/session-manager.ts +37 -34
  219. package/src/agent/loop.ts +16 -1
  220. package/src/approvals/AGENTS.md +4 -0
  221. package/src/approvals/__tests__/guardian-feed-event.test.ts +10 -3
  222. package/src/approvals/guardian-request-resolvers.ts +10 -2
  223. package/src/backup/__tests__/backup-worker.test.ts +36 -8
  224. package/src/backup/__tests__/paths.test.ts +2 -2
  225. package/src/backup/__tests__/restore.test.ts +45 -28
  226. package/src/backup/backup-worker.ts +36 -2
  227. package/src/backup/paths.ts +9 -6
  228. package/src/browser-session/events.ts +0 -9
  229. package/src/calls/call-store.ts +1 -34
  230. package/src/calls/guardian-question-copy.ts +0 -108
  231. package/src/calls/relay-server.ts +0 -24
  232. package/src/calls/twilio-rest.ts +0 -38
  233. package/src/calls/twilio-routes.ts +1 -1
  234. package/src/calls/voice-session-bridge.ts +7 -38
  235. package/src/channels/types.ts +1 -36
  236. package/src/cli/commands/__tests__/cache.test.ts +152 -5
  237. package/src/cli/commands/__tests__/memory-v2.test.ts +14 -28
  238. package/src/cli/commands/__tests__/trust.test.ts +21 -387
  239. package/src/cli/commands/backup.ts +4 -4
  240. package/src/cli/commands/cache-fs.ts +8 -0
  241. package/src/cli/commands/cache.ts +153 -82
  242. package/src/cli/commands/clients.ts +63 -5
  243. package/src/cli/commands/completions.ts +3 -3
  244. package/src/cli/commands/contacts.ts +231 -76
  245. package/src/cli/commands/keys.ts +4 -1
  246. package/src/cli/commands/memory-v2.ts +24 -52
  247. package/src/cli/commands/oauth/shared.ts +2 -29
  248. package/src/cli/commands/pending.ts +102 -0
  249. package/src/cli/commands/skills.ts +77 -35
  250. package/src/cli/commands/trust.ts +70 -430
  251. package/src/cli/commands/usage.ts +25 -16
  252. package/src/cli/lib/daemon-credential-client.ts +14 -0
  253. package/src/cli/program.ts +2 -0
  254. package/src/cli.ts +0 -21
  255. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  256. package/src/config/bundled-skills/messaging/TOOLS.json +14 -4
  257. package/src/config/env-registry.ts +12 -2
  258. package/src/config/env.ts +3 -14
  259. package/src/config/feature-flag-registry.json +30 -30
  260. package/src/config/llm-callsite-catalog.ts +12 -0
  261. package/src/config/llm-context-resolution.ts +80 -0
  262. package/src/config/llm-resolver.ts +58 -22
  263. package/src/config/loader.ts +3 -3
  264. package/src/config/schema.ts +2 -158
  265. package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
  266. package/src/config/schemas/call-site-catalog.ts +271 -0
  267. package/src/config/schemas/calls.ts +5 -5
  268. package/src/config/schemas/inference.ts +1 -1
  269. package/src/config/schemas/ingress.ts +1 -1
  270. package/src/config/schemas/llm.ts +31 -3
  271. package/src/config/schemas/memory-retrieval.ts +2 -2
  272. package/src/config/schemas/memory-v2.ts +9 -0
  273. package/src/config/schemas/security.ts +1 -42
  274. package/src/config/schemas/services.ts +6 -6
  275. package/src/config/schemas/skills.ts +5 -5
  276. package/src/config/schemas/tts.ts +1 -1
  277. package/src/config/seed-inference-profiles.ts +117 -0
  278. package/src/config/skills.ts +0 -90
  279. package/src/config/types.ts +3 -6
  280. package/src/contacts/contact-store.ts +0 -17
  281. package/src/contacts/contacts-write.ts +1 -105
  282. package/src/context/window-manager.ts +44 -5
  283. package/src/credential-execution/process-manager.ts +34 -10
  284. package/src/credential-health/credential-health-service.ts +21 -16
  285. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +75 -82
  286. package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -9
  287. package/src/daemon/connection-policy.ts +1 -26
  288. package/src/daemon/conversation-agent-loop-handlers.ts +53 -4
  289. package/src/daemon/conversation-agent-loop.ts +277 -36
  290. package/src/daemon/conversation-history.ts +8 -8
  291. package/src/daemon/conversation-launch.ts +20 -135
  292. package/src/daemon/conversation-lifecycle.ts +1 -1
  293. package/src/daemon/conversation-messaging.ts +1 -0
  294. package/src/daemon/conversation-process.ts +83 -163
  295. package/src/daemon/conversation-runtime-assembly.ts +219 -76
  296. package/src/daemon/conversation-slash.ts +47 -5
  297. package/src/daemon/conversation-store.ts +7 -31
  298. package/src/daemon/conversation-surfaces.ts +22 -28
  299. package/src/daemon/conversation-tool-setup.ts +3 -33
  300. package/src/daemon/conversation-usage.ts +36 -0
  301. package/src/daemon/conversation.ts +117 -233
  302. package/src/daemon/daemon-control.ts +3 -71
  303. package/src/daemon/daemon-skill-host.ts +8 -11
  304. package/src/daemon/dictation-profile-store.ts +2 -26
  305. package/src/daemon/first-greeting.ts +44 -156
  306. package/src/daemon/handlers/config-channels.ts +12 -12
  307. package/src/daemon/handlers/config-ingress.ts +4 -165
  308. package/src/daemon/handlers/config-model.ts +1 -1
  309. package/src/daemon/handlers/config-voice.ts +0 -42
  310. package/src/daemon/handlers/conversations.ts +11 -190
  311. package/src/daemon/handlers/recording.ts +26 -158
  312. package/src/daemon/handlers/shared.ts +23 -71
  313. package/src/daemon/handlers/skills.ts +42 -93
  314. package/src/daemon/host-bash-proxy.ts +67 -45
  315. package/src/daemon/host-browser-proxy.ts +65 -27
  316. package/src/daemon/host-cu-proxy.ts +40 -39
  317. package/src/daemon/host-file-proxy.ts +58 -37
  318. package/src/daemon/host-transfer-proxy.ts +84 -46
  319. package/src/daemon/lifecycle.ts +49 -15
  320. package/src/daemon/message-types/conversations.ts +7 -0
  321. package/src/daemon/message-types/host-bash.ts +1 -0
  322. package/src/daemon/message-types/host-cu.ts +1 -0
  323. package/src/daemon/message-types/host-file.ts +1 -0
  324. package/src/daemon/message-types/host-transfer.ts +1 -0
  325. package/src/daemon/message-types/messages.ts +10 -9
  326. package/src/daemon/message-types/workspace.ts +1 -1
  327. package/src/daemon/process-message.ts +102 -239
  328. package/src/daemon/server.ts +13 -462
  329. package/src/daemon/shutdown-handlers.ts +2 -2
  330. package/src/daemon/tool-side-effects.ts +125 -107
  331. package/src/daemon/trust-context.ts +13 -0
  332. package/src/daemon/wake-target-adapter.ts +4 -9
  333. package/src/events/domain-events.ts +0 -8
  334. package/src/events/tool-audit-listener.ts +3 -1
  335. package/src/events/tool-domain-event-publisher.ts +0 -10
  336. package/src/events/tool-metrics-listener.ts +0 -17
  337. package/src/events/tool-trace-listener.ts +0 -14
  338. package/src/filing/filing-service.ts +13 -1
  339. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +6 -2
  340. package/src/heartbeat/heartbeat-service.ts +23 -5
  341. package/src/home/__tests__/feed-writer.test.ts +0 -4
  342. package/src/home/__tests__/relationship-state-writer.test.ts +30 -0
  343. package/src/home/feed-writer.ts +1 -2
  344. package/src/home/relationship-state-writer.ts +16 -3
  345. package/src/ipc/__tests__/browser-ipc.test.ts +2 -12
  346. package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -1
  347. package/src/ipc/assistant-server.ts +3 -10
  348. package/src/ipc/routes/__tests__/memory-v2-backfill.test.ts +39 -20
  349. package/src/ipc/routes/route-adapter.ts +1 -1
  350. package/src/ipc/routes/trust-rules.test.ts +0 -95
  351. package/src/ipc/skill-ipc-types.ts +41 -0
  352. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +13 -27
  353. package/src/ipc/skill-routes/__tests__/identity.test.ts +4 -23
  354. package/src/ipc/skill-routes/events.ts +12 -23
  355. package/src/ipc/skill-routes/identity.ts +4 -17
  356. package/src/ipc/skill-routes/index.ts +1 -1
  357. package/src/ipc/skill-server.ts +6 -39
  358. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -8
  359. package/src/live-voice/protocol.ts +4 -13
  360. package/src/mcp/manager.ts +0 -5
  361. package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +55 -0
  362. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +127 -0
  363. package/src/memory/app-git-service.ts +0 -32
  364. package/src/memory/app-store.ts +154 -0
  365. package/src/memory/attachments-store.ts +6 -0
  366. package/src/memory/context-search/sources/memory-v2.ts +578 -0
  367. package/src/memory/context-search/sources/memory.ts +5 -0
  368. package/src/memory/context-search/sources/pkb.ts +10 -1
  369. package/src/memory/context-search/sources/workspace.ts +3 -2
  370. package/src/memory/conversation-crud.ts +29 -4
  371. package/src/memory/conversation-disk-view.ts +1 -5
  372. package/src/memory/conversation-starter-checkpoints.ts +63 -0
  373. package/src/memory/db-connection.ts +62 -0
  374. package/src/memory/db-init.ts +14 -0
  375. package/src/memory/embedding-backend.ts +3 -21
  376. package/src/memory/embedding-gemini.ts +0 -2
  377. package/src/memory/embedding-local.ts +6 -6
  378. package/src/memory/embedding-ollama.ts +6 -6
  379. package/src/memory/embedding-openai.ts +6 -6
  380. package/src/memory/embedding-types.ts +21 -0
  381. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +3 -7
  382. package/src/memory/graph/conversation-graph-memory.ts +35 -13
  383. package/src/memory/graph/injection.test.ts +2 -2
  384. package/src/memory/graph/injection.ts +1 -1
  385. package/src/memory/guardian-action-store.ts +0 -83
  386. package/src/memory/guardian-approvals.ts +0 -48
  387. package/src/memory/indexer.ts +1 -15
  388. package/src/memory/job-handlers/conversation-starters.ts +36 -53
  389. package/src/memory/job-utils.ts +0 -6
  390. package/src/memory/jobs-store.ts +0 -1
  391. package/src/memory/jobs-worker.ts +2 -16
  392. package/src/memory/llm-request-log-store.ts +0 -41
  393. package/src/memory/llm-usage-store.ts +129 -43
  394. package/src/memory/memory-v2-activation-log-store.ts +115 -0
  395. package/src/memory/migrations/233-document-conversations.ts +54 -0
  396. package/src/memory/migrations/234-memory-v2-activation-logs.ts +55 -0
  397. package/src/memory/migrations/235-llm-usage-attribution.ts +31 -0
  398. package/src/memory/migrations/235-slack-compaction-watermark.ts +44 -0
  399. package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +26 -0
  400. package/src/memory/migrations/__tests__/234-memory-v2-activation-logs.test.ts +182 -0
  401. package/src/memory/migrations/index.ts +14 -0
  402. package/src/memory/migrations/registry.ts +24 -0
  403. package/src/memory/raw-query.ts +2 -68
  404. package/src/memory/schema/conversations.ts +7 -0
  405. package/src/memory/schema/infrastructure.ts +25 -0
  406. package/src/memory/search/semantic.ts +5 -16
  407. package/src/memory/tool-usage-store.ts +2 -0
  408. package/src/memory/usage-buckets.ts +40 -1
  409. package/src/memory/usage-grouped-buckets.ts +127 -0
  410. package/src/memory/v2/__tests__/activation.test.ts +289 -90
  411. package/src/memory/v2/__tests__/backfill-jobs.test.ts +2 -129
  412. package/src/memory/v2/__tests__/consolidation-job.test.ts +28 -11
  413. package/src/memory/v2/__tests__/edge-index.test.ts +278 -0
  414. package/src/memory/v2/__tests__/injection.test.ts +384 -15
  415. package/src/memory/v2/__tests__/migration.test.ts +64 -36
  416. package/src/memory/v2/__tests__/page-store.test.ts +191 -8
  417. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +181 -0
  418. package/src/memory/v2/__tests__/skill-store.test.ts +115 -3
  419. package/src/memory/v2/__tests__/static-context.test.ts +153 -0
  420. package/src/memory/v2/activation.ts +168 -97
  421. package/src/memory/v2/backfill-jobs.ts +15 -100
  422. package/src/memory/v2/consolidation-job.ts +14 -12
  423. package/src/memory/v2/edge-index.ts +191 -0
  424. package/src/memory/v2/injection.ts +182 -58
  425. package/src/memory/v2/migration.ts +57 -64
  426. package/src/memory/v2/now-text.ts +2 -3
  427. package/src/memory/v2/page-store.ts +168 -31
  428. package/src/memory/v2/prompts/consolidation.ts +118 -42
  429. package/src/memory/v2/prompts/sweep.ts +3 -3
  430. package/src/memory/v2/skill-store.ts +55 -7
  431. package/src/memory/v2/static-context.ts +62 -0
  432. package/src/memory/v2/types.ts +10 -20
  433. package/src/memory/validation.ts +0 -11
  434. package/src/messaging/draft-store.ts +0 -6
  435. package/src/messaging/provider-types.ts +8 -0
  436. package/src/messaging/provider.ts +7 -0
  437. package/src/messaging/providers/gmail/client.ts +1 -121
  438. package/src/messaging/providers/outlook/client.ts +0 -73
  439. package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +226 -0
  440. package/src/messaging/providers/slack/adapter.ts +122 -21
  441. package/src/messaging/providers/slack/backfill.test.ts +95 -6
  442. package/src/messaging/providers/slack/backfill.ts +89 -11
  443. package/src/messaging/providers/slack/client.ts +10 -124
  444. package/src/messaging/providers/slack/message-metadata.ts +12 -2
  445. package/src/messaging/providers/slack/render-transcript.test.ts +56 -0
  446. package/src/messaging/providers/slack/render-transcript.ts +126 -25
  447. package/src/messaging/providers/slack/types.ts +1 -0
  448. package/src/oauth/connection-resolver.test.ts +8 -0
  449. package/src/oauth/connection-resolver.ts +8 -16
  450. package/src/oauth/credential-token-resolver.ts +97 -0
  451. package/src/oauth/manual-token-connection.ts +30 -34
  452. package/src/oauth/oauth-store.ts +6 -4
  453. package/src/outbound-proxy/certs.ts +0 -7
  454. package/src/outbound-proxy/config.ts +0 -74
  455. package/src/outbound-proxy/health.ts +0 -44
  456. package/src/outbound-proxy/index.ts +0 -22
  457. package/src/permissions/approval-provenance.test.ts +184 -0
  458. package/src/permissions/approval-provenance.ts +70 -0
  459. package/src/permissions/checker.ts +4 -1
  460. package/src/permissions/gateway-threshold-reader.ts +4 -1
  461. package/src/permissions/prompter.ts +9 -2
  462. package/src/permissions/secret-prompter.ts +21 -48
  463. package/src/permissions/types.ts +33 -0
  464. package/src/permissions/workspace-policy.ts +0 -5
  465. package/src/platform/sync-identity.ts +0 -8
  466. package/src/plugins/defaults/injectors.ts +69 -2
  467. package/src/plugins/defaults/overflow-reduce.ts +3 -2
  468. package/src/plugins/types.ts +8 -0
  469. package/src/prompts/system-prompt.ts +34 -70
  470. package/src/prompts/templates/BOOTSTRAP.md +52 -6
  471. package/src/prompts/update-bulletin-job.ts +2 -0
  472. package/src/providers/__tests__/retry-callsite.test.ts +138 -1
  473. package/src/providers/anthropic/client.ts +72 -33
  474. package/src/providers/call-site-routing.ts +42 -3
  475. package/src/providers/gemini/client.ts +18 -2
  476. package/src/providers/managed-proxy/context.ts +0 -5
  477. package/src/providers/model-catalog.ts +105 -19
  478. package/src/providers/openai/chat-completions-provider.ts +6 -0
  479. package/src/providers/openai/responses-provider.ts +7 -1
  480. package/src/providers/provider-send-message.ts +45 -2
  481. package/src/providers/ratelimit.ts +7 -2
  482. package/src/providers/registry.ts +14 -9
  483. package/src/providers/retry.ts +96 -8
  484. package/src/providers/types.ts +13 -0
  485. package/src/providers/usage-tracking.ts +96 -0
  486. package/src/runtime/AGENTS.md +10 -6
  487. package/src/runtime/__tests__/agent-wake.test.ts +89 -0
  488. package/src/runtime/agent-wake.ts +39 -2
  489. package/src/runtime/assistant-event-hub.ts +541 -45
  490. package/src/runtime/assistant-event.ts +1 -6
  491. package/src/runtime/auth/context.ts +0 -9
  492. package/src/runtime/auth/middleware.ts +1 -1
  493. package/src/runtime/auth/route-policy.ts +11 -9
  494. package/src/runtime/auth/token-service.ts +0 -11
  495. package/src/runtime/channel-approvals.ts +6 -2
  496. package/src/runtime/channel-verification-service.ts +3 -5
  497. package/src/runtime/http-errors.ts +0 -34
  498. package/src/runtime/http-router.ts +6 -3
  499. package/src/runtime/http-server.ts +22 -82
  500. package/src/runtime/http-types.ts +5 -0
  501. package/src/runtime/interactive-ui.ts +0 -1
  502. package/src/runtime/middleware/auth.ts +0 -20
  503. package/src/runtime/migrations/__tests__/v1-test-helpers.ts +112 -0
  504. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +11 -4
  505. package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +253 -0
  506. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +19 -6
  507. package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +71 -27
  508. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +41 -2
  509. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +143 -79
  510. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +143 -23
  511. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +2 -2
  512. package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +371 -0
  513. package/src/runtime/migrations/migration-transport.ts +46 -13
  514. package/src/runtime/migrations/migration-wizard.ts +2 -2
  515. package/src/runtime/migrations/origin-mode.ts +40 -0
  516. package/src/runtime/migrations/vbundle-builder.ts +133 -79
  517. package/src/runtime/migrations/vbundle-import-analyzer.ts +9 -7
  518. package/src/runtime/migrations/vbundle-importer.ts +7 -7
  519. package/src/runtime/migrations/vbundle-metadata-merge.ts +1 -1
  520. package/src/runtime/migrations/vbundle-streaming-importer.ts +3 -3
  521. package/src/runtime/migrations/vbundle-streaming-validator.ts +48 -26
  522. package/src/runtime/migrations/vbundle-validator.ts +214 -41
  523. package/src/runtime/pending-interactions.ts +13 -4
  524. package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -1
  525. package/src/runtime/routes/__tests__/backup-routes.test.ts +28 -19
  526. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +235 -0
  527. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +58 -0
  528. package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +54 -0
  529. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +19 -6
  530. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +7 -7
  531. package/src/runtime/routes/acp-routes.test.ts +0 -3
  532. package/src/runtime/routes/acp-routes.ts +3 -7
  533. package/src/runtime/routes/app-management-routes.ts +18 -9
  534. package/src/runtime/routes/approval-routes.ts +55 -14
  535. package/src/runtime/routes/avatar-routes.ts +3 -5
  536. package/src/runtime/routes/browser-routes.ts +1 -15
  537. package/src/runtime/routes/channel-guardian-routes.ts +1 -5
  538. package/src/runtime/routes/channel-readiness-routes.ts +3 -7
  539. package/src/runtime/routes/channel-route-shared.ts +2 -28
  540. package/src/runtime/routes/client-routes.ts +45 -12
  541. package/src/runtime/routes/consolidation-routes.ts +115 -0
  542. package/src/runtime/routes/conversation-list-routes.ts +12 -29
  543. package/src/runtime/routes/conversation-management-routes.ts +14 -51
  544. package/src/runtime/routes/conversation-query-routes.ts +120 -8
  545. package/src/runtime/routes/conversation-routes.ts +44 -528
  546. package/src/runtime/routes/conversation-starter-routes.ts +19 -40
  547. package/src/runtime/routes/documents-routes.ts +53 -18
  548. package/src/runtime/routes/events-routes.ts +59 -91
  549. package/src/runtime/routes/filing-routes.ts +18 -1
  550. package/src/runtime/routes/guardian-action-routes.ts +4 -9
  551. package/src/runtime/routes/host-bash-routes.ts +3 -2
  552. package/src/runtime/routes/host-browser-routes.ts +9 -33
  553. package/src/runtime/routes/host-cu-routes.ts +6 -1
  554. package/src/runtime/routes/host-file-routes.ts +3 -2
  555. package/src/runtime/routes/host-transfer-routes.ts +11 -15
  556. package/src/runtime/routes/identity-routes.ts +78 -6
  557. package/src/runtime/routes/inbound-message-handler.ts +580 -137
  558. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -88
  559. package/src/runtime/routes/inbound-stages/background-dispatch.ts +3 -0
  560. package/src/runtime/routes/index.ts +4 -0
  561. package/src/runtime/routes/integrations/slack/channel.ts +0 -24
  562. package/src/runtime/routes/llm-call-sites-routes.ts +22 -0
  563. package/src/runtime/routes/memory-v2-routes.ts +10 -15
  564. package/src/runtime/routes/migration-routes.ts +188 -31
  565. package/src/runtime/routes/playground/guard.ts +1 -1
  566. package/src/runtime/routes/playground/index.ts +0 -2
  567. package/src/runtime/routes/recording-routes.ts +4 -24
  568. package/src/runtime/routes/rename-conversation-routes.ts +2 -6
  569. package/src/runtime/routes/schedule-routes.ts +3 -6
  570. package/src/runtime/routes/secret-routes.ts +87 -18
  571. package/src/runtime/routes/settings-routes.ts +29 -28
  572. package/src/runtime/routes/skills-routes.ts +12 -31
  573. package/src/runtime/routes/suggest-trust-rule-routes.ts +32 -1
  574. package/src/runtime/routes/task-routes.ts +6 -6
  575. package/src/runtime/routes/trust-rules-routes.ts +3 -94
  576. package/src/runtime/routes/types.ts +4 -4
  577. package/src/runtime/routes/upgrade-broadcast-routes.ts +3 -10
  578. package/src/runtime/routes/usage-routes.ts +87 -10
  579. package/src/runtime/routes/user-routes.ts +17 -31
  580. package/src/runtime/routes/work-items-routes.ts +1 -4
  581. package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -2
  582. package/src/runtime/services/analyze-conversation.ts +7 -17
  583. package/src/runtime/services/conversation-serializer.ts +2 -4
  584. package/src/runtime/verification-outbound-actions.ts +1 -1
  585. package/src/runtime/verification-rate-limiter.ts +1 -1
  586. package/src/schedule/schedule-store.ts +0 -16
  587. package/src/security/secret-scanner.ts +14 -547
  588. package/src/security/secure-keys.ts +31 -11
  589. package/src/security/token-manager.ts +7 -3
  590. package/src/signals/cancel.ts +16 -25
  591. package/src/signals/conversation-undo.ts +2 -27
  592. package/src/signals/emit-event.ts +1 -2
  593. package/src/signals/user-message.ts +108 -22
  594. package/src/skills/catalog-install.ts +1 -0
  595. package/src/skills/clawhub.ts +2 -2
  596. package/src/skills/inline-command-runner.ts +1 -7
  597. package/src/subagent/manager.ts +67 -84
  598. package/src/tasks/task-store.ts +1 -28
  599. package/src/telemetry/types.ts +6 -0
  600. package/src/telemetry/usage-telemetry-reporter.test.ts +38 -15
  601. package/src/telemetry/usage-telemetry-reporter.ts +3 -5
  602. package/src/tools/acp/spawn.test.ts +1 -2
  603. package/src/tools/acp/steer.test.ts +1 -2
  604. package/src/tools/browser/__tests__/browser-status.test.ts +44 -127
  605. package/src/tools/browser/browser-execution.ts +31 -147
  606. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +92 -68
  607. package/src/tools/browser/cdp-client/factory.ts +48 -76
  608. package/src/tools/browser/cdp-client/index.ts +1 -14
  609. package/src/tools/executor.ts +44 -31
  610. package/src/tools/host-filesystem/edit.ts +3 -2
  611. package/src/tools/host-filesystem/read.ts +3 -2
  612. package/src/tools/host-filesystem/transfer.test.ts +45 -42
  613. package/src/tools/host-filesystem/transfer.ts +4 -3
  614. package/src/tools/host-filesystem/write.ts +3 -2
  615. package/src/tools/host-terminal/host-shell.ts +4 -3
  616. package/src/tools/network/script-proxy/index.ts +1 -10
  617. package/src/tools/permission-checker.ts +66 -1
  618. package/src/tools/skills/sandbox-runner.ts +1 -6
  619. package/src/tools/skills/skill-tool-factory.ts +32 -0
  620. package/src/tools/terminal/safe-env.ts +1 -0
  621. package/src/tools/terminal/shell.ts +2 -78
  622. package/src/tools/types.ts +12 -39
  623. package/src/tts/__tests__/provider-catalog.test.ts +2 -2
  624. package/src/tts/provider-catalog.ts +1 -1
  625. package/src/usage/actors.ts +2 -1
  626. package/src/usage/attribution.ts +185 -0
  627. package/src/usage/pricing.ts +166 -0
  628. package/src/usage/types.ts +14 -0
  629. package/src/util/json.ts +13 -0
  630. package/src/util/logger.ts +3 -3
  631. package/src/util/pricing.ts +50 -3
  632. package/src/work-items/work-item-runner.ts +15 -42
  633. package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +4 -3
  634. package/src/workspace/migrations/052-seed-default-inference-profiles.ts +3 -3
  635. package/src/workspace/migrations/060-memory-v2-init.ts +2 -18
  636. package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +59 -0
  637. package/src/workspace/migrations/062-drop-memory-v2-edges-json.ts +27 -0
  638. package/src/workspace/migrations/063-release-notes-dynamic-model-context.ts +70 -0
  639. package/src/workspace/migrations/064-unwind-main-agent-opus-seed.ts +64 -0
  640. package/src/workspace/migrations/registry.ts +8 -0
  641. package/src/workspace/provider-commit-message-generator.ts +3 -3
  642. package/src/__tests__/sandbox-diagnostics.test.ts +0 -138
  643. package/src/__tests__/sandbox-host-parity.test.ts +0 -1024
  644. package/src/__tests__/secret-detection-handler.test.ts +0 -67
  645. package/src/__tests__/secret-scanner-executor.test.ts +0 -450
  646. package/src/__tests__/tcc-sandbox-deny.test.ts +0 -198
  647. package/src/__tests__/terminal-sandbox.test.ts +0 -374
  648. package/src/__tests__/tool-notification-listener.test.ts +0 -65
  649. package/src/context/__tests__/microcompact.test.ts +0 -805
  650. package/src/context/microcompact.ts +0 -443
  651. package/src/daemon/handlers/slack-channel-oauth-install.ts +0 -197
  652. package/src/events/tool-notification-listener.ts +0 -17
  653. package/src/ipc/routes/__tests__/memory-v2-validate.test.ts +0 -219
  654. package/src/memory/v2/__tests__/edges.test.ts +0 -435
  655. package/src/memory/v2/edges.ts +0 -217
  656. package/src/prompts/__tests__/system-prompt-memory-v2.test.ts +0 -197
  657. package/src/runtime/__tests__/chrome-extension-registry.test.ts +0 -518
  658. package/src/runtime/__tests__/client-registry.test.ts +0 -271
  659. package/src/runtime/chrome-extension-registry.ts +0 -368
  660. package/src/runtime/client-registry.ts +0 -254
  661. package/src/runtime/routes/inbound-stages/verification-intercept.ts +0 -329
  662. package/src/tools/secret-detection-handler.ts +0 -269
  663. package/src/tools/terminal/backends/native.ts +0 -327
  664. package/src/tools/terminal/backends/types.ts +0 -37
  665. package/src/tools/terminal/sandbox-diagnostics.ts +0 -87
  666. package/src/tools/terminal/sandbox.ts +0 -40
@@ -5,11 +5,32 @@
5
5
  * point between the agent loop and the HostCuProxy.
6
6
  */
7
7
 
8
- import { afterEach, describe, expect, test } from "bun:test";
9
-
10
- import type { SurfaceConversationContext } from "../daemon/conversation-surfaces.js";
11
- import { surfaceProxyResolver } from "../daemon/conversation-surfaces.js";
12
- import { HostCuProxy } from "../daemon/host-cu-proxy.js";
8
+ import { afterEach, describe, expect, mock, test } from "bun:test";
9
+
10
+ const sentMessages: unknown[] = [];
11
+ let mockHasClient = true; // Default to true for CU unified flow tests
12
+
13
+ mock.module("../runtime/assistant-event-hub.js", () => ({
14
+ broadcastMessage: (msg: unknown) => sentMessages.push(msg),
15
+ assistantEventHub: {
16
+ getMostRecentClientByCapability: (cap: string) =>
17
+ cap === "host_cu" && mockHasClient ? { id: "mock-client" } : null,
18
+ },
19
+ }));
20
+
21
+ mock.module("../runtime/pending-interactions.js", () => ({
22
+ resolve: () => undefined,
23
+ get: () => undefined,
24
+ getByKind: () => [],
25
+ getByConversation: () => [],
26
+ removeByConversation: () => {},
27
+ }));
28
+
29
+ const { surfaceProxyResolver } = await import(
30
+ "../daemon/conversation-surfaces.js"
31
+ );
32
+ const { HostCuProxy } = await import("../daemon/host-cu-proxy.js");
33
+ type SurfaceConversationContext = import("../daemon/conversation-surfaces.js").SurfaceConversationContext;
13
34
 
14
35
  // ---------------------------------------------------------------------------
15
36
  // Test helpers
@@ -20,7 +41,7 @@ import { HostCuProxy } from "../daemon/host-cu-proxy.js";
20
41
  * Only the fields required by the CU routing path are populated.
21
42
  */
22
43
  function buildMockContext(
23
- hostCuProxy?: HostCuProxy,
44
+ hostCuProxy?: InstanceType<typeof HostCuProxy>,
24
45
  ): SurfaceConversationContext {
25
46
  return {
26
47
  conversationId: "test-session",
@@ -47,15 +68,12 @@ function buildMockContext(
47
68
  // ---------------------------------------------------------------------------
48
69
 
49
70
  describe("surfaceProxyResolver — CU tool routing", () => {
50
- let sentMessages: unknown[];
51
- let proxy: HostCuProxy;
71
+ let proxy: InstanceType<typeof HostCuProxy>;
52
72
 
53
73
  function setupProxy(maxSteps?: number): SurfaceConversationContext {
54
- sentMessages = [];
55
- const sendToClient = (msg: unknown) => sentMessages.push(msg);
56
- proxy = new HostCuProxy(sendToClient as never, undefined, maxSteps);
57
- // Mark client as connected so requests are sent
58
- proxy.updateSender(sendToClient as never, true);
74
+ sentMessages.length = 0;
75
+ mockHasClient = true;
76
+ proxy = new HostCuProxy(maxSteps);
59
77
  return buildMockContext(proxy);
60
78
  }
61
79
 
@@ -93,9 +111,8 @@ describe("surfaceProxyResolver — CU tool routing", () => {
93
111
  });
94
112
 
95
113
  test("returns error when proxy exists but client not connected", async () => {
96
- const sendToClient = () => {};
97
- const proxyObj = new HostCuProxy(sendToClient as never);
98
- // Default clientConnected is false — do NOT call updateSender with true
114
+ mockHasClient = false;
115
+ const proxyObj = new HostCuProxy();
99
116
  const ctx = buildMockContext(proxyObj);
100
117
  const result = await surfaceProxyResolver(ctx, "computer_use_click", {
101
118
  element_id: 1,
@@ -33,11 +33,10 @@ describe("buildAssistantEvent", () => {
33
33
  conversationId: "sess_1",
34
34
  text: "hi",
35
35
  };
36
- const event = buildAssistantEvent("ast_1", msg, "sess_1");
36
+ const event = buildAssistantEvent(msg, "sess_1");
37
37
 
38
38
  expect(typeof event.id).toBe("string");
39
39
  expect(event.id.length).toBeGreaterThan(0);
40
- expect(event.assistantId).toBe("ast_1");
41
40
  expect(event.conversationId).toBe("sess_1");
42
41
  expect(event.message).toBe(msg);
43
42
  expect(typeof event.emittedAt).toBe("string");
@@ -46,14 +45,14 @@ describe("buildAssistantEvent", () => {
46
45
 
47
46
  test("generates unique ids for each call", () => {
48
47
  const msg: ServerMessage = { type: "pong" };
49
- const a = buildAssistantEvent("ast", msg);
50
- const b = buildAssistantEvent("ast", msg);
48
+ const a = buildAssistantEvent(msg);
49
+ const b = buildAssistantEvent(msg);
51
50
  expect(a.id).not.toBe(b.id);
52
51
  });
53
52
 
54
53
  test("conversationId is undefined when omitted", () => {
55
54
  const msg: ServerMessage = { type: "pong" };
56
- const event = buildAssistantEvent("ast", msg);
55
+ const event = buildAssistantEvent(msg);
57
56
  expect(event.conversationId).toBeUndefined();
58
57
  });
59
58
  });
@@ -65,8 +64,11 @@ describe("daemon send → one mirrored assistant event", () => {
65
64
  const hub = new AssistantEventHub();
66
65
  const received: AssistantEvent[] = [];
67
66
 
68
- hub.subscribe({ assistantId: "ast_test" }, (e) => {
69
- received.push(e);
67
+ hub.subscribe({
68
+ type: "process",
69
+ callback: (e) => {
70
+ received.push(e);
71
+ },
70
72
  });
71
73
 
72
74
  const msg: ServerMessage = {
@@ -74,11 +76,10 @@ describe("daemon send → one mirrored assistant event", () => {
74
76
  conversationId: "sess_a",
75
77
  text: "hello",
76
78
  };
77
- const event = buildAssistantEvent("ast_test", msg, "sess_a");
79
+ const event = buildAssistantEvent(msg, "sess_a");
78
80
  await hub.publish(event);
79
81
 
80
82
  expect(received).toHaveLength(1);
81
- expect(received[0].assistantId).toBe("ast_test");
82
83
  expect(received[0].conversationId).toBe("sess_a");
83
84
  expect(received[0].message.type).toBe("assistant_text_delta");
84
85
  });
@@ -87,12 +88,15 @@ describe("daemon send → one mirrored assistant event", () => {
87
88
  const hub = new AssistantEventHub();
88
89
  const received: AssistantEvent[] = [];
89
90
 
90
- hub.subscribe({ assistantId: "ast_test" }, (e) => {
91
- received.push(e);
91
+ hub.subscribe({
92
+ type: "process",
93
+ callback: (e) => {
94
+ received.push(e);
95
+ },
92
96
  });
93
97
 
94
98
  const msg: ServerMessage = { type: "pong" }; // no conversationId field
95
- const event = buildAssistantEvent("ast_test", msg, "sess_explicit");
99
+ const event = buildAssistantEvent(msg, "sess_explicit");
96
100
 
97
101
  await hub.publish(event);
98
102
 
@@ -107,11 +111,17 @@ describe("daemon broadcast → one mirrored event per message (not per socket)",
107
111
  const received: AssistantEvent[] = [];
108
112
 
109
113
  // Two subscribers (simulating two wire clients)
110
- hub.subscribe({ assistantId: "ast_bc" }, (e) => {
111
- received.push(e);
114
+ hub.subscribe({
115
+ type: "process",
116
+ callback: (e) => {
117
+ received.push(e);
118
+ },
112
119
  });
113
- hub.subscribe({ assistantId: "ast_bc" }, (e) => {
114
- received.push(e);
120
+ hub.subscribe({
121
+ type: "process",
122
+ callback: (e) => {
123
+ received.push(e);
124
+ },
115
125
  });
116
126
 
117
127
  // Simulate broadcast: server calls publishAssistantEvent once
@@ -119,7 +129,7 @@ describe("daemon broadcast → one mirrored event per message (not per socket)",
119
129
  type: "message_complete",
120
130
  conversationId: "sess_b",
121
131
  };
122
- const event = buildAssistantEvent("ast_bc", msg, "sess_b");
132
+ const event = buildAssistantEvent(msg, "sess_b");
123
133
  await hub.publish(event);
124
134
 
125
135
  // Both hub subscribers receive it (fanout), but only ONE event was published
@@ -130,8 +140,11 @@ describe("daemon broadcast → one mirrored event per message (not per socket)",
130
140
  const hub = new AssistantEventHub();
131
141
  const publishedEvents: AssistantEvent[] = [];
132
142
 
133
- hub.subscribe({ assistantId: "ast_bc" }, (e) => {
134
- publishedEvents.push(e);
143
+ hub.subscribe({
144
+ type: "process",
145
+ callback: (e) => {
146
+ publishedEvents.push(e);
147
+ },
135
148
  });
136
149
 
137
150
  const msgA: ServerMessage = {
@@ -145,8 +158,8 @@ describe("daemon broadcast → one mirrored event per message (not per socket)",
145
158
  };
146
159
 
147
160
  // Simulate: one broadcast + one single send
148
- await hub.publish(buildAssistantEvent("ast_bc", msgA, "s1"));
149
- await hub.publish(buildAssistantEvent("ast_bc", msgB, "s1"));
161
+ await hub.publish(buildAssistantEvent(msgA, "s1"));
162
+ await hub.publish(buildAssistantEvent(msgB, "s1"));
150
163
 
151
164
  expect(publishedEvents).toHaveLength(2);
152
165
  expect(publishedEvents[0].message.type).toBe("assistant_text_delta");
@@ -21,6 +21,7 @@ mock.module("../util/logger.js", () => ({
21
21
  }));
22
22
 
23
23
  import { setSecureKeyViaDaemon } from "../cli/lib/daemon-credential-client.js";
24
+ import { credentialKey } from "../security/credential-key.js";
24
25
  import { getSecureKeyAsync } from "../security/secure-keys.js";
25
26
 
26
27
  describe("daemon credential writes (daemon unreachable)", () => {
@@ -32,7 +33,9 @@ describe("daemon credential writes (daemon unreachable)", () => {
32
33
  );
33
34
  expect(result).toBe(true);
34
35
 
35
- const readBack = await getSecureKeyAsync("test-provider");
36
+ const readBack = await getSecureKeyAsync(
37
+ credentialKey("test-provider", "api_key"),
38
+ );
36
39
  expect(readBack).toBe("test-value");
37
40
  });
38
41
  });
@@ -0,0 +1,125 @@
1
+ import {
2
+ mkdirSync,
3
+ mkdtempSync,
4
+ realpathSync,
5
+ rmSync,
6
+ symlinkSync,
7
+ } from "node:fs";
8
+ import { homedir, tmpdir } from "node:os";
9
+ import { join } from "node:path";
10
+ import { afterEach, expect, test } from "bun:test";
11
+
12
+ import { getDb, resetDb } from "../memory/db-connection.js";
13
+
14
+ const originalWorkspaceDir = process.env.VELLUM_WORKSPACE_DIR;
15
+ const originalAllowRealWorkspace =
16
+ process.env.VELLUM_ALLOW_REAL_WORKSPACE_IN_TESTS;
17
+ const originalTestRealWorkspace = process.env.VELLUM_TEST_REAL_WORKSPACE_DIR;
18
+ const originalHome = process.env.HOME;
19
+
20
+ afterEach(() => {
21
+ resetDb();
22
+ if (originalWorkspaceDir === undefined) {
23
+ delete process.env.VELLUM_WORKSPACE_DIR;
24
+ } else {
25
+ process.env.VELLUM_WORKSPACE_DIR = originalWorkspaceDir;
26
+ }
27
+
28
+ if (originalAllowRealWorkspace === undefined) {
29
+ delete process.env.VELLUM_ALLOW_REAL_WORKSPACE_IN_TESTS;
30
+ } else {
31
+ process.env.VELLUM_ALLOW_REAL_WORKSPACE_IN_TESTS =
32
+ originalAllowRealWorkspace;
33
+ }
34
+
35
+ if (originalTestRealWorkspace === undefined) {
36
+ delete process.env.VELLUM_TEST_REAL_WORKSPACE_DIR;
37
+ } else {
38
+ process.env.VELLUM_TEST_REAL_WORKSPACE_DIR = originalTestRealWorkspace;
39
+ }
40
+
41
+ if (originalHome === undefined) {
42
+ delete process.env.HOME;
43
+ } else {
44
+ process.env.HOME = originalHome;
45
+ }
46
+ });
47
+
48
+ test("getDb refuses test runs without an isolated workspace", () => {
49
+ resetDb();
50
+ delete process.env.VELLUM_WORKSPACE_DIR;
51
+ delete process.env.VELLUM_ALLOW_REAL_WORKSPACE_IN_TESTS;
52
+
53
+ expect(() => getDb()).toThrow(
54
+ "Refusing to open the assistant DB during tests without VELLUM_WORKSPACE_DIR",
55
+ );
56
+ });
57
+
58
+ test("getDb refuses the real workspace during tests even when explicitly set", () => {
59
+ resetDb();
60
+ process.env.VELLUM_WORKSPACE_DIR = join(homedir(), ".vellum", "workspace");
61
+ delete process.env.VELLUM_ALLOW_REAL_WORKSPACE_IN_TESTS;
62
+
63
+ expect(() => getDb()).toThrow(
64
+ "Refusing to open the real assistant workspace DB during tests",
65
+ );
66
+ });
67
+
68
+ test("getDb refuses symlink aliases to the real workspace during tests", () => {
69
+ resetDb();
70
+ const testRoot = realpathSync(
71
+ mkdtempSync(join(tmpdir(), "vellum-db-isolation-")),
72
+ );
73
+
74
+ try {
75
+ const fakeHome = join(testRoot, "home");
76
+ const realWorkspace = join(fakeHome, ".vellum", "workspace");
77
+ const aliasParent = join(testRoot, "aliases");
78
+ const workspaceAlias = join(aliasParent, "workspace-link");
79
+
80
+ mkdirSync(realWorkspace, { recursive: true });
81
+ mkdirSync(aliasParent, { recursive: true });
82
+ symlinkSync(realWorkspace, workspaceAlias, "dir");
83
+
84
+ process.env.HOME = fakeHome;
85
+ process.env.VELLUM_WORKSPACE_DIR = workspaceAlias;
86
+ process.env.VELLUM_TEST_REAL_WORKSPACE_DIR = realWorkspace;
87
+ delete process.env.VELLUM_ALLOW_REAL_WORKSPACE_IN_TESTS;
88
+
89
+ expect(() => getDb()).toThrow(
90
+ "Refusing to open the real assistant workspace DB during tests",
91
+ );
92
+ } finally {
93
+ rmSync(testRoot, { recursive: true, force: true });
94
+ }
95
+ });
96
+
97
+ test("getDb refuses missing children under symlink aliases to the real workspace", () => {
98
+ resetDb();
99
+ const testRoot = realpathSync(
100
+ mkdtempSync(join(tmpdir(), "vellum-db-isolation-")),
101
+ );
102
+
103
+ try {
104
+ const fakeHome = join(testRoot, "home");
105
+ const realWorkspace = join(fakeHome, ".vellum", "workspace");
106
+ const aliasParent = join(testRoot, "aliases");
107
+ const workspaceLink = join(aliasParent, "workspace-link");
108
+ const missingChild = join(workspaceLink, "new-test-workspace");
109
+
110
+ mkdirSync(realWorkspace, { recursive: true });
111
+ mkdirSync(aliasParent, { recursive: true });
112
+ symlinkSync(realWorkspace, workspaceLink, "dir");
113
+
114
+ process.env.HOME = fakeHome;
115
+ process.env.VELLUM_WORKSPACE_DIR = missingChild;
116
+ process.env.VELLUM_TEST_REAL_WORKSPACE_DIR = realWorkspace;
117
+ delete process.env.VELLUM_ALLOW_REAL_WORKSPACE_IN_TESTS;
118
+
119
+ expect(() => getDb()).toThrow(
120
+ "Refusing to open the real assistant workspace DB during tests",
121
+ );
122
+ } finally {
123
+ rmSync(testRoot, { recursive: true, force: true });
124
+ }
125
+ });
@@ -57,6 +57,7 @@ import { migrateRenameThreadStartersCheckpointsDown } from "../memory/migrations
57
57
  import { migrateBackfillAudioAttachmentMimeTypesDown } from "../memory/migrations/191-backfill-audio-attachment-mime-types.js";
58
58
  import {
59
59
  migrateJobDeferrals,
60
+ migrateLlmUsageAttribution,
60
61
  migrateMemoryEntityRelationDedup,
61
62
  migrateMemoryItemsFingerprintScopeUnique,
62
63
  migrateMemoryItemsScopeSaltedFingerprints,
@@ -1767,6 +1768,106 @@ describe("memory migration down() functions", () => {
1767
1768
  });
1768
1769
  });
1769
1770
 
1771
+ describe("migrateLlmUsageAttribution", () => {
1772
+ test("adds nullable attribution columns without rewriting existing usage rows", () => {
1773
+ const db = createTestDb();
1774
+ const raw = getRaw(db);
1775
+
1776
+ raw.exec(/*sql*/ `
1777
+ CREATE TABLE llm_usage_events (
1778
+ id TEXT PRIMARY KEY,
1779
+ created_at INTEGER NOT NULL,
1780
+ conversation_id TEXT,
1781
+ run_id TEXT,
1782
+ request_id TEXT,
1783
+ actor TEXT NOT NULL,
1784
+ provider TEXT NOT NULL,
1785
+ model TEXT NOT NULL,
1786
+ input_tokens INTEGER NOT NULL,
1787
+ output_tokens INTEGER NOT NULL,
1788
+ cache_creation_input_tokens INTEGER,
1789
+ cache_read_input_tokens INTEGER,
1790
+ estimated_cost_usd REAL,
1791
+ pricing_status TEXT NOT NULL,
1792
+ llm_call_count INTEGER,
1793
+ metadata_json TEXT
1794
+ );
1795
+ INSERT INTO llm_usage_events (
1796
+ id,
1797
+ created_at,
1798
+ actor,
1799
+ provider,
1800
+ model,
1801
+ input_tokens,
1802
+ output_tokens,
1803
+ pricing_status
1804
+ ) VALUES (
1805
+ 'usage-1',
1806
+ 1000,
1807
+ 'main_agent',
1808
+ 'anthropic',
1809
+ 'claude-sonnet-4-20250514',
1810
+ 100,
1811
+ 50,
1812
+ 'priced'
1813
+ );
1814
+ `);
1815
+
1816
+ migrateLlmUsageAttribution(db);
1817
+
1818
+ const row = raw
1819
+ .query(
1820
+ /*sql*/ `
1821
+ SELECT call_site, inference_profile, inference_profile_source
1822
+ FROM llm_usage_events
1823
+ WHERE id = 'usage-1'
1824
+ `,
1825
+ )
1826
+ .get() as {
1827
+ call_site: string | null;
1828
+ inference_profile: string | null;
1829
+ inference_profile_source: string | null;
1830
+ };
1831
+ expect(row.call_site).toBeNull();
1832
+ expect(row.inference_profile).toBeNull();
1833
+ expect(row.inference_profile_source).toBeNull();
1834
+ });
1835
+
1836
+ test("idempotency: calling migration twice does not throw", () => {
1837
+ const db = createTestDb();
1838
+ const raw = getRaw(db);
1839
+
1840
+ raw.exec(/*sql*/ `
1841
+ CREATE TABLE llm_usage_events (
1842
+ id TEXT PRIMARY KEY,
1843
+ created_at INTEGER NOT NULL,
1844
+ actor TEXT NOT NULL,
1845
+ provider TEXT NOT NULL,
1846
+ model TEXT NOT NULL,
1847
+ input_tokens INTEGER NOT NULL,
1848
+ output_tokens INTEGER NOT NULL,
1849
+ pricing_status TEXT NOT NULL
1850
+ )
1851
+ `);
1852
+
1853
+ migrateLlmUsageAttribution(db);
1854
+ migrateLlmUsageAttribution(db);
1855
+
1856
+ for (const column of [
1857
+ "call_site",
1858
+ "inference_profile",
1859
+ "inference_profile_source",
1860
+ ]) {
1861
+ const found = raw
1862
+ .query(
1863
+ `SELECT 1 FROM pragma_table_info('llm_usage_events') WHERE name = '${column}'`,
1864
+ )
1865
+ .get();
1866
+ expect(found).toBeTruthy();
1867
+ }
1868
+ });
1869
+ });
1870
+
1770
1871
  // ── v9: downDropActiveSearchIndex ────────────────────────────────────
1771
1872
 
1772
1873
  describe("v9: downDropActiveSearchIndex", () => {
@@ -0,0 +1,169 @@
1
+ import { Database } from "bun:sqlite";
2
+ import { describe, expect, test } from "bun:test";
3
+
4
+ import { drizzle } from "drizzle-orm/bun-sqlite";
5
+
6
+ import { getSqliteFrom } from "../memory/db-connection.js";
7
+ import {
8
+ downSlackCompactionWatermark,
9
+ migrateSlackCompactionWatermark,
10
+ } from "../memory/migrations/235-slack-compaction-watermark.js";
11
+ import * as schema from "../memory/schema.js";
12
+
13
+ interface ColumnRow {
14
+ name: string;
15
+ type: string;
16
+ notnull: number;
17
+ }
18
+
19
+ interface ConversationCompactionRow {
20
+ id: string;
21
+ context_summary: string | null;
22
+ context_compacted_message_count: number;
23
+ context_compacted_at: number | null;
24
+ slack_context_compaction_watermark_ts: string | null;
25
+ slack_context_compaction_watermark_at: number | null;
26
+ }
27
+
28
+ function createTestDb() {
29
+ const sqlite = new Database(":memory:");
30
+ sqlite.exec("PRAGMA journal_mode=WAL");
31
+ sqlite.exec("PRAGMA foreign_keys = ON");
32
+ return drizzle(sqlite, { schema });
33
+ }
34
+
35
+ function bootstrapCheckpointsTable(raw: Database): void {
36
+ raw.exec(/*sql*/ `
37
+ CREATE TABLE IF NOT EXISTS memory_checkpoints (
38
+ key TEXT PRIMARY KEY,
39
+ value TEXT NOT NULL,
40
+ updated_at INTEGER NOT NULL
41
+ )
42
+ `);
43
+ }
44
+
45
+ function bootstrapLegacyConversations(raw: Database): void {
46
+ raw.exec(/*sql*/ `
47
+ CREATE TABLE conversations (
48
+ id TEXT PRIMARY KEY,
49
+ title TEXT,
50
+ created_at INTEGER NOT NULL,
51
+ updated_at INTEGER NOT NULL,
52
+ context_summary TEXT,
53
+ context_compacted_message_count INTEGER NOT NULL DEFAULT 0,
54
+ context_compacted_at INTEGER
55
+ )
56
+ `);
57
+ }
58
+
59
+ function getConversationColumns(raw: Database): Map<string, ColumnRow> {
60
+ const columns = raw
61
+ .query(`PRAGMA table_info(conversations)`)
62
+ .all() as ColumnRow[];
63
+ return new Map(columns.map((column) => [column.name, column]));
64
+ }
65
+
66
+ describe("migrateSlackCompactionWatermark", () => {
67
+ test("adds nullable Slack watermark columns and preserves existing compaction state", () => {
68
+ const db = createTestDb();
69
+ const raw = getSqliteFrom(db);
70
+ bootstrapCheckpointsTable(raw);
71
+ bootstrapLegacyConversations(raw);
72
+
73
+ raw
74
+ .query(
75
+ /*sql*/ `
76
+ INSERT INTO conversations (
77
+ id,
78
+ title,
79
+ created_at,
80
+ updated_at,
81
+ context_summary,
82
+ context_compacted_message_count,
83
+ context_compacted_at
84
+ ) VALUES (?, ?, ?, ?, ?, ?, ?)
85
+ `,
86
+ )
87
+ .run(
88
+ "conv-1",
89
+ "legacy slack thread",
90
+ 1000,
91
+ 2000,
92
+ "existing compacted summary",
93
+ 42,
94
+ 3000,
95
+ );
96
+
97
+ migrateSlackCompactionWatermark(db);
98
+
99
+ const columns = getConversationColumns(raw);
100
+ expect(columns.get("slack_context_compaction_watermark_ts")).toMatchObject({
101
+ type: "TEXT",
102
+ notnull: 0,
103
+ });
104
+ expect(columns.get("slack_context_compaction_watermark_at")).toMatchObject({
105
+ type: "INTEGER",
106
+ notnull: 0,
107
+ });
108
+
109
+ const row = raw
110
+ .query(
111
+ /*sql*/ `
112
+ SELECT
113
+ id,
114
+ context_summary,
115
+ context_compacted_message_count,
116
+ context_compacted_at,
117
+ slack_context_compaction_watermark_ts,
118
+ slack_context_compaction_watermark_at
119
+ FROM conversations
120
+ WHERE id = ?
121
+ `,
122
+ )
123
+ .get("conv-1") as ConversationCompactionRow | null;
124
+
125
+ expect(row).toEqual({
126
+ id: "conv-1",
127
+ context_summary: "existing compacted summary",
128
+ context_compacted_message_count: 42,
129
+ context_compacted_at: 3000,
130
+ slack_context_compaction_watermark_ts: null,
131
+ slack_context_compaction_watermark_at: null,
132
+ });
133
+ });
134
+
135
+ test("is idempotent when columns already exist", () => {
136
+ const db = createTestDb();
137
+ const raw = getSqliteFrom(db);
138
+ bootstrapCheckpointsTable(raw);
139
+ bootstrapLegacyConversations(raw);
140
+ raw.exec(
141
+ `ALTER TABLE conversations ADD COLUMN slack_context_compaction_watermark_ts TEXT`,
142
+ );
143
+ raw.exec(
144
+ `ALTER TABLE conversations ADD COLUMN slack_context_compaction_watermark_at INTEGER`,
145
+ );
146
+
147
+ expect(() => migrateSlackCompactionWatermark(db)).not.toThrow();
148
+
149
+ const columns = getConversationColumns(raw);
150
+ expect(columns.has("slack_context_compaction_watermark_ts")).toBe(true);
151
+ expect(columns.has("slack_context_compaction_watermark_at")).toBe(true);
152
+ });
153
+
154
+ test("down migration drops Slack watermark columns and is idempotent", () => {
155
+ const db = createTestDb();
156
+ const raw = getSqliteFrom(db);
157
+ bootstrapCheckpointsTable(raw);
158
+ bootstrapLegacyConversations(raw);
159
+
160
+ migrateSlackCompactionWatermark(db);
161
+
162
+ downSlackCompactionWatermark(db);
163
+ expect(() => downSlackCompactionWatermark(db)).not.toThrow();
164
+
165
+ const columns = getConversationColumns(raw);
166
+ expect(columns.has("slack_context_compaction_watermark_ts")).toBe(false);
167
+ expect(columns.has("slack_context_compaction_watermark_at")).toBe(false);
168
+ });
169
+ });