@vellumai/assistant 0.5.13 → 0.5.14

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
@@ -32,6 +32,7 @@ let renderedHistoryContent: {
32
32
  toolCallsBeforeText: boolean;
33
33
  contentOrder: string[];
34
34
  surfaces: unknown[];
35
+ thinkingSegments: string[];
35
36
  } = {
36
37
  text: "",
37
38
  textSegments: [],
@@ -39,6 +40,7 @@ let renderedHistoryContent: {
39
40
  toolCallsBeforeText: false,
40
41
  contentOrder: [],
41
42
  surfaces: [],
43
+ thinkingSegments: [],
42
44
  };
43
45
 
44
46
  let deliveryFailAtIndex = -1;
@@ -111,6 +113,7 @@ describe("channel-reply-delivery", () => {
111
113
  toolCallsBeforeText: false,
112
114
  contentOrder: [],
113
115
  surfaces: [],
116
+ thinkingSegments: [],
114
117
  };
115
118
  });
116
119
 
@@ -197,6 +200,7 @@ describe("channel-reply-delivery", () => {
197
200
  toolCallsBeforeText: false,
198
201
  contentOrder: ["text:0", "tool:0", "text:1"],
199
202
  surfaces: [],
203
+ thinkingSegments: [],
200
204
  };
201
205
 
202
206
  await deliverReplyViaCallback(
@@ -432,6 +436,7 @@ describe("channel-reply-delivery", () => {
432
436
  toolCallsBeforeText: false,
433
437
  contentOrder: ["text:0", "tool:0", "text:1", "tool:1", "text:2"],
434
438
  surfaces: [],
439
+ thinkingSegments: [],
435
440
  };
436
441
 
437
442
  const delivered: number[] = [];
@@ -1,23 +1,7 @@
1
- import { mkdtempSync, rmSync } from "node:fs";
2
- import { tmpdir } from "node:os";
3
- import { join } from "node:path";
4
1
  import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
5
2
 
6
3
  import { eq } from "drizzle-orm";
7
4
 
8
- const testDir = mkdtempSync(join(tmpdir(), "channel-retry-sweep-test-"));
9
-
10
- mock.module("../util/platform.js", () => ({
11
- getDataDir: () => testDir,
12
- isMacOS: () => process.platform === "darwin",
13
- isLinux: () => process.platform === "linux",
14
- isWindows: () => process.platform === "win32",
15
- getPidPath: () => join(testDir, "test.pid"),
16
- getDbPath: () => join(testDir, "test.db"),
17
- getLogPath: () => join(testDir, "test.log"),
18
- ensureDataDir: () => {},
19
- }));
20
-
21
5
  mock.module("../util/logger.js", () => ({
22
6
  getLogger: () =>
23
7
  new Proxy({} as Record<string, unknown>, {
@@ -34,11 +18,6 @@ initializeDb();
34
18
 
35
19
  afterAll(() => {
36
20
  resetDb();
37
- try {
38
- rmSync(testDir, { recursive: true });
39
- } catch {
40
- // Best effort cleanup
41
- }
42
21
  });
43
22
 
44
23
  function resetTables(): void {
@@ -21,21 +21,11 @@ import {
21
21
  test,
22
22
  } from "bun:test";
23
23
 
24
- // Use a temp directory so trust-store doesn't touch ~/.vellum
25
- const checkerTestDir = mkdtempSync(join(tmpdir(), "checker-test-"));
26
-
27
- mock.module("../util/platform.js", () => ({
28
- getRootDir: () => checkerTestDir,
29
- getDataDir: () => join(checkerTestDir, "data"),
30
- getWorkspaceSkillsDir: () => join(checkerTestDir, "skills"),
31
- isMacOS: () => process.platform === "darwin",
32
- isLinux: () => process.platform === "linux",
33
- isWindows: () => process.platform === "win32",
34
- getPidPath: () => join(checkerTestDir, "test.pid"),
35
- getDbPath: () => join(checkerTestDir, "test.db"),
36
- getLogPath: () => join(checkerTestDir, "test.log"),
37
- ensureDataDir: () => {},
38
- }));
24
+ // Use the preload-provided workspace directory so trust-store doesn't touch ~/.vellum
25
+ const checkerTestDir = process.env.VELLUM_WORKSPACE_DIR!;
26
+
27
+ // Point the file-based trust backend at the test temp dir.
28
+ process.env.GATEWAY_SECURITY_DIR = join(checkerTestDir, "protected");
39
29
 
40
30
  // Capture logger.warn() calls so tests can assert on deprecation warnings.
41
31
  const loggerWarnCalls: string[] = [];
@@ -175,14 +165,6 @@ describe("Permission Checker", () => {
175
165
  } catch {
176
166
  /* may not exist */
177
167
  }
178
- try {
179
- rmSync(join(checkerTestDir, "workspace", "skills"), {
180
- recursive: true,
181
- force: true,
182
- });
183
- } catch {
184
- /* may not exist */
185
- }
186
168
  });
187
169
 
188
170
  // ── classifyRisk ────────────────────────────────────────────────
@@ -1484,7 +1466,7 @@ describe("Permission Checker", () => {
1484
1466
 
1485
1467
  describe("default workspace prompt file allow rules", () => {
1486
1468
  test("file_edit of workspace IDENTITY.md is auto-allowed", async () => {
1487
- const identityPath = join(checkerTestDir, "workspace", "IDENTITY.md");
1469
+ const identityPath = join(checkerTestDir, "IDENTITY.md");
1488
1470
  const result = await check("file_edit", { path: identityPath }, "/tmp");
1489
1471
  expect(result.decision).toBe("allow");
1490
1472
  expect(result.matchedRule).toBeDefined();
@@ -1492,7 +1474,7 @@ describe("Permission Checker", () => {
1492
1474
  });
1493
1475
 
1494
1476
  test("file_read of workspace USER.md is auto-allowed", async () => {
1495
- const userPath = join(checkerTestDir, "workspace", "USER.md");
1477
+ const userPath = join(checkerTestDir, "USER.md");
1496
1478
  const result = await check("file_read", { path: userPath }, "/tmp");
1497
1479
  expect(result.decision).toBe("allow");
1498
1480
  expect(result.matchedRule).toBeDefined();
@@ -1500,7 +1482,7 @@ describe("Permission Checker", () => {
1500
1482
  });
1501
1483
 
1502
1484
  test("file_write of workspace SOUL.md is auto-allowed", async () => {
1503
- const soulPath = join(checkerTestDir, "workspace", "SOUL.md");
1485
+ const soulPath = join(checkerTestDir, "SOUL.md");
1504
1486
  const result = await check("file_write", { path: soulPath }, "/tmp");
1505
1487
  expect(result.decision).toBe("allow");
1506
1488
  expect(result.matchedRule).toBeDefined();
@@ -1508,7 +1490,7 @@ describe("Permission Checker", () => {
1508
1490
  });
1509
1491
 
1510
1492
  test("file_write of workspace BOOTSTRAP.md is auto-allowed", async () => {
1511
- const bootstrapPath = join(checkerTestDir, "workspace", "BOOTSTRAP.md");
1493
+ const bootstrapPath = join(checkerTestDir, "BOOTSTRAP.md");
1512
1494
  const result = await check("file_write", { path: bootstrapPath }, "/tmp");
1513
1495
  expect(result.decision).toBe("allow");
1514
1496
  expect(result.matchedRule).toBeDefined();
@@ -1516,7 +1498,7 @@ describe("Permission Checker", () => {
1516
1498
  });
1517
1499
 
1518
1500
  test("file_read of workspace UPDATES.md is auto-allowed", async () => {
1519
- const updatesPath = join(checkerTestDir, "workspace", "UPDATES.md");
1501
+ const updatesPath = join(checkerTestDir, "UPDATES.md");
1520
1502
  const result = await check("file_read", { path: updatesPath }, "/tmp");
1521
1503
  expect(result.decision).toBe("allow");
1522
1504
  expect(result.matchedRule).toBeDefined();
@@ -1524,7 +1506,7 @@ describe("Permission Checker", () => {
1524
1506
  });
1525
1507
 
1526
1508
  test("file_write of workspace UPDATES.md is auto-allowed", async () => {
1527
- const updatesPath = join(checkerTestDir, "workspace", "UPDATES.md");
1509
+ const updatesPath = join(checkerTestDir, "UPDATES.md");
1528
1510
  const result = await check("file_write", { path: updatesPath }, "/tmp");
1529
1511
  expect(result.decision).toBe("allow");
1530
1512
  expect(result.matchedRule).toBeDefined();
@@ -1532,7 +1514,7 @@ describe("Permission Checker", () => {
1532
1514
  });
1533
1515
 
1534
1516
  test("file_edit of workspace UPDATES.md is auto-allowed", async () => {
1535
- const updatesPath = join(checkerTestDir, "workspace", "UPDATES.md");
1517
+ const updatesPath = join(checkerTestDir, "UPDATES.md");
1536
1518
  const result = await check("file_edit", { path: updatesPath }, "/tmp");
1537
1519
  expect(result.decision).toBe("allow");
1538
1520
  expect(result.matchedRule).toBeDefined();
@@ -1540,7 +1522,7 @@ describe("Permission Checker", () => {
1540
1522
  });
1541
1523
 
1542
1524
  test("file_write of non-workspace file is auto-allowed (Low risk)", async () => {
1543
- const otherPath = join(checkerTestDir, "workspace", "OTHER.md");
1525
+ const otherPath = join(checkerTestDir, "OTHER.md");
1544
1526
  // Use a workingDir that doesn't contain the path so it's not workspace-scoped
1545
1527
  const result = await check("file_write", { path: otherPath }, "/home");
1546
1528
  // Low risk → auto-allowed even outside workspace
@@ -2067,7 +2049,7 @@ describe("Permission Checker", () => {
2067
2049
  expect(risk).toBe(RiskLevel.Low);
2068
2050
  });
2069
2051
 
2070
- test("file_write to skill directory prompts as High risk", async () => {
2052
+ test("file_write to skill directory prompts via default ask rule", async () => {
2071
2053
  ensureSkillsDir();
2072
2054
  const skillPath = join(
2073
2055
  checkerTestDir,
@@ -2077,7 +2059,10 @@ describe("Permission Checker", () => {
2077
2059
  );
2078
2060
  const result = await check("file_write", { path: skillPath }, "/tmp");
2079
2061
  expect(result.decision).toBe("prompt");
2080
- expect(result.reason).toContain("High risk");
2062
+ expect(result.matchedRule).toBeDefined();
2063
+ expect(result.matchedRule!.id).toBe(
2064
+ "default:ask-file_write-managed-skills",
2065
+ );
2081
2066
  });
2082
2067
 
2083
2068
  test("file_write to skill directory is NOT allowed by a generic file_write allow rule (High risk)", async () => {
@@ -2092,7 +2077,6 @@ describe("Permission Checker", () => {
2092
2077
  const result = await check("file_write", { path: skillPath }, "/tmp");
2093
2078
  // High risk requires explicit allowHighRisk — a plain allow rule is insufficient.
2094
2079
  expect(result.decision).toBe("prompt");
2095
- expect(result.reason).toContain("High risk");
2096
2080
  });
2097
2081
 
2098
2082
  test("file_write to skill directory is allowed with allowHighRisk: true rule", async () => {
@@ -2592,10 +2576,8 @@ describe("Permission Checker", () => {
2592
2576
  "executor.ts",
2593
2577
  );
2594
2578
  const result = await check("file_write", { path: skillPath }, "/tmp");
2579
+ // The important invariant is that it prompts (default ask rule or strict mode).
2595
2580
  expect(result.decision).toBe("prompt");
2596
- // In strict mode the "no matching rule" check fires before the
2597
- // high-risk fallback — the important invariant is that it prompts.
2598
- expect(result.reason).toContain("requires approval");
2599
2581
  });
2600
2582
 
2601
2583
  test("strict mode: file_edit of skill source prompts (no implicit allow)", async () => {
@@ -2609,7 +2591,6 @@ describe("Permission Checker", () => {
2609
2591
  );
2610
2592
  const result = await check("file_edit", { path: skillPath }, "/tmp");
2611
2593
  expect(result.decision).toBe("prompt");
2612
- expect(result.reason).toContain("requires approval");
2613
2594
  });
2614
2595
 
2615
2596
  test("strict mode: file_write to non-skill path prompts as Strict mode", async () => {
@@ -2621,7 +2602,7 @@ describe("Permission Checker", () => {
2621
2602
  expect(result.reason).toContain("Strict mode");
2622
2603
  });
2623
2604
 
2624
- test("workspace mode: file_write to skill source still prompts as High risk", async () => {
2605
+ test("workspace mode: file_write to skill source still prompts", async () => {
2625
2606
  testConfig.permissions.mode = "workspace";
2626
2607
  ensureSkillsDir();
2627
2608
  const skillPath = join(
@@ -2632,7 +2613,6 @@ describe("Permission Checker", () => {
2632
2613
  );
2633
2614
  const result = await check("file_write", { path: skillPath }, "/tmp");
2634
2615
  expect(result.decision).toBe("prompt");
2635
- expect(result.reason).toContain("High risk");
2636
2616
  });
2637
2617
 
2638
2618
  test("strict mode: host_file_write to skill source prompts (high risk overrides host ask)", async () => {
@@ -2792,35 +2772,20 @@ describe("Permission Checker", () => {
2792
2772
  // Regression tests: user-created allow rules (priority 100) must override
2793
2773
  // the default ask rules for skill-source mutations (priority 50).
2794
2774
  //
2795
- // Paths use getRootDir()/workspace/skills/ (not getWorkspaceSkillsDir())
2796
- // because getDefaultRuleTemplates builds the managed-skill ask rule from
2797
- // getRootDir(), so using a different prefix would avoid contention with
2798
- // the default rule and silently pass even if the priority regressed.
2799
- //
2800
- // extraDirs is set to the parent "workspace" directory (not "workspace/skills")
2801
- // so that isSkillSourcePath classifies the paths as High risk without creating
2802
- // a duplicate extra-0 ask rule for the exact same path as the managed rule.
2803
- // The third test explicitly asserts the matched rule ID is the managed-skill
2804
- // rule to guard against regressions in default rule generation.
2775
+ // Paths use the real workspace skills directory (getWorkspaceSkillsDir())
2776
+ // so that getDefaultRuleTemplates builds the managed-skill ask rule for the
2777
+ // exact same path. The third test explicitly asserts the matched rule ID is
2778
+ // the managed-skill rule to guard against regressions in default rule
2779
+ // generation.
2805
2780
 
2806
2781
  describe("user override of skill mutation default ask rules", () => {
2807
2782
  // Must match the path getDefaultRuleTemplates computes for managedSkillsDir
2808
- const wsSkillsDir = join(checkerTestDir, "workspace", "skills");
2809
- // Use parent directory for extraDirs — broad enough for isSkillSourcePath
2810
- // to recognize skill paths, but distinct from the managed-skill rule path.
2811
- const wsDir = join(checkerTestDir, "workspace");
2783
+ const wsSkillsDir = join(checkerTestDir, "skills");
2812
2784
 
2813
2785
  function ensureSkillsDir(): void {
2814
2786
  mkdirSync(wsSkillsDir, { recursive: true });
2815
2787
  }
2816
2788
 
2817
- beforeEach(() => {
2818
- // Register the workspace parent dir so isSkillSourcePath detects skill
2819
- // paths under workspace/skills/ without duplicating the managed-skill
2820
- // default ask rule (the mock for getWorkspaceSkillsDir points elsewhere).
2821
- testConfig.skills.load.extraDirs = [wsDir];
2822
- });
2823
-
2824
2789
  test("user allowHighRisk rule at priority 100 overrides default ask for skill source writes", async () => {
2825
2790
  ensureSkillsDir();
2826
2791
  const skillPath = join(wsSkillsDir, "my-skill", "executor.ts");
@@ -1,21 +1,9 @@
1
- import {
2
- existsSync,
3
- mkdirSync,
4
- mkdtempSync,
5
- rmSync,
6
- writeFileSync,
7
- } from "node:fs";
8
- import { tmpdir } from "node:os";
1
+ import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
9
2
  import { join } from "node:path";
10
- import { afterEach, beforeEach, describe, expect, test } from "bun:test";
3
+ import { describe, expect, test } from "bun:test";
11
4
  import { mock } from "bun:test";
12
5
 
13
- let TEST_DIR = "";
14
-
15
- mock.module("../util/platform.js", () => ({
16
- getRootDir: () => TEST_DIR,
17
- getWorkspaceSkillsDir: () => join(TEST_DIR, "skills"),
18
- }));
6
+ const TEST_DIR = process.env.VELLUM_WORKSPACE_DIR!;
19
7
 
20
8
  mock.module("../util/logger.js", () => ({
21
9
  getLogger: () =>
@@ -31,15 +19,6 @@ import {
31
19
  verifyAndRecordSkillHash,
32
20
  } from "../skills/clawhub.js";
33
21
 
34
- beforeEach(() => {
35
- TEST_DIR = mkdtempSync(join(tmpdir(), "clawhub-test-"));
36
- mkdirSync(join(TEST_DIR, "skills"), { recursive: true });
37
- });
38
-
39
- afterEach(() => {
40
- rmSync(TEST_DIR, { recursive: true, force: true });
41
- });
42
-
43
22
  // ---------------------------------------------------------------------------
44
23
  // Slug validation (exercised through public API)
45
24
  // ---------------------------------------------------------------------------
@@ -125,6 +104,7 @@ describe("integrity manifest", () => {
125
104
  }
126
105
 
127
106
  test("malformed integrity JSON is handled gracefully", () => {
107
+ mkdirSync(join(TEST_DIR, "skills"), { recursive: true });
128
108
  const integrityPath = join(TEST_DIR, "skills", ".integrity.json");
129
109
  writeFileSync(integrityPath, "{not valid json!!!", "utf-8");
130
110
  createSkillFiles("valid-slug");
@@ -139,7 +119,11 @@ describe("integrity manifest", () => {
139
119
  });
140
120
 
141
121
  test("missing integrity manifest is created on first install", () => {
142
- const integrityPath = join(TEST_DIR, "skills", ".integrity.json");
122
+ const skillsDir = join(TEST_DIR, "skills");
123
+ mkdirSync(skillsDir, { recursive: true });
124
+ const integrityPath = join(skillsDir, ".integrity.json");
125
+ // Remove any manifest left by earlier tests so we test the fresh-creation path
126
+ rmSync(integrityPath, { force: true });
143
127
  expect(existsSync(integrityPath)).toBe(false);
144
128
  createSkillFiles("new-skill");
145
129
 
@@ -5,26 +5,8 @@
5
5
  // sensitive subcommands are intentionally elevated to Medium or High.
6
6
  // See #18982 / #18998 for the regression that motivated this guard.
7
7
 
8
- import { mkdtempSync } from "node:fs";
9
- import { tmpdir } from "node:os";
10
- import { join } from "node:path";
11
8
  import { describe, expect, mock, test } from "bun:test";
12
9
 
13
- const guardTestDir = mkdtempSync(join(tmpdir(), "cli-risk-guard-test-"));
14
-
15
- mock.module("../util/platform.js", () => ({
16
- getRootDir: () => guardTestDir,
17
- getDataDir: () => join(guardTestDir, "data"),
18
- getWorkspaceSkillsDir: () => join(guardTestDir, "skills"),
19
- isMacOS: () => process.platform === "darwin",
20
- isLinux: () => process.platform === "linux",
21
- isWindows: () => process.platform === "win32",
22
- getPidPath: () => join(guardTestDir, "test.pid"),
23
- getDbPath: () => join(guardTestDir, "test.db"),
24
- getLogPath: () => join(guardTestDir, "test.log"),
25
- ensureDataDir: () => {},
26
- }));
27
-
28
10
  mock.module("../util/logger.js", () => ({
29
11
  getLogger: () =>
30
12
  new Proxy({} as Record<string, unknown>, {
@@ -1,4 +1,3 @@
1
- import { randomBytes } from "node:crypto";
2
1
  import {
3
2
  existsSync,
4
3
  mkdirSync,
@@ -6,7 +5,6 @@ import {
6
5
  rmSync,
7
6
  writeFileSync,
8
7
  } from "node:fs";
9
- import { tmpdir } from "node:os";
10
8
  import { join } from "node:path";
11
9
  import {
12
10
  afterAll,
@@ -22,21 +20,16 @@ import {
22
20
  // Mocks — declared before imports that depend on platform/logger
23
21
  // ---------------------------------------------------------------------------
24
22
 
25
- const TEST_DIR = join(
26
- tmpdir(),
27
- `vellum-backfill-test-${randomBytes(4).toString("hex")}`,
28
- );
29
- const WORKSPACE_DIR = join(TEST_DIR, "workspace");
23
+ const WORKSPACE_DIR = process.env.VELLUM_WORKSPACE_DIR!;
30
24
  const CONFIG_PATH = join(WORKSPACE_DIR, "config.json");
31
25
 
32
26
  function ensureTestDir(): void {
33
27
  const dirs = [
34
- TEST_DIR,
35
28
  WORKSPACE_DIR,
36
- join(TEST_DIR, "data"),
37
- join(TEST_DIR, "memory"),
38
- join(TEST_DIR, "memory", "knowledge"),
39
- join(TEST_DIR, "logs"),
29
+ join(WORKSPACE_DIR, "data"),
30
+ join(WORKSPACE_DIR, "data", "memory"),
31
+ join(WORKSPACE_DIR, "data", "memory", "knowledge"),
32
+ join(WORKSPACE_DIR, "data", "logs"),
40
33
  ];
41
34
  for (const dir of dirs) {
42
35
  if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
@@ -64,18 +57,6 @@ mock.module("../util/logger.js", () => ({
64
57
  getLogger: () => makeLoggerStub(),
65
58
  }));
66
59
 
67
- mock.module("../util/platform.js", () => ({
68
- getRootDir: () => TEST_DIR,
69
- getWorkspaceDir: () => WORKSPACE_DIR,
70
- getWorkspaceConfigPath: () => CONFIG_PATH,
71
- getDataDir: () => join(TEST_DIR, "data"),
72
- getLogPath: () => join(TEST_DIR, "logs", "vellum.log"),
73
- ensureDataDir: () => ensureTestDir(),
74
- isMacOS: () => false,
75
- isLinux: () => false,
76
- isWindows: () => false,
77
- }));
78
-
79
60
  // Restore all mocked modules after this file's tests complete to prevent
80
61
  // cross-test contamination when running grouped with other test files.
81
62
  afterAll(() => {
@@ -171,9 +152,9 @@ describe("config loader backfill", () => {
171
152
  ensureTestDir();
172
153
  const resetPaths = [
173
154
  CONFIG_PATH,
174
- join(TEST_DIR, "keys.enc"),
175
- join(TEST_DIR, "data"),
176
- join(TEST_DIR, "memory"),
155
+ join(WORKSPACE_DIR, "keys.enc"),
156
+ join(WORKSPACE_DIR, "data"),
157
+ join(WORKSPACE_DIR, "data", "memory"),
177
158
  ];
178
159
  for (const path of resetPaths) {
179
160
  if (existsSync(path)) {
@@ -181,7 +162,7 @@ describe("config loader backfill", () => {
181
162
  }
182
163
  }
183
164
  ensureTestDir();
184
- _setStorePath(join(TEST_DIR, "keys.enc"));
165
+ _setStorePath(join(WORKSPACE_DIR, "keys.enc"));
185
166
  invalidateConfigCache();
186
167
  });
187
168
 
@@ -1,6 +1,4 @@
1
- import { randomBytes } from "node:crypto";
2
1
  import { existsSync, mkdirSync } from "node:fs";
3
- import { tmpdir } from "node:os";
4
2
  import { join } from "node:path";
5
3
  import { describe, expect, mock, test } from "bun:test";
6
4
 
@@ -8,21 +6,15 @@ import { describe, expect, mock, test } from "bun:test";
8
6
  // Mocks — declared before imports that depend on platform/logger
9
7
  // ---------------------------------------------------------------------------
10
8
 
11
- const TEST_DIR = join(
12
- tmpdir(),
13
- `vellum-schema-cmd-test-${randomBytes(4).toString("hex")}`,
14
- );
15
- const WORKSPACE_DIR = join(TEST_DIR, "workspace");
16
- const CONFIG_PATH = join(WORKSPACE_DIR, "config.json");
9
+ const WORKSPACE_DIR = process.env.VELLUM_WORKSPACE_DIR!;
17
10
 
18
11
  function ensureTestDir(): void {
19
12
  const dirs = [
20
- TEST_DIR,
21
13
  WORKSPACE_DIR,
22
- join(TEST_DIR, "data"),
23
- join(TEST_DIR, "memory"),
24
- join(TEST_DIR, "memory", "knowledge"),
25
- join(TEST_DIR, "logs"),
14
+ join(WORKSPACE_DIR, "data"),
15
+ join(WORKSPACE_DIR, "data", "memory"),
16
+ join(WORKSPACE_DIR, "data", "memory", "knowledge"),
17
+ join(WORKSPACE_DIR, "data", "logs"),
26
18
  ];
27
19
  for (const dir of dirs) {
28
20
  if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
@@ -53,18 +45,6 @@ mock.module("../util/logger.js", () => ({
53
45
  getCliLogger: () => makeLoggerStub(),
54
46
  }));
55
47
 
56
- mock.module("../util/platform.js", () => ({
57
- getRootDir: () => TEST_DIR,
58
- getWorkspaceDir: () => WORKSPACE_DIR,
59
- getWorkspaceConfigPath: () => CONFIG_PATH,
60
- getDataDir: () => join(TEST_DIR, "data"),
61
- getLogPath: () => join(TEST_DIR, "logs", "vellum.log"),
62
- ensureDataDir: () => ensureTestDir(),
63
- isMacOS: () => false,
64
- isLinux: () => false,
65
- isWindows: () => false,
66
- }));
67
-
68
48
  mock.module("../config/loader.js", () => ({
69
49
  getConfig: () => ({
70
50
  services: {
@@ -1,6 +1,4 @@
1
- import { randomBytes } from "node:crypto";
2
1
  import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
3
- import { tmpdir } from "node:os";
4
2
  import { join } from "node:path";
5
3
  import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
6
4
 
@@ -8,21 +6,16 @@ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
8
6
  // Mocks — declared before imports that depend on platform/logger
9
7
  // ---------------------------------------------------------------------------
10
8
 
11
- const TEST_DIR = join(
12
- tmpdir(),
13
- `vellum-schema-test-${randomBytes(4).toString("hex")}`,
14
- );
15
- const WORKSPACE_DIR = join(TEST_DIR, "workspace");
9
+ const WORKSPACE_DIR = process.env.VELLUM_WORKSPACE_DIR!;
16
10
  const CONFIG_PATH = join(WORKSPACE_DIR, "config.json");
17
11
 
18
12
  function ensureTestDir(): void {
19
13
  const dirs = [
20
- TEST_DIR,
21
14
  WORKSPACE_DIR,
22
- join(TEST_DIR, "data"),
23
- join(TEST_DIR, "memory"),
24
- join(TEST_DIR, "memory", "knowledge"),
25
- join(TEST_DIR, "logs"),
15
+ join(WORKSPACE_DIR, "data"),
16
+ join(WORKSPACE_DIR, "data", "memory"),
17
+ join(WORKSPACE_DIR, "data", "memory", "knowledge"),
18
+ join(WORKSPACE_DIR, "data", "logs"),
26
19
  ];
27
20
  for (const dir of dirs) {
28
21
  if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
@@ -50,18 +43,6 @@ mock.module("../util/logger.js", () => ({
50
43
  getLogger: () => makeLoggerStub(),
51
44
  }));
52
45
 
53
- mock.module("../util/platform.js", () => ({
54
- getRootDir: () => TEST_DIR,
55
- getWorkspaceDir: () => WORKSPACE_DIR,
56
- getWorkspaceConfigPath: () => CONFIG_PATH,
57
- getDataDir: () => join(TEST_DIR, "data"),
58
- getLogPath: () => join(TEST_DIR, "logs", "vellum.log"),
59
- ensureDataDir: () => ensureTestDir(),
60
- isMacOS: () => false,
61
- isLinux: () => false,
62
- isWindows: () => false,
63
- }));
64
-
65
46
  import {
66
47
  buildElevenLabsVoiceSpec,
67
48
  resolveVoiceQualityProfile,
@@ -102,8 +83,8 @@ describe("AssistantConfigSchema", () => {
102
83
  expect(result.services["web-search"].mode).toBe("your-own");
103
84
  expect(result.maxTokens).toBe(16000);
104
85
  expect(result.thinking).toEqual({
105
- enabled: false,
106
- streamThinking: false,
86
+ enabled: true,
87
+ streamThinking: true,
107
88
  });
108
89
  expect(result.contextWindow).toEqual({
109
90
  enabled: true,
@@ -175,8 +156,8 @@ describe("AssistantConfigSchema", () => {
175
156
  const result = AssistantConfigSchema.parse({});
176
157
  expect(result.memory.retrieval.dynamicBudget).toEqual({
177
158
  enabled: true,
178
- minInjectTokens: 1200,
179
- maxInjectTokens: 10000,
159
+ minInjectTokens: 2400,
160
+ maxInjectTokens: 16000,
180
161
  targetHeadroomTokens: 10000,
181
162
  });
182
163
  });
@@ -975,13 +956,13 @@ describe("buildElevenLabsVoiceSpec", () => {
975
956
 
976
957
  describe("loadConfig with schema validation", () => {
977
958
  beforeEach(() => {
978
- // Keep TEST_DIR and logs in place to avoid racing async logger stream init.
959
+ // Keep WORKSPACE_DIR and logs in place to avoid racing async logger stream init.
979
960
  ensureTestDir();
980
961
  const resetPaths = [
981
962
  CONFIG_PATH,
982
- join(TEST_DIR, "keys.enc"),
983
- join(TEST_DIR, "data"),
984
- join(TEST_DIR, "memory"),
963
+ join(WORKSPACE_DIR, "keys.enc"),
964
+ join(WORKSPACE_DIR, "data"),
965
+ join(WORKSPACE_DIR, "data", "memory"),
985
966
  ];
986
967
  for (const path of resetPaths) {
987
968
  if (existsSync(path)) {
@@ -989,7 +970,7 @@ describe("loadConfig with schema validation", () => {
989
970
  }
990
971
  }
991
972
  ensureTestDir();
992
- _setStorePath(join(TEST_DIR, "keys.enc"));
973
+ _setStorePath(join(WORKSPACE_DIR, "keys.enc"));
993
974
  invalidateConfigCache();
994
975
  });
995
976
 
@@ -998,7 +979,7 @@ describe("loadConfig with schema validation", () => {
998
979
  invalidateConfigCache();
999
980
  });
1000
981
 
1001
- // Intentionally do not remove TEST_DIR in afterAll.
982
+ // Intentionally do not remove WORKSPACE_DIR in afterAll.
1002
983
  // A late async logger flush may still target logs under this path and can
1003
984
  // intermittently trigger unhandled ENOENT in CI if the directory is removed.
1004
985
  test("loads valid config", () => {
@@ -1021,8 +1002,8 @@ describe("loadConfig with schema validation", () => {
1021
1002
  expect(config.services.inference.model).toBe("claude-opus-4-6");
1022
1003
  expect(config.maxTokens).toBe(16000);
1023
1004
  expect(config.thinking).toEqual({
1024
- enabled: false,
1025
- streamThinking: false,
1005
+ enabled: true,
1006
+ streamThinking: true,
1026
1007
  });
1027
1008
  expect(config.contextWindow).toEqual({
1028
1009
  enabled: true,
@@ -1209,9 +1190,9 @@ describe("Call entrypoint gating", () => {
1209
1190
  ensureTestDir();
1210
1191
  const resetPaths = [
1211
1192
  CONFIG_PATH,
1212
- join(TEST_DIR, "keys.enc"),
1213
- join(TEST_DIR, "data"),
1214
- join(TEST_DIR, "memory"),
1193
+ join(WORKSPACE_DIR, "keys.enc"),
1194
+ join(WORKSPACE_DIR, "data"),
1195
+ join(WORKSPACE_DIR, "data", "memory"),
1215
1196
  ];
1216
1197
  for (const path of resetPaths) {
1217
1198
  if (existsSync(path)) {
@@ -1219,7 +1200,7 @@ describe("Call entrypoint gating", () => {
1219
1200
  }
1220
1201
  }
1221
1202
  ensureTestDir();
1222
- _setStorePath(join(TEST_DIR, "keys.enc"));
1203
+ _setStorePath(join(WORKSPACE_DIR, "keys.enc"));
1223
1204
  invalidateConfigCache();
1224
1205
  });
1225
1206