@vellumai/assistant 0.7.1 → 0.7.2

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 (535) hide show
  1. package/ARCHITECTURE.md +32 -49
  2. package/Dockerfile +1 -0
  3. package/README.md +1 -2
  4. package/__tests__/permissions/gateway-threshold-reader.test.ts +9 -3
  5. package/bun.lock +26 -26
  6. package/docs/architecture/security.md +20 -0
  7. package/docs/plugins.md +7 -9
  8. package/knip.json +1 -0
  9. package/node_modules/@vellumai/gateway-client/src/index.ts +1 -0
  10. package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +39 -1
  11. package/node_modules/@vellumai/gateway-client/src/types.ts +11 -0
  12. package/node_modules/@vellumai/service-contracts/package.json +2 -0
  13. package/node_modules/@vellumai/service-contracts/src/__tests__/contracts.test.ts +4 -0
  14. package/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +107 -0
  15. package/node_modules/@vellumai/service-contracts/src/index.ts +5 -1
  16. package/node_modules/@vellumai/service-contracts/src/ingress.ts +24 -0
  17. package/node_modules/@vellumai/service-contracts/src/twilio-ingress.ts +84 -0
  18. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +9 -0
  19. package/node_modules/@vellumai/twilio-client/bun.lock +24 -0
  20. package/node_modules/@vellumai/twilio-client/package.json +18 -0
  21. package/node_modules/@vellumai/twilio-client/src/__tests__/twilio-client.test.ts +128 -0
  22. package/node_modules/@vellumai/twilio-client/src/index.ts +179 -0
  23. package/node_modules/@vellumai/twilio-client/tsconfig.json +20 -0
  24. package/openapi.yaml +565 -12
  25. package/package.json +6 -3
  26. package/src/__tests__/app-builder-tool-scripts.test.ts +3 -3
  27. package/src/__tests__/app-bundler.test.ts +170 -1
  28. package/src/__tests__/app-control-flow.test.ts +374 -0
  29. package/src/__tests__/app-control-no-global-cgevent.test.ts +98 -0
  30. package/src/__tests__/app-control-tool-schemas.test.ts +621 -0
  31. package/src/__tests__/app-executors.test.ts +30 -43
  32. package/src/__tests__/approval-routes-http.test.ts +23 -6
  33. package/src/__tests__/assistant-event-hub-machine-name.test.ts +146 -0
  34. package/src/__tests__/assistant-event-hub-targeted.test.ts +257 -0
  35. package/src/__tests__/assistant-event-hub.test.ts +109 -2
  36. package/src/__tests__/assistant-event.test.ts +10 -0
  37. package/src/__tests__/assistant-events-sse-hardening.test.ts +7 -2
  38. package/src/__tests__/assistant-feature-flags-integration.test.ts +11 -7
  39. package/src/__tests__/background-shell-host-bash.test.ts +14 -15
  40. package/src/__tests__/bootstrap-turn-cleanup.test.ts +44 -0
  41. package/src/__tests__/btw-routes.test.ts +13 -4
  42. package/src/__tests__/call-controller.test.ts +49 -1
  43. package/src/__tests__/call-domain.test.ts +0 -2
  44. package/src/__tests__/call-routes-http.test.ts +0 -2
  45. package/src/__tests__/channel-readiness-service.test.ts +59 -1
  46. package/src/__tests__/checker.test.ts +3 -4
  47. package/src/__tests__/config-loader-backfill.test.ts +90 -155
  48. package/src/__tests__/config-loader-platform-defaults.test.ts +196 -0
  49. package/src/__tests__/config-schema-cmd.test.ts +0 -1
  50. package/src/__tests__/config-set-platform-guard.test.ts +48 -4
  51. package/src/__tests__/config-watcher-cleanup-throttle.test.ts +2 -2
  52. package/src/__tests__/config-watcher.test.ts +2 -2
  53. package/src/__tests__/conversation-app-control-instantiation.test.ts +392 -0
  54. package/src/__tests__/conversation-app-control-lifecycle.test.ts +237 -0
  55. package/src/__tests__/conversation-init.benchmark.test.ts +0 -2
  56. package/src/__tests__/conversation-lifecycle.test.ts +36 -0
  57. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +283 -0
  58. package/src/__tests__/conversation-routes-disk-view.test.ts +6 -0
  59. package/src/__tests__/conversation-routes-guardian-reply.test.ts +120 -72
  60. package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
  61. package/src/__tests__/conversation-slash-commands.test.ts +0 -4
  62. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +202 -0
  63. package/src/__tests__/conversation-surfaces-app-control.test.ts +317 -0
  64. package/src/__tests__/credential-execution-feature-gates.test.ts +5 -12
  65. package/src/__tests__/credential-execution-managed-contract.test.ts +3 -131
  66. package/src/__tests__/credentials-cli.test.ts +5 -12
  67. package/src/__tests__/cu-unified-flow.test.ts +185 -23
  68. package/src/__tests__/daemon-credential-client.test.ts +101 -19
  69. package/src/__tests__/db-schedule-syntax-migration.test.ts +2 -0
  70. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
  71. package/src/__tests__/gateway-only-enforcement.test.ts +0 -1
  72. package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -2
  73. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +0 -2
  74. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +0 -1
  75. package/src/__tests__/heartbeat-service.test.ts +718 -1
  76. package/src/__tests__/helpers/call-route-handler.ts +7 -1
  77. package/src/__tests__/host-app-control-proxy.test.ts +602 -0
  78. package/src/__tests__/host-app-control-routes.test.ts +263 -0
  79. package/src/__tests__/host-bash-proxy.test.ts +246 -47
  80. package/src/__tests__/host-bash-routes.test.ts +294 -0
  81. package/src/__tests__/host-browser-proxy.test.ts +24 -22
  82. package/src/__tests__/host-browser-routes.test.ts +39 -13
  83. package/src/__tests__/host-cu-proxy.test.ts +41 -52
  84. package/src/__tests__/host-cu-routes-targeted.test.ts +300 -0
  85. package/src/__tests__/host-file-edit-tool.test.ts +47 -1
  86. package/src/__tests__/host-file-proxy-targeted.test.ts +339 -0
  87. package/src/__tests__/host-file-proxy.test.ts +37 -43
  88. package/src/__tests__/host-file-read-tool.test.ts +17 -0
  89. package/src/__tests__/host-file-routes-targeted.test.ts +262 -0
  90. package/src/__tests__/host-file-write-tool.test.ts +42 -1
  91. package/src/__tests__/host-proxy-base.test.ts +312 -0
  92. package/src/__tests__/host-shell-tool.test.ts +22 -4
  93. package/src/__tests__/host-transfer-proxy-targeted.test.ts +583 -0
  94. package/src/__tests__/host-transfer-proxy.test.ts +121 -22
  95. package/src/__tests__/host-transfer-routes-targeted.test.ts +447 -0
  96. package/src/__tests__/http-user-message-parity.test.ts +1 -0
  97. package/src/__tests__/identity-intro-cache.test.ts +29 -0
  98. package/src/__tests__/identity-routes.test.ts +103 -1
  99. package/src/__tests__/init-feature-flag-overrides.test.ts +26 -3
  100. package/src/__tests__/inline-command-runner.test.ts +0 -1
  101. package/src/__tests__/inline-skill-load-permissions.test.ts +5 -11
  102. package/src/__tests__/integration-status.test.ts +85 -5
  103. package/src/__tests__/intent-routing.test.ts +0 -1
  104. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +95 -5
  105. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +17 -0
  106. package/src/__tests__/managed-skill-lifecycle.test.ts +0 -1
  107. package/src/__tests__/mcp-auth-routes.test.ts +197 -0
  108. package/src/__tests__/mcp-cli.test.ts +338 -2
  109. package/src/__tests__/memory-jobs-worker-lanes.test.ts +188 -0
  110. package/src/__tests__/migration-import-commit-http.test.ts +108 -2
  111. package/src/__tests__/mock-gateway-ipc.ts +1 -0
  112. package/src/__tests__/oauth-cli.test.ts +0 -2
  113. package/src/__tests__/oauth2-gateway-transport.test.ts +0 -1
  114. package/src/__tests__/persistence-secret-redaction.test.ts +299 -0
  115. package/src/__tests__/platform-bash-auto-approve.test.ts +5 -9
  116. package/src/__tests__/prechat-onboarding-contract.test.ts +3 -1
  117. package/src/__tests__/process-message-background-slack.test.ts +2 -0
  118. package/src/__tests__/provider-commit-message-generator.test.ts +0 -1
  119. package/src/__tests__/public-ingress-urls.test.ts +97 -0
  120. package/src/__tests__/require-fresh-approval.test.ts +0 -1
  121. package/src/__tests__/retry-backoff.test.ts +87 -0
  122. package/src/__tests__/runtime-events-sse.test.ts +10 -6
  123. package/src/__tests__/sanitize-config-for-transfer.test.ts +24 -2
  124. package/src/__tests__/schedule-retry.test.ts +715 -0
  125. package/src/__tests__/script-proxy-mitm-handler.test.ts +1 -1
  126. package/src/__tests__/secret-ingress-http.test.ts +1 -0
  127. package/src/__tests__/send-endpoint-busy.test.ts +3 -0
  128. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -1
  129. package/src/__tests__/skill-feature-flags.test.ts +43 -41
  130. package/src/__tests__/skill-load-feature-flag.test.ts +13 -14
  131. package/src/__tests__/skill-load-inline-command.test.ts +0 -51
  132. package/src/__tests__/skill-load-inline-includes.test.ts +0 -43
  133. package/src/__tests__/skill-projection.benchmark.test.ts +0 -1
  134. package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -1
  135. package/src/__tests__/slack-channel-config.test.ts +9 -14
  136. package/src/__tests__/system-prompt-ask-mode.test.ts +0 -1
  137. package/src/__tests__/system-prompt.test.ts +0 -1
  138. package/src/__tests__/telegram-config.test.ts +0 -1
  139. package/src/__tests__/test-preload.ts +8 -0
  140. package/src/__tests__/tool-approval-handler.test.ts +3 -4
  141. package/src/__tests__/tool-audit-listener.test.ts +48 -0
  142. package/src/__tests__/tool-execute-pipeline.test.ts +0 -1
  143. package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -1
  144. package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -1
  145. package/src/__tests__/tool-executor.test.ts +0 -1
  146. package/src/__tests__/twilio-config.test.ts +3 -16
  147. package/src/__tests__/twilio-routes.test.ts +3 -5
  148. package/src/__tests__/twilio-validation.test.ts +93 -0
  149. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +1 -4
  150. package/src/__tests__/verification-control-plane-policy.test.ts +2 -4
  151. package/src/__tests__/voice-ingress-preflight.test.ts +19 -0
  152. package/src/__tests__/workspace-migration-006-services-config.test.ts +3 -2
  153. package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +1 -5
  154. package/src/__tests__/workspace-migration-down-functions.test.ts +8 -8
  155. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +10 -6
  156. package/src/backup/__tests__/paths.test.ts +0 -22
  157. package/src/backup/__tests__/restore.test.ts +51 -151
  158. package/src/backup/paths.ts +2 -18
  159. package/src/backup/restore.ts +107 -231
  160. package/src/bundler/app-bundler.ts +51 -3
  161. package/src/calls/relay-server.ts +4 -44
  162. package/src/calls/twilio-config.ts +2 -17
  163. package/src/calls/twilio-rest.ts +33 -105
  164. package/src/calls/twilio-routes.ts +11 -12
  165. package/src/channels/types.ts +8 -7
  166. package/src/cli/commands/__tests__/backup.test.ts +6 -277
  167. package/src/cli/commands/__tests__/gateway.test.ts +288 -0
  168. package/src/cli/commands/__tests__/memory-v2.test.ts +4 -0
  169. package/src/cli/commands/__tests__/webhooks.test.ts +0 -1
  170. package/src/cli/commands/backup.ts +6 -331
  171. package/src/cli/commands/clients.ts +36 -37
  172. package/src/cli/commands/contacts.ts +73 -0
  173. package/src/cli/commands/conversations.ts +2 -5
  174. package/src/cli/commands/credentials.ts +15 -7
  175. package/src/cli/commands/domain.ts +66 -15
  176. package/src/cli/commands/gateway.ts +183 -0
  177. package/src/cli/commands/keys.ts +9 -6
  178. package/src/cli/commands/mcp.ts +116 -156
  179. package/src/cli/commands/memory-v2.ts +296 -1
  180. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -1
  181. package/src/cli/commands/platform/__tests__/connect.test.ts +0 -2
  182. package/src/cli/commands/platform/__tests__/disconnect.test.ts +0 -2
  183. package/src/cli/commands/platform/__tests__/status.test.ts +13 -15
  184. package/src/cli/commands/platform/disconnect.ts +5 -4
  185. package/src/cli/commands/platform/index.ts +0 -18
  186. package/src/cli/lib/daemon-credential-client.ts +110 -28
  187. package/src/cli/program.ts +2 -0
  188. package/src/config/assistant-feature-flags.ts +67 -10
  189. package/src/config/bundled-skills/acp/SKILL.md +6 -0
  190. package/src/config/bundled-skills/acp/TOOLS.json +1 -22
  191. package/src/config/bundled-skills/app-builder/SKILL.md +14 -109
  192. package/src/config/bundled-skills/app-builder/TOOLS.json +1 -28
  193. package/src/config/bundled-skills/app-builder/tools/app-create.ts +1 -10
  194. package/src/config/bundled-skills/app-control/SKILL.md +75 -0
  195. package/src/config/bundled-skills/app-control/TOOLS.json +299 -0
  196. package/src/config/bundled-skills/app-control/tools/app-control-click.ts +12 -0
  197. package/src/config/bundled-skills/app-control/tools/app-control-combo.ts +12 -0
  198. package/src/config/bundled-skills/app-control/tools/app-control-drag.ts +12 -0
  199. package/src/config/bundled-skills/app-control/tools/app-control-observe.ts +12 -0
  200. package/src/config/bundled-skills/app-control/tools/app-control-press.ts +12 -0
  201. package/src/config/bundled-skills/app-control/tools/app-control-sequence.ts +12 -0
  202. package/src/config/bundled-skills/app-control/tools/app-control-start.ts +12 -0
  203. package/src/config/bundled-skills/app-control/tools/app-control-stop.ts +12 -0
  204. package/src/config/bundled-skills/app-control/tools/app-control-type.ts +12 -0
  205. package/src/config/bundled-skills/computer-use/SKILL.md +6 -0
  206. package/src/config/bundled-skills/computer-use/TOOLS.json +67 -43
  207. package/src/config/bundled-skills/contacts/TOOLS.json +0 -16
  208. package/src/config/bundled-skills/document/TOOLS.json +0 -8
  209. package/src/config/bundled-skills/followups/TOOLS.json +0 -12
  210. package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
  211. package/src/config/bundled-skills/image-studio/TOOLS.json +0 -4
  212. package/src/config/bundled-skills/media-processing/TOOLS.json +0 -24
  213. package/src/config/bundled-skills/messaging/TOOLS.json +0 -40
  214. package/src/config/bundled-skills/phone-calls/TOOLS.json +0 -12
  215. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +19 -4
  216. package/src/config/bundled-skills/playbooks/TOOLS.json +0 -16
  217. package/src/config/bundled-skills/schedule/TOOLS.json +14 -14
  218. package/src/config/bundled-skills/sequences/TOOLS.json +0 -36
  219. package/src/config/bundled-skills/settings/SKILL.md +4 -0
  220. package/src/config/bundled-skills/settings/TOOLS.json +0 -12
  221. package/src/config/bundled-skills/skill-management/SKILL.md +6 -0
  222. package/src/config/bundled-skills/skill-management/TOOLS.json +0 -8
  223. package/src/config/bundled-skills/subagent/SKILL.md +6 -2
  224. package/src/config/bundled-skills/subagent/TOOLS.json +0 -20
  225. package/src/config/bundled-skills/transcribe/SKILL.md +4 -0
  226. package/src/config/bundled-skills/transcribe/TOOLS.json +0 -4
  227. package/src/config/bundled-tool-registry.ts +21 -0
  228. package/src/config/env-registry.ts +0 -2
  229. package/src/config/env.ts +19 -12
  230. package/src/config/feature-flag-registry.json +21 -133
  231. package/src/config/loader.ts +73 -99
  232. package/src/config/sanitize-for-transfer.ts +2 -0
  233. package/src/config/schemas/__tests__/memory-lifecycle.test.ts +80 -0
  234. package/src/config/schemas/__tests__/memory-v2.test.ts +7 -4
  235. package/src/config/schemas/calls.ts +0 -9
  236. package/src/config/schemas/heartbeat.ts +63 -0
  237. package/src/config/schemas/ingress.ts +10 -6
  238. package/src/config/schemas/llm.ts +5 -10
  239. package/src/config/schemas/memory-lifecycle.ts +77 -24
  240. package/src/config/schemas/memory-v2.ts +48 -4
  241. package/src/config/schemas/platform.ts +6 -0
  242. package/src/config/schemas/services.ts +1 -15
  243. package/src/config/schemas/skills.ts +0 -6
  244. package/src/config/seed-inference-profiles.ts +1 -1
  245. package/src/contacts/contact-store.ts +0 -30
  246. package/src/contacts/contacts-write.ts +0 -27
  247. package/src/context/window-manager.ts +1 -2
  248. package/src/credential-execution/feature-gates.ts +10 -10
  249. package/src/credential-execution/process-manager.ts +12 -41
  250. package/src/daemon/__tests__/conversation-tool-setup.test.ts +126 -5
  251. package/src/daemon/bootstrap-turn-cleanup.ts +45 -0
  252. package/src/daemon/config-watcher.ts +4 -3
  253. package/src/daemon/conversation-agent-loop-handlers.ts +21 -3
  254. package/src/daemon/conversation-agent-loop.ts +32 -28
  255. package/src/daemon/conversation-lifecycle.ts +8 -1
  256. package/src/daemon/conversation-process.ts +16 -11
  257. package/src/daemon/conversation-runtime-assembly.ts +2 -2
  258. package/src/daemon/conversation-surfaces.ts +125 -4
  259. package/src/daemon/conversation-tool-setup.ts +16 -55
  260. package/src/daemon/conversation.ts +21 -2
  261. package/src/daemon/doordash-steps.ts +1 -1
  262. package/src/daemon/handlers/shared.ts +4 -1
  263. package/src/daemon/host-app-control-proxy.ts +293 -0
  264. package/src/daemon/host-bash-proxy.ts +84 -74
  265. package/src/daemon/host-browser-proxy.ts +67 -82
  266. package/src/daemon/host-cu-proxy.ts +81 -86
  267. package/src/daemon/host-file-proxy.ts +93 -69
  268. package/src/daemon/host-proxy-base.ts +294 -0
  269. package/src/daemon/host-proxy-preactivation.ts +82 -0
  270. package/src/daemon/host-transfer-proxy.ts +247 -129
  271. package/src/daemon/lifecycle.ts +115 -117
  272. package/src/daemon/message-protocol.ts +3 -8
  273. package/src/daemon/message-types/contacts.ts +23 -1
  274. package/src/daemon/message-types/conversations.ts +11 -8
  275. package/src/daemon/message-types/host-app-control.ts +150 -0
  276. package/src/daemon/message-types/host-bash.ts +4 -0
  277. package/src/daemon/message-types/host-cu.ts +2 -0
  278. package/src/daemon/message-types/host-file.ts +4 -0
  279. package/src/daemon/message-types/host-transfer.ts +3 -0
  280. package/src/daemon/message-types/schedules.ts +8 -3
  281. package/src/daemon/message-types/skills.ts +2 -2
  282. package/src/daemon/process-message.ts +18 -1
  283. package/src/daemon/shutdown-handlers.ts +0 -3
  284. package/src/daemon/tool-setup-types.ts +51 -0
  285. package/src/daemon/tool-side-effects.ts +1 -1
  286. package/src/events/tool-audit-listener.ts +2 -1
  287. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +15 -7
  288. package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +216 -0
  289. package/src/heartbeat/heartbeat-run-store.ts +236 -0
  290. package/src/heartbeat/heartbeat-service.ts +280 -49
  291. package/src/home/__tests__/post-connect-feed.test.ts +99 -0
  292. package/src/home/__tests__/relationship-state-writer.test.ts +11 -9
  293. package/src/home/__tests__/suggested-prompts.test.ts +89 -0
  294. package/src/home/post-connect-feed.ts +68 -0
  295. package/src/home/relationship-state-writer.ts +17 -92
  296. package/src/home/suggested-prompts.ts +46 -10
  297. package/src/inbound/public-ingress-urls.ts +32 -34
  298. package/src/ipc/__tests__/route-error-envelope.test.ts +80 -0
  299. package/src/ipc/assistant-server.ts +14 -1
  300. package/src/ipc/cli-client.ts +32 -1
  301. package/src/live-voice/live-voice-metrics.ts +10 -10
  302. package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +304 -0
  303. package/src/mcp/mcp-auth-orchestrator.ts +213 -0
  304. package/src/mcp/mcp-auth-state.ts +133 -0
  305. package/src/mcp/mcp-oauth-provider.ts +19 -0
  306. package/src/memory/__tests__/jobs-store-job-classes.test.ts +24 -0
  307. package/src/memory/__tests__/qdrant-client-sentinel.test.ts +49 -0
  308. package/src/memory/__tests__/sparse-tokenize.test.ts +66 -0
  309. package/src/memory/anisotropy.test.ts +247 -0
  310. package/src/memory/anisotropy.ts +443 -0
  311. package/src/memory/auto-analysis-constants.ts +17 -0
  312. package/src/memory/auto-analysis-guard.ts +5 -15
  313. package/src/memory/canonical-guardian-store.ts +7 -7
  314. package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +122 -0
  315. package/src/memory/context-search/agent-protocol.ts +6 -6
  316. package/src/memory/context-search/agent-runner.ts +32 -7
  317. package/src/memory/context-search/sources/memory-v2.ts +17 -5
  318. package/src/memory/conversation-crud.ts +1 -1
  319. package/src/memory/conversation-key-store.ts +2 -15
  320. package/src/memory/db-init.ts +4 -0
  321. package/src/memory/embedding-backend.ts +9 -21
  322. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +49 -4
  323. package/src/memory/graph/conversation-graph-memory.ts +1 -24
  324. package/src/memory/graph/graph-search.ts +8 -0
  325. package/src/memory/graph/retriever.ts +28 -0
  326. package/src/memory/graph/tools.ts +1 -1
  327. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +8 -2
  328. package/src/memory/jobs/embed-concept-page.ts +28 -2
  329. package/src/memory/jobs/embed-pkb-file.test.ts +2 -2
  330. package/src/memory/jobs-store.ts +66 -22
  331. package/src/memory/jobs-worker.ts +112 -63
  332. package/src/memory/memory-v2-activation-log-store.ts +1 -1
  333. package/src/memory/migrations/237-heartbeat-runs.ts +45 -0
  334. package/src/memory/migrations/238-schedule-retry-policy.ts +20 -0
  335. package/src/memory/migrations/index.ts +5 -0
  336. package/src/memory/migrations/registry.ts +8 -0
  337. package/src/memory/pkb/pkb-search.ts +7 -0
  338. package/src/memory/qdrant-client.ts +50 -20
  339. package/src/memory/schema/infrastructure.ts +15 -0
  340. package/src/memory/search/semantic.ts +7 -0
  341. package/src/memory/sparse-tokenize.ts +49 -0
  342. package/src/memory/v2/__tests__/activation.test.ts +77 -95
  343. package/src/memory/v2/__tests__/injection.test.ts +43 -21
  344. package/src/memory/v2/__tests__/sim.test.ts +166 -6
  345. package/src/memory/v2/__tests__/sparse-bm25.test.ts +292 -0
  346. package/src/memory/v2/__tests__/static-context.test.ts +0 -1
  347. package/src/memory/v2/activation.ts +69 -88
  348. package/src/memory/v2/consolidation-job.ts +3 -5
  349. package/src/memory/v2/constants.ts +7 -0
  350. package/src/memory/v2/injection.ts +86 -53
  351. package/src/memory/v2/prompts/consolidation.ts +312 -91
  352. package/src/memory/v2/qdrant.ts +99 -1
  353. package/src/memory/v2/sim.ts +126 -16
  354. package/src/memory/v2/skill-qdrant.ts +12 -3
  355. package/src/memory/v2/skill-store.ts +16 -1
  356. package/src/memory/v2/sparse-bm25.ts +245 -0
  357. package/src/memory/v2/static-context.ts +6 -5
  358. package/src/messaging/providers/gmail/types.ts +0 -49
  359. package/src/messaging/providers/slack/adapter.ts +1 -31
  360. package/src/messaging/providers/slack/types.ts +0 -32
  361. package/src/notifications/README.md +10 -10
  362. package/src/notifications/broadcaster.ts +1 -1
  363. package/src/notifications/guardian-question-mode.ts +5 -5
  364. package/src/oauth/connect-orchestrator.ts +4 -0
  365. package/src/oauth/credential-token-resolver.ts +1 -3
  366. package/src/oauth/manual-token-connection.ts +0 -4
  367. package/src/outbound-proxy/index.ts +1 -37
  368. package/src/outbound-proxy/logging.ts +1 -1
  369. package/src/outbound-proxy/policy.ts +6 -5
  370. package/src/outbound-proxy/router.ts +2 -1
  371. package/src/permissions/approval-policy.test.ts +6 -275
  372. package/src/permissions/approval-policy.ts +0 -51
  373. package/src/permissions/checker.test.ts +0 -1
  374. package/src/permissions/checker.ts +3 -17
  375. package/src/permissions/gateway-threshold-reader.ts +2 -0
  376. package/src/permissions/prompter.ts +34 -1
  377. package/src/permissions/secret-prompter.ts +6 -2
  378. package/src/prompts/bootstrap-cleanup.ts +27 -0
  379. package/src/prompts/system-prompt.ts +3 -18
  380. package/src/prompts/templates/SOUL.md +13 -1
  381. package/src/providers/speech-to-text/provider-catalog.ts +7 -8
  382. package/src/runtime/assistant-event-hub.ts +118 -96
  383. package/src/runtime/assistant-event.ts +1 -0
  384. package/src/runtime/auth/__tests__/middleware.test.ts +11 -56
  385. package/src/runtime/auth/middleware.ts +0 -96
  386. package/src/runtime/auth/route-policy.ts +19 -0
  387. package/src/runtime/btw-sidechain.ts +2 -3
  388. package/src/runtime/channel-invite-transport.ts +2 -48
  389. package/src/runtime/channel-invite-transports/email.ts +1 -1
  390. package/src/runtime/channel-invite-transports/slack.ts +1 -1
  391. package/src/runtime/channel-invite-transports/telegram.ts +1 -1
  392. package/src/runtime/channel-invite-transports/voice.ts +1 -1
  393. package/src/runtime/channel-invite-transports/whatsapp.ts +1 -1
  394. package/src/runtime/channel-invite-types.ts +54 -0
  395. package/src/runtime/channel-readiness-service.ts +32 -13
  396. package/src/runtime/http-server.ts +3 -329
  397. package/src/runtime/http-types.ts +0 -5
  398. package/src/runtime/migrations/__tests__/vbundle-import-parity.test.ts +413 -0
  399. package/src/runtime/migrations/__tests__/vbundle-import-policy.test.ts +260 -0
  400. package/src/runtime/migrations/__tests__/vbundle-import-version-compat.test.ts +189 -0
  401. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +153 -1
  402. package/src/runtime/migrations/__tests__/vbundle-symlink-importer.test.ts +451 -0
  403. package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -0
  404. package/src/runtime/migrations/__tests__/vbundle-symlink-streaming.test.ts +515 -0
  405. package/src/runtime/migrations/__tests__/vbundle-symlink-tar.test.ts +437 -0
  406. package/src/runtime/migrations/__tests__/vbundle-symlink-walker.test.ts +319 -0
  407. package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +51 -1
  408. package/src/runtime/migrations/migration-transport.ts +7 -7
  409. package/src/runtime/migrations/vbundle-builder.ts +327 -60
  410. package/src/runtime/migrations/vbundle-import-analyzer.ts +4 -4
  411. package/src/runtime/migrations/vbundle-import-policy.ts +172 -0
  412. package/src/runtime/migrations/vbundle-importer.ts +245 -68
  413. package/src/runtime/migrations/vbundle-streaming-importer.ts +326 -35
  414. package/src/runtime/migrations/vbundle-streaming-validator.ts +157 -4
  415. package/src/runtime/migrations/vbundle-tar-stream.ts +15 -6
  416. package/src/runtime/migrations/vbundle-validator.ts +114 -0
  417. package/src/runtime/pending-interactions.ts +35 -9
  418. package/src/runtime/routes/__tests__/backup-routes.test.ts +22 -150
  419. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +98 -0
  420. package/src/runtime/routes/__tests__/gateway-log-routes.test.ts +242 -0
  421. package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +112 -0
  422. package/src/runtime/routes/approval-interception-types.ts +13 -0
  423. package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +1 -1
  424. package/src/runtime/routes/backup-routes.ts +15 -38
  425. package/src/runtime/routes/btw-routes.ts +14 -37
  426. package/src/runtime/routes/client-routes.ts +1 -0
  427. package/src/runtime/routes/contact-prompt-routes.ts +183 -0
  428. package/src/runtime/routes/conversation-query-routes.ts +36 -1
  429. package/src/runtime/routes/conversation-routes.ts +30 -13
  430. package/src/runtime/routes/document-pdf-renderer.ts +165 -0
  431. package/src/runtime/routes/documents-routes.ts +30 -0
  432. package/src/runtime/routes/errors.ts +19 -4
  433. package/src/runtime/routes/events-routes.ts +12 -6
  434. package/src/runtime/routes/gateway-log-routes.ts +79 -0
  435. package/src/runtime/routes/guardian-approval-interception.ts +2 -8
  436. package/src/runtime/routes/heartbeat-routes.ts +103 -38
  437. package/src/runtime/routes/host-app-control-routes.ts +134 -0
  438. package/src/runtime/routes/host-bash-routes.ts +36 -6
  439. package/src/runtime/routes/host-browser-routes.ts +108 -13
  440. package/src/runtime/routes/host-cu-routes.ts +44 -14
  441. package/src/runtime/routes/host-file-routes.ts +33 -10
  442. package/src/runtime/routes/host-transfer-routes.ts +64 -24
  443. package/src/runtime/routes/http-adapter.ts +1 -0
  444. package/src/runtime/routes/identity-intro-cache.ts +30 -0
  445. package/src/runtime/routes/identity-routes.ts +15 -43
  446. package/src/runtime/routes/inbound-message-handler.ts +1 -9
  447. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +0 -7
  448. package/src/runtime/routes/inbound-stages/edit-intercept.ts +0 -8
  449. package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +0 -20
  450. package/src/runtime/routes/inbound-stages/transcribe-audio.ts +5 -13
  451. package/src/runtime/routes/index.ts +8 -0
  452. package/src/runtime/routes/mcp-auth-routes.ts +132 -0
  453. package/src/runtime/routes/memory-item-routes.ts +10 -12
  454. package/src/runtime/routes/memory-v2-routes.ts +441 -1
  455. package/src/runtime/routes/migration-routes.ts +96 -0
  456. package/src/runtime/routes/schedule-routes.ts +7 -0
  457. package/src/runtime/verification-templates.ts +4 -7
  458. package/src/schedule/integration-status.ts +66 -2
  459. package/src/schedule/recurrence-engine.ts +4 -1
  460. package/src/schedule/retry-backoff.ts +18 -0
  461. package/src/schedule/retry-policy.ts +82 -0
  462. package/src/schedule/schedule-recovery.ts +64 -0
  463. package/src/schedule/schedule-store.ts +106 -2
  464. package/src/schedule/scheduler-types.ts +25 -0
  465. package/src/schedule/scheduler.ts +63 -38
  466. package/src/security/oauth-callback-registry.ts +8 -0
  467. package/src/sequence/analytics.ts +5 -5
  468. package/src/sequence/engine.ts +1 -1
  469. package/src/skills/catalog-files.ts +2 -8
  470. package/src/skills/include-graph.ts +5 -5
  471. package/src/skills/remote-skill-policy.ts +5 -5
  472. package/src/skills/skill-file-provider.ts +1 -1
  473. package/src/skills/skill-file-types.ts +13 -0
  474. package/src/skills/skillssh-audit-types.ts +28 -0
  475. package/src/skills/skillssh-registry.ts +8 -21
  476. package/src/telemetry/types.ts +2 -0
  477. package/src/telemetry/usage-telemetry-reporter.test.ts +21 -0
  478. package/src/telemetry/usage-telemetry-reporter.ts +1 -0
  479. package/src/tools/app-control/skill-proxy-bridge.ts +28 -0
  480. package/src/tools/apps/executors.ts +56 -69
  481. package/src/tools/browser/__tests__/browser-status.test.ts +21 -18
  482. package/src/tools/browser/browser-execution.ts +2 -2
  483. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +55 -4
  484. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +12 -6
  485. package/src/tools/browser/cdp-client/factory.ts +23 -24
  486. package/src/tools/browser/cdp-client/index.ts +1 -14
  487. package/src/tools/computer-use/definitions.ts +42 -20
  488. package/src/tools/executor.ts +2 -0
  489. package/src/tools/host-filesystem/edit.ts +26 -0
  490. package/src/tools/host-filesystem/read.ts +26 -0
  491. package/src/tools/host-filesystem/transfer.ts +31 -1
  492. package/src/tools/host-filesystem/write.ts +26 -0
  493. package/src/tools/host-terminal/host-shell.ts +58 -0
  494. package/src/tools/schedule/create.ts +6 -0
  495. package/src/tools/schedule/list.ts +2 -0
  496. package/src/tools/schedule/update.ts +10 -0
  497. package/src/tools/shared/filesystem/file-ops-service.ts +2 -0
  498. package/src/tools/shared/filesystem/path-policy.ts +25 -1
  499. package/src/tools/skills/load.ts +0 -32
  500. package/src/tools/tool-approval-handler.ts +1 -5
  501. package/src/tools/types.ts +4 -0
  502. package/src/usage/pricing.ts +1 -1
  503. package/src/workspace/hatched-date.ts +86 -0
  504. package/src/workspace/migrations/003-seed-device-id.ts +1 -1
  505. package/src/workspace/migrations/006-services-config.ts +8 -5
  506. package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +3 -9
  507. package/src/workspace/migrations/021-move-signals-to-workspace.ts +4 -10
  508. package/src/workspace/migrations/022-move-hooks-to-workspace.ts +4 -10
  509. package/src/workspace/migrations/023-move-config-files-to-workspace.ts +4 -11
  510. package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +3 -10
  511. package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +3 -2
  512. package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +2 -1
  513. package/src/workspace/migrations/059-move-pid-to-workspace.ts +3 -8
  514. package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +3 -8
  515. package/src/workspace/migrations/AGENTS.md +1 -1
  516. package/src/workspace/migrations/migrate-to-workspace-volume.ts +4 -10
  517. package/src/workspace/migrations/utils.ts +21 -0
  518. package/src/__tests__/host-browser-e2e-cloud.test.ts +0 -443
  519. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +0 -226
  520. package/src/__tests__/host-browser-ws-events-e2e.test.ts +0 -427
  521. package/src/__tests__/twilio-rest.test.ts +0 -34
  522. package/src/backup/__tests__/backup-key.test.ts +0 -152
  523. package/src/backup/__tests__/backup-worker.test.ts +0 -782
  524. package/src/backup/__tests__/offsite-writer.test.ts +0 -641
  525. package/src/backup/__tests__/stream-crypt.test.ts +0 -228
  526. package/src/backup/backup-key.ts +0 -137
  527. package/src/backup/backup-worker.ts +0 -472
  528. package/src/backup/offsite-writer.ts +0 -222
  529. package/src/backup/stream-crypt.ts +0 -263
  530. package/src/daemon/message-types/pairing.ts +0 -58
  531. package/src/outbound-proxy/config.ts +0 -20
  532. package/src/outbound-proxy/health.ts +0 -18
  533. package/src/outbound-proxy/types.ts +0 -150
  534. package/src/runtime/capability-tokens.ts +0 -190
  535. package/src/signals/mcp-reload.ts +0 -18
@@ -55,7 +55,6 @@ mock.module("../config/loader.js", () => ({
55
55
  getConfig: () => mockConfig,
56
56
  loadConfig: () => mockConfig,
57
57
  invalidateConfigCache: () => {},
58
- saveConfig: () => {},
59
58
  loadRawConfig: () => ({}),
60
59
  saveRawConfig: () => {},
61
60
  getNestedValue: () => undefined,
@@ -39,7 +39,6 @@ mock.module("../config/loader.js", () => ({
39
39
  }),
40
40
  loadConfig: () => ({}),
41
41
  invalidateConfigCache: () => {},
42
- saveConfig: () => {},
43
42
  loadRawConfig: () => ({}),
44
43
  saveRawConfig: () => {},
45
44
  }));
@@ -46,7 +46,6 @@ mock.module("../config/loader.js", () => ({
46
46
  getConfig: () => mockConfig,
47
47
  loadConfig: () => mockConfig,
48
48
  invalidateConfigCache: () => {},
49
- saveConfig: () => {},
50
49
  loadRawConfig: () => ({}),
51
50
  saveRawConfig: () => {},
52
51
  getNestedValue: () => undefined,
@@ -82,7 +82,6 @@ mock.module("../config/loader.js", () => ({
82
82
  getConfig: () => mockConfig,
83
83
  loadConfig: () => mockConfig,
84
84
  invalidateConfigCache: () => {},
85
- saveConfig: () => {},
86
85
  loadRawConfig: () => ({}),
87
86
  saveRawConfig: () => {},
88
87
  getNestedValue: () => undefined,
@@ -20,11 +20,6 @@ mock.module("../config/loader.js", () => ({
20
20
  loadConfig: () => mockLoadConfigResult,
21
21
  }));
22
22
 
23
- mock.module("../inbound/public-ingress-urls.js", () => ({
24
- getPublicBaseUrl: () => "https://test.example.com",
25
- getTwilioRelayUrl: () => "wss://test.example.com/twilio/relay",
26
- }));
27
-
28
23
  import { getTwilioConfig } from "../calls/twilio-config.js";
29
24
  import { credentialKey } from "../security/credential-key.js";
30
25
 
@@ -36,7 +31,7 @@ describe("twilio-config", () => {
36
31
  mockLoadConfigResult = {
37
32
  twilio: {
38
33
  accountSid: "AC_test_sid",
39
- phoneNumber: "+15551234567",
34
+ phoneNumber: "+15550123",
40
35
  },
41
36
  };
42
37
  });
@@ -45,14 +40,12 @@ describe("twilio-config", () => {
45
40
  const config = await getTwilioConfig();
46
41
  expect(config.accountSid).toBe("AC_test_sid");
47
42
  expect(config.authToken).toBe("test_auth_token");
48
- expect(config.phoneNumber).toBe("+15551234567");
49
- expect(config.webhookBaseUrl).toBe("https://test.example.com");
50
- expect(config.wssBaseUrl).toBe("wss://test.example.com/twilio/relay");
43
+ expect(config.phoneNumber).toBe("+15550123");
51
44
  });
52
45
 
53
46
  test("throws ConfigError when account SID is missing", async () => {
54
47
  mockLoadConfigResult = {
55
- twilio: { accountSid: "", phoneNumber: "+15551234567" },
48
+ twilio: { accountSid: "", phoneNumber: "+15550123" },
56
49
  };
57
50
  expect(getTwilioConfig()).rejects.toThrow(
58
51
  /Twilio credentials not configured/,
@@ -61,12 +54,6 @@ describe("twilio-config", () => {
61
54
 
62
55
  test("throws ConfigError when auth token is missing", async () => {
63
56
  mockSecureKeys = {};
64
- mockLoadConfigResult = {
65
- twilio: {
66
- accountSid: "AC_test_sid",
67
- phoneNumber: "+15551234567",
68
- },
69
- };
70
57
  expect(getTwilioConfig()).rejects.toThrow(
71
58
  /Twilio credentials not configured/,
72
59
  );
@@ -209,8 +209,6 @@ mock.module("../calls/twilio-config.js", () => ({
209
209
  accountSid: "AC_test",
210
210
  authToken: "test-auth-token-for-webhooks",
211
211
  phoneNumber: "+15550001111",
212
- webhookBaseUrl: "https://test.example.com",
213
- wssBaseUrl: "wss://test.example.com",
214
212
  }),
215
213
  resolveTwilioPhoneNumber: () => readMockTwilioPhoneNumber(),
216
214
  }));
@@ -813,7 +811,7 @@ describe("twilio webhook routes", () => {
813
811
  // Call handleVoiceWebhook directly since direct routes are blocked.
814
812
 
815
813
  describe("voice webhook TwiML relay URL", () => {
816
- test("TwiML relay URL is sourced from getTwilioRelayUrl", async () => {
814
+ test("TwiML relay URL uses placeholder for gateway resolution", async () => {
817
815
  const session = createTestSession("conv-twiml-1", "CA_twiml_1");
818
816
  const req = makeVoiceRequest(session.id, { CallSid: "CA_twiml_1" });
819
817
 
@@ -822,7 +820,7 @@ describe("twilio webhook routes", () => {
822
820
  expect(res.status).toBe(200);
823
821
  const twiml = await res.text();
824
822
  expect(twiml).toContain(
825
- "wss://ingress.example.com/webhooks/twilio/relay",
823
+ "wss://__VELLUM_PUBLIC_BASE_URL__/webhooks/twilio/relay",
826
824
  );
827
825
  });
828
826
 
@@ -1138,7 +1136,7 @@ describe("twilio webhook routes", () => {
1138
1136
  expect(twiml).not.toContain("transcriptionProvider=");
1139
1137
  // callSessionId is in the URL path, not as a query param
1140
1138
  expect(twiml).toContain(
1141
- `wss://ingress.example.com/webhooks/twilio/media-stream/${session.id}`,
1139
+ `wss://__VELLUM_PUBLIC_BASE_URL__/webhooks/twilio/media-stream/${session.id}`,
1142
1140
  );
1143
1141
  expect(twiml).not.toContain("?callSessionId=");
1144
1142
  });
@@ -0,0 +1,93 @@
1
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
2
+
3
+ let mockConfig: Record<string, unknown>;
4
+ let mockVerifyCalls: Array<{
5
+ url: string;
6
+ params: Record<string, string>;
7
+ signature: string;
8
+ authToken: string;
9
+ }> = [];
10
+
11
+ mock.module("../util/logger.js", () => ({
12
+ getLogger: () =>
13
+ new Proxy({} as Record<string, unknown>, {
14
+ get: () => () => {},
15
+ }),
16
+ }));
17
+
18
+ mock.module("../config/loader.js", () => ({
19
+ loadConfig: () => mockConfig,
20
+ }));
21
+
22
+ mock.module("../calls/twilio-provider.js", () => ({
23
+ TwilioConversationRelayProvider: class {
24
+ static getAuthToken() {
25
+ return "test-auth-token";
26
+ }
27
+
28
+ static verifyWebhookSignature(
29
+ url: string,
30
+ params: Record<string, string>,
31
+ signature: string,
32
+ authToken: string,
33
+ ) {
34
+ mockVerifyCalls.push({ url, params, signature, authToken });
35
+ return signature === "valid";
36
+ }
37
+ },
38
+ }));
39
+
40
+ import { validateTwilioWebhook } from "../runtime/middleware/twilio-validation.js";
41
+
42
+ describe("Twilio validation middleware", () => {
43
+ beforeEach(() => {
44
+ mockVerifyCalls = [];
45
+ mockConfig = {
46
+ ingress: {
47
+ publicBaseUrl: "https://generic.example.com",
48
+ },
49
+ };
50
+ });
51
+
52
+ test("validates signatures against Twilio-specific public ingress first", async () => {
53
+ mockConfig = {
54
+ ingress: {
55
+ publicBaseUrl: " https://twilio.example.com/// ",
56
+ },
57
+ };
58
+ const req = new Request(
59
+ "http://127.0.0.1:7821/v1/calls/twilio/voice-webhook?callSessionId=session-123",
60
+ {
61
+ method: "POST",
62
+ headers: { "x-twilio-signature": "valid" },
63
+ body: new URLSearchParams({ CallSid: "CA123" }),
64
+ },
65
+ );
66
+
67
+ const result = await validateTwilioWebhook(req);
68
+
69
+ expect(result).toEqual({ body: "CallSid=CA123" });
70
+ expect(mockVerifyCalls).toEqual([
71
+ {
72
+ url: "https://twilio.example.com/v1/calls/twilio/voice-webhook?callSessionId=session-123",
73
+ params: { CallSid: "CA123" },
74
+ signature: "valid",
75
+ authToken: "test-auth-token",
76
+ },
77
+ ]);
78
+ });
79
+
80
+ test("falls back to generic public ingress when Twilio-specific ingress is empty", async () => {
81
+ const req = new Request("http://127.0.0.1:7821/v1/calls/twilio/status", {
82
+ method: "POST",
83
+ headers: { "x-twilio-signature": "valid" },
84
+ body: new URLSearchParams({ CallSid: "CA123" }),
85
+ });
86
+
87
+ await validateTwilioWebhook(req);
88
+
89
+ expect(mockVerifyCalls[0]?.url).toBe(
90
+ "https://generic.example.com/v1/calls/twilio/status",
91
+ );
92
+ });
93
+ });
@@ -56,7 +56,6 @@ mock.module("../config/loader.js", () => ({
56
56
  getConfig: () => testConfig,
57
57
  loadConfig: () => testConfig,
58
58
  invalidateConfigCache: () => {},
59
- saveConfig: () => {},
60
59
  loadRawConfig: () => ({}),
61
60
  saveRawConfig: () => {},
62
61
  getNestedValue: () => undefined,
@@ -153,9 +152,7 @@ describe("vellum-self-knowledge skill", () => {
153
152
 
154
153
  test("references the GitHub repo for deep implementation questions", async () => {
155
154
  const result = await executeSkillLoad({ skill: "vellum-self-knowledge" });
156
- expect(result.content).toContain(
157
- "github.com/vellum-ai/vellum-assistant",
158
- );
155
+ expect(result.content).toContain("github.com/vellum-ai/vellum-assistant");
159
156
  expect(result.content).toContain("ARCHITECTURE.md");
160
157
  });
161
158
 
@@ -49,7 +49,6 @@ mock.module("../config/loader.js", () => ({
49
49
  getConfig: () => mockConfig,
50
50
  loadConfig: () => mockConfig,
51
51
  invalidateConfigCache: () => {},
52
- saveConfig: () => {},
53
52
  loadRawConfig: () => ({}),
54
53
  saveRawConfig: () => {},
55
54
  getNestedValue: () => undefined,
@@ -700,15 +699,14 @@ describe("ToolExecutor verification control-plane policy gate", () => {
700
699
  expect(result.content).toBe("ok");
701
700
  });
702
701
 
703
- test("non-guardian invocation of unrelated bash command is allowed (sandbox bash is auto-approved)", async () => {
702
+ test("non-guardian invocation of unrelated bash command requires guardian grant", async () => {
704
703
  const executor = new ToolExecutor(makePrompter());
705
704
  const result = await executor.execute(
706
705
  "bash",
707
706
  { command: "curl http://localhost:3000/v1/messages" },
708
707
  makeContext({ trustClass: "trusted_contact" }),
709
708
  );
710
- expect(result.isError).toBe(false);
711
- expect(result.content).toBe("ok");
709
+ expect(result.isError).toBe(true);
712
710
  });
713
711
 
714
712
  test("non-guardian invocation of unrelated tool is unaffected", async () => {
@@ -33,4 +33,23 @@ describe("voice ingress preflight", () => {
33
33
  expect(result.ingressConfig.ingress?.enabled).toBe(false);
34
34
  }
35
35
  });
36
+
37
+ test("accepts public base URL for Twilio when configured", async () => {
38
+ mockLoadConfig = () => ({
39
+ ingress: {
40
+ enabled: true,
41
+ publicBaseUrl: "https://twilio.example.com/",
42
+ },
43
+ });
44
+
45
+ const result = await preflightVoiceIngress();
46
+
47
+ expect(result.ok).toBe(true);
48
+ if (result.ok) {
49
+ expect(result.publicBaseUrl).toBe("https://twilio.example.com");
50
+ expect(result.ingressConfig.ingress?.publicBaseUrl).toBe(
51
+ "https://twilio.example.com",
52
+ );
53
+ }
54
+ });
36
55
  });
@@ -183,8 +183,9 @@ describe("006-services-config migration", () => {
183
183
  });
184
184
 
185
185
  test("merges with existing backfilled services object", async () => {
186
- // Simulates the scenario where backfillConfigDefaults wrote a default
187
- // services object before migrations run, and legacy fields coexist.
186
+ // Simulates a legacy-daemon scenario where an older loader wrote a
187
+ // schema-default services object to disk before migrations run, and
188
+ // legacy top-level fields coexist with it.
188
189
  writeConfig({
189
190
  provider: "openai",
190
191
  model: "gpt-4o",
@@ -84,7 +84,6 @@ describe("011-backfill-installation-id migration", () => {
84
84
  getExternalAssistantIdFn.mockReturnValue("my-assistant");
85
85
  getMemoryCheckpointFn.mockReturnValue(null);
86
86
  randomUUIDFn.mockReturnValue("generated-uuid-1234");
87
- delete process.env.BASE_DATA_DIR;
88
87
  });
89
88
 
90
89
  test("no-op when no lockfile exists", () => {
@@ -284,12 +283,9 @@ describe("011-backfill-installation-id migration", () => {
284
283
  expect(parsed.assistants[0].installationId).toBe("sqlite-id");
285
284
  });
286
285
 
287
- test("ignores BASE_DATA_DIR and always reads lockfile from homedir", () => {
288
- process.env.BASE_DATA_DIR = "/custom-base";
286
+ test("always reads lockfile from homedir (per-user, not per-instance)", () => {
289
287
  getMemoryCheckpointFn.mockReturnValue("sqlite-id");
290
288
 
291
- // Lockfile under BASE_DATA_DIR should be ignored — the migration
292
- // always reads from homedir() (per-user, not per-instance).
293
289
  setupFs({
294
290
  [LOCK_PATH]: makeLockfile([{ assistantId: "my-assistant" }]),
295
291
  });
@@ -32,7 +32,7 @@ mock.module("../security/credential-key.js", () => ({
32
32
  credentialKey: (...args: string[]) => args.join(":"),
33
33
  }));
34
34
 
35
- // Mock getRootDir for 016-extract-feature-flags-to-protected
35
+ // Mutable root dir used by 016-extract-feature-flags-to-protected tests
36
36
  let mockRootDir: string = "/tmp/mock-root";
37
37
  // ---------------------------------------------------------------------------
38
38
  // Imports — after mocking
@@ -763,21 +763,21 @@ describe("014-migrate-to-workspace-volume down()", () => {
763
763
  // ---------------------------------------------------------------------------
764
764
 
765
765
  describe("016-extract-feature-flags-to-protected down()", () => {
766
- let savedBaseDataDir: string | undefined;
766
+ let savedWorkspaceDir: string | undefined;
767
767
 
768
768
  beforeEach(() => {
769
- // The migration has an inlined platform helpers that reads BASE_DATA_DIR,
770
- // so we set that env var so the inlined function resolves to mockRootDir.
769
+ // getVellumRoot() resolves via dirname(VELLUM_WORKSPACE_DIR), so we set
770
+ // VELLUM_WORKSPACE_DIR to <mockRootDir>/workspace so dirname gives mockRootDir.
771
771
  const baseDir = freshWorkspace();
772
772
  mockRootDir = join(baseDir, ".vellum");
773
773
  mkdirSync(mockRootDir, { recursive: true });
774
- savedBaseDataDir = process.env.BASE_DATA_DIR;
775
- process.env.BASE_DATA_DIR = baseDir;
774
+ savedWorkspaceDir = process.env.VELLUM_WORKSPACE_DIR;
775
+ process.env.VELLUM_WORKSPACE_DIR = join(mockRootDir, "workspace");
776
776
  });
777
777
 
778
778
  afterEach(() => {
779
- if (savedBaseDataDir === undefined) delete process.env.BASE_DATA_DIR;
780
- else process.env.BASE_DATA_DIR = savedBaseDataDir;
779
+ if (savedWorkspaceDir === undefined) delete process.env.VELLUM_WORKSPACE_DIR;
780
+ else process.env.VELLUM_WORKSPACE_DIR = savedWorkspaceDir;
781
781
  });
782
782
 
783
783
  test("moves feature flags from protected dir back to config.json", () => {
@@ -119,15 +119,17 @@ describe("038-unify-llm-callsite-configs migration", () => {
119
119
  // ─── Schema-default-injection regression (the original bug) ────────────
120
120
 
121
121
  test("legacy services.inference.{provider,model} win over schema-default-injected llm.default", () => {
122
- // Reproduces the production bug: between PR #26095 (added
123
- // `LLMSchema.default(LLMSchema.parse({}))` to AssistantConfigSchema)
124
- // and PR #26101 (this migration), any daemon boot caused the loader's
125
- // `backfillConfigDefaults()` to write a schema-default `llm.default`
122
+ // Reproduces a production bug from a legacy-daemon era: between PR
123
+ // #26095 (added `LLMSchema.default(LLMSchema.parse({}))` to
124
+ // AssistantConfigSchema) and PR #26101 (this migration), any daemon
125
+ // boot caused the loader to write a schema-default `llm.default`
126
126
  // block to disk. Migration 038's old idempotency check (`return early
127
127
  // if llm.default exists`) then silently skipped, and migration 039
128
128
  // stripped `services.inference.{provider,model}` — losing the user's
129
129
  // actual configuration. The fix prefers legacy source keys over the
130
- // injected schema defaults whenever both are present.
130
+ // injected schema defaults whenever both are present. (The loader
131
+ // no longer writes defaults to disk, but workspaces still on disk
132
+ // from that era can carry the bad state forward.)
131
133
  writeConfig({
132
134
  services: {
133
135
  inference: {
@@ -806,7 +808,9 @@ describe("038-unify-llm-callsite-configs migration", () => {
806
808
  // documented no-op — it leaves the config exactly as it found it,
807
809
  // whether the `llm` block is present or absent.
808
810
  const original = {
809
- services: { inference: { mode: "your-own", provider: "openai", model: "gpt-5.4" } },
811
+ services: {
812
+ inference: { mode: "your-own", provider: "openai", model: "gpt-5.4" },
813
+ },
810
814
  maxTokens: 32000,
811
815
  llm: {
812
816
  default: {
@@ -5,7 +5,6 @@ import { afterEach, describe, expect, test } from "bun:test";
5
5
  import {
6
6
  deriveSafeAncestor,
7
7
  formatBackupFilename,
8
- getBackupKeyPath,
9
8
  getBackupRootDir,
10
9
  getDefaultOffsiteBackupsDir,
11
10
  getICloudDriveRoot,
@@ -162,27 +161,6 @@ describe("resolveOffsiteDestinations", () => {
162
161
  });
163
162
  });
164
163
 
165
- describe("getBackupKeyPath", () => {
166
- const ORIGINAL_KEY_PATH = process.env.VELLUM_BACKUP_KEY_PATH;
167
-
168
- afterEach(() => {
169
- if (ORIGINAL_KEY_PATH === undefined) {
170
- delete process.env.VELLUM_BACKUP_KEY_PATH;
171
- } else {
172
- process.env.VELLUM_BACKUP_KEY_PATH = ORIGINAL_KEY_PATH;
173
- }
174
- });
175
-
176
- test("ends with /.backup.key when env var is unset", () => {
177
- delete process.env.VELLUM_BACKUP_KEY_PATH;
178
- expect(getBackupKeyPath().endsWith("/.backup.key")).toBe(true);
179
- });
180
-
181
- test("returns the env var override when VELLUM_BACKUP_KEY_PATH is set", () => {
182
- process.env.VELLUM_BACKUP_KEY_PATH = "/workspace/.backup.key";
183
- expect(getBackupKeyPath()).toBe("/workspace/.backup.key");
184
- });
185
- });
186
164
 
187
165
  describe("formatBackupFilename", () => {
188
166
  const fixture = new Date("2026-04-11T15:30:45.000Z");