@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
@@ -4,6 +4,7 @@ import type { AssistantEvent } from "../runtime/assistant-event.js";
4
4
  import {
5
5
  formatSseFrame,
6
6
  formatSseHeartbeat,
7
+ formatSseHeartbeatWithData,
7
8
  } from "../runtime/assistant-event.js";
8
9
 
9
10
  // ── Type / shape tests ────────────────────────────────────────────────────────
@@ -125,3 +126,12 @@ describe("formatSseHeartbeat", () => {
125
126
  expect(formatSseHeartbeat().startsWith(":")).toBe(true);
126
127
  });
127
128
  });
129
+
130
+ describe("formatSseHeartbeatWithData", () => {
131
+ test("includes both a comment and a data-bearing event", () => {
132
+ const hb = formatSseHeartbeatWithData();
133
+ expect(hb).toContain(": heartbeat\n\n");
134
+ expect(hb).toContain("event: assistant_event\n");
135
+ expect(hb).toContain('data: {"type":"heartbeat"}\n');
136
+ });
137
+ });
@@ -261,7 +261,8 @@ describe("SSE route — heartbeat", () => {
261
261
  reader.cancel();
262
262
 
263
263
  const text = new TextDecoder().decode(value);
264
- expect(text).toBe(": heartbeat\n\n");
264
+ expect(text).toContain(": heartbeat");
265
+ expect(text).toContain('{"type":"heartbeat"}');
265
266
  });
266
267
 
267
268
  test("emits multiple heartbeats over time", async () => {
@@ -297,7 +298,11 @@ describe("SSE route — heartbeat", () => {
297
298
  reader.cancel();
298
299
 
299
300
  expect(chunks.length).toBeGreaterThan(0);
300
- expect(chunks.every((c) => c === ": heartbeat\n\n")).toBe(true);
301
+ expect(
302
+ chunks.every(
303
+ (c) => c.includes(": heartbeat") && c.includes('{"type":"heartbeat"}'),
304
+ ),
305
+ ).toBe(true);
301
306
  });
302
307
  });
303
308
 
@@ -12,7 +12,7 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
12
12
  // Test-scoped config state
13
13
  // ---------------------------------------------------------------------------
14
14
 
15
- const DECLARED_FLAG_ID = "sounds";
15
+ const DECLARED_FLAG_ID = "email-channel";
16
16
  const DECLARED_FLAG_KEY = DECLARED_FLAG_ID;
17
17
 
18
18
  const { isAssistantFeatureFlagEnabled, _setOverridesForTesting } =
@@ -54,10 +54,12 @@ describe("isAssistantFeatureFlagEnabled", () => {
54
54
 
55
55
  test("missing persisted value falls back to defaults registry defaultEnabled", () => {
56
56
  // No explicit config at all — should fall back to defaults registry
57
- // which has defaultEnabled: true for sounds
57
+ // which has defaultEnabled: false for email-channel
58
58
  const config = {} as any;
59
59
 
60
- expect(isAssistantFeatureFlagEnabled(DECLARED_FLAG_KEY, config)).toBe(true);
60
+ expect(isAssistantFeatureFlagEnabled(DECLARED_FLAG_KEY, config)).toBe(
61
+ false,
62
+ );
61
63
  });
62
64
 
63
65
  test("unknown flag defaults to true when no persisted override", () => {
@@ -67,10 +69,12 @@ describe("isAssistantFeatureFlagEnabled", () => {
67
69
  });
68
70
 
69
71
  test("undeclared flag respects persisted override", () => {
70
- _setOverridesForTesting({ browser: false });
72
+ _setOverridesForTesting({ "some-undeclared-flag": false });
71
73
  const config = {} as any;
72
74
 
73
- expect(isAssistantFeatureFlagEnabled("browser", config)).toBe(false);
75
+ expect(isAssistantFeatureFlagEnabled("some-undeclared-flag", config)).toBe(
76
+ false,
77
+ );
74
78
  });
75
79
  });
76
80
 
@@ -87,7 +91,7 @@ describe("isAssistantFeatureFlagEnabled with skillFlagKey", () => {
87
91
  ).toBe(false);
88
92
  });
89
93
 
90
- test("enabled when no override set (registry default is true)", () => {
94
+ test("disabled when no override set (registry default is false)", () => {
91
95
  const config = {} as any;
92
96
 
93
97
  expect(
@@ -95,6 +99,6 @@ describe("isAssistantFeatureFlagEnabled with skillFlagKey", () => {
95
99
  skillFlagKey({ featureFlag: DECLARED_FLAG_ID })!,
96
100
  config,
97
101
  ),
98
- ).toBe(true);
102
+ ).toBe(false);
99
103
  });
100
104
  });
@@ -74,7 +74,6 @@ mock.module("../config/loader.js", () => ({
74
74
  getConfig: () => mockConfig,
75
75
  loadConfig: () => mockConfig,
76
76
  invalidateConfigCache: () => {},
77
- saveConfig: () => {},
78
77
  loadRawConfig: () => ({}),
79
78
  saveRawConfig: () => {},
80
79
  getNestedValue: () => undefined,
@@ -91,10 +90,16 @@ mock.module("../util/logger.js", () => ({
91
90
  // Mock HostBashProxy singleton — proxy delegation tests configure this.
92
91
  let mockProxyAvailable = false;
93
92
  let mockProxyRequestImpl: (
94
- input: { command: string; working_dir?: string; timeout_seconds?: number; env?: Record<string, string> },
93
+ input: {
94
+ command: string;
95
+ working_dir?: string;
96
+ timeout_seconds?: number;
97
+ env?: Record<string, string>;
98
+ },
95
99
  conversationId: string,
96
100
  signal?: AbortSignal,
97
- ) => Promise<ToolExecutionResult> = () => Promise.resolve({ content: "", isError: false });
101
+ ) => Promise<ToolExecutionResult> = () =>
102
+ Promise.resolve({ content: "", isError: false });
98
103
 
99
104
  mock.module("../daemon/host-bash-proxy.js", () => ({
100
105
  HostBashProxy: {
@@ -182,8 +187,7 @@ describe("host_bash background mode — proxy path", () => {
182
187
  };
183
188
  setupMockProxy(proxyResult);
184
189
 
185
- const ctx = makeContext({
186
- });
190
+ const ctx = makeContext({});
187
191
 
188
192
  const result = await hostShellTool.execute(
189
193
  { command: "echo bg-proxy", background: true },
@@ -203,8 +207,7 @@ describe("host_bash background mode — proxy path", () => {
203
207
  };
204
208
  setupMockProxy(proxyResult);
205
209
 
206
- const ctx = makeContext({
207
- });
210
+ const ctx = makeContext({});
208
211
 
209
212
  await hostShellTool.execute(
210
213
  { command: "echo bg-proxy", background: true },
@@ -227,8 +230,7 @@ describe("host_bash background mode — proxy path", () => {
227
230
  };
228
231
  setupMockProxy(proxyResult);
229
232
 
230
- const ctx = makeContext({
231
- });
233
+ const ctx = makeContext({});
232
234
 
233
235
  await hostShellTool.execute(
234
236
  { command: "echo bg-proxy", background: true },
@@ -257,8 +259,7 @@ describe("host_bash background mode — proxy path", () => {
257
259
  };
258
260
  setupMockProxy(proxyResult);
259
261
 
260
- const ctx = makeContext({
261
- });
262
+ const ctx = makeContext({});
262
263
 
263
264
  await hostShellTool.execute(
264
265
  { command: "bad-command", background: true },
@@ -280,8 +281,7 @@ describe("host_bash background mode — proxy path", () => {
280
281
  mockProxyRequestImpl = () =>
281
282
  Promise.reject(new Error("proxy transport error"));
282
283
 
283
- const ctx = makeContext({
284
- });
284
+ const ctx = makeContext({});
285
285
 
286
286
  await hostShellTool.execute(
287
287
  { command: "echo fail", background: true },
@@ -305,8 +305,7 @@ describe("host_bash background mode — proxy path", () => {
305
305
  };
306
306
  setupMockProxy(proxyResult);
307
307
 
308
- const ctx = makeContext({
309
- });
308
+ const ctx = makeContext({});
310
309
 
311
310
  const result = await hostShellTool.execute(
312
311
  { command: "echo bg-proxy", background: true },
@@ -0,0 +1,44 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import {
4
+ BOOTSTRAP_CLEANUP_USER_TURN_THRESHOLD,
5
+ countBootstrapUserTurns,
6
+ shouldCleanupBootstrapAfterTurn,
7
+ } from "../daemon/bootstrap-turn-cleanup.js";
8
+
9
+ function message(role: string, content: string) {
10
+ return { role, content };
11
+ }
12
+
13
+ describe("bootstrap turn cleanup", () => {
14
+ test("does not count the hidden wake-up greeting as a user turn", () => {
15
+ const messages = [
16
+ message(
17
+ "user",
18
+ JSON.stringify([{ type: "text", text: "Wake up, my friend." }]),
19
+ ),
20
+ message("assistant", "hello"),
21
+ message("user", "real request"),
22
+ ];
23
+
24
+ expect(countBootstrapUserTurns(messages)).toBe(1);
25
+ });
26
+
27
+ test("cleans up after the configured user-turn threshold", () => {
28
+ const messages = Array.from(
29
+ { length: BOOTSTRAP_CLEANUP_USER_TURN_THRESHOLD },
30
+ (_value, index) => message("user", `request ${index + 1}`),
31
+ );
32
+
33
+ expect(shouldCleanupBootstrapAfterTurn(messages)).toBe(true);
34
+ });
35
+
36
+ test("keeps bootstrap before the configured user-turn threshold", () => {
37
+ const messages = Array.from(
38
+ { length: BOOTSTRAP_CLEANUP_USER_TURN_THRESHOLD - 1 },
39
+ (_value, index) => message("user", `request ${index + 1}`),
40
+ );
41
+
42
+ expect(shouldCleanupBootstrapAfterTurn(messages)).toBe(false);
43
+ });
44
+ });
@@ -73,13 +73,16 @@ mock.module("../prompts/persona-resolver.js", () => ({
73
73
 
74
74
  mock.module("../runtime/routes/identity-intro-cache.js", () => ({
75
75
  getCachedIntro: () => null,
76
+ readWorkspaceIdentityIntro: () => null,
76
77
  setCachedIntro: () => {},
77
78
  computeIdentityContentHash: () => "test-hash",
78
79
  }));
79
80
 
80
81
  // Mock getOrCreateConversation from conversation-store so the handler
81
82
  // never touches DaemonServer.
82
- const mockGetOrCreateConversation = mock(async (_id: string) => makeMockSession());
83
+ const mockGetOrCreateConversation = mock(async (_id: string) =>
84
+ makeMockSession(),
85
+ );
83
86
 
84
87
  mock.module("../daemon/conversation-store.js", () => ({
85
88
  getOrCreateConversation: mockGetOrCreateConversation,
@@ -114,7 +117,10 @@ import type {
114
117
  SendMessageOptions,
115
118
  } from "../providers/types.js";
116
119
  import { ROUTES } from "../runtime/routes/btw-routes.js";
117
- import { BadRequestError, ServiceUnavailableError } from "../runtime/routes/errors.js";
120
+ import {
121
+ BadRequestError,
122
+ ServiceUnavailableError,
123
+ } from "../runtime/routes/errors.js";
118
124
  import type { RouteHandlerArgs } from "../runtime/routes/types.js";
119
125
 
120
126
  // ---------------------------------------------------------------------------
@@ -199,7 +205,8 @@ async function readStream(stream: ReadableStream<Uint8Array>): Promise<string> {
199
205
  chunks.push(value);
200
206
  }
201
207
  return new TextDecoder().decode(
202
- new Uint8Array(chunks.reduce((a, c) => a + c.length, 0)).buffer.byteLength === 0
208
+ new Uint8Array(chunks.reduce((a, c) => a + c.length, 0)).buffer
209
+ .byteLength === 0
203
210
  ? new Uint8Array(0)
204
211
  : Buffer.concat(chunks),
205
212
  );
@@ -415,6 +422,8 @@ describe("POST /v1/btw", () => {
415
422
  });
416
423
  await readStream(result as ReadableStream<Uint8Array>);
417
424
 
418
- expect(mockGetOrCreateConversation).toHaveBeenCalledWith("existing-conv-id");
425
+ expect(mockGetOrCreateConversation).toHaveBeenCalledWith(
426
+ "existing-conv-id",
427
+ );
419
428
  });
420
429
  });
@@ -38,6 +38,10 @@ mock.module("../config/loader.js", () => {
38
38
  },
39
39
  memory: { enabled: false },
40
40
  notifications: {},
41
+ ingress: {
42
+ enabled: true,
43
+ publicBaseUrl: "https://generic.example.com",
44
+ },
41
45
  services: {
42
46
  tts: {
43
47
  mode: "your-own" as const,
@@ -77,7 +81,6 @@ mock.module("../config/loader.js", () => {
77
81
  getConfig: () => config,
78
82
  loadConfig: () => config,
79
83
  loadRawConfig: () => ({}),
80
- saveConfig: () => {},
81
84
  saveRawConfig: () => {},
82
85
  invalidateConfigCache: () => {},
83
86
  applyNestedDefaults: (c: unknown) => c,
@@ -468,6 +471,7 @@ describe("call-controller", () => {
468
471
  const cfg = loadConfig();
469
472
  cfg.services.tts.provider = "elevenlabs";
470
473
  cfg.services.tts.providers["fish-audio"].referenceId = "";
474
+ cfg.ingress.publicBaseUrl = "https://generic.example.com";
471
475
  // Reset TTS provider registry to ensure clean state
472
476
  registerTestTtsProviders();
473
477
  });
@@ -2532,6 +2536,50 @@ describe("call-controller", () => {
2532
2536
  controller.destroy();
2533
2537
  });
2534
2538
 
2539
+ test("synthesized provider: play URL uses public base URL", async () => {
2540
+ const cfg = loadConfig();
2541
+ cfg.ingress.publicBaseUrl = "https://twilio.example.com/";
2542
+ cfg.services.tts.provider = "fish-audio";
2543
+ cfg.services.tts.providers["fish-audio"].referenceId = "fish-ref-123";
2544
+
2545
+ _resetTtsProviderRegistry();
2546
+ const fishAudioStreaming: TtsProvider = {
2547
+ id: "fish-audio",
2548
+ capabilities: {
2549
+ supportsStreaming: true,
2550
+ supportedFormats: ["mp3", "wav", "opus"],
2551
+ },
2552
+ async synthesize() {
2553
+ return {
2554
+ audio: Buffer.from("fish-audio-buffer"),
2555
+ contentType: "audio/mpeg",
2556
+ };
2557
+ },
2558
+ async synthesizeStream(_request, onChunk) {
2559
+ onChunk(Buffer.from("fish-audio-stream"));
2560
+ return {
2561
+ audio: Buffer.from("fish-audio-stream"),
2562
+ contentType: "audio/mpeg",
2563
+ };
2564
+ },
2565
+ };
2566
+ registerTtsProvider(fishAudioStreaming);
2567
+
2568
+ mockStartVoiceTurn.mockImplementation(
2569
+ createMockVoiceTurn(["Hello from synthesized path."]),
2570
+ );
2571
+ const { relay, controller } = setupController();
2572
+
2573
+ await controller.handleCallerUtterance("Hi");
2574
+
2575
+ expect(relay.sentPlayUrls.length).toBeGreaterThan(0);
2576
+ expect(relay.sentPlayUrls[0]).toStartWith(
2577
+ "https://twilio.example.com/v1/audio/",
2578
+ );
2579
+
2580
+ controller.destroy();
2581
+ });
2582
+
2535
2583
  test("Deepgram selected path resolves useSynthesizedPath to true", () => {
2536
2584
  const cfg = loadConfig();
2537
2585
  cfg.services.tts.provider = "deepgram";
@@ -28,8 +28,6 @@ mock.module("../calls/twilio-config.js", () => ({
28
28
  accountSid: "AC_test",
29
29
  authToken: "test_token",
30
30
  phoneNumber: assistantId === "ast-alpha" ? "+15550003333" : "+15550001111",
31
- webhookBaseUrl: "https://test.example.com",
32
- wssBaseUrl: "wss://test.example.com",
33
31
  }),
34
32
  }));
35
33
 
@@ -77,8 +77,6 @@ mock.module("../calls/twilio-config.js", () => ({
77
77
  accountSid: "AC_test",
78
78
  authToken: "test_token",
79
79
  phoneNumber: assistantId === "asst-alpha" ? "+15550009999" : "+15550001111",
80
- webhookBaseUrl: "https://test.example.com",
81
- wssBaseUrl: "wss://test.example.com",
82
80
  }),
83
81
  }));
84
82
 
@@ -292,7 +292,7 @@ describe("ChannelReadinessService", () => {
292
292
  test("phone readiness accepts managed callback routing when ingress is absent", async () => {
293
293
  mockGetIsPlatform = true;
294
294
  mockHasTwilioCredentials = true;
295
- mockTwilioPhoneNumber = "+15555550123";
295
+ mockTwilioPhoneNumber = "+15550123";
296
296
 
297
297
  const readiness = createReadinessService();
298
298
  const [snapshot] = await readiness.getReadiness("phone");
@@ -305,6 +305,64 @@ describe("ChannelReadinessService", () => {
305
305
  });
306
306
  });
307
307
 
308
+ test("phone readiness accepts Twilio-specific ingress without generic public ingress", async () => {
309
+ mockHasTwilioCredentials = true;
310
+ mockTwilioPhoneNumber = "+15550123";
311
+ mockRawConfig = {
312
+ ingress: {
313
+ publicBaseUrl: "https://twilio.example.com",
314
+ },
315
+ };
316
+
317
+ const readiness = createReadinessService();
318
+ const [snapshot] = await readiness.getReadiness("phone");
319
+
320
+ expect(snapshot.ready).toBe(true);
321
+ expect(snapshot.localChecks).toContainEqual({
322
+ name: "ingress",
323
+ passed: true,
324
+ message: "Twilio public ingress URL is configured",
325
+ });
326
+ });
327
+
328
+ test("phone readiness fails when publicBaseUrl is whitespace only", async () => {
329
+ mockHasTwilioCredentials = true;
330
+ mockTwilioPhoneNumber = "+15550123";
331
+ mockRawConfig = {
332
+ ingress: {
333
+ publicBaseUrl: " ",
334
+ },
335
+ };
336
+
337
+ const readiness = createReadinessService();
338
+ const [snapshot] = await readiness.getReadiness("phone");
339
+
340
+ expect(snapshot.ready).toBe(false);
341
+ expect(snapshot.reasons).toContainEqual({
342
+ code: "ingress",
343
+ text: "No Twilio public ingress URL or managed callback route is configured",
344
+ });
345
+ });
346
+
347
+ test("telegram readiness fails when publicBaseUrl is empty", async () => {
348
+ mockSecureKeys[credentialKey("telegram", "bot_token")] = "123:abc";
349
+ mockSecureKeys[credentialKey("telegram", "webhook_secret")] = "secret";
350
+ mockRawConfig = {
351
+ ingress: {
352
+ publicBaseUrl: "",
353
+ },
354
+ };
355
+
356
+ const readiness = createReadinessService();
357
+ const [snapshot] = await readiness.getReadiness("telegram");
358
+
359
+ expect(snapshot.ready).toBe(false);
360
+ expect(snapshot.reasons).toContainEqual({
361
+ code: "ingress",
362
+ text: "No public ingress URL or managed callback route is configured",
363
+ });
364
+ });
365
+
308
366
  test("getReadiness with no channel returns all registered channels", async () => {
309
367
  service.registerProbe(
310
368
  makeProbe("phone", [{ name: "a", passed: true, message: "ok" }]),
@@ -51,7 +51,6 @@ mock.module("../config/loader.js", () => ({
51
51
  getConfig: () => testConfig,
52
52
  loadConfig: () => testConfig,
53
53
  invalidateConfigCache: () => {},
54
- saveConfig: () => {},
55
54
  loadRawConfig: () => ({}),
56
55
  saveRawConfig: () => {},
57
56
  getNestedValue: () => undefined,
@@ -117,14 +116,14 @@ import * as platformModule from "../util/platform.js";
117
116
  /** Default gateway thresholds matching the old config fallback defaults. */
118
117
  const DEFAULT_GATEWAY_THRESHOLDS = {
119
118
  interactive: "low",
120
- background: "medium",
119
+ autonomous: "medium",
121
120
  headless: "none",
122
121
  } as const;
123
122
 
124
123
  /** Strict gateway thresholds — equivalent to autoApproveUpTo: "none". */
125
124
  const STRICT_GATEWAY_THRESHOLDS = {
126
125
  interactive: "none",
127
- background: "none",
126
+ autonomous: "none",
128
127
  headless: "none",
129
128
  } as const;
130
129
 
@@ -201,7 +200,7 @@ describe("Permission Checker", () => {
201
200
  beforeEach(() => {
202
201
  // Reset IPC mock to low risk (tests override as needed)
203
202
  mockRisk("low");
204
- // Default gateway threshold (conversation: low, background: medium, headless: none)
203
+ // Default gateway threshold (interactive: low, autonomous: medium, headless: none)
205
204
  mockIpcResponse("get_global_thresholds", DEFAULT_GATEWAY_THRESHOLDS);
206
205
  // Clear the gateway threshold cache so each test gets a fresh threshold read
207
206
  _clearGlobalCacheForTesting();