@vellumai/assistant 0.5.12 → 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 (442) hide show
  1. package/.env.example +1 -6
  2. package/AGENTS.md +4 -0
  3. package/ARCHITECTURE.md +0 -1
  4. package/Dockerfile +41 -9
  5. package/bunfig.toml +1 -0
  6. package/docs/architecture/memory.md +3 -3
  7. package/node_modules/@vellumai/ces-contracts/src/index.ts +7 -0
  8. package/node_modules/@vellumai/ces-contracts/src/rpc.ts +5 -0
  9. package/openapi.yaml +127 -22
  10. package/package.json +1 -1
  11. package/src/__tests__/access-request-decision.test.ts +2 -32
  12. package/src/__tests__/actor-token-service.test.ts +1 -31
  13. package/src/__tests__/anthropic-provider.test.ts +53 -40
  14. package/src/__tests__/app-git-history.test.ts +9 -17
  15. package/src/__tests__/app-git-service.test.ts +14 -20
  16. package/src/__tests__/app-store-dir-names.test.ts +10 -20
  17. package/src/__tests__/approval-cascade.test.ts +2 -19
  18. package/src/__tests__/approval-primitive.test.ts +2 -27
  19. package/src/__tests__/approval-routes-http.test.ts +2 -30
  20. package/src/__tests__/assistant-events-sse-hardening.test.ts +2 -28
  21. package/src/__tests__/assistant-feature-flags-integration.test.ts +2 -45
  22. package/src/__tests__/attachments-store.test.ts +5 -32
  23. package/src/__tests__/audit-log-rotation.test.ts +5 -36
  24. package/src/__tests__/avatar-e2e.test.ts +1 -9
  25. package/src/__tests__/avatar-generator.test.ts +1 -7
  26. package/src/__tests__/browser-fill-credential.test.ts +0 -4
  27. package/src/__tests__/browser-manager.test.ts +0 -6
  28. package/src/__tests__/call-controller.test.ts +1 -22
  29. package/src/__tests__/call-conversation-messages.test.ts +0 -21
  30. package/src/__tests__/call-domain.test.ts +0 -25
  31. package/src/__tests__/call-pointer-messages.test.ts +0 -21
  32. package/src/__tests__/call-recovery.test.ts +0 -22
  33. package/src/__tests__/call-routes-http.test.ts +0 -24
  34. package/src/__tests__/call-store.test.ts +0 -21
  35. package/src/__tests__/cancel-resolves-conversation-key.test.ts +0 -24
  36. package/src/__tests__/canonical-guardian-store.test.ts +48 -21
  37. package/src/__tests__/channel-approval-routes.test.ts +6 -26
  38. package/src/__tests__/channel-approvals.test.ts +1 -38
  39. package/src/__tests__/channel-delivery-store.test.ts +0 -21
  40. package/src/__tests__/channel-guardian.test.ts +0 -26
  41. package/src/__tests__/channel-reply-delivery.test.ts +5 -0
  42. package/src/__tests__/channel-retry-sweep.test.ts +0 -21
  43. package/src/__tests__/checker.test.ts +26 -61
  44. package/src/__tests__/clawhub.test.ts +9 -25
  45. package/src/__tests__/cli-command-risk-guard.test.ts +0 -18
  46. package/src/__tests__/config-loader-backfill.test.ts +9 -28
  47. package/src/__tests__/config-schema-cmd.test.ts +5 -25
  48. package/src/__tests__/config-schema.test.ts +21 -40
  49. package/src/__tests__/config-watcher.test.ts +4 -91
  50. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -21
  51. package/src/__tests__/contacts-tools.test.ts +0 -21
  52. package/src/__tests__/context-memory-e2e.test.ts +0 -21
  53. package/src/__tests__/context-window-manager.test.ts +130 -3
  54. package/src/__tests__/conversation-abort-tool-results.test.ts +0 -4
  55. package/src/__tests__/conversation-agent-loop-overflow.test.ts +0 -4
  56. package/src/__tests__/conversation-agent-loop.test.ts +0 -4
  57. package/src/__tests__/conversation-attachments.test.ts +1 -24
  58. package/src/__tests__/conversation-attention-store.test.ts +0 -21
  59. package/src/__tests__/conversation-attention-telegram.test.ts +0 -22
  60. package/src/__tests__/conversation-clear-safety.test.ts +0 -22
  61. package/src/__tests__/conversation-confirmation-signals.test.ts +2 -21
  62. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +0 -24
  63. package/src/__tests__/conversation-disk-view-integration.test.ts +1 -23
  64. package/src/__tests__/conversation-disk-view.test.ts +5 -27
  65. package/src/__tests__/conversation-error.test.ts +1 -1
  66. package/src/__tests__/conversation-fork-crud.test.ts +1 -33
  67. package/src/__tests__/conversation-fork-route.test.ts +0 -27
  68. package/src/__tests__/conversation-history-web-search.test.ts +23 -16
  69. package/src/__tests__/conversation-init.benchmark.test.ts +22 -43
  70. package/src/__tests__/conversation-key-store-disk-view.test.ts +8 -34
  71. package/src/__tests__/conversation-load-history-repair.test.ts +0 -4
  72. package/src/__tests__/conversation-pre-run-repair.test.ts +0 -4
  73. package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -4
  74. package/src/__tests__/conversation-queue.test.ts +8 -8
  75. package/src/__tests__/conversation-routes-disk-view.test.ts +13 -51
  76. package/src/__tests__/conversation-runtime-assembly.test.ts +64 -38
  77. package/src/__tests__/conversation-slash-commands.test.ts +5 -0
  78. package/src/__tests__/conversation-slash-queue.test.ts +0 -4
  79. package/src/__tests__/conversation-slash-unknown.test.ts +0 -4
  80. package/src/__tests__/conversation-speed-override.test.ts +326 -0
  81. package/src/__tests__/conversation-starter-routes.test.ts +0 -23
  82. package/src/__tests__/conversation-store.test.ts +0 -21
  83. package/src/__tests__/conversation-unread-route.test.ts +0 -24
  84. package/src/__tests__/conversation-usage.test.ts +56 -21
  85. package/src/__tests__/conversation-wipe.test.ts +0 -21
  86. package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -4
  87. package/src/__tests__/conversation-workspace-injection.test.ts +0 -4
  88. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -4
  89. package/src/__tests__/credential-execution-shell-lockdown.test.ts +8 -5
  90. package/src/__tests__/credential-vault-unit.test.ts +9 -428
  91. package/src/__tests__/credentials-cli.test.ts +10 -10
  92. package/src/__tests__/daemon-assistant-events.test.ts +0 -19
  93. package/src/__tests__/date-context.test.ts +77 -97
  94. package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +7 -24
  95. package/src/__tests__/db-llm-request-log-provider-migration.test.ts +29 -42
  96. package/src/__tests__/delete-managed-skill-tool.test.ts +2 -10
  97. package/src/__tests__/deterministic-verification-control-plane.test.ts +1 -26
  98. package/src/__tests__/docker-signing-key-bootstrap.test.ts +61 -15
  99. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +2 -36
  100. package/src/__tests__/email-cli.test.ts +6 -6
  101. package/src/__tests__/ephemeral-permissions.test.ts +5 -17
  102. package/src/__tests__/first-greeting.test.ts +11 -32
  103. package/src/__tests__/followup-tools.test.ts +0 -21
  104. package/src/__tests__/gateway-only-enforcement.test.ts +0 -20
  105. package/src/__tests__/guardian-action-conversation-turn.test.ts +0 -23
  106. package/src/__tests__/guardian-action-followup-executor.test.ts +0 -23
  107. package/src/__tests__/guardian-action-followup-store.test.ts +0 -21
  108. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -21
  109. package/src/__tests__/guardian-action-late-reply.test.ts +0 -21
  110. package/src/__tests__/guardian-action-store.test.ts +0 -21
  111. package/src/__tests__/guardian-action-sweep.test.ts +0 -21
  112. package/src/__tests__/guardian-binding-drift-heal.test.ts +0 -23
  113. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +172 -22
  114. package/src/__tests__/guardian-dispatch.test.ts +0 -21
  115. package/src/__tests__/guardian-grant-minting.test.ts +0 -22
  116. package/src/__tests__/guardian-outbound-http.test.ts +0 -22
  117. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +0 -23
  118. package/src/__tests__/guardian-routing-invariants.test.ts +0 -22
  119. package/src/__tests__/guardian-routing-state.test.ts +0 -22
  120. package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -24
  121. package/src/__tests__/headless-browser-interactions.test.ts +0 -4
  122. package/src/__tests__/headless-browser-navigate.test.ts +0 -4
  123. package/src/__tests__/headless-browser-read-tools.test.ts +0 -4
  124. package/src/__tests__/headless-browser-snapshot.test.ts +0 -4
  125. package/src/__tests__/heartbeat-service.test.ts +99 -26
  126. package/src/__tests__/hooks-blocking.test.ts +3 -3
  127. package/src/__tests__/hooks-config.test.ts +7 -7
  128. package/src/__tests__/hooks-discovery.test.ts +3 -3
  129. package/src/__tests__/hooks-integration.test.ts +5 -5
  130. package/src/__tests__/hooks-manager.test.ts +3 -3
  131. package/src/__tests__/hooks-runner.test.ts +5 -23
  132. package/src/__tests__/hooks-settings.test.ts +3 -3
  133. package/src/__tests__/hooks-templates.test.ts +3 -3
  134. package/src/__tests__/http-conversation-lineage.test.ts +0 -27
  135. package/src/__tests__/identity-intro-cache.test.ts +0 -4
  136. package/src/__tests__/inbound-invite-redemption.test.ts +0 -22
  137. package/src/__tests__/inline-skill-load-permissions.test.ts +5 -16
  138. package/src/__tests__/intent-routing.test.ts +2 -55
  139. package/src/__tests__/invite-redemption-service.test.ts +0 -21
  140. package/src/__tests__/invite-routes-http.test.ts +0 -21
  141. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +0 -17
  142. package/src/__tests__/journal-context.test.ts +8 -75
  143. package/src/__tests__/list-messages-attachments.test.ts +0 -22
  144. package/src/__tests__/llm-context-route-provider.test.ts +0 -21
  145. package/src/__tests__/llm-request-log-turn-query.test.ts +46 -28
  146. package/src/__tests__/llm-usage-store.test.ts +0 -21
  147. package/src/__tests__/log-export-workspace.test.ts +1 -1
  148. package/src/__tests__/managed-skill-lifecycle.test.ts +1 -1
  149. package/src/__tests__/managed-store.test.ts +1 -1
  150. package/src/__tests__/mcp-cli.test.ts +7 -10
  151. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +0 -21
  152. package/src/__tests__/memory-jobs-worker-backoff.test.ts +0 -11
  153. package/src/__tests__/memory-lifecycle-e2e.test.ts +0 -21
  154. package/src/__tests__/memory-recall-log-store.test.ts +0 -27
  155. package/src/__tests__/memory-recall-quality.test.ts +0 -21
  156. package/src/__tests__/memory-regressions.experimental.test.ts +31 -30
  157. package/src/__tests__/memory-regressions.test.ts +282 -70
  158. package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -21
  159. package/src/__tests__/memory-upsert-concurrency.test.ts +0 -21
  160. package/src/__tests__/messaging-send-tool.test.ts +201 -0
  161. package/src/__tests__/migration-cross-version-compatibility.test.ts +18 -13
  162. package/src/__tests__/migration-export-http.test.ts +7 -1
  163. package/src/__tests__/migration-import-commit-http.test.ts +16 -14
  164. package/src/__tests__/migration-import-preflight-http.test.ts +27 -44
  165. package/src/__tests__/migration-validate-http.test.ts +1 -28
  166. package/src/__tests__/native-web-search.test.ts +25 -22
  167. package/src/__tests__/navigate-settings-tab.test.ts +6 -2
  168. package/src/__tests__/non-member-access-request.test.ts +0 -22
  169. package/src/__tests__/notification-guardian-path.test.ts +0 -21
  170. package/src/__tests__/notification-schedule-dedup.test.ts +1 -25
  171. package/src/__tests__/oauth-apps-routes.test.ts +103 -2
  172. package/src/__tests__/oauth-cli.test.ts +52 -0
  173. package/src/__tests__/oauth-provider-profiles.test.ts +0 -16
  174. package/src/__tests__/oauth-provider-serializer.test.ts +232 -0
  175. package/src/__tests__/oauth-providers-routes.test.ts +257 -0
  176. package/src/__tests__/oauth-store.test.ts +0 -21
  177. package/src/__tests__/onboarding-template-contract.test.ts +2 -2
  178. package/src/__tests__/openai-provider.test.ts +261 -0
  179. package/src/__tests__/pairing-concurrent.test.ts +6 -6
  180. package/src/__tests__/pairing-routes.test.ts +7 -1
  181. package/src/__tests__/path-policy.test.ts +1 -1
  182. package/src/__tests__/platform.test.ts +62 -251
  183. package/src/__tests__/playbook-execution.test.ts +0 -21
  184. package/src/__tests__/playbook-tools.test.ts +0 -21
  185. package/src/__tests__/pricing.test.ts +100 -0
  186. package/src/__tests__/relay-server.test.ts +1 -25
  187. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -24
  188. package/src/__tests__/runtime-events-sse-parity.test.ts +2 -24
  189. package/src/__tests__/runtime-events-sse.test.ts +0 -24
  190. package/src/__tests__/sandbox-diagnostics.test.ts +2 -1
  191. package/src/__tests__/scaffold-managed-skill-tool.test.ts +1 -1
  192. package/src/__tests__/schedule-store.test.ts +0 -21
  193. package/src/__tests__/schedule-tools.test.ts +0 -21
  194. package/src/__tests__/scheduler-recurrence.test.ts +0 -21
  195. package/src/__tests__/scoped-approval-grants.test.ts +0 -21
  196. package/src/__tests__/scoped-grant-security-matrix.test.ts +0 -21
  197. package/src/__tests__/secret-allowlist.test.ts +1 -1
  198. package/src/__tests__/secret-ingress-channel.test.ts +0 -5
  199. package/src/__tests__/secret-ingress-cli.test.ts +0 -6
  200. package/src/__tests__/secret-ingress-http.test.ts +0 -5
  201. package/src/__tests__/secret-ingress.test.ts +0 -5
  202. package/src/__tests__/send-endpoint-busy.test.ts +0 -24
  203. package/src/__tests__/sequence-store.test.ts +0 -21
  204. package/src/__tests__/server-history-render.test.ts +0 -24
  205. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -4
  206. package/src/__tests__/skill-feature-flags.test.ts +8 -0
  207. package/src/__tests__/skill-load-inline-command.test.ts +9 -0
  208. package/src/__tests__/skill-load-inline-includes.test.ts +9 -0
  209. package/src/__tests__/skill-load-tool.test.ts +11 -0
  210. package/src/__tests__/skill-secret-handling-guard.test.ts +212 -0
  211. package/src/__tests__/skills-uninstall.test.ts +10 -8
  212. package/src/__tests__/skills.test.ts +1 -1
  213. package/src/__tests__/slack-channel-config.test.ts +1 -1
  214. package/src/__tests__/slack-inbound-verification.test.ts +0 -22
  215. package/src/__tests__/starter-bundle.test.ts +4 -1
  216. package/src/__tests__/suggestion-routes.test.ts +2 -0
  217. package/src/__tests__/system-prompt.test.ts +1 -1
  218. package/src/__tests__/terminal-tools.test.ts +1 -1
  219. package/src/__tests__/test-preload.ts +31 -0
  220. package/src/__tests__/token-estimator-accuracy.benchmark.test.ts +1 -1
  221. package/src/__tests__/tool-execution-abort-cleanup.test.ts +1 -1
  222. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -1
  223. package/src/__tests__/tool-executor.test.ts +0 -20
  224. package/src/__tests__/tool-input-summary.test.ts +124 -0
  225. package/src/__tests__/tool-preview-lifecycle.test.ts +2 -1
  226. package/src/__tests__/trust-store.test.ts +7 -1
  227. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -1
  228. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +1 -1
  229. package/src/__tests__/trusted-contact-multichannel.test.ts +1 -1
  230. package/src/__tests__/trusted-contact-verification.test.ts +1 -1
  231. package/src/__tests__/turn-boundary-resolution.test.ts +1 -1
  232. package/src/__tests__/twilio-routes.test.ts +1 -1
  233. package/src/__tests__/update-bulletin.test.ts +1 -1
  234. package/src/__tests__/vbundle-pax-and-symlink.test.ts +1 -1
  235. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +1 -0
  236. package/src/__tests__/voice-scoped-grant-consumer.test.ts +1 -1
  237. package/src/__tests__/voice-session-bridge.test.ts +1 -1
  238. package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +4 -4
  239. package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -1
  240. package/src/__tests__/workspace-migration-down-functions.test.ts +15 -3
  241. package/src/__tests__/workspace-migration-seed-device-id.test.ts +40 -4
  242. package/src/agent/loop.ts +6 -9
  243. package/src/approvals/guardian-decision-primitive.ts +46 -18
  244. package/src/approvals/guardian-request-resolvers.ts +19 -2
  245. package/src/calls/active-call-lease.ts +2 -2
  246. package/src/cli/AGENTS.md +1 -1
  247. package/src/cli/commands/doctor.ts +9 -9
  248. package/src/cli/commands/memory.ts +142 -0
  249. package/src/cli/commands/oauth/__tests__/connect.test.ts +13 -11
  250. package/src/cli/commands/oauth/__tests__/ping.test.ts +1 -1
  251. package/src/cli/commands/oauth/connect.ts +13 -12
  252. package/src/cli/commands/oauth/index.ts +1 -1
  253. package/src/cli/commands/oauth/providers.ts +47 -62
  254. package/src/cli/commands/platform/__tests__/connect.test.ts +250 -0
  255. package/src/cli/commands/platform/__tests__/disconnect.test.ts +290 -0
  256. package/src/cli/commands/platform/__tests__/status.test.ts +282 -0
  257. package/src/cli/commands/platform/connect.ts +17 -7
  258. package/src/cli/commands/platform/disconnect.ts +28 -3
  259. package/src/cli/commands/platform/index.ts +3 -3
  260. package/src/cli.ts +1 -299
  261. package/src/config/assistant-feature-flags.ts +23 -15
  262. package/src/config/bundled-skills/app-builder/TOOLS.json +16 -0
  263. package/src/config/bundled-skills/app-builder/tools/app-create.ts +4 -0
  264. package/src/config/bundled-skills/app-builder/tools/app-delete.ts +5 -1
  265. package/src/config/bundled-skills/app-builder/tools/app-generate-icon.ts +9 -1
  266. package/src/config/bundled-skills/app-builder/tools/app-refresh.ts +5 -1
  267. package/src/config/bundled-skills/contacts/TOOLS.json +8 -0
  268. package/src/config/bundled-skills/contacts/tools/contact-search.ts +10 -1
  269. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +16 -2
  270. package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +1 -0
  271. package/src/config/bundled-skills/messaging/SKILL.md +7 -7
  272. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +37 -0
  273. package/src/config/bundled-skills/settings/TOOLS.json +5 -3
  274. package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +4 -2
  275. package/src/config/bundled-skills/slack/SKILL.md +18 -0
  276. package/src/config/env-registry.ts +15 -11
  277. package/src/config/env.ts +1 -11
  278. package/src/config/feature-flag-registry.json +17 -1
  279. package/src/config/schema.ts +4 -0
  280. package/src/config/schemas/heartbeat.ts +6 -1
  281. package/src/config/schemas/inference.ts +14 -3
  282. package/src/config/schemas/memory-processing.ts +16 -8
  283. package/src/config/schemas/memory-retrieval.ts +3 -3
  284. package/src/config/skills.ts +1 -1
  285. package/src/context/window-manager.ts +174 -51
  286. package/src/credential-execution/client.ts +14 -2
  287. package/src/credential-execution/executable-discovery.ts +2 -2
  288. package/src/daemon/approved-devices-store.ts +2 -2
  289. package/src/daemon/assistant-attachments.ts +2 -0
  290. package/src/daemon/config-watcher.ts +4 -50
  291. package/src/daemon/conversation-agent-loop-handlers.ts +9 -1
  292. package/src/daemon/conversation-agent-loop.ts +12 -0
  293. package/src/daemon/conversation-error.ts +3 -5
  294. package/src/daemon/conversation-history.ts +7 -3
  295. package/src/daemon/conversation-lifecycle.ts +16 -0
  296. package/src/daemon/conversation-messaging.ts +1 -0
  297. package/src/daemon/conversation-notifiers.ts +67 -30
  298. package/src/daemon/conversation-process.ts +161 -2
  299. package/src/daemon/conversation-queue-manager.ts +2 -0
  300. package/src/daemon/conversation-runtime-assembly.ts +33 -11
  301. package/src/daemon/conversation-slash.ts +14 -3
  302. package/src/daemon/conversation-tool-setup.ts +2 -0
  303. package/src/daemon/conversation-usage.ts +32 -4
  304. package/src/daemon/conversation.ts +33 -1
  305. package/src/daemon/daemon-control.ts +32 -16
  306. package/src/daemon/date-context.ts +47 -45
  307. package/src/daemon/dictation-profile-store.ts +2 -2
  308. package/src/daemon/first-greeting.ts +6 -1
  309. package/src/daemon/handlers/conversations.ts +19 -0
  310. package/src/daemon/handlers/shared.ts +14 -21
  311. package/src/daemon/lifecycle.ts +18 -15
  312. package/src/daemon/message-types/conversations.ts +2 -0
  313. package/src/daemon/message-types/guardian-actions.ts +3 -17
  314. package/src/daemon/message-types/integrations.ts +11 -1
  315. package/src/daemon/message-types/messages.ts +1 -0
  316. package/src/daemon/pairing-store.ts +2 -79
  317. package/src/daemon/server.ts +154 -8
  318. package/src/daemon/watch-handler.ts +65 -21
  319. package/src/email/guardrails.ts +3 -3
  320. package/src/heartbeat/heartbeat-service.ts +14 -7
  321. package/src/hooks/cli.ts +2 -2
  322. package/src/hooks/config.ts +2 -2
  323. package/src/hooks/discovery.ts +2 -2
  324. package/src/hooks/manager.ts +2 -2
  325. package/src/hooks/runner.ts +5 -2
  326. package/src/hooks/templates.ts +2 -2
  327. package/src/index.ts +0 -12
  328. package/src/memory/admin.ts +181 -2
  329. package/src/memory/app-git-service.ts +61 -4
  330. package/src/memory/attachments-store.ts +2 -0
  331. package/src/memory/canonical-guardian-store.ts +16 -0
  332. package/src/memory/conversation-queries.ts +6 -6
  333. package/src/memory/db-init.ts +8 -0
  334. package/src/memory/embedding-local.ts +5 -2
  335. package/src/memory/indexer.ts +44 -26
  336. package/src/memory/items-extractor.ts +34 -82
  337. package/src/memory/job-handlers/batch-extraction.ts +741 -0
  338. package/src/memory/job-handlers/journal-carry-forward.test.ts +383 -0
  339. package/src/memory/job-handlers/journal-carry-forward.ts +255 -0
  340. package/src/memory/jobs-store.ts +28 -0
  341. package/src/memory/jobs-worker.ts +56 -9
  342. package/src/memory/journal-memory.ts +8 -2
  343. package/src/memory/lifecycle-events-store.ts +4 -2
  344. package/src/memory/llm-request-log-store.ts +40 -2
  345. package/src/memory/llm-usage-store.ts +4 -3
  346. package/src/memory/migrations/199-guardian-request-enrichment-columns.ts +71 -0
  347. package/src/memory/migrations/200-usage-llm-call-count.ts +20 -0
  348. package/src/memory/migrations/index.ts +2 -0
  349. package/src/memory/query-expansion.ts +83 -0
  350. package/src/memory/retriever.test.ts +119 -0
  351. package/src/memory/retriever.ts +513 -105
  352. package/src/memory/schema/guardian.ts +4 -0
  353. package/src/memory/schema/infrastructure.ts +1 -0
  354. package/src/memory/search/formatting.test.ts +140 -0
  355. package/src/memory/search/formatting.ts +143 -198
  356. package/src/memory/search/mmr.ts +136 -0
  357. package/src/memory/search/staleness.ts +0 -15
  358. package/src/memory/search/tier-classifier.ts +10 -21
  359. package/src/memory/search/types.ts +17 -0
  360. package/src/messaging/providers/slack/adapter.ts +51 -5
  361. package/src/notifications/broadcaster.ts +13 -0
  362. package/src/notifications/copy-composer.ts +8 -0
  363. package/src/oauth/connect-orchestrator.ts +1 -1
  364. package/src/oauth/connection-resolver.ts +2 -2
  365. package/src/oauth/provider-serializer.ts +116 -0
  366. package/src/permissions/trust-store.ts +24 -7
  367. package/src/prompts/__tests__/build-cli-reference-section.test.ts +5 -0
  368. package/src/prompts/journal-context.ts +54 -36
  369. package/src/prompts/persona-resolver.ts +1 -1
  370. package/src/prompts/system-prompt.ts +38 -28
  371. package/src/prompts/templates/BOOTSTRAP.md +14 -1
  372. package/src/prompts/templates/HEARTBEAT.md +10 -0
  373. package/src/prompts/templates/NOW.md +19 -25
  374. package/src/prompts/templates/SOUL.md +13 -1
  375. package/src/prompts/templates/UPDATES.md +12 -0
  376. package/src/prompts/update-bulletin.ts +1 -1
  377. package/src/providers/anthropic/client.ts +89 -18
  378. package/src/providers/model-catalog.ts +22 -2
  379. package/src/providers/model-intents.ts +2 -2
  380. package/src/providers/openai/client.ts +40 -1
  381. package/src/providers/retry.ts +23 -4
  382. package/src/providers/types.ts +2 -0
  383. package/src/runtime/assistant-scope.ts +1 -1
  384. package/src/runtime/auth/__tests__/credential-service.test.ts +1 -0
  385. package/src/runtime/auth/route-policy.ts +1 -0
  386. package/src/runtime/auth/token-service.ts +51 -29
  387. package/src/runtime/confirmation-request-guardian-bridge.ts +3 -1
  388. package/src/runtime/guardian-decision-types.ts +16 -10
  389. package/src/runtime/http-server.ts +10 -29
  390. package/src/runtime/http-types.ts +1 -0
  391. package/src/runtime/migrations/rebind-secrets-screen.ts +2 -2
  392. package/src/runtime/migrations/vbundle-builder.ts +7 -4
  393. package/src/runtime/migrations/vbundle-import-analyzer.ts +0 -4
  394. package/src/runtime/migrations/vbundle-importer.ts +1 -1
  395. package/src/runtime/routes/conversation-query-routes.ts +40 -8
  396. package/src/runtime/routes/conversation-routes.ts +125 -3
  397. package/src/runtime/routes/guardian-action-routes.ts +9 -3
  398. package/src/runtime/routes/identity-routes.ts +25 -4
  399. package/src/runtime/routes/llm-context-normalization.ts +1 -0
  400. package/src/runtime/routes/log-export-routes.ts +34 -12
  401. package/src/runtime/routes/migration-routes.ts +6 -10
  402. package/src/runtime/routes/oauth-apps.ts +2 -9
  403. package/src/runtime/routes/oauth-providers.ts +60 -0
  404. package/src/runtime/routes/pairing-routes.ts +0 -8
  405. package/src/runtime/routes/secret-routes.ts +9 -2
  406. package/src/runtime/routes/settings-routes.ts +0 -1
  407. package/src/runtime/routes/telemetry-routes.ts +16 -4
  408. package/src/security/encrypted-store.ts +2 -2
  409. package/src/security/secret-allowlist.ts +3 -3
  410. package/src/signals/emit-event.ts +42 -0
  411. package/src/signals/user-message.ts +37 -0
  412. package/src/telemetry/usage-telemetry-reporter.test.ts +83 -19
  413. package/src/telemetry/usage-telemetry-reporter.ts +23 -17
  414. package/src/tools/browser/browser-manager.ts +2 -2
  415. package/src/tools/browser/runtime-check.ts +2 -2
  416. package/src/tools/credentials/vault.ts +2 -249
  417. package/src/tools/memory/definitions.ts +1 -1
  418. package/src/tools/memory/handlers.test.ts +50 -8
  419. package/src/tools/memory/handlers.ts +3 -1
  420. package/src/tools/side-effects.ts +1 -6
  421. package/src/tools/terminal/safe-env.ts +3 -2
  422. package/src/tools/terminal/shell.ts +11 -14
  423. package/src/tools/tool-approval-handler.ts +20 -1
  424. package/src/tools/tool-input-summary.ts +66 -0
  425. package/src/tools/types.ts +4 -0
  426. package/src/usage/types.ts +4 -0
  427. package/src/util/device-id.ts +10 -10
  428. package/src/util/platform.ts +72 -124
  429. package/src/util/pricing.ts +19 -6
  430. package/src/util/strip-comment-lines.ts +28 -0
  431. package/src/workspace/git-service.ts +8 -18
  432. package/src/workspace/migrations/003-seed-device-id.ts +6 -4
  433. package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +7 -1
  434. package/src/workspace/migrations/017-seed-persona-dirs.ts +2 -4
  435. package/src/workspace/migrations/021-move-signals-to-workspace.ts +84 -0
  436. package/src/workspace/migrations/022-move-hooks-to-workspace.ts +94 -0
  437. package/src/workspace/migrations/023-move-config-files-to-workspace.ts +86 -0
  438. package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +126 -0
  439. package/src/workspace/migrations/migrate-to-workspace-volume.ts +3 -6
  440. package/src/workspace/migrations/registry.ts +8 -0
  441. package/src/signals/confirm.ts +0 -82
  442. package/src/signals/trust-rule.ts +0 -174
@@ -37,25 +37,37 @@ mock.module("@anthropic-ai/sdk", () => ({
37
37
  constructor(args: Record<string, unknown>) {
38
38
  lastConstructorArgs = { ...args };
39
39
  }
40
+ #streamImpl = (
41
+ params: Record<string, unknown>,
42
+ options?: Record<string, unknown>,
43
+ ) => {
44
+ lastStreamParams = JSON.parse(JSON.stringify(params));
45
+ _lastStreamOptions = options ?? null;
46
+ const handlers: Record<string, ((...args: unknown[]) => void)[]> = {};
47
+ return {
48
+ on(event: string, cb: (...args: unknown[]) => void) {
49
+ (handlers[event] ??= []).push(cb);
50
+ return this;
51
+ },
52
+ async finalMessage() {
53
+ // Fire text events
54
+ for (const cb of handlers["text"] ?? []) cb("Hello");
55
+ return fakeResponse;
56
+ },
57
+ };
58
+ };
40
59
  messages = {
41
60
  stream: (
42
61
  params: Record<string, unknown>,
43
62
  options?: Record<string, unknown>,
44
- ) => {
45
- lastStreamParams = JSON.parse(JSON.stringify(params));
46
- _lastStreamOptions = options ?? null;
47
- const handlers: Record<string, ((...args: unknown[]) => void)[]> = {};
48
- return {
49
- on(event: string, cb: (...args: unknown[]) => void) {
50
- (handlers[event] ??= []).push(cb);
51
- return this;
52
- },
53
- async finalMessage() {
54
- // Fire text events
55
- for (const cb of handlers["text"] ?? []) cb("Hello");
56
- return fakeResponse;
57
- },
58
- };
63
+ ) => this.#streamImpl(params, options),
64
+ };
65
+ beta = {
66
+ messages: {
67
+ stream: (
68
+ params: Record<string, unknown>,
69
+ options?: Record<string, unknown>,
70
+ ) => this.#streamImpl(params, options),
59
71
  },
60
72
  };
61
73
  },
@@ -138,16 +150,16 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
138
150
  // -----------------------------------------------------------------------
139
151
  // System prompt cache control
140
152
  // -----------------------------------------------------------------------
141
- test("system prompt has cache_control ephemeral", async () => {
153
+ test("system prompt has cache_control ephemeral with 1h TTL", async () => {
142
154
  await provider.sendMessage([userMsg("Hi")], undefined, "You are helpful.");
143
155
 
144
156
  const system = lastStreamParams!.system as Array<{
145
157
  type: string;
146
158
  text: string;
147
- cache_control?: { type: string };
159
+ cache_control?: { type: string; ttl?: string };
148
160
  }>;
149
161
  expect(system).toHaveLength(1);
150
- expect(system[0].cache_control).toEqual({ type: "ephemeral" });
162
+ expect(system[0].cache_control).toEqual({ type: "ephemeral", ttl: "1h" });
151
163
  });
152
164
 
153
165
  test("no system param when system prompt is omitted", async () => {
@@ -166,13 +178,13 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
166
178
  const system = lastStreamParams!.system as Array<{
167
179
  type: string;
168
180
  text: string;
169
- cache_control?: { type: string };
181
+ cache_control?: { type: string; ttl?: string };
170
182
  }>;
171
183
  expect(system).toHaveLength(2);
172
184
  expect(system[0].text).toBe(staticBlock);
173
- expect(system[0].cache_control).toEqual({ type: "ephemeral" });
185
+ expect(system[0].cache_control).toEqual({ type: "ephemeral", ttl: "1h" });
174
186
  expect(system[1].text).toBe(dynamicBlock);
175
- expect(system[1].cache_control).toEqual({ type: "ephemeral" });
187
+ expect(system[1].cache_control).toEqual({ type: "ephemeral", ttl: "1h" });
176
188
  });
177
189
 
178
190
  // -----------------------------------------------------------------------
@@ -183,7 +195,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
183
195
 
184
196
  const tools = lastStreamParams!.tools as Array<{
185
197
  name: string;
186
- cache_control?: { type: string };
198
+ cache_control?: { type: string; ttl?: string };
187
199
  }>;
188
200
  expect(tools).toHaveLength(3);
189
201
 
@@ -192,7 +204,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
192
204
  expect(tools[1].cache_control).toBeUndefined();
193
205
 
194
206
  // Last tool: cache_control ephemeral
195
- expect(tools[2].cache_control).toEqual({ type: "ephemeral" });
207
+ expect(tools[2].cache_control).toEqual({ type: "ephemeral", ttl: "1h" });
196
208
  });
197
209
 
198
210
  test("single tool gets cache_control", async () => {
@@ -200,10 +212,10 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
200
212
 
201
213
  const tools = lastStreamParams!.tools as Array<{
202
214
  name: string;
203
- cache_control?: { type: string };
215
+ cache_control?: { type: string; ttl?: string };
204
216
  }>;
205
217
  expect(tools).toHaveLength(1);
206
- expect(tools[0].cache_control).toEqual({ type: "ephemeral" });
218
+ expect(tools[0].cache_control).toEqual({ type: "ephemeral", ttl: "1h" });
207
219
  });
208
220
 
209
221
  test("no tools param when tools are omitted", async () => {
@@ -223,7 +235,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
223
235
  content: Array<{
224
236
  type: string;
225
237
  text: string;
226
- cache_control?: { type: string };
238
+ cache_control?: { type: string; ttl?: string };
227
239
  }>;
228
240
  }>;
229
241
  const lastUser = messages[messages.length - 1];
@@ -248,7 +260,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
248
260
  content: Array<{
249
261
  type: string;
250
262
  text: string;
251
- cache_control?: { type: string };
263
+ cache_control?: { type: string; ttl?: string };
252
264
  }>;
253
265
  }>;
254
266
 
@@ -264,7 +276,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
264
276
  // Second user turn (second-to-last): cache_control ephemeral
265
277
  const secondUserLastBlock =
266
278
  userMessages[1].content[userMessages[1].content.length - 1];
267
- expect(secondUserLastBlock.cache_control).toEqual({ type: "ephemeral" });
279
+ expect(secondUserLastBlock.cache_control).toEqual({ type: "ephemeral", ttl: "1h" });
268
280
 
269
281
  // Third user turn (last): no cache_control
270
282
  const thirdUserLastBlock =
@@ -280,7 +292,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
280
292
  content: Array<{
281
293
  type: string;
282
294
  text: string;
283
- cache_control?: { type: string };
295
+ cache_control?: { type: string; ttl?: string };
284
296
  }>;
285
297
  }>;
286
298
  const userMessages = sent.filter((m) => m.role === "user");
@@ -303,12 +315,12 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
303
315
 
304
316
  const sent = lastStreamParams!.messages as Array<{
305
317
  role: string;
306
- content: Array<{ type: string; cache_control?: { type: string } }>;
318
+ content: Array<{ type: string; cache_control?: { type: string; ttl?: string } }>;
307
319
  }>;
308
320
  const userMsgs = sent.filter((m) => m.role === "user");
309
321
  // First user msg (second-to-last) should get cache
310
322
  const firstLast = userMsgs[0].content[userMsgs[0].content.length - 1];
311
- expect(firstLast.cache_control).toEqual({ type: "ephemeral" });
323
+ expect(firstLast.cache_control).toEqual({ type: "ephemeral", ttl: "1h" });
312
324
  // tool_result msg (last) should NOT get cache
313
325
  const secondLast = userMsgs[1].content[userMsgs[1].content.length - 1];
314
326
  expect(secondLast.cache_control).toBeUndefined();
@@ -330,7 +342,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
330
342
  content: Array<{
331
343
  type: string;
332
344
  text: string;
333
- cache_control?: { type: string };
345
+ cache_control?: { type: string; ttl?: string };
334
346
  }>;
335
347
  }>;
336
348
  const assistantMsgs = sent.filter((m) => m.role === "assistant");
@@ -361,7 +373,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
361
373
  content: Array<{
362
374
  type: string;
363
375
  text: string;
364
- cache_control?: { type: string };
376
+ cache_control?: { type: string; ttl?: string };
365
377
  }>;
366
378
  }>;
367
379
  const user = sent[0];
@@ -402,7 +414,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
402
414
  content: Array<{
403
415
  type: string;
404
416
  text: string;
405
- cache_control?: { type: string };
417
+ cache_control?: { type: string; ttl?: string };
406
418
  }>;
407
419
  }>;
408
420
  const user = sent[0];
@@ -436,7 +448,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
436
448
  content: Array<{
437
449
  type: string;
438
450
  text: string;
439
- cache_control?: { type: string };
451
+ cache_control?: { type: string; ttl?: string };
440
452
  }>;
441
453
  }>;
442
454
  const user = sent[0];
@@ -1309,7 +1321,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
1309
1321
  content: Array<{
1310
1322
  type: string;
1311
1323
  text: string;
1312
- cache_control?: { type: string };
1324
+ cache_control?: { type: string; ttl?: string };
1313
1325
  }>;
1314
1326
  }>;
1315
1327
  const userMsgs = sent.filter((m) => m.role === "user");
@@ -1321,7 +1333,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
1321
1333
 
1322
1334
  // Turn 2 (second-to-last): cache on last block only
1323
1335
  expect(userMsgs[1].content[0].cache_control).toBeUndefined();
1324
- expect(userMsgs[1].content[1].cache_control).toEqual({ type: "ephemeral" });
1336
+ expect(userMsgs[1].content[1].cache_control).toEqual({ type: "ephemeral", ttl: "1h" });
1325
1337
 
1326
1338
  // Turn 3 (last): no cache
1327
1339
  expect(userMsgs[2].content[0].cache_control).toBeUndefined();
@@ -1548,16 +1560,17 @@ describe("AnthropicProvider — Managed Proxy Fallback", () => {
1548
1560
 
1549
1561
  // System prompt cache control
1550
1562
  const system = lastStreamParams!.system as Array<{
1551
- cache_control?: { type: string };
1563
+ cache_control?: { type: string; ttl?: string };
1552
1564
  }>;
1553
- expect(system[0].cache_control).toEqual({ type: "ephemeral" });
1565
+ expect(system[0].cache_control).toEqual({ type: "ephemeral", ttl: "1h" });
1554
1566
 
1555
1567
  // Last tool cache control
1556
1568
  const tools = lastStreamParams!.tools as Array<{
1557
- cache_control?: { type: string };
1569
+ cache_control?: { type: string; ttl?: string };
1558
1570
  }>;
1559
1571
  expect(tools[tools.length - 1].cache_control).toEqual({
1560
1572
  type: "ephemeral",
1573
+ ttl: "1h",
1561
1574
  });
1562
1575
  });
1563
1576
  });
@@ -1,28 +1,20 @@
1
- import { existsSync, mkdirSync, readFileSync, rmSync } from "node:fs";
1
+ import { existsSync, readFileSync, rmSync } from "node:fs";
2
2
  import { tmpdir } from "node:os";
3
3
  import { join } from "node:path";
4
- import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
4
+ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
5
5
 
6
6
  import { _resetGitServiceRegistry } from "../workspace/git-service.js";
7
7
 
8
- // Mock getDataDir to use a temp directory
9
8
  let testDataDir: string;
10
9
 
11
- mock.module("../util/platform.js", () => ({
12
- getDataDir: () => testDataDir,
13
- getProjectDir: () => testDataDir,
14
- }));
15
-
16
- // Re-import after mocking so modules use our temp dir
17
- const { createApp, updateApp, getAppDirPath } =
18
- await import("../memory/app-store.js");
19
- const {
20
- getAppHistory,
10
+ import {
11
+ commitAppTurnChanges,
21
12
  getAppDiff,
22
13
  getAppFileAtVersion,
14
+ getAppHistory,
23
15
  restoreAppVersion,
24
- commitAppTurnChanges,
25
- } = await import("../memory/app-git-service.js");
16
+ } from "../memory/app-git-service.js";
17
+ import { createApp, getAppDirPath, updateApp } from "../memory/app-store.js";
26
18
 
27
19
  describe("App Git History", () => {
28
20
  beforeEach(() => {
@@ -32,7 +24,7 @@ describe("App Git History", () => {
32
24
  .toString(36)
33
25
  .slice(2)}`,
34
26
  );
35
- mkdirSync(join(testDataDir, "apps"), { recursive: true });
27
+ process.env.VELLUM_WORKSPACE_DIR = testDataDir;
36
28
  _resetGitServiceRegistry();
37
29
  });
38
30
 
@@ -55,7 +47,7 @@ describe("App Git History", () => {
55
47
 
56
48
  const history = await getAppHistory(app.id);
57
49
  expect(history.length).toBeGreaterThanOrEqual(2);
58
- expect(history[0].message).toContain("Turn 2");
50
+ expect(history[0].message).toContain("update ");
59
51
  expect(history[0].commitHash).toMatch(/^[0-9a-f]+$/);
60
52
  expect(history[0].timestamp).toBeGreaterThan(0);
61
53
  });
@@ -1,29 +1,21 @@
1
1
  import { execFileSync } from "node:child_process";
2
- import { existsSync, mkdirSync, readFileSync, rmSync } from "node:fs";
2
+ import { existsSync, readFileSync, rmSync } from "node:fs";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
- import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
5
+ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
6
6
 
7
7
  import { commitAppTurnChanges } from "../memory/app-git-service.js";
8
- import { _resetGitServiceRegistry } from "../workspace/git-service.js";
9
-
10
- // Mock getDataDir to use a temp directory
11
- let testDataDir: string;
12
-
13
- mock.module("../util/platform.js", () => ({
14
- getDataDir: () => testDataDir,
15
- getProjectDir: () => testDataDir,
16
- }));
17
-
18
- // Re-import app-store after mocking so it uses our temp dir
19
- const {
8
+ import {
20
9
  createApp,
21
- updateApp,
22
10
  deleteApp,
23
- writeAppFile,
24
11
  editAppFile,
25
12
  getAppsDir,
26
- } = await import("../memory/app-store.js");
13
+ updateApp,
14
+ writeAppFile,
15
+ } from "../memory/app-store.js";
16
+ import { _resetGitServiceRegistry } from "../workspace/git-service.js";
17
+
18
+ let testDataDir: string;
27
19
 
28
20
  describe("App Git Service", () => {
29
21
  beforeEach(() => {
@@ -31,7 +23,7 @@ describe("App Git Service", () => {
31
23
  tmpdir(),
32
24
  `vellum-app-git-test-${Date.now()}-${Math.random().toString(36).slice(2)}`,
33
25
  );
34
- mkdirSync(join(testDataDir, "apps"), { recursive: true });
26
+ process.env.VELLUM_WORKSPACE_DIR = testDataDir;
35
27
  _resetGitServiceRegistry();
36
28
  });
37
29
 
@@ -100,7 +92,9 @@ describe("App Git Service", () => {
100
92
  expect(commits.length).toBeLessThanOrEqual(2);
101
93
  // The turn commit message should appear (or files are in the initial commit)
102
94
  expect(
103
- commits.some((c) => c.includes("Turn 1") || c.includes("Initial commit")),
95
+ commits.some(
96
+ (c) => c.includes("update ") || c.includes("Initial commit"),
97
+ ),
104
98
  ).toBe(true);
105
99
  });
106
100
 
@@ -141,6 +135,6 @@ describe("App Git Service", () => {
141
135
 
142
136
  const appsDir = getAppsDir();
143
137
  const commits = getGitLog(appsDir);
144
- expect(commits[0]).toContain("Turn 2: app changes");
138
+ expect(commits[0]).toContain("update ");
145
139
  });
146
140
  });
@@ -7,32 +7,22 @@ import {
7
7
  } from "node:fs";
8
8
  import { tmpdir } from "node:os";
9
9
  import { join } from "node:path";
10
- import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
11
-
12
- // ---------------------------------------------------------------------------
13
- // Mock getDataDir to use a temp directory
14
- // ---------------------------------------------------------------------------
10
+ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
15
11
 
16
12
  let testDataDir: string;
17
13
 
18
- mock.module("../util/platform.js", () => ({
19
- getDataDir: () => testDataDir,
20
- getProjectDir: () => testDataDir,
21
- }));
22
-
23
- // Re-import app-store after mocking so it uses our temp dir
24
- const {
25
- slugify,
14
+ import {
15
+ createApp,
16
+ deleteApp,
26
17
  generateAppDirName,
27
- validateDirName,
28
- resolveAppDir,
18
+ getApp,
29
19
  getAppDirPath,
30
20
  getAppsDir,
31
- createApp,
32
- getApp,
21
+ resolveAppDir,
22
+ slugify,
33
23
  updateApp,
34
- deleteApp,
35
- } = await import("../memory/app-store.js");
24
+ validateDirName,
25
+ } from "../memory/app-store.js";
36
26
 
37
27
  // ---------------------------------------------------------------------------
38
28
  // Helpers
@@ -59,7 +49,7 @@ function makeAppParams(name: string) {
59
49
 
60
50
  beforeEach(() => {
61
51
  testDataDir = freshTempDir();
62
- mkdirSync(join(testDataDir, "apps"), { recursive: true });
52
+ process.env.VELLUM_WORKSPACE_DIR = testDataDir;
63
53
  });
64
54
 
65
55
  afterEach(() => {
@@ -5,10 +5,7 @@
5
5
  * allow_conversation, always_allow, always_deny), other pending confirmations in
6
6
  * the same conversation that match are auto-resolved.
7
7
  */
8
- import { mkdtempSync, rmSync } from "node:fs";
9
- import { tmpdir } from "node:os";
10
- import { join } from "node:path";
11
- import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
8
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
12
9
 
13
10
  import { Minimatch } from "minimatch";
14
11
 
@@ -22,8 +19,6 @@ import type { ConfirmationStateChanged } from "../daemon/message-types/messages.
22
19
  import type { Message, ProviderResponse } from "../providers/types.js";
23
20
  import type { ConfirmationDetails } from "../runtime/pending-interactions.js";
24
21
 
25
- const testDir = mkdtempSync(join(tmpdir(), "approval-cascade-test-"));
26
-
27
22
  // ---------------------------------------------------------------------------
28
23
  // Mocks — must precede Conversation import
29
24
  // ---------------------------------------------------------------------------
@@ -49,10 +44,6 @@ mock.module("../util/logger.js", () => ({
49
44
  getLogger: () => makeLoggerStub(),
50
45
  }));
51
46
 
52
- mock.module("../util/platform.js", () => ({
53
- getDataDir: () => testDir,
54
- }));
55
-
56
47
  mock.module("../memory/guardian-action-store.js", () => ({
57
48
  getGuardianActionRequest: () => null,
58
49
  resolveGuardianActionRequest: () => {},
@@ -265,7 +256,7 @@ function makeConversation(
265
256
  "system prompt",
266
257
  4096,
267
258
  sendToClient ?? (() => {}),
268
- testDir,
259
+ process.env.VELLUM_WORKSPACE_DIR!,
269
260
  );
270
261
  }
271
262
 
@@ -325,14 +316,6 @@ function makeConfirmationDetails(patterns: string[]): ConfirmationDetails {
325
316
  };
326
317
  }
327
318
 
328
- afterAll(() => {
329
- try {
330
- rmSync(testDir, { recursive: true, force: true });
331
- } catch {
332
- /* best effort */
333
- }
334
- });
335
-
336
319
  beforeEach(() => {
337
320
  pendingInteractions.clear();
338
321
  });
@@ -1,20 +1,4 @@
1
- import { mkdtempSync, rmSync } from "node:fs";
2
- import { tmpdir } from "node:os";
3
- import { join } from "node:path";
4
- import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
5
-
6
- const testDir = mkdtempSync(join(tmpdir(), "approval-primitive-test-"));
7
-
8
- mock.module("../util/platform.js", () => ({
9
- getDataDir: () => testDir,
10
- isMacOS: () => process.platform === "darwin",
11
- isLinux: () => process.platform === "linux",
12
- isWindows: () => process.platform === "win32",
13
- getPidPath: () => join(testDir, "test.pid"),
14
- getDbPath: () => join(testDir, "test.db"),
15
- getLogPath: () => join(testDir, "test.log"),
16
- ensureDataDir: () => {},
17
- }));
1
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
18
2
 
19
3
  mock.module("../util/logger.js", () => ({
20
4
  getLogger: () =>
@@ -29,7 +13,7 @@ import {
29
13
  mintGrantFromDecision,
30
14
  type MintGrantParams,
31
15
  } from "../approvals/approval-primitive.js";
32
- import { getDb, initializeDb, resetDb } from "../memory/db.js";
16
+ import { getDb, initializeDb } from "../memory/db.js";
33
17
  import { scopedApprovalGrants } from "../memory/schema.js";
34
18
  import { computeToolApprovalDigest } from "../security/tool-approval-digest.js";
35
19
 
@@ -40,15 +24,6 @@ function clearTables(): void {
40
24
  db.delete(scopedApprovalGrants).run();
41
25
  }
42
26
 
43
- afterAll(() => {
44
- resetDb();
45
- try {
46
- rmSync(testDir, { recursive: true });
47
- } catch {
48
- /* best effort */
49
- }
50
- });
51
-
52
27
  // ---------------------------------------------------------------------------
53
28
  // Helper to build mint params with sensible defaults
54
29
  // ---------------------------------------------------------------------------
@@ -4,30 +4,11 @@
4
4
  * Tests POST /v1/confirm, POST /v1/secret, and POST /v1/trust-rules
5
5
  * through RuntimeHttpServer with pending-interactions tracking.
6
6
  */
7
- import { mkdtempSync, realpathSync, rmSync } from "node:fs";
8
- import { tmpdir } from "node:os";
9
- import { join } from "node:path";
10
- import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
7
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
11
8
 
12
9
  import type { Conversation } from "../daemon/conversation.js";
13
10
  import type { ServerMessage } from "../daemon/message-protocol.js";
14
11
 
15
- const testDir = realpathSync(
16
- mkdtempSync(join(tmpdir(), "approval-routes-http-test-")),
17
- );
18
-
19
- mock.module("../util/platform.js", () => ({
20
- getRootDir: () => testDir,
21
- getDataDir: () => testDir,
22
- isMacOS: () => process.platform === "darwin",
23
- isLinux: () => process.platform === "linux",
24
- isWindows: () => process.platform === "win32",
25
- getPidPath: () => join(testDir, "test.pid"),
26
- getDbPath: () => join(testDir, "test.db"),
27
- getLogPath: () => join(testDir, "test.log"),
28
- ensureDataDir: () => {},
29
- }));
30
-
31
12
  mock.module("../util/logger.js", () => ({
32
13
  getLogger: () =>
33
14
  new Proxy({} as Record<string, unknown>, {
@@ -86,7 +67,7 @@ mock.module("../permissions/trust-store.js", () => ({
86
67
  getRules: () => [],
87
68
  }));
88
69
 
89
- import { getDb, initializeDb, resetDb } from "../memory/db.js";
70
+ import { getDb, initializeDb } from "../memory/db.js";
90
71
  import { AssistantEventHub } from "../runtime/assistant-event-hub.js";
91
72
  import { RuntimeHttpServer } from "../runtime/http-server.js";
92
73
  import * as pendingInteractions from "../runtime/pending-interactions.js";
@@ -248,15 +229,6 @@ describe("standalone approval endpoints — HTTP layer", () => {
248
229
  eventHub = new AssistantEventHub();
249
230
  });
250
231
 
251
- afterAll(() => {
252
- resetDb();
253
- try {
254
- rmSync(testDir, { recursive: true, force: true });
255
- } catch {
256
- /* best effort */
257
- }
258
- });
259
-
260
232
  async function startServer(
261
233
  conversationFactory: () => Conversation,
262
234
  ): Promise<void> {
@@ -8,24 +8,7 @@
8
8
  * - Subscription cleanup on request abort.
9
9
  * - Subscription cleanup on reader cancel.
10
10
  */
11
- import { mkdtempSync, realpathSync, rmSync } from "node:fs";
12
- import { tmpdir } from "node:os";
13
- import { join } from "node:path";
14
- import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
15
-
16
- const testDir = realpathSync(mkdtempSync(join(tmpdir(), "sse-hardening-")));
17
-
18
- mock.module("../util/platform.js", () => ({
19
- getRootDir: () => testDir,
20
- getDataDir: () => testDir,
21
- isMacOS: () => process.platform === "darwin",
22
- isLinux: () => process.platform === "linux",
23
- isWindows: () => process.platform === "win32",
24
- getPidPath: () => join(testDir, "test.pid"),
25
- getDbPath: () => join(testDir, "test.db"),
26
- getLogPath: () => join(testDir, "test.log"),
27
- ensureDataDir: () => {},
28
- }));
11
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
29
12
 
30
13
  mock.module("../util/logger.js", () => ({
31
14
  getLogger: () =>
@@ -46,21 +29,12 @@ mock.module("../config/loader.js", () => ({
46
29
  }),
47
30
  }));
48
31
 
49
- import { getDb, initializeDb, resetDb } from "../memory/db.js";
32
+ import { getDb, initializeDb } from "../memory/db.js";
50
33
  import { AssistantEventHub } from "../runtime/assistant-event-hub.js";
51
34
  import { handleSubscribeAssistantEvents } from "../runtime/routes/events-routes.js";
52
35
 
53
36
  initializeDb();
54
37
 
55
- afterAll(() => {
56
- resetDb();
57
- try {
58
- rmSync(testDir, { recursive: true, force: true });
59
- } catch {
60
- /* best effort */
61
- }
62
- });
63
-
64
38
  // ── Helpers ───────────────────────────────────────────────────────────────────
65
39
 
66
40
  function clearTables() {