@vellumai/assistant 0.5.13 → 0.5.15

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 (425) hide show
  1. package/.env.example +1 -6
  2. package/AGENTS.md +4 -0
  3. package/ARCHITECTURE.md +0 -1
  4. package/bunfig.toml +1 -0
  5. package/docs/architecture/memory.md +3 -3
  6. package/openapi.yaml +127 -22
  7. package/package.json +1 -1
  8. package/src/__tests__/access-request-decision.test.ts +2 -32
  9. package/src/__tests__/actor-token-service.test.ts +1 -31
  10. package/src/__tests__/anthropic-provider.test.ts +53 -40
  11. package/src/__tests__/app-git-history.test.ts +9 -17
  12. package/src/__tests__/app-git-service.test.ts +14 -20
  13. package/src/__tests__/app-store-dir-names.test.ts +10 -20
  14. package/src/__tests__/approval-cascade.test.ts +2 -19
  15. package/src/__tests__/approval-primitive.test.ts +2 -27
  16. package/src/__tests__/approval-routes-http.test.ts +2 -30
  17. package/src/__tests__/assistant-events-sse-hardening.test.ts +2 -28
  18. package/src/__tests__/assistant-feature-flags-integration.test.ts +2 -45
  19. package/src/__tests__/attachments-store.test.ts +5 -32
  20. package/src/__tests__/audit-log-rotation.test.ts +5 -36
  21. package/src/__tests__/avatar-e2e.test.ts +1 -9
  22. package/src/__tests__/avatar-generator.test.ts +1 -7
  23. package/src/__tests__/browser-fill-credential.test.ts +0 -4
  24. package/src/__tests__/browser-manager.test.ts +0 -6
  25. package/src/__tests__/call-controller.test.ts +1 -22
  26. package/src/__tests__/call-conversation-messages.test.ts +0 -21
  27. package/src/__tests__/call-domain.test.ts +0 -25
  28. package/src/__tests__/call-pointer-messages.test.ts +0 -21
  29. package/src/__tests__/call-recovery.test.ts +0 -22
  30. package/src/__tests__/call-routes-http.test.ts +0 -24
  31. package/src/__tests__/call-store.test.ts +0 -21
  32. package/src/__tests__/cancel-resolves-conversation-key.test.ts +0 -24
  33. package/src/__tests__/canonical-guardian-store.test.ts +48 -21
  34. package/src/__tests__/channel-approval-routes.test.ts +6 -26
  35. package/src/__tests__/channel-approvals.test.ts +1 -38
  36. package/src/__tests__/channel-delivery-store.test.ts +0 -21
  37. package/src/__tests__/channel-guardian.test.ts +0 -26
  38. package/src/__tests__/channel-reply-delivery.test.ts +5 -0
  39. package/src/__tests__/channel-retry-sweep.test.ts +0 -21
  40. package/src/__tests__/checker.test.ts +26 -61
  41. package/src/__tests__/clawhub.test.ts +9 -25
  42. package/src/__tests__/cli-command-risk-guard.test.ts +0 -18
  43. package/src/__tests__/config-loader-backfill.test.ts +9 -28
  44. package/src/__tests__/config-schema-cmd.test.ts +5 -25
  45. package/src/__tests__/config-schema.test.ts +21 -40
  46. package/src/__tests__/config-watcher.test.ts +4 -91
  47. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -21
  48. package/src/__tests__/contacts-tools.test.ts +0 -21
  49. package/src/__tests__/context-memory-e2e.test.ts +0 -21
  50. package/src/__tests__/context-window-manager.test.ts +130 -3
  51. package/src/__tests__/conversation-abort-tool-results.test.ts +0 -4
  52. package/src/__tests__/conversation-agent-loop-overflow.test.ts +0 -4
  53. package/src/__tests__/conversation-agent-loop.test.ts +0 -4
  54. package/src/__tests__/conversation-attachments.test.ts +1 -24
  55. package/src/__tests__/conversation-attention-store.test.ts +0 -21
  56. package/src/__tests__/conversation-attention-telegram.test.ts +0 -22
  57. package/src/__tests__/conversation-clear-safety.test.ts +0 -22
  58. package/src/__tests__/conversation-confirmation-signals.test.ts +2 -21
  59. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +0 -24
  60. package/src/__tests__/conversation-disk-view-integration.test.ts +1 -23
  61. package/src/__tests__/conversation-disk-view.test.ts +5 -27
  62. package/src/__tests__/conversation-error.test.ts +1 -1
  63. package/src/__tests__/conversation-fork-crud.test.ts +1 -33
  64. package/src/__tests__/conversation-fork-route.test.ts +0 -27
  65. package/src/__tests__/conversation-history-web-search.test.ts +23 -16
  66. package/src/__tests__/conversation-init.benchmark.test.ts +22 -43
  67. package/src/__tests__/conversation-key-store-disk-view.test.ts +8 -34
  68. package/src/__tests__/conversation-load-history-repair.test.ts +0 -4
  69. package/src/__tests__/conversation-pre-run-repair.test.ts +0 -4
  70. package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -4
  71. package/src/__tests__/conversation-queue.test.ts +8 -8
  72. package/src/__tests__/conversation-routes-disk-view.test.ts +13 -51
  73. package/src/__tests__/conversation-runtime-assembly.test.ts +64 -38
  74. package/src/__tests__/conversation-slash-commands.test.ts +5 -0
  75. package/src/__tests__/conversation-slash-queue.test.ts +0 -4
  76. package/src/__tests__/conversation-slash-unknown.test.ts +0 -4
  77. package/src/__tests__/conversation-speed-override.test.ts +326 -0
  78. package/src/__tests__/conversation-starter-routes.test.ts +0 -23
  79. package/src/__tests__/conversation-store.test.ts +0 -21
  80. package/src/__tests__/conversation-unread-route.test.ts +0 -24
  81. package/src/__tests__/conversation-usage.test.ts +56 -21
  82. package/src/__tests__/conversation-wipe.test.ts +0 -21
  83. package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -4
  84. package/src/__tests__/conversation-workspace-injection.test.ts +0 -4
  85. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -4
  86. package/src/__tests__/credential-execution-shell-lockdown.test.ts +8 -5
  87. package/src/__tests__/credential-vault-unit.test.ts +9 -428
  88. package/src/__tests__/credentials-cli.test.ts +10 -10
  89. package/src/__tests__/daemon-assistant-events.test.ts +0 -19
  90. package/src/__tests__/date-context.test.ts +77 -97
  91. package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +7 -24
  92. package/src/__tests__/db-llm-request-log-provider-migration.test.ts +29 -42
  93. package/src/__tests__/delete-managed-skill-tool.test.ts +2 -10
  94. package/src/__tests__/deterministic-verification-control-plane.test.ts +1 -26
  95. package/src/__tests__/docker-signing-key-bootstrap.test.ts +61 -15
  96. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +2 -36
  97. package/src/__tests__/email-cli.test.ts +6 -6
  98. package/src/__tests__/ephemeral-permissions.test.ts +5 -17
  99. package/src/__tests__/first-greeting.test.ts +4 -32
  100. package/src/__tests__/followup-tools.test.ts +0 -21
  101. package/src/__tests__/gateway-only-enforcement.test.ts +0 -20
  102. package/src/__tests__/guardian-action-conversation-turn.test.ts +0 -23
  103. package/src/__tests__/guardian-action-followup-executor.test.ts +0 -23
  104. package/src/__tests__/guardian-action-followup-store.test.ts +0 -21
  105. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -21
  106. package/src/__tests__/guardian-action-late-reply.test.ts +0 -21
  107. package/src/__tests__/guardian-action-store.test.ts +0 -21
  108. package/src/__tests__/guardian-action-sweep.test.ts +0 -21
  109. package/src/__tests__/guardian-binding-drift-heal.test.ts +0 -23
  110. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +172 -22
  111. package/src/__tests__/guardian-dispatch.test.ts +0 -21
  112. package/src/__tests__/guardian-grant-minting.test.ts +0 -22
  113. package/src/__tests__/guardian-outbound-http.test.ts +0 -22
  114. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +0 -23
  115. package/src/__tests__/guardian-routing-invariants.test.ts +0 -22
  116. package/src/__tests__/guardian-routing-state.test.ts +0 -22
  117. package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -24
  118. package/src/__tests__/headless-browser-interactions.test.ts +0 -4
  119. package/src/__tests__/headless-browser-navigate.test.ts +0 -4
  120. package/src/__tests__/headless-browser-read-tools.test.ts +0 -4
  121. package/src/__tests__/headless-browser-snapshot.test.ts +0 -4
  122. package/src/__tests__/heartbeat-service.test.ts +99 -26
  123. package/src/__tests__/hooks-blocking.test.ts +3 -3
  124. package/src/__tests__/hooks-config.test.ts +7 -7
  125. package/src/__tests__/hooks-discovery.test.ts +3 -3
  126. package/src/__tests__/hooks-integration.test.ts +5 -5
  127. package/src/__tests__/hooks-manager.test.ts +3 -3
  128. package/src/__tests__/hooks-runner.test.ts +5 -23
  129. package/src/__tests__/hooks-settings.test.ts +3 -3
  130. package/src/__tests__/hooks-templates.test.ts +3 -3
  131. package/src/__tests__/http-conversation-lineage.test.ts +0 -27
  132. package/src/__tests__/identity-intro-cache.test.ts +0 -4
  133. package/src/__tests__/inbound-invite-redemption.test.ts +0 -22
  134. package/src/__tests__/inline-skill-load-permissions.test.ts +5 -16
  135. package/src/__tests__/intent-routing.test.ts +2 -55
  136. package/src/__tests__/invite-redemption-service.test.ts +0 -21
  137. package/src/__tests__/invite-routes-http.test.ts +0 -21
  138. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +0 -17
  139. package/src/__tests__/journal-context.test.ts +8 -75
  140. package/src/__tests__/list-messages-attachments.test.ts +0 -22
  141. package/src/__tests__/llm-context-route-provider.test.ts +0 -21
  142. package/src/__tests__/llm-request-log-turn-query.test.ts +46 -28
  143. package/src/__tests__/llm-usage-store.test.ts +0 -21
  144. package/src/__tests__/log-export-workspace.test.ts +1 -1
  145. package/src/__tests__/managed-skill-lifecycle.test.ts +1 -1
  146. package/src/__tests__/managed-store.test.ts +1 -1
  147. package/src/__tests__/mcp-cli.test.ts +7 -10
  148. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +0 -21
  149. package/src/__tests__/memory-jobs-worker-backoff.test.ts +0 -11
  150. package/src/__tests__/memory-lifecycle-e2e.test.ts +0 -21
  151. package/src/__tests__/memory-recall-log-store.test.ts +0 -27
  152. package/src/__tests__/memory-recall-quality.test.ts +0 -21
  153. package/src/__tests__/memory-regressions.experimental.test.ts +31 -30
  154. package/src/__tests__/memory-regressions.test.ts +282 -70
  155. package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -21
  156. package/src/__tests__/memory-upsert-concurrency.test.ts +0 -21
  157. package/src/__tests__/messaging-send-tool.test.ts +201 -0
  158. package/src/__tests__/migration-cross-version-compatibility.test.ts +18 -13
  159. package/src/__tests__/migration-export-http.test.ts +7 -1
  160. package/src/__tests__/migration-import-commit-http.test.ts +16 -14
  161. package/src/__tests__/migration-import-preflight-http.test.ts +27 -44
  162. package/src/__tests__/migration-validate-http.test.ts +1 -28
  163. package/src/__tests__/native-web-search.test.ts +25 -22
  164. package/src/__tests__/non-member-access-request.test.ts +0 -22
  165. package/src/__tests__/notification-guardian-path.test.ts +0 -21
  166. package/src/__tests__/notification-schedule-dedup.test.ts +1 -25
  167. package/src/__tests__/oauth-apps-routes.test.ts +103 -2
  168. package/src/__tests__/oauth-cli.test.ts +52 -0
  169. package/src/__tests__/oauth-provider-profiles.test.ts +0 -16
  170. package/src/__tests__/oauth-provider-serializer.test.ts +232 -0
  171. package/src/__tests__/oauth-providers-routes.test.ts +257 -0
  172. package/src/__tests__/oauth-store.test.ts +0 -21
  173. package/src/__tests__/onboarding-template-contract.test.ts +2 -2
  174. package/src/__tests__/openai-provider.test.ts +261 -0
  175. package/src/__tests__/pairing-concurrent.test.ts +6 -6
  176. package/src/__tests__/pairing-routes.test.ts +7 -1
  177. package/src/__tests__/path-policy.test.ts +1 -1
  178. package/src/__tests__/platform.test.ts +64 -88
  179. package/src/__tests__/playbook-execution.test.ts +0 -21
  180. package/src/__tests__/playbook-tools.test.ts +0 -21
  181. package/src/__tests__/pricing.test.ts +100 -0
  182. package/src/__tests__/relay-server.test.ts +1 -25
  183. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -24
  184. package/src/__tests__/runtime-events-sse-parity.test.ts +2 -24
  185. package/src/__tests__/runtime-events-sse.test.ts +0 -24
  186. package/src/__tests__/sandbox-diagnostics.test.ts +2 -1
  187. package/src/__tests__/scaffold-managed-skill-tool.test.ts +1 -1
  188. package/src/__tests__/schedule-store.test.ts +0 -21
  189. package/src/__tests__/schedule-tools.test.ts +0 -21
  190. package/src/__tests__/scheduler-recurrence.test.ts +0 -21
  191. package/src/__tests__/scoped-approval-grants.test.ts +0 -21
  192. package/src/__tests__/scoped-grant-security-matrix.test.ts +0 -21
  193. package/src/__tests__/secret-allowlist.test.ts +1 -1
  194. package/src/__tests__/secret-ingress-channel.test.ts +0 -5
  195. package/src/__tests__/secret-ingress-cli.test.ts +0 -6
  196. package/src/__tests__/secret-ingress-http.test.ts +0 -5
  197. package/src/__tests__/secret-ingress.test.ts +0 -5
  198. package/src/__tests__/send-endpoint-busy.test.ts +0 -24
  199. package/src/__tests__/sequence-store.test.ts +0 -21
  200. package/src/__tests__/server-history-render.test.ts +0 -24
  201. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -4
  202. package/src/__tests__/skill-load-inline-command.test.ts +9 -0
  203. package/src/__tests__/skill-load-inline-includes.test.ts +9 -0
  204. package/src/__tests__/skill-load-tool.test.ts +11 -0
  205. package/src/__tests__/skills-uninstall.test.ts +10 -8
  206. package/src/__tests__/skills.test.ts +1 -1
  207. package/src/__tests__/slack-channel-config.test.ts +1 -1
  208. package/src/__tests__/slack-inbound-verification.test.ts +0 -22
  209. package/src/__tests__/starter-bundle.test.ts +4 -1
  210. package/src/__tests__/suggestion-routes.test.ts +2 -0
  211. package/src/__tests__/system-prompt.test.ts +1 -1
  212. package/src/__tests__/terminal-tools.test.ts +1 -1
  213. package/src/__tests__/test-preload.ts +31 -0
  214. package/src/__tests__/tool-execution-abort-cleanup.test.ts +1 -1
  215. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -1
  216. package/src/__tests__/tool-executor.test.ts +0 -20
  217. package/src/__tests__/tool-input-summary.test.ts +124 -0
  218. package/src/__tests__/tool-preview-lifecycle.test.ts +2 -1
  219. package/src/__tests__/trust-store.test.ts +7 -1
  220. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -1
  221. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +1 -1
  222. package/src/__tests__/trusted-contact-multichannel.test.ts +1 -1
  223. package/src/__tests__/trusted-contact-verification.test.ts +1 -1
  224. package/src/__tests__/turn-boundary-resolution.test.ts +1 -1
  225. package/src/__tests__/twilio-routes.test.ts +1 -1
  226. package/src/__tests__/update-bulletin.test.ts +1 -1
  227. package/src/__tests__/vbundle-pax-and-symlink.test.ts +1 -1
  228. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +1 -0
  229. package/src/__tests__/voice-scoped-grant-consumer.test.ts +1 -1
  230. package/src/__tests__/voice-session-bridge.test.ts +1 -1
  231. package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +4 -4
  232. package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -1
  233. package/src/__tests__/workspace-migration-down-functions.test.ts +15 -3
  234. package/src/__tests__/workspace-migration-seed-device-id.test.ts +40 -4
  235. package/src/agent/loop.ts +6 -9
  236. package/src/approvals/guardian-decision-primitive.ts +46 -18
  237. package/src/approvals/guardian-request-resolvers.ts +19 -2
  238. package/src/calls/active-call-lease.ts +2 -2
  239. package/src/cli/AGENTS.md +1 -1
  240. package/src/cli/commands/doctor.ts +9 -9
  241. package/src/cli/commands/memory.ts +142 -0
  242. package/src/cli/commands/oauth/__tests__/connect.test.ts +13 -11
  243. package/src/cli/commands/oauth/__tests__/ping.test.ts +1 -1
  244. package/src/cli/commands/oauth/connect.ts +13 -12
  245. package/src/cli/commands/oauth/index.ts +1 -1
  246. package/src/cli/commands/oauth/providers.ts +47 -62
  247. package/src/cli/commands/platform/__tests__/connect.test.ts +72 -46
  248. package/src/cli/commands/platform/__tests__/disconnect.test.ts +54 -1
  249. package/src/cli/commands/platform/__tests__/status.test.ts +36 -0
  250. package/src/cli/commands/platform/connect.ts +17 -7
  251. package/src/cli/commands/platform/disconnect.ts +28 -3
  252. package/src/cli/commands/platform/index.ts +3 -3
  253. package/src/cli.ts +1 -299
  254. package/src/config/assistant-feature-flags.ts +23 -15
  255. package/src/config/bundled-skills/app-builder/TOOLS.json +16 -0
  256. package/src/config/bundled-skills/app-builder/tools/app-create.ts +4 -0
  257. package/src/config/bundled-skills/app-builder/tools/app-delete.ts +5 -1
  258. package/src/config/bundled-skills/app-builder/tools/app-generate-icon.ts +9 -1
  259. package/src/config/bundled-skills/app-builder/tools/app-refresh.ts +5 -1
  260. package/src/config/bundled-skills/contacts/TOOLS.json +8 -0
  261. package/src/config/bundled-skills/contacts/tools/contact-search.ts +10 -1
  262. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +16 -2
  263. package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +1 -0
  264. package/src/config/bundled-skills/messaging/SKILL.md +7 -7
  265. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +37 -0
  266. package/src/config/bundled-skills/slack/SKILL.md +18 -0
  267. package/src/config/env-registry.ts +15 -11
  268. package/src/config/env.ts +1 -11
  269. package/src/config/feature-flag-registry.json +16 -0
  270. package/src/config/schema.ts +4 -0
  271. package/src/config/schemas/heartbeat.ts +6 -1
  272. package/src/config/schemas/inference.ts +14 -3
  273. package/src/config/schemas/memory-processing.ts +16 -8
  274. package/src/config/schemas/memory-retrieval.ts +3 -3
  275. package/src/config/skills.ts +1 -1
  276. package/src/context/window-manager.ts +174 -51
  277. package/src/credential-execution/executable-discovery.ts +2 -2
  278. package/src/daemon/approved-devices-store.ts +2 -2
  279. package/src/daemon/assistant-attachments.ts +2 -0
  280. package/src/daemon/config-watcher.ts +4 -50
  281. package/src/daemon/conversation-agent-loop-handlers.ts +9 -1
  282. package/src/daemon/conversation-agent-loop.ts +12 -0
  283. package/src/daemon/conversation-error.ts +3 -5
  284. package/src/daemon/conversation-history.ts +7 -3
  285. package/src/daemon/conversation-lifecycle.ts +16 -0
  286. package/src/daemon/conversation-messaging.ts +1 -0
  287. package/src/daemon/conversation-notifiers.ts +67 -30
  288. package/src/daemon/conversation-process.ts +161 -2
  289. package/src/daemon/conversation-queue-manager.ts +2 -0
  290. package/src/daemon/conversation-runtime-assembly.ts +33 -11
  291. package/src/daemon/conversation-slash.ts +14 -3
  292. package/src/daemon/conversation-tool-setup.ts +2 -0
  293. package/src/daemon/conversation-usage.ts +32 -4
  294. package/src/daemon/conversation.ts +33 -1
  295. package/src/daemon/daemon-control.ts +32 -16
  296. package/src/daemon/date-context.ts +47 -45
  297. package/src/daemon/dictation-profile-store.ts +2 -2
  298. package/src/daemon/handlers/conversations.ts +19 -0
  299. package/src/daemon/handlers/shared.ts +14 -21
  300. package/src/daemon/lifecycle.ts +5 -7
  301. package/src/daemon/message-types/conversations.ts +2 -0
  302. package/src/daemon/message-types/guardian-actions.ts +3 -17
  303. package/src/daemon/message-types/integrations.ts +11 -1
  304. package/src/daemon/message-types/messages.ts +1 -0
  305. package/src/daemon/pairing-store.ts +2 -79
  306. package/src/daemon/server.ts +154 -8
  307. package/src/daemon/watch-handler.ts +65 -21
  308. package/src/email/guardrails.ts +3 -3
  309. package/src/heartbeat/heartbeat-service.ts +14 -7
  310. package/src/hooks/cli.ts +2 -2
  311. package/src/hooks/config.ts +2 -2
  312. package/src/hooks/discovery.ts +2 -2
  313. package/src/hooks/manager.ts +2 -2
  314. package/src/hooks/runner.ts +5 -2
  315. package/src/hooks/templates.ts +2 -2
  316. package/src/memory/admin.ts +181 -2
  317. package/src/memory/app-git-service.ts +61 -4
  318. package/src/memory/attachments-store.ts +2 -0
  319. package/src/memory/canonical-guardian-store.ts +16 -0
  320. package/src/memory/db-init.ts +8 -0
  321. package/src/memory/embedding-local.ts +5 -2
  322. package/src/memory/indexer.ts +44 -26
  323. package/src/memory/items-extractor.ts +34 -82
  324. package/src/memory/job-handlers/batch-extraction.ts +741 -0
  325. package/src/memory/job-handlers/journal-carry-forward.test.ts +383 -0
  326. package/src/memory/job-handlers/journal-carry-forward.ts +255 -0
  327. package/src/memory/jobs-store.ts +28 -0
  328. package/src/memory/jobs-worker.ts +56 -9
  329. package/src/memory/lifecycle-events-store.ts +4 -2
  330. package/src/memory/llm-request-log-store.ts +40 -2
  331. package/src/memory/llm-usage-store.ts +4 -3
  332. package/src/memory/migrations/199-guardian-request-enrichment-columns.ts +71 -0
  333. package/src/memory/migrations/200-usage-llm-call-count.ts +20 -0
  334. package/src/memory/migrations/index.ts +2 -0
  335. package/src/memory/query-expansion.ts +83 -0
  336. package/src/memory/retriever.test.ts +119 -0
  337. package/src/memory/retriever.ts +513 -105
  338. package/src/memory/schema/guardian.ts +4 -0
  339. package/src/memory/schema/infrastructure.ts +1 -0
  340. package/src/memory/search/formatting.test.ts +140 -0
  341. package/src/memory/search/formatting.ts +143 -198
  342. package/src/memory/search/mmr.ts +136 -0
  343. package/src/memory/search/staleness.ts +0 -15
  344. package/src/memory/search/tier-classifier.ts +10 -21
  345. package/src/memory/search/types.ts +17 -0
  346. package/src/messaging/providers/slack/adapter.ts +51 -5
  347. package/src/notifications/broadcaster.ts +13 -0
  348. package/src/notifications/copy-composer.ts +8 -0
  349. package/src/oauth/connect-orchestrator.ts +1 -1
  350. package/src/oauth/connection-resolver.ts +2 -2
  351. package/src/oauth/provider-serializer.ts +116 -0
  352. package/src/permissions/trust-store.ts +24 -7
  353. package/src/prompts/__tests__/build-cli-reference-section.test.ts +5 -0
  354. package/src/prompts/journal-context.ts +50 -35
  355. package/src/prompts/persona-resolver.ts +1 -1
  356. package/src/prompts/system-prompt.ts +27 -28
  357. package/src/prompts/templates/BOOTSTRAP.md +14 -1
  358. package/src/prompts/templates/HEARTBEAT.md +10 -0
  359. package/src/prompts/templates/NOW.md +19 -25
  360. package/src/prompts/templates/SOUL.md +13 -1
  361. package/src/prompts/templates/UPDATES.md +12 -0
  362. package/src/prompts/update-bulletin.ts +1 -1
  363. package/src/providers/anthropic/client.ts +89 -18
  364. package/src/providers/model-catalog.ts +22 -2
  365. package/src/providers/model-intents.ts +2 -2
  366. package/src/providers/openai/client.ts +40 -1
  367. package/src/providers/retry.ts +23 -4
  368. package/src/providers/types.ts +2 -0
  369. package/src/runtime/assistant-scope.ts +1 -1
  370. package/src/runtime/auth/__tests__/credential-service.test.ts +1 -0
  371. package/src/runtime/auth/route-policy.ts +1 -0
  372. package/src/runtime/auth/token-service.ts +51 -29
  373. package/src/runtime/confirmation-request-guardian-bridge.ts +3 -1
  374. package/src/runtime/guardian-decision-types.ts +16 -10
  375. package/src/runtime/http-server.ts +3 -14
  376. package/src/runtime/http-types.ts +1 -0
  377. package/src/runtime/migrations/vbundle-builder.ts +7 -4
  378. package/src/runtime/migrations/vbundle-import-analyzer.ts +0 -4
  379. package/src/runtime/migrations/vbundle-importer.ts +1 -1
  380. package/src/runtime/routes/conversation-query-routes.ts +40 -8
  381. package/src/runtime/routes/conversation-routes.ts +125 -3
  382. package/src/runtime/routes/guardian-action-routes.ts +9 -3
  383. package/src/runtime/routes/identity-routes.ts +25 -4
  384. package/src/runtime/routes/llm-context-normalization.ts +1 -0
  385. package/src/runtime/routes/log-export-routes.ts +34 -12
  386. package/src/runtime/routes/migration-routes.ts +6 -10
  387. package/src/runtime/routes/oauth-apps.ts +2 -9
  388. package/src/runtime/routes/oauth-providers.ts +60 -0
  389. package/src/runtime/routes/pairing-routes.ts +0 -8
  390. package/src/runtime/routes/settings-routes.ts +0 -1
  391. package/src/runtime/routes/telemetry-routes.ts +16 -4
  392. package/src/security/encrypted-store.ts +2 -2
  393. package/src/security/secret-allowlist.ts +3 -3
  394. package/src/signals/emit-event.ts +42 -0
  395. package/src/signals/user-message.ts +37 -0
  396. package/src/telemetry/usage-telemetry-reporter.test.ts +83 -19
  397. package/src/telemetry/usage-telemetry-reporter.ts +23 -17
  398. package/src/tools/browser/runtime-check.ts +2 -2
  399. package/src/tools/credentials/vault.ts +2 -249
  400. package/src/tools/memory/definitions.ts +1 -1
  401. package/src/tools/memory/handlers.test.ts +50 -8
  402. package/src/tools/memory/handlers.ts +3 -1
  403. package/src/tools/side-effects.ts +1 -6
  404. package/src/tools/terminal/safe-env.ts +3 -2
  405. package/src/tools/terminal/shell.ts +11 -14
  406. package/src/tools/tool-approval-handler.ts +20 -1
  407. package/src/tools/tool-input-summary.ts +66 -0
  408. package/src/tools/types.ts +4 -0
  409. package/src/usage/types.ts +4 -0
  410. package/src/util/device-id.ts +10 -10
  411. package/src/util/platform.ts +71 -33
  412. package/src/util/pricing.ts +19 -6
  413. package/src/util/strip-comment-lines.ts +28 -0
  414. package/src/workspace/git-service.ts +8 -18
  415. package/src/workspace/migrations/003-seed-device-id.ts +6 -4
  416. package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +7 -1
  417. package/src/workspace/migrations/017-seed-persona-dirs.ts +2 -4
  418. package/src/workspace/migrations/021-move-signals-to-workspace.ts +84 -0
  419. package/src/workspace/migrations/022-move-hooks-to-workspace.ts +94 -0
  420. package/src/workspace/migrations/023-move-config-files-to-workspace.ts +86 -0
  421. package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +126 -0
  422. package/src/workspace/migrations/migrate-to-workspace-volume.ts +3 -6
  423. package/src/workspace/migrations/registry.ts +8 -0
  424. package/src/signals/confirm.ts +0 -82
  425. package/src/signals/trust-rule.ts +0 -174
@@ -24,9 +24,9 @@ describe("buildTemporalContext", () => {
24
24
  expect(result).toEndWith("</temporal_context>");
25
25
  });
26
26
 
27
- test("includes today date and weekday", () => {
27
+ test("includes today date, weekday, time and offset on one line", () => {
28
28
  const result = buildTemporalContext({ nowMs: WED_FEB_18, timeZone: "UTC" });
29
- expect(result).toContain("Today: 2026-02-18 (Wednesday)");
29
+ expect(result).toContain("Today: 2026-02-18 (Wed) 12:00 +00:00");
30
30
  });
31
31
 
32
32
  test("includes timezone", () => {
@@ -34,22 +34,16 @@ describe("buildTemporalContext", () => {
34
34
  nowMs: WED_FEB_18,
35
35
  timeZone: "America/New_York",
36
36
  });
37
- expect(result).toContain("Timezone: America/New_York");
37
+ expect(result).toContain("TZ: America/New_York");
38
38
  });
39
39
 
40
- test("includes current local time as ISO 8601 with offset", () => {
40
+ test("does not include UTC time, timezone source, or seconds", () => {
41
41
  const result = buildTemporalContext({ nowMs: WED_FEB_18, timeZone: "UTC" });
42
- expect(result).toContain("Current local time: 2026-02-18T12:00:00+00:00");
43
- });
44
-
45
- test("includes current UTC time from assistant host clock", () => {
46
- const result = buildTemporalContext({ nowMs: WED_FEB_18, timeZone: "UTC" });
47
- expect(result).toContain("Current UTC time: 2026-02-18T12:00:00.000Z");
48
- });
49
-
50
- test("includes timezone source", () => {
51
- const result = buildTemporalContext({ nowMs: WED_FEB_18, timeZone: "UTC" });
52
- expect(result).toContain("Timezone source:");
42
+ expect(result).not.toContain("Current UTC time");
43
+ expect(result).not.toContain("Current local time");
44
+ expect(result).not.toContain("Timezone source:");
45
+ // No seconds in the time
46
+ expect(result).not.toContain("12:00:00");
53
47
  });
54
48
 
55
49
  test("does not include week definitions, next weekend, next work week, or horizon dates", () => {
@@ -60,25 +54,25 @@ describe("buildTemporalContext", () => {
60
54
  expect(result).not.toContain("Upcoming dates");
61
55
  });
62
56
 
63
- test("uses user timezone when provided and records source metadata", () => {
57
+ test("uses user timezone when provided", () => {
64
58
  const result = buildTemporalContext({
65
59
  nowMs: WED_FEB_18,
66
60
  hostTimeZone: "UTC",
67
61
  userTimeZone: "America/New_York",
68
62
  });
69
- expect(result).toContain("Timezone: America/New_York");
70
- expect(result).toContain("Current local time: 2026-02-18T07:00:00-05:00");
71
- expect(result).toContain("Timezone source: user_profile_memory");
63
+ expect(result).toContain("TZ: America/New_York");
64
+ expect(result).toContain("Today: 2026-02-18 (Wed) 07:00 -05:00");
65
+ expect(result).not.toContain("(host fallback)");
72
66
  });
73
67
 
74
- test("shows user timezone only when different from primary timezone", () => {
68
+ test("shows user TZ only when different from primary timezone", () => {
75
69
  // When user timezone equals the primary timezone, omit it
76
70
  const sameResult = buildTemporalContext({
77
71
  nowMs: WED_FEB_18,
78
72
  hostTimeZone: "UTC",
79
73
  configuredUserTimeZone: "UTC",
80
74
  });
81
- expect(sameResult).not.toContain("User timezone:");
75
+ expect(sameResult).not.toContain("User TZ:");
82
76
 
83
77
  // When user timezone differs from host, it becomes the primary timezone
84
78
  // and the host timezone is shown as a secondary annotation
@@ -87,19 +81,19 @@ describe("buildTemporalContext", () => {
87
81
  hostTimeZone: "UTC",
88
82
  userTimeZone: "America/New_York",
89
83
  });
90
- expect(diffResult).toContain("Timezone: America/New_York");
91
- expect(diffResult).toContain("Assistant host timezone: UTC");
92
- expect(diffResult).not.toContain("User timezone:");
84
+ expect(diffResult).toContain("TZ: America/New_York");
85
+ expect(diffResult).toContain("Host TZ: UTC");
86
+ expect(diffResult).not.toContain("User TZ:");
93
87
  });
94
88
 
95
- test("shows assistant host timezone only when different from primary timezone", () => {
89
+ test("shows host TZ only when different from primary timezone", () => {
96
90
  // When host timezone equals the primary timezone, omit it
97
91
  const sameResult = buildTemporalContext({
98
92
  nowMs: WED_FEB_18,
99
93
  hostTimeZone: "UTC",
100
94
  timeZone: "UTC",
101
95
  });
102
- expect(sameResult).not.toContain("Assistant host timezone:");
96
+ expect(sameResult).not.toContain("Host TZ:");
103
97
 
104
98
  // When different, include it
105
99
  const diffResult = buildTemporalContext({
@@ -107,7 +101,7 @@ describe("buildTemporalContext", () => {
107
101
  hostTimeZone: "UTC",
108
102
  userTimeZone: "America/New_York",
109
103
  });
110
- expect(diffResult).toContain("Assistant host timezone: UTC");
104
+ expect(diffResult).toContain("Host TZ: UTC");
111
105
  });
112
106
 
113
107
  test("uses configured user timezone when profile timezone is unavailable", () => {
@@ -117,9 +111,9 @@ describe("buildTemporalContext", () => {
117
111
  configuredUserTimeZone: "America/Chicago",
118
112
  userTimeZone: null,
119
113
  });
120
- expect(result).toContain("Timezone: America/Chicago");
121
- expect(result).toContain("Current local time: 2026-02-18T06:00:00-06:00");
122
- expect(result).toContain("Timezone source: user_settings");
114
+ expect(result).toContain("TZ: America/Chicago");
115
+ expect(result).toContain("Today: 2026-02-18 (Wed) 06:00 -06:00");
116
+ expect(result).not.toContain("(host fallback)");
123
117
  });
124
118
 
125
119
  test("configured user timezone takes precedence over profile timezone", () => {
@@ -129,19 +123,17 @@ describe("buildTemporalContext", () => {
129
123
  configuredUserTimeZone: "America/Los_Angeles",
130
124
  userTimeZone: "America/New_York",
131
125
  });
132
- expect(result).toContain("Timezone: America/Los_Angeles");
133
- expect(result).toContain("Current local time: 2026-02-18T04:00:00-08:00");
134
- expect(result).toContain("Timezone source: user_settings");
126
+ expect(result).toContain("TZ: America/Los_Angeles");
127
+ expect(result).toContain("Today: 2026-02-18 (Wed) 04:00 -08:00");
135
128
  });
136
129
 
137
- test("falls back to host timezone when user timezone is unavailable", () => {
130
+ test("falls back to host timezone with (host fallback) suffix", () => {
138
131
  const result = buildTemporalContext({
139
132
  nowMs: WED_FEB_18,
140
133
  hostTimeZone: "UTC",
141
134
  userTimeZone: null,
142
135
  });
143
- expect(result).toContain("Timezone: UTC");
144
- expect(result).toContain("Timezone source: assistant_host_fallback");
136
+ expect(result).toContain("TZ: UTC (host fallback)");
145
137
  });
146
138
 
147
139
  test("accepts UTC/GMT offset-style user timezone values", () => {
@@ -150,9 +142,9 @@ describe("buildTemporalContext", () => {
150
142
  hostTimeZone: "UTC",
151
143
  userTimeZone: "UTC+2",
152
144
  });
153
- expect(result).toContain("Timezone: Etc/GMT-2");
154
- expect(result).toContain("Current local time: 2026-02-18T14:00:00+02:00");
155
- expect(result).toContain("Timezone source: user_profile_memory");
145
+ expect(result).toContain("TZ: Etc/GMT-2");
146
+ expect(result).toContain("Today: 2026-02-18 (Wed) 14:00 +02:00");
147
+ expect(result).not.toContain("(host fallback)");
156
148
  });
157
149
 
158
150
  test("accepts fractional UTC/GMT offset-style user timezone values", () => {
@@ -161,30 +153,30 @@ describe("buildTemporalContext", () => {
161
153
  hostTimeZone: "UTC",
162
154
  userTimeZone: "UTC+5:30",
163
155
  });
164
- expect(result).toContain("Timezone: +05:30");
165
- expect(result).toContain("Current local time: 2026-02-18T17:30:00+05:30");
166
- expect(result).toContain("Timezone source: user_profile_memory");
156
+ expect(result).toContain("TZ: +05:30");
157
+ expect(result).toContain("Today: 2026-02-18 (Wed) 17:30 +05:30");
158
+ expect(result).not.toContain("(host fallback)");
167
159
  });
168
160
 
169
- test("formats midnight hours as 00 (never 24) in local ISO output", () => {
161
+ test("formats midnight hours as 00 (never 24)", () => {
170
162
  const justAfterMidnight = Date.UTC(2026, 1, 19, 0, 5, 0);
171
163
  const result = buildTemporalContext({
172
164
  nowMs: justAfterMidnight,
173
165
  timeZone: "UTC",
174
166
  });
175
- expect(result).toContain("Current local time: 2026-02-19T00:05:00+00:00");
176
- expect(result).not.toContain("T24:05:00");
167
+ expect(result).toContain("00:05 +00:00");
168
+ expect(result).not.toContain("24:05");
177
169
  });
178
170
 
179
171
  test("Today line includes full YYYY-MM-DD format with year", () => {
180
172
  const result = buildTemporalContext({ nowMs: WED_FEB_18, timeZone: "UTC" });
181
- expect(result).toMatch(/Today: \d{4}-\d{2}-\d{2} \(\w+\)/);
173
+ expect(result).toMatch(/Today: \d{4}-\d{2}-\d{2} \(\w{3}\) \d{2}:\d{2}/);
182
174
  expect(result).toContain("2026-02-18");
183
175
  });
184
176
 
185
177
  test("handles year boundary correctly", () => {
186
178
  const result = buildTemporalContext({ nowMs: TUE_DEC_29, timeZone: "UTC" });
187
- expect(result).toContain("Today: 2026-12-29 (Tuesday)");
179
+ expect(result).toContain("Today: 2026-12-29 (Tue)");
188
180
  });
189
181
  });
190
182
 
@@ -198,8 +190,7 @@ describe("DST-safe timezone behavior", () => {
198
190
  nowMs: WED_FEB_18,
199
191
  timeZone: "America/New_York",
200
192
  });
201
- expect(result).toContain("Today: 2026-02-18 (Wednesday)");
202
- expect(result).toContain("Current local time: 2026-02-18T07:00:00-05:00");
193
+ expect(result).toContain("Today: 2026-02-18 (Wed) 07:00 -05:00");
203
194
  });
204
195
 
205
196
  test("date labels are correct in timezone ahead of UTC", () => {
@@ -209,7 +200,7 @@ describe("DST-safe timezone behavior", () => {
209
200
  nowMs: nearMidnight,
210
201
  timeZone: "Asia/Tokyo",
211
202
  });
212
- expect(result).toContain("Today: 2026-02-19 (Thursday)");
203
+ expect(result).toContain("Today: 2026-02-19 (Thu) 08:00 +09:00");
213
204
  });
214
205
 
215
206
  test("local offset tracks daylight saving changes", () => {
@@ -219,7 +210,7 @@ describe("DST-safe timezone behavior", () => {
219
210
  nowMs: summer,
220
211
  timeZone: "America/New_York",
221
212
  });
222
- expect(result).toContain("Current local time: 2026-07-01T08:00:00-04:00");
213
+ expect(result).toContain("Today: 2026-07-01 (Wed) 08:00 -04:00");
223
214
  });
224
215
  });
225
216
 
@@ -233,83 +224,72 @@ describe("extractUserTimeZoneFromRecall", () => {
233
224
  expect(extractUserTimeZoneFromRecall(" ")).toBeNull();
234
225
  });
235
226
 
236
- test("extracts IANA timezone from user_identity section", () => {
227
+ test("extracts IANA timezone from identity item", () => {
237
228
  const text = `<memory_context __injected>
238
-
239
- <user_identity>
240
- User's timezone is America/New_York
241
- User works as a software engineer
242
- </user_identity>
243
-
229
+ <recalled>
230
+ <item id="item:1" kind="identity" importance="0.90" timestamp="2026-03-01 10:00 PST">User's timezone is America/New_York</item>
231
+ <item id="item:2" kind="identity" importance="0.80" timestamp="2026-03-01 10:00 PST">User works as a software engineer</item>
232
+ </recalled>
244
233
  </memory_context>`;
245
234
  expect(extractUserTimeZoneFromRecall(text)).toBe("America/New_York");
246
235
  });
247
236
 
248
- test("extracts timezone from 'timezone: ...' line in identity", () => {
237
+ test("extracts timezone from 'timezone: ...' in identity item", () => {
249
238
  const text = `<memory_context __injected>
250
-
251
- <user_identity>
252
- - name: Alice
253
- - timezone: Europe/London
254
- - role: designer
255
- </user_identity>
256
-
239
+ <recalled>
240
+ <item id="item:1" kind="identity" importance="0.90" timestamp="2026-03-01 10:00 PST">timezone: Europe/London</item>
241
+ <item id="item:2" kind="identity" importance="0.80" timestamp="2026-03-01 10:00 PST">name: Alice</item>
242
+ </recalled>
257
243
  </memory_context>`;
258
244
  expect(extractUserTimeZoneFromRecall(text)).toBe("Europe/London");
259
245
  });
260
246
 
261
247
  test("extracts UTC offset timezone", () => {
262
248
  const text = `<memory_context __injected>
263
-
264
- <user_identity>
265
- User's time zone is UTC+5:30
266
- </user_identity>
267
-
249
+ <recalled>
250
+ <item id="item:1" kind="identity" importance="0.90" timestamp="2026-03-01 10:00 PST">User's time zone is UTC+5:30</item>
251
+ </recalled>
268
252
  </memory_context>`;
269
253
  const result = extractUserTimeZoneFromRecall(text);
270
254
  expect(result).not.toBeNull();
271
255
  expect(result).toBe("+05:30");
272
256
  });
273
257
 
274
- test("falls back to scanning full text when no identity section", () => {
258
+ test("falls back to scanning full text when no identity items", () => {
275
259
  const text = `<memory_context __injected>
276
-
277
- <relevant_context>
278
- <episode source="Mar 5">
279
- User mentioned their timezone is Asia/Tokyo
280
- </episode>
281
- </relevant_context>
282
-
260
+ <recalled>
261
+ <segment id="seg:1" timestamp="2026-03-05 10:00 PST">User mentioned their timezone is Asia/Tokyo</segment>
262
+ </recalled>
283
263
  </memory_context>`;
284
264
  expect(extractUserTimeZoneFromRecall(text)).toBe("Asia/Tokyo");
285
265
  });
286
266
 
287
267
  test("returns null when no timezone info present", () => {
288
268
  const text = `<memory_context __injected>
289
-
290
- <user_identity>
291
- User's name is Bob
292
- User works at Acme Corp
293
- </user_identity>
294
-
269
+ <recalled>
270
+ <item id="item:1" kind="identity" importance="0.90" timestamp="2026-03-01 10:00 PST">User's name is Bob</item>
271
+ <item id="item:2" kind="identity" importance="0.80" timestamp="2026-03-01 10:00 PST">User works at Acme Corp</item>
272
+ </recalled>
295
273
  </memory_context>`;
296
274
  expect(extractUserTimeZoneFromRecall(text)).toBeNull();
297
275
  });
298
276
 
299
- test("prefers identity section over other sections", () => {
277
+ test("prefers identity items over other recalled content", () => {
300
278
  const text = `<memory_context __injected>
301
-
302
- <user_identity>
303
- User's timezone is America/Chicago
304
- </user_identity>
305
-
306
- <relevant_context>
307
- <episode source="Mar 5">
308
- Discussed timezone America/Los_Angeles for the deployment
309
- </episode>
310
- </relevant_context>
311
-
279
+ <recalled>
280
+ <item id="item:1" kind="identity" importance="0.90" timestamp="2026-03-01 10:00 PST">User's timezone is America/Chicago</item>
281
+ <segment id="seg:1" timestamp="2026-03-05 10:00 PST">Discussed timezone America/Los_Angeles for the deployment</segment>
282
+ </recalled>
312
283
  </memory_context>`;
313
284
  expect(extractUserTimeZoneFromRecall(text)).toBe("America/Chicago");
314
285
  });
286
+
287
+ test("extracts timezone from identity item without timezone keyword via second pass", () => {
288
+ const text = `<memory_context __injected>
289
+ <recalled>
290
+ <item id="item:1" kind="identity" importance="0.90" timestamp="2026-03-01 10:00 PST">America/Denver</item>
291
+ </recalled>
292
+ </memory_context>`;
293
+ expect(extractUserTimeZoneFromRecall(text)).toBe("America/Denver");
294
+ });
315
295
  });
@@ -1,26 +1,10 @@
1
- import { mkdtempSync, rmSync } from "node:fs";
2
- import { tmpdir } from "node:os";
3
- import { join } from "node:path";
1
+ import { rmSync } from "node:fs";
4
2
  import { Database } from "bun:sqlite";
5
3
  import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
6
4
 
7
5
  import { drizzle } from "drizzle-orm/bun-sqlite";
8
-
9
- const testDir = mkdtempSync(join(tmpdir(), "conversation-fork-lineage-"));
10
- const dbPath = join(testDir, "test.db");
11
6
  const originalBunTest = process.env.BUN_TEST;
12
7
 
13
- mock.module("../util/platform.js", () => ({
14
- getDataDir: () => testDir,
15
- isMacOS: () => process.platform === "darwin",
16
- isLinux: () => process.platform === "linux",
17
- isWindows: () => process.platform === "win32",
18
- getPidPath: () => join(testDir, "test.pid"),
19
- getDbPath: () => dbPath,
20
- getLogPath: () => join(testDir, "test.log"),
21
- ensureDataDir: () => {},
22
- }));
23
-
24
8
  mock.module("../util/logger.js", () => ({
25
9
  getLogger: () =>
26
10
  new Proxy({} as Record<string, unknown>, {
@@ -32,6 +16,7 @@ import { initializeDb, resetDb } from "../memory/db.js";
32
16
  import { getSqliteFrom } from "../memory/db-connection.js";
33
17
  import { migrateConversationForkLineage } from "../memory/migrations/183-add-conversation-fork-lineage.js";
34
18
  import * as schema from "../memory/schema.js";
19
+ import { getDbPath } from "../util/platform.js";
35
20
 
36
21
  function createTestDb() {
37
22
  const sqlite = new Database(":memory:");
@@ -42,7 +27,9 @@ function createTestDb() {
42
27
 
43
28
  function getColumnNames(raw: Database): string[] {
44
29
  return (
45
- raw.query(`PRAGMA table_info(conversations)`).all() as Array<{ name: string }>
30
+ raw.query(`PRAGMA table_info(conversations)`).all() as Array<{
31
+ name: string;
32
+ }>
46
33
  ).map((column) => column.name);
47
34
  }
48
35
 
@@ -79,6 +66,7 @@ function bootstrapPreLineageConversations(raw: Database): void {
79
66
 
80
67
  function removeTestDbFiles(): void {
81
68
  resetDb();
69
+ const dbPath = getDbPath();
82
70
  rmSync(dbPath, { force: true });
83
71
  rmSync(`${dbPath}-shm`, { force: true });
84
72
  rmSync(`${dbPath}-wal`, { force: true });
@@ -93,17 +81,12 @@ describe("conversation fork lineage migration", () => {
93
81
  afterAll(() => {
94
82
  process.env.BUN_TEST = originalBunTest;
95
83
  removeTestDbFiles();
96
- try {
97
- rmSync(testDir, { recursive: true });
98
- } catch {
99
- /* best effort */
100
- }
101
84
  });
102
85
 
103
86
  test("fresh DB initialization includes nullable lineage columns and parent lookup index", () => {
104
87
  initializeDb();
105
88
 
106
- const raw = new Database(dbPath);
89
+ const raw = new Database(getDbPath());
107
90
  const columns = getColumnNames(raw);
108
91
 
109
92
  expect(columns).toContain("fork_parent_conversation_id");
@@ -1,26 +1,18 @@
1
- import { mkdtempSync, rmSync } from "node:fs";
2
- import { tmpdir } from "node:os";
3
- import { join } from "node:path";
1
+ import { rmSync } from "node:fs";
4
2
  import { Database } from "bun:sqlite";
5
- import { afterAll, afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
3
+ import {
4
+ afterAll,
5
+ afterEach,
6
+ beforeEach,
7
+ describe,
8
+ expect,
9
+ mock,
10
+ test,
11
+ } from "bun:test";
6
12
 
7
13
  import { drizzle } from "drizzle-orm/bun-sqlite";
8
-
9
- const testDir = mkdtempSync(join(tmpdir(), "llm-request-log-provider-"));
10
- const dbPath = join(testDir, "test.db");
11
14
  const originalBunTest = process.env.BUN_TEST;
12
15
 
13
- mock.module("../util/platform.js", () => ({
14
- getDataDir: () => testDir,
15
- isMacOS: () => process.platform === "darwin",
16
- isLinux: () => process.platform === "linux",
17
- isWindows: () => process.platform === "win32",
18
- getPidPath: () => join(testDir, "test.pid"),
19
- getDbPath: () => dbPath,
20
- getLogPath: () => join(testDir, "test.log"),
21
- ensureDataDir: () => {},
22
- }));
23
-
24
16
  mock.module("../util/logger.js", () => ({
25
17
  getLogger: () =>
26
18
  new Proxy({} as Record<string, unknown>, {
@@ -32,6 +24,7 @@ import { initializeDb, resetDb } from "../memory/db.js";
32
24
  import { getSqliteFrom } from "../memory/db-connection.js";
33
25
  import { migrateLlmRequestLogProvider } from "../memory/migrations/184-llm-request-log-provider.js";
34
26
  import * as schema from "../memory/schema.js";
27
+ import { getDbPath } from "../util/platform.js";
35
28
 
36
29
  function createTestDb() {
37
30
  const sqlite = new Database(":memory:");
@@ -40,7 +33,9 @@ function createTestDb() {
40
33
  return drizzle(sqlite, { schema });
41
34
  }
42
35
 
43
- function getColumnInfo(raw: Database): Array<{ name: string; notnull: number }> {
36
+ function getColumnInfo(
37
+ raw: Database,
38
+ ): Array<{ name: string; notnull: number }> {
44
39
  return raw.query(`PRAGMA table_info(llm_request_logs)`).all() as Array<{
45
40
  name: string;
46
41
  notnull: number;
@@ -61,6 +56,7 @@ function bootstrapPreProviderLlmRequestLogs(raw: Database): void {
61
56
  }
62
57
 
63
58
  function removeTestDbFiles(): void {
59
+ const dbPath = getDbPath();
64
60
  rmSync(dbPath, { force: true });
65
61
  rmSync(`${dbPath}-shm`, { force: true });
66
62
  rmSync(`${dbPath}-wal`, { force: true });
@@ -86,17 +82,12 @@ describe("llm_request_logs provider migration", () => {
86
82
  }
87
83
  resetDb();
88
84
  removeTestDbFiles();
89
- try {
90
- rmSync(testDir, { recursive: true });
91
- } catch {
92
- /* best effort */
93
- }
94
85
  });
95
86
 
96
87
  test("fresh DB initialization includes llm_request_logs.provider", () => {
97
88
  initializeDb();
98
89
 
99
- const raw = new Database(dbPath);
90
+ const raw = new Database(getDbPath());
100
91
  const columns = getColumnInfo(raw);
101
92
 
102
93
  expect(columns.some((column) => column.name === "provider")).toBe(true);
@@ -132,9 +123,9 @@ describe("llm_request_logs provider migration", () => {
132
123
 
133
124
  migrateLlmRequestLogProvider(db);
134
125
 
135
- expect(getColumnInfo(raw).some((column) => column.name === "provider")).toBe(
136
- true,
137
- );
126
+ expect(
127
+ getColumnInfo(raw).some((column) => column.name === "provider"),
128
+ ).toBe(true);
138
129
 
139
130
  const row = raw
140
131
  .query(
@@ -142,17 +133,15 @@ describe("llm_request_logs provider migration", () => {
142
133
  FROM llm_request_logs
143
134
  WHERE id = 'log-upgrade'`,
144
135
  )
145
- .get() as
146
- | {
147
- id: string;
148
- conversation_id: string;
149
- message_id: string | null;
150
- provider: string | null;
151
- request_payload: string;
152
- response_payload: string;
153
- created_at: number;
154
- }
155
- | null;
136
+ .get() as {
137
+ id: string;
138
+ conversation_id: string;
139
+ message_id: string | null;
140
+ provider: string | null;
141
+ request_payload: string;
142
+ response_payload: string;
143
+ created_at: number;
144
+ } | null;
156
145
 
157
146
  expect(row).toEqual({
158
147
  id: "log-upgrade",
@@ -200,9 +189,7 @@ describe("llm_request_logs provider migration", () => {
200
189
  expect(() => migrateLlmRequestLogProvider(db)).not.toThrow();
201
190
 
202
191
  const row = raw
203
- .query(
204
- `SELECT provider FROM llm_request_logs WHERE id = 'log-rerun'`,
205
- )
192
+ .query(`SELECT provider FROM llm_request_logs WHERE id = 'log-rerun'`)
206
193
  .get() as { provider: string | null } | null;
207
194
 
208
195
  expect(row).toEqual({
@@ -5,17 +5,10 @@ import {
5
5
  rmSync,
6
6
  writeFileSync,
7
7
  } from "node:fs";
8
- import { mkdtempSync } from "node:fs";
9
- import { tmpdir } from "node:os";
10
8
  import { join } from "node:path";
11
9
  import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
12
10
 
13
- let TEST_DIR = "";
14
-
15
- mock.module("../util/platform.js", () => ({
16
- getRootDir: () => TEST_DIR,
17
- getWorkspaceSkillsDir: () => join(TEST_DIR, "skills"),
18
- }));
11
+ const TEST_DIR = process.env.VELLUM_WORKSPACE_DIR!;
19
12
 
20
13
  mock.module("../util/logger.js", () => ({
21
14
  getLogger: () =>
@@ -51,12 +44,11 @@ function createSkill(id: string): void {
51
44
  }
52
45
 
53
46
  beforeEach(() => {
54
- TEST_DIR = mkdtempSync(join(tmpdir(), "delete-tool-test-"));
55
47
  mkdirSync(join(TEST_DIR, "skills"), { recursive: true });
56
48
  });
57
49
 
58
50
  afterEach(() => {
59
- rmSync(TEST_DIR, { recursive: true, force: true });
51
+ rmSync(join(TEST_DIR, "skills"), { recursive: true, force: true });
60
52
  });
61
53
 
62
54
  describe("delete_managed_skill tool", () => {
@@ -9,29 +9,12 @@
9
9
  * 4. Channel verification reply templates are non-empty and deterministic.
10
10
  */
11
11
 
12
- import { mkdtempSync, rmSync } from "node:fs";
13
- import { tmpdir } from "node:os";
14
- import { join } from "node:path";
15
- import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
12
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
16
13
 
17
14
  // ---------------------------------------------------------------------------
18
15
  // Test isolation: in-memory SQLite via temp directory
19
16
  // ---------------------------------------------------------------------------
20
17
 
21
- const testDir = mkdtempSync(join(tmpdir(), "deterministic-verify-test-"));
22
-
23
- mock.module("../util/platform.js", () => ({
24
- getRootDir: () => testDir,
25
- getDataDir: () => testDir,
26
- isMacOS: () => process.platform === "darwin",
27
- isLinux: () => process.platform === "linux",
28
- isWindows: () => process.platform === "win32",
29
- getPidPath: () => join(testDir, "test.pid"),
30
- getDbPath: () => join(testDir, "test.db"),
31
- getLogPath: () => join(testDir, "test.log"),
32
- ensureDataDir: () => {},
33
- }));
34
-
35
18
  mock.module("../util/logger.js", () => ({
36
19
  getLogger: () =>
37
20
  new Proxy({} as Record<string, unknown>, {
@@ -63,14 +46,6 @@ beforeEach(() => {
63
46
  initializeDb();
64
47
  });
65
48
 
66
- afterAll(() => {
67
- try {
68
- rmSync(testDir, { recursive: true, force: true });
69
- } catch {
70
- /* best effort */
71
- }
72
- });
73
-
74
49
  // ---------------------------------------------------------------------------
75
50
  // Template tests: channel verification reply templates are deterministic
76
51
  // ---------------------------------------------------------------------------