@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
@@ -9,14 +9,6 @@
9
9
  "description": "Automatically trigger conversation analysis on the same cadence as memory extraction (batch threshold, idle debounce, end-of-conversation). The analysis agent has full tool access and writes back to memory and skills without user approval.",
10
10
  "defaultEnabled": false
11
11
  },
12
- {
13
- "id": "browser",
14
- "scope": "assistant",
15
- "key": "browser",
16
- "label": "Browser",
17
- "description": "Enable browser skill prerequisites section in the system prompt",
18
- "defaultEnabled": true
19
- },
20
12
  {
21
13
  "id": "user-hosted-enabled",
22
14
  "scope": "client",
@@ -41,29 +33,13 @@
41
33
  "description": "Enable the entire email integration: email CLI commands, email channel, domain registration, sequences, email readiness probes, invite adapters, and the email-setup skill",
42
34
  "defaultEnabled": false
43
35
  },
44
- {
45
- "id": "app-builder-multifile",
46
- "scope": "assistant",
47
- "key": "app-builder-multifile",
48
- "label": "App Builder Multi-file",
49
- "description": "Enable multi-file TSX app creation with esbuild compilation instead of single-HTML apps",
50
- "defaultEnabled": true
51
- },
52
- {
53
- "id": "mobile-pairing",
54
- "scope": "client",
55
- "key": "mobile-pairing",
56
- "label": "Mobile Pairing",
57
- "description": "Show the Mobile (iOS) pairing card in Settings > Account",
58
- "defaultEnabled": false
59
- },
60
36
  {
61
37
  "id": "settings-developer-nav",
62
- "scope": "assistant",
38
+ "scope": "client",
63
39
  "key": "settings-developer-nav",
64
40
  "label": "Settings Developer Nav",
65
41
  "description": "Control Developer nav visibility in macOS settings",
66
- "defaultEnabled": true
42
+ "defaultEnabled": false
67
43
  },
68
44
  {
69
45
  "id": "developer-menu-items",
@@ -105,54 +81,6 @@
105
81
  "description": "Surface credential grant and audit inspection endpoints for reviewing active grants and access logs",
106
82
  "defaultEnabled": false
107
83
  },
108
- {
109
- "id": "ces-managed-sidecar",
110
- "scope": "assistant",
111
- "key": "ces-managed-sidecar",
112
- "label": "CES Managed Sidecar Transport",
113
- "description": "Use managed sidecar transport for CES communication when running in a containerized environment",
114
- "defaultEnabled": true
115
- },
116
- {
117
- "id": "ces-credential-backend",
118
- "scope": "assistant",
119
- "key": "ces-credential-backend",
120
- "label": "CES Credential Backend",
121
- "description": "Route credential reads and writes through the CES process instead of accessing the encrypted store directly",
122
- "defaultEnabled": true
123
- },
124
- {
125
- "id": "settings-billing",
126
- "scope": "client",
127
- "key": "settings-billing",
128
- "label": "Billing Settings Tab",
129
- "description": "Show the Billing tab in Settings when signed in, displaying credits balance and top-up",
130
- "defaultEnabled": true
131
- },
132
- {
133
- "id": "referral-codes",
134
- "scope": "client",
135
- "key": "referral-codes",
136
- "label": "Referral Codes",
137
- "description": "Surface the Earn Credits referral entry points (sidebar drawer row and Billing tab button) that open the referral modal",
138
- "defaultEnabled": true
139
- },
140
- {
141
- "id": "managed-sign-in",
142
- "scope": "client",
143
- "key": "managed-sign-in",
144
- "label": "Managed Sign In",
145
- "description": "Enable managed (organization-hosted) sign-in flow in the onboarding experience",
146
- "defaultEnabled": true
147
- },
148
- {
149
- "id": "conversation-starters",
150
- "scope": "assistant",
151
- "key": "conversation-starters",
152
- "label": "Recommended Starts",
153
- "description": "Show a curated row of recommended starting actions on the empty conversation page, ordered by relevance as confident first-click options",
154
- "defaultEnabled": true
155
- },
156
84
  {
157
85
  "id": "deploy-to-vercel",
158
86
  "scope": "assistant",
@@ -193,37 +121,13 @@
193
121
  "description": "Auto-expand completed tool call step groups instead of showing them collapsed",
194
122
  "defaultEnabled": false
195
123
  },
196
- {
197
- "id": "show-thinking-blocks",
198
- "scope": "client",
199
- "key": "show-thinking-blocks",
200
- "label": "Show Thinking Blocks",
201
- "description": "Display the assistant's thinking/reasoning inline in chat messages as collapsible blocks",
202
- "defaultEnabled": true
203
- },
204
- {
205
- "id": "inline-skill-commands",
206
- "scope": "assistant",
207
- "key": "inline-skill-commands",
208
- "label": "Inline Skill Command Expansion",
209
- "description": "Enable secure inline skill command expansion via !`command` syntax, with version-pinned approval and sandboxed execution at skill load time",
210
- "defaultEnabled": true
211
- },
212
- {
213
- "id": "channel-voice-transcription",
214
- "scope": "assistant",
215
- "key": "channel-voice-transcription",
216
- "label": "Channel Voice Transcription",
217
- "description": "Auto-transcribe voice/audio messages received from channels (Telegram, WhatsApp) before processing",
218
- "defaultEnabled": true
219
- },
220
124
  {
221
125
  "id": "sounds",
222
126
  "scope": "assistant",
223
127
  "key": "sounds",
224
128
  "label": "Sounds",
225
129
  "description": "Enable the Sounds tab in Settings and all app sound playback (event sounds, random ambient sounds)",
226
- "defaultEnabled": true
130
+ "defaultEnabled": false
227
131
  },
228
132
  {
229
133
  "id": "message-tts",
@@ -239,7 +143,7 @@
239
143
  "key": "backward-releases",
240
144
  "label": "Backward Releases",
241
145
  "description": "Show older versions in the version picker, allowing rollback to previous releases",
242
- "defaultEnabled": true
146
+ "defaultEnabled": false
243
147
  },
244
148
  {
245
149
  "id": "voice-mode",
@@ -281,14 +185,6 @@
281
185
  "description": "Enable assistant sandboxing via Apple Containers on macOS 26+, providing a lightweight native sandbox without third-party dependencies",
282
186
  "defaultEnabled": false
283
187
  },
284
- {
285
- "id": "tool-result-truncation",
286
- "scope": "assistant",
287
- "key": "tool-result-truncation",
288
- "label": "Post-Turn Tool Result Truncation",
289
- "description": "Truncate large tool results after each assistant turn, persisting full content to disk for on-demand re-reads",
290
- "defaultEnabled": true
291
- },
292
188
  {
293
189
  "id": "managed-gemini-embeddings-enabled",
294
190
  "scope": "assistant",
@@ -305,14 +201,6 @@
305
201
  "description": "Show the 'Fork from here' option in message overflow menus",
306
202
  "defaultEnabled": false
307
203
  },
308
- {
309
- "id": "onboarding-pre-chat",
310
- "scope": "client",
311
- "key": "onboarding-pre-chat",
312
- "label": "Pre-Chat Onboarding Flow",
313
- "description": "Gates the 3-screen pre-chat onboarding flow (tools, tasks/tone, name exchange) shown before the first conversation",
314
- "defaultEnabled": true
315
- },
316
204
  {
317
205
  "id": "home-tab",
318
206
  "scope": "client",
@@ -321,14 +209,6 @@
321
209
  "description": "Replace the knowledge graph top-level tab with a new Home page showing relationship progression, facts, and capability tiers",
322
210
  "defaultEnabled": false
323
211
  },
324
- {
325
- "id": "channel-avatar-sync",
326
- "scope": "assistant",
327
- "key": "channel-avatar-sync",
328
- "label": "Channel Avatar Sync",
329
- "description": "Automatically sync the assistant's avatar to connected channels (Slack) when the avatar changes or a new channel is connected",
330
- "defaultEnabled": true
331
- },
332
212
  {
333
213
  "id": "meet",
334
214
  "scope": "assistant",
@@ -345,20 +225,12 @@
345
225
  "description": "Show a live HUD in the top-right of the conversation with scroll geometry, velocity, update rate, and anchor-preserver activity. Developer diagnostic for investigating scroll jank.",
346
226
  "defaultEnabled": false
347
227
  },
348
- {
349
- "id": "message-height-cache",
350
- "scope": "client",
351
- "key": "message-height-cache",
352
- "label": "Message Height Cache",
353
- "description": "Swap the transcript's LazyVStack for a plain VStack so scrollContentHeight is the true sum of row heights (no LazyVStack estimator drift). Row frames are not pinned — the earlier frame-pinning approach was removed because it caused overlap when rows grew past their first measurement (streaming, expanding thinking blocks). Tradeoff: eager layout — every row measures up-front, which can stall for many seconds to minutes on very long conversations.",
354
- "defaultEnabled": true
355
- },
356
228
  {
357
229
  "id": "coding-agents-panel",
358
230
  "scope": "client",
359
231
  "key": "coding-agents-panel",
360
232
  "label": "Coding Agents Panel",
361
- "description": "Gate native macOS/iOS Coding Agents panel entry points and inline ACP session deep links.",
233
+ "description": "Gate native macOS Coding Agents panel entry points and inline ACP session deep links.",
362
234
  "defaultEnabled": false
363
235
  },
364
236
  {
@@ -384,6 +256,22 @@
384
256
  "label": "Account Deletion",
385
257
  "description": "Surfaces the user-initiated account deletion flow in client settings.",
386
258
  "defaultEnabled": false
259
+ },
260
+ {
261
+ "id": "app-control",
262
+ "scope": "assistant",
263
+ "key": "app-control",
264
+ "label": "App Control",
265
+ "description": "Enable the app-control skill (per-app screenshot + raw input bypassing AX tree)",
266
+ "defaultEnabled": false
267
+ },
268
+ {
269
+ "id": "analyze-conversation",
270
+ "scope": "assistant",
271
+ "key": "analyze-conversation",
272
+ "label": "Analyze Conversation",
273
+ "description": "Show the 'Analyze' / 'Analyze conversation' option in conversation context menus and the conversation title actions dropdown.",
274
+ "defaultEnabled": false
387
275
  }
388
276
  ]
389
277
  }
@@ -49,6 +49,34 @@ function cloneDefaultConfig(): AssistantConfig {
49
49
  return applyNestedDefaults({});
50
50
  }
51
51
 
52
+ /**
53
+ * Returns deployment-context-aware config defaults that override schema
54
+ * defaults for platform-managed assistants. Only applied when initializing
55
+ * a fresh config (config.json does not yet exist).
56
+ *
57
+ * IS_PLATFORM is set by the Vellum platform launcher for all hosted
58
+ * assistant deployments. Local, Docker, and bare-metal assistants are
59
+ * unaffected.
60
+ */
61
+ function getDeploymentContextDefaults(): Record<string, unknown> {
62
+ if (process.env.IS_PLATFORM !== "true" && process.env.IS_PLATFORM !== "1") {
63
+ return {};
64
+ }
65
+ const managed = { mode: "managed" as const };
66
+ return {
67
+ services: {
68
+ inference: managed,
69
+ "image-generation": managed,
70
+ "web-search": managed,
71
+ "google-oauth": managed,
72
+ "outlook-oauth": managed,
73
+ "linear-oauth": managed,
74
+ "github-oauth": managed,
75
+ "notion-oauth": managed,
76
+ },
77
+ };
78
+ }
79
+
52
80
  /**
53
81
  * Build a filesystem-safe ISO-8601 timestamp for use in quarantine filenames.
54
82
  * Replaces `:` (invalid on Windows, confusing on macOS Finder) with `-` so the
@@ -237,6 +265,11 @@ const DEPRECATED_FIELDS: Record<string, string> = {
237
265
  "permissions.autoApproveUpTo":
238
266
  "permissions.autoApproveUpTo has been removed. The gateway now controls all " +
239
267
  "auto-approve thresholds. The field will be removed from your config file.",
268
+ "memory.jobs.batchSize":
269
+ "memory.jobs.batchSize has been removed. The memory job worker now uses " +
270
+ "per-lane concurrency caps (slowLlmConcurrency, fastConcurrency, " +
271
+ "embedConcurrency) instead of a single batch size. " +
272
+ "The field will be removed from your config file.",
240
273
  };
241
274
 
242
275
  /**
@@ -289,42 +322,6 @@ function deleteNestedKeyByDotPath(
289
322
  deleteNestedKey(obj, keys);
290
323
  }
291
324
 
292
- /**
293
- * Deep-merge missing keys from `defaults` into `target`.
294
- * Only adds keys that do not already exist in `target`; never overwrites.
295
- * Returns true if any key was added.
296
- */
297
- export function deepMergeMissing(
298
- target: Record<string, unknown>,
299
- defaults: Record<string, unknown>,
300
- ): boolean {
301
- let changed = false;
302
- for (const key of Object.keys(defaults)) {
303
- if (!(key in target)) {
304
- target[key] = defaults[key];
305
- changed = true;
306
- } else if (
307
- defaults[key] != null &&
308
- typeof defaults[key] === "object" &&
309
- !Array.isArray(defaults[key]) &&
310
- target[key] != null &&
311
- typeof target[key] === "object" &&
312
- !Array.isArray(target[key])
313
- ) {
314
- // Recurse into nested objects
315
- if (
316
- deepMergeMissing(
317
- target[key] as Record<string, unknown>,
318
- defaults[key] as Record<string, unknown>,
319
- )
320
- ) {
321
- changed = true;
322
- }
323
- }
324
- }
325
- return changed;
326
- }
327
-
328
325
  /**
329
326
  * Recursively strip `null` leaves from a plain-object value, returning a
330
327
  * deep clone with all `null`-valued keys removed at every nesting level.
@@ -409,47 +406,14 @@ export function deepMergeOverwrite(
409
406
  }
410
407
  }
411
408
 
412
- /**
413
- * Read the existing config.json from disk, merge any missing schema-default
414
- * keys, and rewrite only when there is an effective change.
415
- */
416
- function backfillConfigDefaults(
417
- configPath: string,
418
- fullDefaults: Record<string, unknown>,
419
- ): void {
420
- let raw: unknown;
421
- try {
422
- raw = JSON.parse(readFileSync(configPath, "utf-8"));
423
- } catch {
424
- return; // Unreadable file — skip backfill
425
- }
426
-
427
- // Only backfill into plain objects (not arrays, strings, etc.)
428
- if (raw == null || typeof raw !== "object" || Array.isArray(raw)) {
429
- return;
430
- }
431
-
432
- deepMergeMissing(raw as Record<string, unknown>, fullDefaults);
433
- // Compare serialized JSON to decide whether a write is needed.
434
- // deepMergeMissing can report false-positive mutations (e.g. setting a key
435
- // to a value identical to what was already there), so comparing the final
436
- // JSON avoids a hot-loop where writing triggers the config-watcher which
437
- // reloads and backfills again endlessly.
438
- const newJson = JSON.stringify(raw, null, 2) + "\n";
439
- const existingJson = readFileSync(configPath, "utf-8");
440
- if (newJson !== existingJson) {
441
- writeFileSync(configPath, newJson);
442
- log.info("Backfilled missing config defaults in %s", configPath);
443
- }
444
- }
445
-
446
409
  /**
447
410
  * Merge default workspace config from the file referenced by
448
411
  * VELLUM_DEFAULT_WORKSPACE_CONFIG_PATH into the workspace config on disk.
449
412
  *
450
- * Called once at daemon startup (before the first loadConfig()) so the
451
- * defaults are persisted to the workspace config file alongside any
452
- * schema-level defaults that loadConfig() backfills.
413
+ * Called once at daemon startup (before the first loadConfig()) so platform
414
+ * overrides are persisted to disk before the daemon's first config read.
415
+ * Schema defaults are no longer materialized into the file on load — the
416
+ * in-memory `loadConfig()` cache applies them at access time instead.
453
417
  */
454
418
  export function mergeDefaultWorkspaceConfig(): void {
455
419
  const defaultConfigPath = process.env.VELLUM_DEFAULT_WORKSPACE_CONFIG_PATH;
@@ -587,26 +551,45 @@ export function loadConfig(): AssistantConfig {
587
551
  }
588
552
  }
589
553
 
590
- // If the config file didn't exist, write the full defaults to disk so
591
- // users can discover and edit all available options.
592
- // If it existed, backfill any missing schema keys from defaults without
593
- // overwriting existing user values.
594
- try {
595
- const dir = dirname(configPath);
596
- if (!existsSync(dir)) {
597
- mkdirSync(dir, { recursive: true });
598
- }
599
- // Strip dataDir (runtime-derived) from the persisted config
600
- const { dataDir: _, ...persistable } = config;
601
-
602
- if (!configFileExisted) {
554
+ // First-launch seed only: when config.json does not exist, write the full
555
+ // schema defaults to disk so users can discover and edit all available
556
+ // options. When the file already exists, leave it alone disk represents
557
+ // user intent, while the in-memory `cached: AssistantConfig` (above) has
558
+ // all schema defaults applied via `applyNestedDefaults`/`validateWithSchema`,
559
+ // so consumers calling `getConfig().memory.v2.bm25_b` continue to receive
560
+ // the schema default whenever the field is absent on disk.
561
+ //
562
+ // The previous behavior — eagerly merging missing keys back into the file
563
+ // on every load silently baked stale defaults into existing users'
564
+ // config.json. Once a default landed in the file, future schema-default
565
+ // changes were inert because the merge only filled absent keys and never
566
+ // reconciled existing values. Contract: disk = user intent, in-memory
567
+ // cache = effective values.
568
+ if (!configFileExisted) {
569
+ try {
570
+ const dir = dirname(configPath);
571
+ if (!existsSync(dir)) {
572
+ mkdirSync(dir, { recursive: true });
573
+ }
574
+ // Strip dataDir (runtime-derived) from the persisted config
575
+ const { dataDir: _, ...persistable } = config;
576
+
577
+ // Layer deployment context defaults on top of schema defaults.
578
+ // These are overrides the daemon derives from its environment (e.g.
579
+ // IS_PLATFORM → all service modes = "managed"). Schema defaults
580
+ // remain the fallback for non-platform deployments.
581
+ const contextDefaults = getDeploymentContextDefaults();
582
+ if (Object.keys(contextDefaults).length > 0) {
583
+ deepMergeOverwrite(
584
+ persistable as Record<string, unknown>,
585
+ contextDefaults,
586
+ );
587
+ }
603
588
  writeFileSync(configPath, JSON.stringify(persistable, null, 2) + "\n");
604
589
  log.info("Wrote default config to %s", configPath);
605
- } else {
606
- backfillConfigDefaults(configPath, persistable);
590
+ } catch (err) {
591
+ log.warn({ err }, "Failed to write default config file");
607
592
  }
608
- } catch (err) {
609
- log.warn({ err }, "Failed to write/backfill config file");
610
593
  }
611
594
 
612
595
  cached = config;
@@ -636,15 +619,6 @@ function isManagedGeminiFFEnabled(config: AssistantConfig): boolean {
636
619
  }
637
620
  }
638
621
 
639
- export function saveConfig(config: AssistantConfig): void {
640
- ensureMigratedDataDir();
641
- const configPath = getConfigPath();
642
-
643
- writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
644
-
645
- cached = config;
646
- }
647
-
648
622
  export function getConfig(): AssistantConfig {
649
623
  return loadConfig();
650
624
  }
@@ -5,6 +5,7 @@
5
5
  * Fields removed or reset:
6
6
  * - `ingress.publicBaseUrl` → set to `""`
7
7
  * - `ingress.enabled` → deleted
8
+ * - `ingress.publicBaseUrlManagedBy` → deleted
8
9
  * - `daemon` → deleted entirely
9
10
  * - `skills.load.extraDirs` → set to `[]`
10
11
  * - `hostBrowser.cdpInspect.desktopAuto` → deleted **only when the source
@@ -41,6 +42,7 @@ export function sanitizeConfigForTransfer(configJson: string): string {
41
42
  const ingress = config.ingress as Record<string, unknown>;
42
43
  ingress.publicBaseUrl = "";
43
44
  delete ingress.enabled;
45
+ delete ingress.publicBaseUrlManagedBy;
44
46
  }
45
47
 
46
48
  // Strip daemon entirely
@@ -0,0 +1,80 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import { MemoryJobsConfigSchema } from "../memory-lifecycle.js";
4
+
5
+ describe("MemoryJobsConfigSchema", () => {
6
+ test("parses an empty object to documented defaults", () => {
7
+ const parsed = MemoryJobsConfigSchema.parse({});
8
+ expect(parsed).toEqual({
9
+ workerConcurrency: 2,
10
+ stalledJobTimeoutMs: 30 * 60 * 1000,
11
+ slowLlmConcurrency: 1,
12
+ fastConcurrency: 2,
13
+ embedConcurrency: 2,
14
+ });
15
+ });
16
+
17
+ test("derives lane caps from workerConcurrency when only it is set", () => {
18
+ const parsed = MemoryJobsConfigSchema.parse({ workerConcurrency: 4 });
19
+ expect(parsed.workerConcurrency).toBe(4);
20
+ expect(parsed.slowLlmConcurrency).toBe(2);
21
+ expect(parsed.fastConcurrency).toBe(4);
22
+ expect(parsed.embedConcurrency).toBe(4);
23
+ });
24
+
25
+ test("floors and clamps slowLlmConcurrency to at least 1 when deriving", () => {
26
+ const parsed = MemoryJobsConfigSchema.parse({ workerConcurrency: 1 });
27
+ expect(parsed.slowLlmConcurrency).toBe(1);
28
+ expect(parsed.fastConcurrency).toBe(1);
29
+ expect(parsed.embedConcurrency).toBe(1);
30
+ });
31
+
32
+ test("explicit lane cap overrides the derivation", () => {
33
+ const parsed = MemoryJobsConfigSchema.parse({
34
+ workerConcurrency: 4,
35
+ slowLlmConcurrency: 1,
36
+ });
37
+ expect(parsed.slowLlmConcurrency).toBe(1);
38
+ expect(parsed.fastConcurrency).toBe(4);
39
+ expect(parsed.embedConcurrency).toBe(4);
40
+ });
41
+
42
+ test("explicit lane caps without workerConcurrency keep workerConcurrency default", () => {
43
+ const parsed = MemoryJobsConfigSchema.parse({
44
+ slowLlmConcurrency: 3,
45
+ fastConcurrency: 5,
46
+ embedConcurrency: 7,
47
+ });
48
+ expect(parsed.workerConcurrency).toBe(2);
49
+ expect(parsed.slowLlmConcurrency).toBe(3);
50
+ expect(parsed.fastConcurrency).toBe(5);
51
+ expect(parsed.embedConcurrency).toBe(7);
52
+ });
53
+
54
+ test.each([
55
+ "slowLlmConcurrency",
56
+ "fastConcurrency",
57
+ "embedConcurrency",
58
+ "workerConcurrency",
59
+ ] as const)("rejects %s = 0", (field) => {
60
+ expect(() => MemoryJobsConfigSchema.parse({ [field]: 0 })).toThrow();
61
+ });
62
+
63
+ test.each([
64
+ "slowLlmConcurrency",
65
+ "fastConcurrency",
66
+ "embedConcurrency",
67
+ "workerConcurrency",
68
+ ] as const)("rejects negative %s", (field) => {
69
+ expect(() => MemoryJobsConfigSchema.parse({ [field]: -1 })).toThrow();
70
+ });
71
+
72
+ test.each([
73
+ "slowLlmConcurrency",
74
+ "fastConcurrency",
75
+ "embedConcurrency",
76
+ "workerConcurrency",
77
+ ] as const)("rejects non-integer %s", (field) => {
78
+ expect(() => MemoryJobsConfigSchema.parse({ [field]: 1.5 })).toThrow();
79
+ });
80
+ });
@@ -16,10 +16,13 @@ describe("MemoryV2ConfigSchema", () => {
16
16
  k: 0.5,
17
17
  hops: 2,
18
18
  top_k: 20,
19
+ ann_candidate_limit: null,
19
20
  top_k_skills: 5,
20
21
  epsilon: 0.01,
21
- dense_weight: 0.7,
22
- sparse_weight: 0.3,
22
+ dense_weight: 0.85,
23
+ sparse_weight: 0.15,
24
+ bm25_k1: 1.2,
25
+ bm25_b: 0.4,
23
26
  consolidation_interval_hours: 4,
24
27
  max_page_chars: 5000,
25
28
  consolidation_prompt_path: null,
@@ -155,8 +158,8 @@ describe("MemoryConfigSchema integration with v2 block", () => {
155
158
  expect(parsed.v2.enabled).toBe(false);
156
159
  expect(parsed.v2.sweep_enabled).toBe(false);
157
160
  expect(parsed.v2.d).toBe(0.3);
158
- expect(parsed.v2.dense_weight).toBe(0.7);
159
- expect(parsed.v2.sparse_weight).toBe(0.3);
161
+ expect(parsed.v2.dense_weight).toBe(0.85);
162
+ expect(parsed.v2.sparse_weight).toBe(0.15);
160
163
  expect(parsed.v2.top_k_skills).toBe(5);
161
164
  expect(parsed.v2.consolidation_interval_hours).toBe(4);
162
165
  expect(parsed.v2.max_page_chars).toBe(5000);
@@ -232,12 +232,3 @@ export const CallsConfigSchema = z
232
232
  .describe(
233
233
  "Phone call configuration — controls telephony, voice, safety, and call behavior",
234
234
  );
235
-
236
- export type CallsConfig = z.infer<typeof CallsConfigSchema>;
237
- export type CallsDisclosureConfig = z.infer<typeof CallsDisclosureConfigSchema>;
238
- export type CallsSafetyConfig = z.infer<typeof CallsSafetyConfigSchema>;
239
- export type CallsVoiceConfig = z.infer<typeof CallsVoiceConfigSchema>;
240
- export type CallerIdentityConfig = z.infer<typeof CallerIdentityConfigSchema>;
241
- export type CallsVerificationConfig = z.infer<
242
- typeof CallsVerificationConfigSchema
243
- >;
@@ -1,3 +1,4 @@
1
+ import { Cron } from "croner";
1
2
  import { z } from "zod";
2
3
 
3
4
  export const HeartbeatConfigSchema = z
@@ -12,6 +13,20 @@ export const HeartbeatConfigSchema = z
12
13
  .positive("heartbeat.intervalMs must be a positive integer")
13
14
  .default(6 * 3_600_000)
14
15
  .describe("Time between heartbeat checks in milliseconds"),
16
+ cronExpression: z
17
+ .string()
18
+ .nullable()
19
+ .default(null)
20
+ .describe(
21
+ "Cron expression for heartbeat timing. When set, heartbeats fire at the specified clock times instead of using intervalMs.",
22
+ ),
23
+ timezone: z
24
+ .string()
25
+ .nullable()
26
+ .default(null)
27
+ .describe(
28
+ "Timezone for cron expression evaluation, e.g. 'America/New_York'. Ignored when cronExpression is null.",
29
+ ),
15
30
  activeHoursStart: z
16
31
  .number({ error: "heartbeat.activeHoursStart must be a number" })
17
32
  .int("heartbeat.activeHoursStart must be an integer")
@@ -80,6 +95,54 @@ export const HeartbeatConfigSchema = z
80
95
  message,
81
96
  });
82
97
  }
98
+
99
+ // Validate cronExpression and timezone when cronExpression is set.
100
+ // Separate the validations so timezone errors are attributed to the
101
+ // timezone path — if both paths point at cronExpression, the config
102
+ // loader's delete-and-retry would strip cronExpression but leave the
103
+ // invalid timezone, cascading to a full defaults reset.
104
+ if (config.cronExpression != null) {
105
+ try {
106
+ new Cron(config.cronExpression, { maxRuns: 0 });
107
+ } catch (err) {
108
+ ctx.addIssue({
109
+ code: z.ZodIssueCode.custom,
110
+ path: ["cronExpression"],
111
+ message: err instanceof Error ? err.message : String(err),
112
+ });
113
+ }
114
+ if (config.timezone != null) {
115
+ try {
116
+ new Cron(config.cronExpression, {
117
+ maxRuns: 0,
118
+ timezone: config.timezone,
119
+ });
120
+ } catch {
121
+ // The cron expression itself is valid (or already flagged above),
122
+ // so a failure here is from the timezone.
123
+ try {
124
+ Intl.DateTimeFormat(undefined, { timeZone: config.timezone });
125
+ } catch (tzErr) {
126
+ ctx.addIssue({
127
+ code: z.ZodIssueCode.custom,
128
+ path: ["timezone"],
129
+ message: tzErr instanceof Error ? tzErr.message : String(tzErr),
130
+ });
131
+ }
132
+ }
133
+ }
134
+ } else if (config.timezone != null) {
135
+ // cronExpression is null but timezone is set — validate timezone independently
136
+ try {
137
+ Intl.DateTimeFormat(undefined, { timeZone: config.timezone });
138
+ } catch (err) {
139
+ ctx.addIssue({
140
+ code: z.ZodIssueCode.custom,
141
+ path: ["timezone"],
142
+ message: err instanceof Error ? err.message : String(err),
143
+ });
144
+ }
145
+ }
83
146
  });
84
147
 
85
148
  export type HeartbeatConfig = z.infer<typeof HeartbeatConfigSchema>;