@vellumai/assistant 0.7.0 → 0.7.1

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 (666) hide show
  1. package/ARCHITECTURE.md +6 -7
  2. package/Dockerfile +1 -0
  3. package/README.md +2 -2
  4. package/__tests__/permissions/gateway-threshold-reader.test.ts +79 -139
  5. package/bun.lock +3 -0
  6. package/docs/architecture/security.md +18 -16
  7. package/knip.json +1 -0
  8. package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +1 -5
  9. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -5
  10. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -16
  11. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +1 -9
  12. package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +12 -12
  13. package/node_modules/@vellumai/slack-text/bun.lock +24 -0
  14. package/node_modules/@vellumai/slack-text/package.json +18 -0
  15. package/node_modules/@vellumai/slack-text/src/index.test.ts +153 -0
  16. package/node_modules/@vellumai/slack-text/src/index.ts +235 -0
  17. package/node_modules/@vellumai/slack-text/tsconfig.json +20 -0
  18. package/openapi.yaml +294 -107
  19. package/package.json +4 -2
  20. package/scripts/generate-openapi.ts +16 -111
  21. package/src/__tests__/agent-wake-override-profile.test.ts +23 -1
  22. package/src/__tests__/anthropic-provider.test.ts +56 -13
  23. package/src/__tests__/app-conversation-ids-backfill.test.ts +278 -0
  24. package/src/__tests__/app-conversation-ids.test.ts +151 -0
  25. package/src/__tests__/approval-cascade.test.ts +0 -15
  26. package/src/__tests__/approval-routes-http.test.ts +6 -17
  27. package/src/__tests__/assistant-event-hub.test.ts +126 -77
  28. package/src/__tests__/assistant-event.test.ts +0 -5
  29. package/src/__tests__/assistant-events-sse-hardening.test.ts +37 -15
  30. package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -29
  31. package/src/__tests__/background-shell-host-bash.test.ts +34 -43
  32. package/src/__tests__/call-controller.test.ts +1 -1
  33. package/src/__tests__/call-site-routing-provider.test.ts +193 -0
  34. package/src/__tests__/channel-approval-routes.test.ts +10 -296
  35. package/src/__tests__/channel-approvals.test.ts +25 -17
  36. package/src/__tests__/channel-guardian.test.ts +100 -146
  37. package/src/__tests__/checker.test.ts +20 -34
  38. package/src/__tests__/compact-event-conversation-id-guard.test.ts +50 -0
  39. package/src/__tests__/compaction-events.test.ts +2 -0
  40. package/src/__tests__/config-schema.test.ts +6 -48
  41. package/src/__tests__/config-watcher.test.ts +12 -0
  42. package/src/__tests__/connection-policy.test.ts +1 -52
  43. package/src/__tests__/contacts-write.test.ts +2 -64
  44. package/src/__tests__/context-image-dimensions.test.ts +1 -1
  45. package/src/__tests__/context-search-memory-source.test.ts +120 -1
  46. package/src/__tests__/context-search-memory-v2-source.test.ts +383 -0
  47. package/src/__tests__/context-search-pkb-source.test.ts +49 -0
  48. package/src/__tests__/context-search-workspace-source.test.ts +9 -22
  49. package/src/__tests__/context-window-manager.test.ts +46 -0
  50. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
  51. package/src/__tests__/conversation-agent-loop-overflow.test.ts +102 -29
  52. package/src/__tests__/conversation-agent-loop.test.ts +980 -13
  53. package/src/__tests__/conversation-analysis-routes.test.ts +12 -10
  54. package/src/__tests__/conversation-attention-telegram.test.ts +11 -3
  55. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -291
  56. package/src/__tests__/conversation-history-web-search.test.ts +4 -3
  57. package/src/__tests__/conversation-inference-profile-route.test.ts +12 -23
  58. package/src/__tests__/conversation-lifecycle.test.ts +4 -4
  59. package/src/__tests__/conversation-process-callsite.test.ts +79 -2
  60. package/src/__tests__/conversation-queue.test.ts +3 -8
  61. package/src/__tests__/conversation-routes-disk-view.test.ts +1 -161
  62. package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -32
  63. package/src/__tests__/conversation-routes-slash-commands.test.ts +75 -66
  64. package/src/__tests__/conversation-runtime-assembly.test.ts +257 -3
  65. package/src/__tests__/conversation-slash-commands.test.ts +24 -4
  66. package/src/__tests__/conversation-slash-queue.test.ts +2 -0
  67. package/src/__tests__/conversation-speed-override.test.ts +0 -3
  68. package/src/__tests__/conversation-starter-routes.test.ts +79 -2
  69. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -5
  70. package/src/__tests__/conversation-surfaces-standalone.test.ts +18 -14
  71. package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -2
  72. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +8 -46
  73. package/src/__tests__/conversation-usage.test.ts +253 -3
  74. package/src/__tests__/credential-execution-shell-lockdown.test.ts +0 -39
  75. package/src/__tests__/credential-health-service.test.ts +68 -0
  76. package/src/__tests__/credential-security-e2e.test.ts +4 -3
  77. package/src/__tests__/credential-security-invariants.test.ts +1 -5
  78. package/src/__tests__/credential-token-resolver.test.ts +180 -0
  79. package/src/__tests__/cu-unified-flow.test.ts +33 -16
  80. package/src/__tests__/daemon-assistant-events.test.ts +34 -21
  81. package/src/__tests__/daemon-credential-client.test.ts +4 -1
  82. package/src/__tests__/db-connection-isolation.test.ts +125 -0
  83. package/src/__tests__/db-migration-rollback.test.ts +101 -0
  84. package/src/__tests__/db-slack-compaction-watermark-migration.test.ts +169 -0
  85. package/src/__tests__/deterministic-verification-control-plane.test.ts +7 -80
  86. package/src/__tests__/document-conversations.test.ts +332 -0
  87. package/src/__tests__/embedding-managed-proxy-selection.test.ts +2 -2
  88. package/src/__tests__/emit-event-signal.test.ts +4 -6
  89. package/src/__tests__/events-client-registration.test.ts +193 -49
  90. package/src/__tests__/filing-service.test.ts +58 -7
  91. package/src/__tests__/first-greeting.test.ts +156 -150
  92. package/src/__tests__/fixtures/mock-chrome-extension.ts +108 -66
  93. package/src/__tests__/get-skill-detail-audit.test.ts +3 -8
  94. package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
  95. package/src/__tests__/guardian-dispatch.test.ts +1 -1
  96. package/src/__tests__/guardian-grant-minting.test.ts +7 -2
  97. package/src/__tests__/guardian-routing-invariants.test.ts +7 -2
  98. package/src/__tests__/guardian-routing-state.test.ts +1 -1
  99. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +32 -11
  100. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -83
  101. package/src/__tests__/headless-browser-mode.test.ts +4 -9
  102. package/src/__tests__/headless-browser-navigate.test.ts +21 -20
  103. package/src/__tests__/heartbeat-service.test.ts +289 -7
  104. package/src/__tests__/helpers/channel-test-adapter.ts +2 -2
  105. package/src/__tests__/helpers/create-guardian-binding.ts +91 -0
  106. package/src/__tests__/host-bash-proxy.test.ts +46 -122
  107. package/src/__tests__/host-browser-e2e-cloud.test.ts +36 -497
  108. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +26 -96
  109. package/src/__tests__/host-browser-proxy.test.ts +111 -185
  110. package/src/__tests__/host-browser-routes.test.ts +45 -75
  111. package/src/__tests__/host-browser-ws-events-e2e.test.ts +26 -30
  112. package/src/__tests__/host-cu-proxy.test.ts +56 -111
  113. package/src/__tests__/host-file-proxy.test.ts +44 -98
  114. package/src/__tests__/host-file-read-tool.test.ts +42 -21
  115. package/src/__tests__/host-shell-tool.test.ts +33 -68
  116. package/src/__tests__/host-transfer-pending-interactions.test.ts +2 -18
  117. package/src/__tests__/host-transfer-proxy.test.ts +43 -53
  118. package/src/__tests__/http-user-message-parity.test.ts +0 -6
  119. package/src/__tests__/inbound-slack-persistence.test.ts +31 -0
  120. package/src/__tests__/injector-chain.test.ts +10 -5
  121. package/src/__tests__/injector-pkb-v2-silenced.test.ts +124 -0
  122. package/src/__tests__/inline-command-runner.test.ts +0 -66
  123. package/src/__tests__/inline-skill-load-permissions.test.ts +0 -2
  124. package/src/__tests__/install-skill-routing.test.ts +1 -13
  125. package/src/__tests__/llm-callsite-catalog.test.ts +34 -0
  126. package/src/__tests__/llm-catalog-parity.test.ts +90 -0
  127. package/src/__tests__/llm-context-resolution.test.ts +180 -0
  128. package/src/__tests__/llm-resolver.test.ts +80 -12
  129. package/src/__tests__/llm-usage-store.test.ts +269 -4
  130. package/src/__tests__/log-export-routes.test.ts +89 -0
  131. package/src/__tests__/managed-profile-guard.test.ts +225 -0
  132. package/src/__tests__/managed-skill-lifecycle.test.ts +0 -10
  133. package/src/__tests__/manual-token-reconciliation.test.ts +334 -0
  134. package/src/__tests__/memory-v2-static-injector.test.ts +95 -0
  135. package/src/__tests__/migration-cross-version-compatibility.test.ts +197 -291
  136. package/src/__tests__/migration-export-http.test.ts +33 -26
  137. package/src/__tests__/migration-export-streaming.test.ts +18 -10
  138. package/src/__tests__/migration-export-to-gcs.test.ts +49 -9
  139. package/src/__tests__/migration-import-commit-http.test.ts +66 -21
  140. package/src/__tests__/migration-import-from-gcs.test.ts +50 -9
  141. package/src/__tests__/migration-import-from-url.test.ts +20 -6
  142. package/src/__tests__/migration-import-preflight-http.test.ts +95 -95
  143. package/src/__tests__/migration-parity-persistence.test.ts +62 -25
  144. package/src/__tests__/migration-transport.test.ts +115 -23
  145. package/src/__tests__/migration-validate-http.test.ts +105 -80
  146. package/src/__tests__/migration-wizard.test.ts +133 -27
  147. package/src/__tests__/non-member-access-request.test.ts +1 -1
  148. package/src/__tests__/notification-guardian-path.test.ts +1 -1
  149. package/src/__tests__/oauth-store.test.ts +19 -0
  150. package/src/__tests__/platform-bash-auto-approve.test.ts +21 -12
  151. package/src/__tests__/prechat-onboarding-contract.test.ts +31 -7
  152. package/src/__tests__/pricing.test.ts +68 -4
  153. package/src/__tests__/process-message-background-slack.test.ts +331 -0
  154. package/src/__tests__/provider-managed-proxy-integration.test.ts +153 -17
  155. package/src/__tests__/provider-send-message-override-profile.test.ts +50 -0
  156. package/src/__tests__/provider-usage-tracking.test.ts +208 -0
  157. package/src/__tests__/reaction-persistence.test.ts +9 -6
  158. package/src/__tests__/rebind-secrets-screen.test.ts +53 -16
  159. package/src/__tests__/recording-handler.test.ts +64 -81
  160. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +4 -3
  161. package/src/__tests__/relay-server.test.ts +18 -13
  162. package/src/__tests__/require-fresh-approval.test.ts +13 -22
  163. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
  164. package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
  165. package/src/__tests__/runtime-events-sse.test.ts +3 -12
  166. package/src/__tests__/search-skills-unified.test.ts +9 -15
  167. package/src/__tests__/secret-ingress-cli.test.ts +2 -5
  168. package/src/__tests__/secret-ingress-http.test.ts +0 -4
  169. package/src/__tests__/secret-onetime-send.test.ts +4 -2
  170. package/src/__tests__/secret-prompt-log-hygiene.test.ts +24 -7
  171. package/src/__tests__/secret-prompter-channel-fallback.test.ts +42 -47
  172. package/src/__tests__/secret-response-routing.test.ts +29 -15
  173. package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -1
  174. package/src/__tests__/secret-scanner.test.ts +2 -545
  175. package/src/__tests__/send-endpoint-busy.test.ts +9 -24
  176. package/src/__tests__/settings-routes.test.ts +1 -1
  177. package/src/__tests__/shell-credential-ref.test.ts +0 -8
  178. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -56
  179. package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -11
  180. package/src/__tests__/skill-tool-factory.test.ts +97 -0
  181. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -30
  182. package/src/__tests__/skills-files-catalog-fallback.test.ts +11 -17
  183. package/src/__tests__/slack-inbound-verification.test.ts +1 -62
  184. package/src/__tests__/subagent-fork-notifications.test.ts +57 -47
  185. package/src/__tests__/subagent-manager-notify.test.ts +70 -70
  186. package/src/__tests__/subagent-notify-parent.test.ts +80 -83
  187. package/src/__tests__/system-prompt.test.ts +115 -13
  188. package/src/__tests__/terminal-tools.test.ts +0 -89
  189. package/src/__tests__/thread-backfill.test.ts +945 -31
  190. package/src/__tests__/tool-domain-event-publisher.test.ts +0 -36
  191. package/src/__tests__/tool-execute-pipeline.test.ts +0 -6
  192. package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -16
  193. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +9 -19
  194. package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -7
  195. package/src/__tests__/tool-executor.test.ts +12 -19
  196. package/src/__tests__/tool-metrics-listener.test.ts +0 -35
  197. package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
  198. package/src/__tests__/tool-trace-listener.test.ts +0 -17
  199. package/src/__tests__/transfer-progress-screen.test.ts +63 -26
  200. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -149
  201. package/src/__tests__/trusted-contact-multichannel.test.ts +2 -4
  202. package/src/__tests__/trusted-contact-verification.test.ts +1 -1
  203. package/src/__tests__/tts-catalog-parity.test.ts +16 -5
  204. package/src/__tests__/usage-attribution.test.ts +247 -0
  205. package/src/__tests__/usage-cli.test.ts +143 -0
  206. package/src/__tests__/usage-grouped-buckets.test.ts +155 -0
  207. package/src/__tests__/usage-routes.test.ts +150 -0
  208. package/src/__tests__/validation-results-screen.test.ts +39 -16
  209. package/src/__tests__/vbundle-pax-and-symlink.test.ts +12 -3
  210. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +49 -137
  211. package/src/__tests__/verification-control-plane-policy.test.ts +4 -7
  212. package/src/__tests__/voice-session-bridge.test.ts +5 -5
  213. package/src/__tests__/workspace-migration-062-drop-memory-v2-edges-json.test.ts +103 -0
  214. package/src/__tests__/workspace-migration-063-release-notes-dynamic-model-context.test.ts +77 -0
  215. package/src/__tests__/workspace-migration-064-unwind-main-agent-opus-seed.test.ts +225 -0
  216. package/src/__tests__/workspace-migration-memory-v2-init.test.ts +8 -30
  217. package/src/acp/index.ts +0 -15
  218. package/src/acp/session-manager.ts +37 -34
  219. package/src/agent/loop.ts +16 -1
  220. package/src/approvals/AGENTS.md +4 -0
  221. package/src/approvals/__tests__/guardian-feed-event.test.ts +10 -3
  222. package/src/approvals/guardian-request-resolvers.ts +10 -2
  223. package/src/backup/__tests__/backup-worker.test.ts +36 -8
  224. package/src/backup/__tests__/paths.test.ts +2 -2
  225. package/src/backup/__tests__/restore.test.ts +45 -28
  226. package/src/backup/backup-worker.ts +36 -2
  227. package/src/backup/paths.ts +9 -6
  228. package/src/browser-session/events.ts +0 -9
  229. package/src/calls/call-store.ts +1 -34
  230. package/src/calls/guardian-question-copy.ts +0 -108
  231. package/src/calls/relay-server.ts +0 -24
  232. package/src/calls/twilio-rest.ts +0 -38
  233. package/src/calls/twilio-routes.ts +1 -1
  234. package/src/calls/voice-session-bridge.ts +7 -38
  235. package/src/channels/types.ts +1 -36
  236. package/src/cli/commands/__tests__/cache.test.ts +152 -5
  237. package/src/cli/commands/__tests__/memory-v2.test.ts +14 -28
  238. package/src/cli/commands/__tests__/trust.test.ts +21 -387
  239. package/src/cli/commands/backup.ts +4 -4
  240. package/src/cli/commands/cache-fs.ts +8 -0
  241. package/src/cli/commands/cache.ts +153 -82
  242. package/src/cli/commands/clients.ts +63 -5
  243. package/src/cli/commands/completions.ts +3 -3
  244. package/src/cli/commands/contacts.ts +231 -76
  245. package/src/cli/commands/keys.ts +4 -1
  246. package/src/cli/commands/memory-v2.ts +24 -52
  247. package/src/cli/commands/oauth/shared.ts +2 -29
  248. package/src/cli/commands/pending.ts +102 -0
  249. package/src/cli/commands/skills.ts +77 -35
  250. package/src/cli/commands/trust.ts +70 -430
  251. package/src/cli/commands/usage.ts +25 -16
  252. package/src/cli/lib/daemon-credential-client.ts +14 -0
  253. package/src/cli/program.ts +2 -0
  254. package/src/cli.ts +0 -21
  255. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  256. package/src/config/bundled-skills/messaging/TOOLS.json +14 -4
  257. package/src/config/env-registry.ts +12 -2
  258. package/src/config/env.ts +3 -14
  259. package/src/config/feature-flag-registry.json +30 -30
  260. package/src/config/llm-callsite-catalog.ts +12 -0
  261. package/src/config/llm-context-resolution.ts +80 -0
  262. package/src/config/llm-resolver.ts +58 -22
  263. package/src/config/loader.ts +3 -3
  264. package/src/config/schema.ts +2 -158
  265. package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
  266. package/src/config/schemas/call-site-catalog.ts +271 -0
  267. package/src/config/schemas/calls.ts +5 -5
  268. package/src/config/schemas/inference.ts +1 -1
  269. package/src/config/schemas/ingress.ts +1 -1
  270. package/src/config/schemas/llm.ts +31 -3
  271. package/src/config/schemas/memory-retrieval.ts +2 -2
  272. package/src/config/schemas/memory-v2.ts +9 -0
  273. package/src/config/schemas/security.ts +1 -42
  274. package/src/config/schemas/services.ts +6 -6
  275. package/src/config/schemas/skills.ts +5 -5
  276. package/src/config/schemas/tts.ts +1 -1
  277. package/src/config/seed-inference-profiles.ts +117 -0
  278. package/src/config/skills.ts +0 -90
  279. package/src/config/types.ts +3 -6
  280. package/src/contacts/contact-store.ts +0 -17
  281. package/src/contacts/contacts-write.ts +1 -105
  282. package/src/context/window-manager.ts +44 -5
  283. package/src/credential-execution/process-manager.ts +34 -10
  284. package/src/credential-health/credential-health-service.ts +21 -16
  285. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +75 -82
  286. package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -9
  287. package/src/daemon/connection-policy.ts +1 -26
  288. package/src/daemon/conversation-agent-loop-handlers.ts +53 -4
  289. package/src/daemon/conversation-agent-loop.ts +277 -36
  290. package/src/daemon/conversation-history.ts +8 -8
  291. package/src/daemon/conversation-launch.ts +20 -135
  292. package/src/daemon/conversation-lifecycle.ts +1 -1
  293. package/src/daemon/conversation-messaging.ts +1 -0
  294. package/src/daemon/conversation-process.ts +83 -163
  295. package/src/daemon/conversation-runtime-assembly.ts +219 -76
  296. package/src/daemon/conversation-slash.ts +47 -5
  297. package/src/daemon/conversation-store.ts +7 -31
  298. package/src/daemon/conversation-surfaces.ts +22 -28
  299. package/src/daemon/conversation-tool-setup.ts +3 -33
  300. package/src/daemon/conversation-usage.ts +36 -0
  301. package/src/daemon/conversation.ts +117 -233
  302. package/src/daemon/daemon-control.ts +3 -71
  303. package/src/daemon/daemon-skill-host.ts +8 -11
  304. package/src/daemon/dictation-profile-store.ts +2 -26
  305. package/src/daemon/first-greeting.ts +44 -156
  306. package/src/daemon/handlers/config-channels.ts +12 -12
  307. package/src/daemon/handlers/config-ingress.ts +4 -165
  308. package/src/daemon/handlers/config-model.ts +1 -1
  309. package/src/daemon/handlers/config-voice.ts +0 -42
  310. package/src/daemon/handlers/conversations.ts +11 -190
  311. package/src/daemon/handlers/recording.ts +26 -158
  312. package/src/daemon/handlers/shared.ts +23 -71
  313. package/src/daemon/handlers/skills.ts +42 -93
  314. package/src/daemon/host-bash-proxy.ts +67 -45
  315. package/src/daemon/host-browser-proxy.ts +65 -27
  316. package/src/daemon/host-cu-proxy.ts +40 -39
  317. package/src/daemon/host-file-proxy.ts +58 -37
  318. package/src/daemon/host-transfer-proxy.ts +84 -46
  319. package/src/daemon/lifecycle.ts +49 -15
  320. package/src/daemon/message-types/conversations.ts +7 -0
  321. package/src/daemon/message-types/host-bash.ts +1 -0
  322. package/src/daemon/message-types/host-cu.ts +1 -0
  323. package/src/daemon/message-types/host-file.ts +1 -0
  324. package/src/daemon/message-types/host-transfer.ts +1 -0
  325. package/src/daemon/message-types/messages.ts +10 -9
  326. package/src/daemon/message-types/workspace.ts +1 -1
  327. package/src/daemon/process-message.ts +102 -239
  328. package/src/daemon/server.ts +13 -462
  329. package/src/daemon/shutdown-handlers.ts +2 -2
  330. package/src/daemon/tool-side-effects.ts +125 -107
  331. package/src/daemon/trust-context.ts +13 -0
  332. package/src/daemon/wake-target-adapter.ts +4 -9
  333. package/src/events/domain-events.ts +0 -8
  334. package/src/events/tool-audit-listener.ts +3 -1
  335. package/src/events/tool-domain-event-publisher.ts +0 -10
  336. package/src/events/tool-metrics-listener.ts +0 -17
  337. package/src/events/tool-trace-listener.ts +0 -14
  338. package/src/filing/filing-service.ts +13 -1
  339. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +6 -2
  340. package/src/heartbeat/heartbeat-service.ts +23 -5
  341. package/src/home/__tests__/feed-writer.test.ts +0 -4
  342. package/src/home/__tests__/relationship-state-writer.test.ts +30 -0
  343. package/src/home/feed-writer.ts +1 -2
  344. package/src/home/relationship-state-writer.ts +16 -3
  345. package/src/ipc/__tests__/browser-ipc.test.ts +2 -12
  346. package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -1
  347. package/src/ipc/assistant-server.ts +3 -10
  348. package/src/ipc/routes/__tests__/memory-v2-backfill.test.ts +39 -20
  349. package/src/ipc/routes/route-adapter.ts +1 -1
  350. package/src/ipc/routes/trust-rules.test.ts +0 -95
  351. package/src/ipc/skill-ipc-types.ts +41 -0
  352. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +13 -27
  353. package/src/ipc/skill-routes/__tests__/identity.test.ts +4 -23
  354. package/src/ipc/skill-routes/events.ts +12 -23
  355. package/src/ipc/skill-routes/identity.ts +4 -17
  356. package/src/ipc/skill-routes/index.ts +1 -1
  357. package/src/ipc/skill-server.ts +6 -39
  358. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -8
  359. package/src/live-voice/protocol.ts +4 -13
  360. package/src/mcp/manager.ts +0 -5
  361. package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +55 -0
  362. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +127 -0
  363. package/src/memory/app-git-service.ts +0 -32
  364. package/src/memory/app-store.ts +154 -0
  365. package/src/memory/attachments-store.ts +6 -0
  366. package/src/memory/context-search/sources/memory-v2.ts +578 -0
  367. package/src/memory/context-search/sources/memory.ts +5 -0
  368. package/src/memory/context-search/sources/pkb.ts +10 -1
  369. package/src/memory/context-search/sources/workspace.ts +3 -2
  370. package/src/memory/conversation-crud.ts +29 -4
  371. package/src/memory/conversation-disk-view.ts +1 -5
  372. package/src/memory/conversation-starter-checkpoints.ts +63 -0
  373. package/src/memory/db-connection.ts +62 -0
  374. package/src/memory/db-init.ts +14 -0
  375. package/src/memory/embedding-backend.ts +3 -21
  376. package/src/memory/embedding-gemini.ts +0 -2
  377. package/src/memory/embedding-local.ts +6 -6
  378. package/src/memory/embedding-ollama.ts +6 -6
  379. package/src/memory/embedding-openai.ts +6 -6
  380. package/src/memory/embedding-types.ts +21 -0
  381. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +3 -7
  382. package/src/memory/graph/conversation-graph-memory.ts +35 -13
  383. package/src/memory/graph/injection.test.ts +2 -2
  384. package/src/memory/graph/injection.ts +1 -1
  385. package/src/memory/guardian-action-store.ts +0 -83
  386. package/src/memory/guardian-approvals.ts +0 -48
  387. package/src/memory/indexer.ts +1 -15
  388. package/src/memory/job-handlers/conversation-starters.ts +36 -53
  389. package/src/memory/job-utils.ts +0 -6
  390. package/src/memory/jobs-store.ts +0 -1
  391. package/src/memory/jobs-worker.ts +2 -16
  392. package/src/memory/llm-request-log-store.ts +0 -41
  393. package/src/memory/llm-usage-store.ts +129 -43
  394. package/src/memory/memory-v2-activation-log-store.ts +115 -0
  395. package/src/memory/migrations/233-document-conversations.ts +54 -0
  396. package/src/memory/migrations/234-memory-v2-activation-logs.ts +55 -0
  397. package/src/memory/migrations/235-llm-usage-attribution.ts +31 -0
  398. package/src/memory/migrations/235-slack-compaction-watermark.ts +44 -0
  399. package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +26 -0
  400. package/src/memory/migrations/__tests__/234-memory-v2-activation-logs.test.ts +182 -0
  401. package/src/memory/migrations/index.ts +14 -0
  402. package/src/memory/migrations/registry.ts +24 -0
  403. package/src/memory/raw-query.ts +2 -68
  404. package/src/memory/schema/conversations.ts +7 -0
  405. package/src/memory/schema/infrastructure.ts +25 -0
  406. package/src/memory/search/semantic.ts +5 -16
  407. package/src/memory/tool-usage-store.ts +2 -0
  408. package/src/memory/usage-buckets.ts +40 -1
  409. package/src/memory/usage-grouped-buckets.ts +127 -0
  410. package/src/memory/v2/__tests__/activation.test.ts +289 -90
  411. package/src/memory/v2/__tests__/backfill-jobs.test.ts +2 -129
  412. package/src/memory/v2/__tests__/consolidation-job.test.ts +28 -11
  413. package/src/memory/v2/__tests__/edge-index.test.ts +278 -0
  414. package/src/memory/v2/__tests__/injection.test.ts +384 -15
  415. package/src/memory/v2/__tests__/migration.test.ts +64 -36
  416. package/src/memory/v2/__tests__/page-store.test.ts +191 -8
  417. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +181 -0
  418. package/src/memory/v2/__tests__/skill-store.test.ts +115 -3
  419. package/src/memory/v2/__tests__/static-context.test.ts +153 -0
  420. package/src/memory/v2/activation.ts +168 -97
  421. package/src/memory/v2/backfill-jobs.ts +15 -100
  422. package/src/memory/v2/consolidation-job.ts +14 -12
  423. package/src/memory/v2/edge-index.ts +191 -0
  424. package/src/memory/v2/injection.ts +182 -58
  425. package/src/memory/v2/migration.ts +57 -64
  426. package/src/memory/v2/now-text.ts +2 -3
  427. package/src/memory/v2/page-store.ts +168 -31
  428. package/src/memory/v2/prompts/consolidation.ts +118 -42
  429. package/src/memory/v2/prompts/sweep.ts +3 -3
  430. package/src/memory/v2/skill-store.ts +55 -7
  431. package/src/memory/v2/static-context.ts +62 -0
  432. package/src/memory/v2/types.ts +10 -20
  433. package/src/memory/validation.ts +0 -11
  434. package/src/messaging/draft-store.ts +0 -6
  435. package/src/messaging/provider-types.ts +8 -0
  436. package/src/messaging/provider.ts +7 -0
  437. package/src/messaging/providers/gmail/client.ts +1 -121
  438. package/src/messaging/providers/outlook/client.ts +0 -73
  439. package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +226 -0
  440. package/src/messaging/providers/slack/adapter.ts +122 -21
  441. package/src/messaging/providers/slack/backfill.test.ts +95 -6
  442. package/src/messaging/providers/slack/backfill.ts +89 -11
  443. package/src/messaging/providers/slack/client.ts +10 -124
  444. package/src/messaging/providers/slack/message-metadata.ts +12 -2
  445. package/src/messaging/providers/slack/render-transcript.test.ts +56 -0
  446. package/src/messaging/providers/slack/render-transcript.ts +126 -25
  447. package/src/messaging/providers/slack/types.ts +1 -0
  448. package/src/oauth/connection-resolver.test.ts +8 -0
  449. package/src/oauth/connection-resolver.ts +8 -16
  450. package/src/oauth/credential-token-resolver.ts +97 -0
  451. package/src/oauth/manual-token-connection.ts +30 -34
  452. package/src/oauth/oauth-store.ts +6 -4
  453. package/src/outbound-proxy/certs.ts +0 -7
  454. package/src/outbound-proxy/config.ts +0 -74
  455. package/src/outbound-proxy/health.ts +0 -44
  456. package/src/outbound-proxy/index.ts +0 -22
  457. package/src/permissions/approval-provenance.test.ts +184 -0
  458. package/src/permissions/approval-provenance.ts +70 -0
  459. package/src/permissions/checker.ts +4 -1
  460. package/src/permissions/gateway-threshold-reader.ts +4 -1
  461. package/src/permissions/prompter.ts +9 -2
  462. package/src/permissions/secret-prompter.ts +21 -48
  463. package/src/permissions/types.ts +33 -0
  464. package/src/permissions/workspace-policy.ts +0 -5
  465. package/src/platform/sync-identity.ts +0 -8
  466. package/src/plugins/defaults/injectors.ts +69 -2
  467. package/src/plugins/defaults/overflow-reduce.ts +3 -2
  468. package/src/plugins/types.ts +8 -0
  469. package/src/prompts/system-prompt.ts +34 -70
  470. package/src/prompts/templates/BOOTSTRAP.md +52 -6
  471. package/src/prompts/update-bulletin-job.ts +2 -0
  472. package/src/providers/__tests__/retry-callsite.test.ts +138 -1
  473. package/src/providers/anthropic/client.ts +72 -33
  474. package/src/providers/call-site-routing.ts +42 -3
  475. package/src/providers/gemini/client.ts +18 -2
  476. package/src/providers/managed-proxy/context.ts +0 -5
  477. package/src/providers/model-catalog.ts +105 -19
  478. package/src/providers/openai/chat-completions-provider.ts +6 -0
  479. package/src/providers/openai/responses-provider.ts +7 -1
  480. package/src/providers/provider-send-message.ts +45 -2
  481. package/src/providers/ratelimit.ts +7 -2
  482. package/src/providers/registry.ts +14 -9
  483. package/src/providers/retry.ts +96 -8
  484. package/src/providers/types.ts +13 -0
  485. package/src/providers/usage-tracking.ts +96 -0
  486. package/src/runtime/AGENTS.md +10 -6
  487. package/src/runtime/__tests__/agent-wake.test.ts +89 -0
  488. package/src/runtime/agent-wake.ts +39 -2
  489. package/src/runtime/assistant-event-hub.ts +541 -45
  490. package/src/runtime/assistant-event.ts +1 -6
  491. package/src/runtime/auth/context.ts +0 -9
  492. package/src/runtime/auth/middleware.ts +1 -1
  493. package/src/runtime/auth/route-policy.ts +11 -9
  494. package/src/runtime/auth/token-service.ts +0 -11
  495. package/src/runtime/channel-approvals.ts +6 -2
  496. package/src/runtime/channel-verification-service.ts +3 -5
  497. package/src/runtime/http-errors.ts +0 -34
  498. package/src/runtime/http-router.ts +6 -3
  499. package/src/runtime/http-server.ts +22 -82
  500. package/src/runtime/http-types.ts +5 -0
  501. package/src/runtime/interactive-ui.ts +0 -1
  502. package/src/runtime/middleware/auth.ts +0 -20
  503. package/src/runtime/migrations/__tests__/v1-test-helpers.ts +112 -0
  504. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +11 -4
  505. package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +253 -0
  506. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +19 -6
  507. package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +71 -27
  508. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +41 -2
  509. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +143 -79
  510. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +143 -23
  511. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +2 -2
  512. package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +371 -0
  513. package/src/runtime/migrations/migration-transport.ts +46 -13
  514. package/src/runtime/migrations/migration-wizard.ts +2 -2
  515. package/src/runtime/migrations/origin-mode.ts +40 -0
  516. package/src/runtime/migrations/vbundle-builder.ts +133 -79
  517. package/src/runtime/migrations/vbundle-import-analyzer.ts +9 -7
  518. package/src/runtime/migrations/vbundle-importer.ts +7 -7
  519. package/src/runtime/migrations/vbundle-metadata-merge.ts +1 -1
  520. package/src/runtime/migrations/vbundle-streaming-importer.ts +3 -3
  521. package/src/runtime/migrations/vbundle-streaming-validator.ts +48 -26
  522. package/src/runtime/migrations/vbundle-validator.ts +214 -41
  523. package/src/runtime/pending-interactions.ts +13 -4
  524. package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -1
  525. package/src/runtime/routes/__tests__/backup-routes.test.ts +28 -19
  526. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +235 -0
  527. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +58 -0
  528. package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +54 -0
  529. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +19 -6
  530. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +7 -7
  531. package/src/runtime/routes/acp-routes.test.ts +0 -3
  532. package/src/runtime/routes/acp-routes.ts +3 -7
  533. package/src/runtime/routes/app-management-routes.ts +18 -9
  534. package/src/runtime/routes/approval-routes.ts +55 -14
  535. package/src/runtime/routes/avatar-routes.ts +3 -5
  536. package/src/runtime/routes/browser-routes.ts +1 -15
  537. package/src/runtime/routes/channel-guardian-routes.ts +1 -5
  538. package/src/runtime/routes/channel-readiness-routes.ts +3 -7
  539. package/src/runtime/routes/channel-route-shared.ts +2 -28
  540. package/src/runtime/routes/client-routes.ts +45 -12
  541. package/src/runtime/routes/consolidation-routes.ts +115 -0
  542. package/src/runtime/routes/conversation-list-routes.ts +12 -29
  543. package/src/runtime/routes/conversation-management-routes.ts +14 -51
  544. package/src/runtime/routes/conversation-query-routes.ts +120 -8
  545. package/src/runtime/routes/conversation-routes.ts +44 -528
  546. package/src/runtime/routes/conversation-starter-routes.ts +19 -40
  547. package/src/runtime/routes/documents-routes.ts +53 -18
  548. package/src/runtime/routes/events-routes.ts +59 -91
  549. package/src/runtime/routes/filing-routes.ts +18 -1
  550. package/src/runtime/routes/guardian-action-routes.ts +4 -9
  551. package/src/runtime/routes/host-bash-routes.ts +3 -2
  552. package/src/runtime/routes/host-browser-routes.ts +9 -33
  553. package/src/runtime/routes/host-cu-routes.ts +6 -1
  554. package/src/runtime/routes/host-file-routes.ts +3 -2
  555. package/src/runtime/routes/host-transfer-routes.ts +11 -15
  556. package/src/runtime/routes/identity-routes.ts +78 -6
  557. package/src/runtime/routes/inbound-message-handler.ts +580 -137
  558. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -88
  559. package/src/runtime/routes/inbound-stages/background-dispatch.ts +3 -0
  560. package/src/runtime/routes/index.ts +4 -0
  561. package/src/runtime/routes/integrations/slack/channel.ts +0 -24
  562. package/src/runtime/routes/llm-call-sites-routes.ts +22 -0
  563. package/src/runtime/routes/memory-v2-routes.ts +10 -15
  564. package/src/runtime/routes/migration-routes.ts +188 -31
  565. package/src/runtime/routes/playground/guard.ts +1 -1
  566. package/src/runtime/routes/playground/index.ts +0 -2
  567. package/src/runtime/routes/recording-routes.ts +4 -24
  568. package/src/runtime/routes/rename-conversation-routes.ts +2 -6
  569. package/src/runtime/routes/schedule-routes.ts +3 -6
  570. package/src/runtime/routes/secret-routes.ts +87 -18
  571. package/src/runtime/routes/settings-routes.ts +29 -28
  572. package/src/runtime/routes/skills-routes.ts +12 -31
  573. package/src/runtime/routes/suggest-trust-rule-routes.ts +32 -1
  574. package/src/runtime/routes/task-routes.ts +6 -6
  575. package/src/runtime/routes/trust-rules-routes.ts +3 -94
  576. package/src/runtime/routes/types.ts +4 -4
  577. package/src/runtime/routes/upgrade-broadcast-routes.ts +3 -10
  578. package/src/runtime/routes/usage-routes.ts +87 -10
  579. package/src/runtime/routes/user-routes.ts +17 -31
  580. package/src/runtime/routes/work-items-routes.ts +1 -4
  581. package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -2
  582. package/src/runtime/services/analyze-conversation.ts +7 -17
  583. package/src/runtime/services/conversation-serializer.ts +2 -4
  584. package/src/runtime/verification-outbound-actions.ts +1 -1
  585. package/src/runtime/verification-rate-limiter.ts +1 -1
  586. package/src/schedule/schedule-store.ts +0 -16
  587. package/src/security/secret-scanner.ts +14 -547
  588. package/src/security/secure-keys.ts +31 -11
  589. package/src/security/token-manager.ts +7 -3
  590. package/src/signals/cancel.ts +16 -25
  591. package/src/signals/conversation-undo.ts +2 -27
  592. package/src/signals/emit-event.ts +1 -2
  593. package/src/signals/user-message.ts +108 -22
  594. package/src/skills/catalog-install.ts +1 -0
  595. package/src/skills/clawhub.ts +2 -2
  596. package/src/skills/inline-command-runner.ts +1 -7
  597. package/src/subagent/manager.ts +67 -84
  598. package/src/tasks/task-store.ts +1 -28
  599. package/src/telemetry/types.ts +6 -0
  600. package/src/telemetry/usage-telemetry-reporter.test.ts +38 -15
  601. package/src/telemetry/usage-telemetry-reporter.ts +3 -5
  602. package/src/tools/acp/spawn.test.ts +1 -2
  603. package/src/tools/acp/steer.test.ts +1 -2
  604. package/src/tools/browser/__tests__/browser-status.test.ts +44 -127
  605. package/src/tools/browser/browser-execution.ts +31 -147
  606. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +92 -68
  607. package/src/tools/browser/cdp-client/factory.ts +48 -76
  608. package/src/tools/browser/cdp-client/index.ts +1 -14
  609. package/src/tools/executor.ts +44 -31
  610. package/src/tools/host-filesystem/edit.ts +3 -2
  611. package/src/tools/host-filesystem/read.ts +3 -2
  612. package/src/tools/host-filesystem/transfer.test.ts +45 -42
  613. package/src/tools/host-filesystem/transfer.ts +4 -3
  614. package/src/tools/host-filesystem/write.ts +3 -2
  615. package/src/tools/host-terminal/host-shell.ts +4 -3
  616. package/src/tools/network/script-proxy/index.ts +1 -10
  617. package/src/tools/permission-checker.ts +66 -1
  618. package/src/tools/skills/sandbox-runner.ts +1 -6
  619. package/src/tools/skills/skill-tool-factory.ts +32 -0
  620. package/src/tools/terminal/safe-env.ts +1 -0
  621. package/src/tools/terminal/shell.ts +2 -78
  622. package/src/tools/types.ts +12 -39
  623. package/src/tts/__tests__/provider-catalog.test.ts +2 -2
  624. package/src/tts/provider-catalog.ts +1 -1
  625. package/src/usage/actors.ts +2 -1
  626. package/src/usage/attribution.ts +185 -0
  627. package/src/usage/pricing.ts +166 -0
  628. package/src/usage/types.ts +14 -0
  629. package/src/util/json.ts +13 -0
  630. package/src/util/logger.ts +3 -3
  631. package/src/util/pricing.ts +50 -3
  632. package/src/work-items/work-item-runner.ts +15 -42
  633. package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +4 -3
  634. package/src/workspace/migrations/052-seed-default-inference-profiles.ts +3 -3
  635. package/src/workspace/migrations/060-memory-v2-init.ts +2 -18
  636. package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +59 -0
  637. package/src/workspace/migrations/062-drop-memory-v2-edges-json.ts +27 -0
  638. package/src/workspace/migrations/063-release-notes-dynamic-model-context.ts +70 -0
  639. package/src/workspace/migrations/064-unwind-main-agent-opus-seed.ts +64 -0
  640. package/src/workspace/migrations/registry.ts +8 -0
  641. package/src/workspace/provider-commit-message-generator.ts +3 -3
  642. package/src/__tests__/sandbox-diagnostics.test.ts +0 -138
  643. package/src/__tests__/sandbox-host-parity.test.ts +0 -1024
  644. package/src/__tests__/secret-detection-handler.test.ts +0 -67
  645. package/src/__tests__/secret-scanner-executor.test.ts +0 -450
  646. package/src/__tests__/tcc-sandbox-deny.test.ts +0 -198
  647. package/src/__tests__/terminal-sandbox.test.ts +0 -374
  648. package/src/__tests__/tool-notification-listener.test.ts +0 -65
  649. package/src/context/__tests__/microcompact.test.ts +0 -805
  650. package/src/context/microcompact.ts +0 -443
  651. package/src/daemon/handlers/slack-channel-oauth-install.ts +0 -197
  652. package/src/events/tool-notification-listener.ts +0 -17
  653. package/src/ipc/routes/__tests__/memory-v2-validate.test.ts +0 -219
  654. package/src/memory/v2/__tests__/edges.test.ts +0 -435
  655. package/src/memory/v2/edges.ts +0 -217
  656. package/src/prompts/__tests__/system-prompt-memory-v2.test.ts +0 -197
  657. package/src/runtime/__tests__/chrome-extension-registry.test.ts +0 -518
  658. package/src/runtime/__tests__/client-registry.test.ts +0 -271
  659. package/src/runtime/chrome-extension-registry.ts +0 -368
  660. package/src/runtime/client-registry.ts +0 -254
  661. package/src/runtime/routes/inbound-stages/verification-intercept.ts +0 -329
  662. package/src/tools/secret-detection-handler.ts +0 -269
  663. package/src/tools/terminal/backends/native.ts +0 -327
  664. package/src/tools/terminal/backends/types.ts +0 -37
  665. package/src/tools/terminal/sandbox-diagnostics.ts +0 -87
  666. package/src/tools/terminal/sandbox.ts +0 -40
@@ -31,6 +31,7 @@ import { tmpdir } from "node:os";
31
31
  import { join } from "node:path";
32
32
  import { afterEach, beforeEach, describe, expect, test } from "bun:test";
33
33
 
34
+ import { defaultV1Options } from "../../runtime/migrations/__tests__/v1-test-helpers.js";
34
35
  import { buildVBundle } from "../../runtime/migrations/vbundle-builder.js";
35
36
  import type { PathResolver } from "../../runtime/migrations/vbundle-import-analyzer.js";
36
37
  import type {
@@ -78,11 +79,13 @@ const NULL_RESOLVER: PathResolver = {
78
79
  * the file path along with the manifest the builder embedded so tests can
79
80
  * compare against it.
80
81
  */
81
- function writeTinyPlaintextBundle(
82
- fileName: string,
83
- ): { path: string; manifest: ManifestType } {
82
+ function writeTinyPlaintextBundle(fileName: string): {
83
+ path: string;
84
+ manifest: ManifestType;
85
+ } {
84
86
  const { archive, manifest } = buildVBundle({
85
87
  files: [
88
+ { path: "data/db/assistant.db", data: new Uint8Array() },
86
89
  {
87
90
  path: "workspace/notes/hello.txt",
88
91
  data: new TextEncoder().encode("hello world"),
@@ -92,8 +95,7 @@ function writeTinyPlaintextBundle(
92
95
  data: new TextEncoder().encode("a tiny bundle for tests"),
93
96
  },
94
97
  ],
95
- source: "restore-test",
96
- description: "tiny bundle for restore.test.ts",
98
+ ...defaultV1Options(),
97
99
  });
98
100
 
99
101
  const path = join(TEST_DIR, fileName);
@@ -117,21 +119,35 @@ function makeStubCommitImpl(): {
117
119
  const calls: RecordedCall[] = [];
118
120
  const commitImpl = (options: ImportCommitOptions): ImportCommitResult => {
119
121
  calls.push({ options });
120
- const manifest =
122
+ const manifest: ManifestType =
121
123
  options.preValidatedManifest ??
122
124
  ({
123
- schema_version: "1.0",
125
+ schema_version: 1,
126
+ bundle_id: "00000000-0000-4000-8000-000000000000",
124
127
  created_at: new Date().toISOString(),
125
- files: [],
126
- manifest_sha256: "stub",
127
- } satisfies ManifestType);
128
+ assistant: { id: "self", name: "Test", runtime_version: "0.0.0-test" },
129
+ origin: { mode: "self-hosted-local" },
130
+ compatibility: {
131
+ min_runtime_version: "0.0.0-test",
132
+ max_runtime_version: null,
133
+ },
134
+ contents: [],
135
+ checksum:
136
+ "0000000000000000000000000000000000000000000000000000000000000000",
137
+ secrets_redacted: false,
138
+ export_options: {
139
+ include_logs: false,
140
+ include_browser_state: false,
141
+ include_memory_vectors: false,
142
+ },
143
+ } as ManifestType);
128
144
  return {
129
145
  ok: true,
130
146
  report: {
131
147
  success: true,
132
148
  summary: {
133
- total_files: manifest.files.length,
134
- files_created: manifest.files.length,
149
+ total_files: manifest.contents.length,
150
+ files_created: manifest.contents.length,
135
151
  files_overwritten: 0,
136
152
  files_skipped: 0,
137
153
  backups_created: 0,
@@ -178,8 +194,9 @@ describe("verifySnapshot", () => {
178
194
  expect(result.valid).toBe(true);
179
195
  expect(result.manifest).toBeDefined();
180
196
  expect(result.error).toBeUndefined();
181
- expect(result.manifest?.manifest_sha256).toBe(manifest.manifest_sha256);
182
- expect(result.manifest?.files.length).toBe(2);
197
+ expect(result.manifest?.checksum).toBe(manifest.checksum);
198
+ // 3 = synthetic data/db/assistant.db + workspace/notes/hello.txt + workspace/notes/about.txt
199
+ expect(result.manifest?.contents.length).toBe(3);
183
200
  });
184
201
 
185
202
  test("encrypted: returns valid:true after decrypting first", async () => {
@@ -244,11 +261,13 @@ describe("verifySnapshot", () => {
244
261
  // validateVBundle catches the bad manifest.
245
262
  const { archive } = buildVBundle({
246
263
  files: [
264
+ { path: "data/db/assistant.db", data: new Uint8Array() },
247
265
  {
248
266
  path: "workspace/notes/hello.txt",
249
267
  data: new TextEncoder().encode("hello"),
250
268
  },
251
269
  ],
270
+ ...defaultV1Options(),
252
271
  });
253
272
 
254
273
  // Flip a few bytes in the middle of the gzipped archive — this almost
@@ -292,21 +311,19 @@ describe("restoreFromSnapshot", () => {
292
311
  const passed = calls[0].options;
293
312
  // The wrapper should pass the pre-validated manifest + entries so
294
313
  // commitImport doesn't re-validate.
295
- expect(passed.preValidatedManifest?.manifest_sha256).toBe(
296
- manifest.manifest_sha256,
297
- );
314
+ expect(passed.preValidatedManifest?.checksum).toBe(manifest.checksum);
298
315
  expect(passed.preValidatedEntries).toBeDefined();
299
316
  expect(passed.preValidatedEntries?.has("manifest.json")).toBe(true);
300
- expect(
301
- passed.preValidatedEntries?.has("workspace/notes/hello.txt"),
302
- ).toBe(true);
317
+ expect(passed.preValidatedEntries?.has("workspace/notes/hello.txt")).toBe(
318
+ true,
319
+ );
303
320
  // archiveData must be the actual bundle bytes.
304
321
  expect(passed.archiveData).toBeInstanceOf(Uint8Array);
305
322
  expect(passed.archiveData.length).toBeGreaterThan(0);
306
323
 
307
324
  // Public result is shaped correctly.
308
- expect(result.manifest.manifest_sha256).toBe(manifest.manifest_sha256);
309
- expect(result.restoredFiles).toBe(2);
325
+ expect(result.manifest.checksum).toBe(manifest.checksum);
326
+ expect(result.restoredFiles).toBe(3);
310
327
  });
311
328
 
312
329
  test("encrypted round-trip: decrypts then commits, and cleans up the temp file", async () => {
@@ -327,8 +344,8 @@ describe("restoreFromSnapshot", () => {
327
344
  const after = listRestoreTempArtifacts();
328
345
 
329
346
  expect(calls.length).toBe(1);
330
- expect(result.manifest.manifest_sha256).toBe(manifest.manifest_sha256);
331
- expect(result.restoredFiles).toBe(2);
347
+ expect(result.manifest.checksum).toBe(manifest.checksum);
348
+ expect(result.restoredFiles).toBe(3);
332
349
 
333
350
  // Decrypted temp file must be cleaned up after the call.
334
351
  expect(after.length).toBe(before.length);
@@ -377,6 +394,7 @@ describe("restoreFromSnapshot", () => {
377
394
  // the OS keychain / CES and are not part of the backup round trip.
378
395
  const { archive, manifest } = buildVBundle({
379
396
  files: [
397
+ { path: "data/db/assistant.db", data: new Uint8Array() },
380
398
  {
381
399
  path: "workspace/notes/hello.txt",
382
400
  data: new TextEncoder().encode("hello"),
@@ -386,6 +404,7 @@ describe("restoreFromSnapshot", () => {
386
404
  data: new TextEncoder().encode("sk-test-1234"),
387
405
  },
388
406
  ],
407
+ ...defaultV1Options(),
389
408
  });
390
409
 
391
410
  const path = join(TEST_DIR, "with-creds.vbundle");
@@ -399,7 +418,7 @@ describe("restoreFromSnapshot", () => {
399
418
 
400
419
  // The restore result must not expose a `credentials` field — the public
401
420
  // type only has `manifest` and `restoredFiles`.
402
- expect(result.manifest.manifest_sha256).toBe(manifest.manifest_sha256);
421
+ expect(result.manifest.checksum).toBe(manifest.checksum);
403
422
  expect("credentials" in result).toBe(false);
404
423
  });
405
424
 
@@ -468,9 +487,7 @@ describe("restoreFromSnapshot", () => {
468
487
 
469
488
  // Stub that simulates a write failure (the importer returns this for
470
489
  // disk errors like permission denied or partial bundle writes).
471
- const failingCommit = (
472
- _opts: ImportCommitOptions,
473
- ): ImportCommitResult => ({
490
+ const failingCommit = (_opts: ImportCommitOptions): ImportCommitResult => ({
474
491
  ok: false,
475
492
  reason: "write_failed",
476
493
  message: "disk full",
@@ -26,18 +26,24 @@
26
26
  * surface against temp directories with tiny fake bundles.
27
27
  */
28
28
 
29
+ import { hostname } from "node:os";
29
30
  import { Database } from "bun:sqlite";
30
31
 
31
32
  import { getConfig } from "../config/loader.js";
32
33
  import type { BackupConfig } from "../config/schema.js";
34
+ import { getAssistantName } from "../daemon/identity-helpers.js";
33
35
  import {
34
36
  getMemoryCheckpoint as realGetMemoryCheckpoint,
35
37
  setMemoryCheckpoint as realSetMemoryCheckpoint,
36
38
  } from "../memory/checkpoints.js";
39
+ import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
40
+ import type { VBundleOriginMode } from "../runtime/migrations/origin-mode.js";
37
41
  import type { StreamExportVBundleResult } from "../runtime/migrations/vbundle-builder.js";
38
42
  import { streamExportVBundle as realStreamExportVBundle } from "../runtime/migrations/vbundle-builder.js";
43
+ import { getDaemonRuntimeMode } from "../runtime/runtime-mode.js";
39
44
  import { getLogger } from "../util/logger.js";
40
45
  import { getDbPath, getWorkspaceDir } from "../util/platform.js";
46
+ import { APP_VERSION } from "../version.js";
41
47
  import { ensureBackupKey as realEnsureBackupKey } from "./backup-key.js";
42
48
  import type { SnapshotEntry } from "./list-snapshots.js";
43
49
  import { pruneLocalSnapshots, writeLocalSnapshot } from "./local-writer.js";
@@ -185,10 +191,38 @@ async function performBackup(
185
191
  // mirrors the pattern in `handleMigrationExport`: open a fresh Database
186
192
  // handle, run PRAGMA wal_checkpoint(TRUNCATE), close it. Any failure is
187
193
  // best-effort — the export still proceeds with whatever is on disk.
194
+ //
195
+ // The backup worker bundles credentials by design (its purpose is local
196
+ // recovery), so `secretsRedacted: false`. Backups run locally on the host
197
+ // machine; managed deployments delegate to the platform. Hardcoding to
198
+ // self-hosted ensures the resulting bundle satisfies the v1 schema's
199
+ // refine for managed/secrets_redacted — `getOriginMode()` would return
200
+ // "managed" in a managed deployment, producing a non-restorable bundle.
201
+ const originMode: VBundleOriginMode =
202
+ getDaemonRuntimeMode() === "docker"
203
+ ? "self-hosted-remote"
204
+ : "self-hosted-local";
188
205
  const result = await streamExport({
189
206
  workspaceDir,
190
- source: "backup-worker",
191
- description: "Automated backup snapshot",
207
+ assistant: {
208
+ id: DAEMON_INTERNAL_ASSISTANT_ID,
209
+ name: getAssistantName() ?? "Assistant",
210
+ runtime_version: APP_VERSION,
211
+ },
212
+ origin: {
213
+ mode: originMode,
214
+ hostname: hostname(),
215
+ },
216
+ compatibility: {
217
+ min_runtime_version: APP_VERSION,
218
+ max_runtime_version: null,
219
+ },
220
+ exportOptions: {
221
+ include_logs: true,
222
+ include_browser_state: false,
223
+ include_memory_vectors: false,
224
+ },
225
+ secretsRedacted: false,
192
226
  checkpoint: () => {
193
227
  const dbPath = getDbPath();
194
228
  try {
@@ -6,7 +6,7 @@ import {
6
6
  getBackupKeyPathOverride,
7
7
  } from "../config/env-registry.js";
8
8
  import type { BackupDestination } from "../config/schema.js";
9
- import { getProtectedDir } from "../util/platform.js";
9
+ import { getWorkspaceDir } from "../util/platform.js";
10
10
 
11
11
  /**
12
12
  * Returns the backup root directory. Respects the `VELLUM_BACKUP_DIR`
@@ -134,13 +134,16 @@ export function resolveOffsiteDestinations(
134
134
  }
135
135
 
136
136
  /**
137
- * Returns the path to the backup encryption key file. By default this is
138
- * `~/.vellum/protected/backup.key`, but the `VELLUM_BACKUP_KEY_PATH` env var
139
- * can override it for containerized deployments where the key must live on a
140
- * persistent volume.
137
+ * Returns the path to the backup encryption key file.
138
+ *
139
+ * The `VELLUM_BACKUP_KEY_PATH` env var can override this for containerized
140
+ * deployments where the key must live on a persistent volume.
141
+ *
142
+ * TODO: The backup key is a credential and should eventually be managed by the
143
+ * gateway (behind IPC), not stored on the daemon's filesystem.
141
144
  */
142
145
  export function getBackupKeyPath(): string {
143
- return getBackupKeyPathOverride() ?? join(getProtectedDir(), "backup.key");
146
+ return getBackupKeyPathOverride() ?? join(getWorkspaceDir(), ".backup.key");
144
147
  }
145
148
 
146
149
  /**
@@ -132,15 +132,6 @@ export function isTargetInvalidated(targetId: string): boolean {
132
132
  return invalidatedTargetIds.has(targetId);
133
133
  }
134
134
 
135
- /**
136
- * Test-only helper: snapshot the current invalidated set without
137
- * draining it. Exported so unit tests can assert exact set contents
138
- * across multiple frames; production code must not rely on this.
139
- */
140
- export function __peekInvalidatedTargetIdsForTests(): string[] {
141
- return Array.from(invalidatedTargetIds);
142
- }
143
-
144
135
  /**
145
136
  * Atomically remove and return a target id from the invalidated set.
146
137
  * Returns `true` when the id was present (and has now been removed),
@@ -2,7 +2,7 @@ import { and, desc, eq, notInArray, or } from "drizzle-orm";
2
2
  import { v4 as uuid } from "uuid";
3
3
 
4
4
  import { getDb } from "../memory/db-connection.js";
5
- import { rawChanges, rawGet, rawRun } from "../memory/raw-query.js";
5
+ import { rawChanges, rawRun } from "../memory/raw-query.js";
6
6
  import {
7
7
  callEvents,
8
8
  callPendingQuestions,
@@ -379,39 +379,6 @@ export function buildCallbackDedupeKey(
379
379
  return `${callSid}:${callStatus}:${discriminator}`;
380
380
  }
381
381
 
382
- /**
383
- * Check whether a callback dedupe key has already been processed (read-only).
384
- * Returns true if the key already exists, false otherwise.
385
- */
386
- export function isCallbackProcessed(dedupeKey: string): boolean {
387
- return (
388
- rawGet<{ 1: number }>(
389
- `SELECT 1 FROM processed_callbacks WHERE dedupe_key = ?`,
390
- dedupeKey,
391
- ) != null
392
- );
393
- }
394
-
395
- /**
396
- * Record a callback as processed. Should be called AFTER downstream writes
397
- * (session updates, event recording) have succeeded so that Twilio retries
398
- * are not silently dropped if those writes fail.
399
- *
400
- * Uses INSERT OR IGNORE so concurrent calls for the same key are safe.
401
- */
402
- export function recordProcessedCallback(
403
- dedupeKey: string,
404
- callSessionId: string,
405
- ): void {
406
- rawRun(
407
- `INSERT OR IGNORE INTO processed_callbacks (id, dedupe_key, call_session_id, created_at) VALUES (?, ?, ?, ?)`,
408
- uuid(),
409
- dedupeKey,
410
- callSessionId,
411
- Date.now(),
412
- );
413
- }
414
-
415
382
  /**
416
383
  * Atomically claim a callback for processing. Returns a unique claim ID
417
384
  * (string) if this caller won the claim, or null if another caller already
@@ -6,18 +6,7 @@
6
6
  * when the provider is unavailable or generation fails/times out.
7
7
  */
8
8
 
9
- import {
10
- createTimeout,
11
- extractText,
12
- resolveConfiguredProvider,
13
- userMessage,
14
- } from "../providers/provider-send-message.js";
15
- import { getLogger } from "../util/logger.js";
16
-
17
- const log = getLogger("guardian-question-copy");
18
-
19
9
  /** Timeout for the generative copy call (ms). */
20
- const GENERATION_TIMEOUT_MS = 5_000;
21
10
 
22
11
  export interface GuardianCopy {
23
12
  conversationTitle: string;
@@ -39,100 +28,3 @@ export function buildFallbackCopy(questionText: string): GuardianCopy {
39
28
  ].join("\n"),
40
29
  };
41
30
  }
42
-
43
- /**
44
- * Generate guardian conversation copy (title + initial message) via the configured
45
- * LLM provider. Returns deterministic fallback when the provider is unavailable,
46
- * generation times out, or any error occurs.
47
- */
48
- export async function generateGuardianCopy(
49
- questionText: string,
50
- requestCode?: string,
51
- ): Promise<GuardianCopy> {
52
- const fallback = buildFallbackCopy(questionText);
53
-
54
- // If no provider is configured, return fallback immediately
55
- const resolved = await resolveConfiguredProvider("guardianQuestionCopy");
56
- if (!resolved) {
57
- log.debug(
58
- "No provider available for guardian copy generation, using fallback",
59
- );
60
- return fallback;
61
- }
62
-
63
- const { signal, cleanup } = createTimeout(GENERATION_TIMEOUT_MS);
64
-
65
- try {
66
- const prompt = [
67
- "Generate a conversation title and initial message for a guardian question during a live phone call.",
68
- "",
69
- `Question: ${questionText}`,
70
- ...(requestCode ? [`Reference code: ${requestCode}`] : []),
71
- "",
72
- "Requirements:",
73
- '- TITLE: An emoji-prefixed, attention-oriented, concise title (under 80 characters). Do NOT start with "Guardian question:". Use a relevant warning or alert emoji.',
74
- "- MESSAGE: A clear initial message that includes the question text, mentions this is a live phone call waiting for the user's input, and asks them to reply with their answer.",
75
- "",
76
- "Respond in exactly this format (no extra text):",
77
- "TITLE: <your title>",
78
- "MESSAGE: <your message>",
79
- ].join("\n");
80
-
81
- const response = await resolved.provider.sendMessage(
82
- [userMessage(prompt)],
83
- undefined,
84
- undefined,
85
- { signal, config: { callSite: "guardianQuestionCopy" } },
86
- );
87
-
88
- const text = extractText(response);
89
- const parsed = parseGeneratedCopy(text);
90
-
91
- if (parsed) {
92
- return parsed;
93
- }
94
-
95
- log.warn(
96
- { raw: text },
97
- "Failed to parse generated guardian copy, using fallback",
98
- );
99
- return fallback;
100
- } catch (err) {
101
- if (signal.aborted) {
102
- log.warn("Guardian copy generation timed out, using fallback");
103
- } else {
104
- log.warn({ err }, "Guardian copy generation failed, using fallback");
105
- }
106
- return fallback;
107
- } finally {
108
- cleanup();
109
- }
110
- }
111
-
112
- /**
113
- * Parse the structured TITLE/MESSAGE response from the model.
114
- * Returns null if the format is not matched.
115
- */
116
- function parseGeneratedCopy(text: string): GuardianCopy | null {
117
- const titleMatch = text.match(/^TITLE:\s*(.+)/m);
118
- const messageMatch = text.match(/^MESSAGE:\s*([\s\S]+)/m);
119
-
120
- if (!titleMatch || !messageMatch) {
121
- return null;
122
- }
123
-
124
- const title = titleMatch[1].trim();
125
- const message = messageMatch[1].trim();
126
-
127
- // Sanity checks: title must be non-empty and under 80 chars, message must be non-empty
128
- if (!title || title.length > 80 || !message) {
129
- return null;
130
- }
131
-
132
- // Reject the old static prefix — the model is guided towards better titles but has final say
133
- if (/^guardian question:/i.test(title)) {
134
- return null;
135
- }
136
-
137
- return { conversationTitle: title, initialMessage: message };
138
- }
@@ -15,8 +15,6 @@ import {
15
15
  listGuardianChannels,
16
16
  } from "../contacts/contact-store.js";
17
17
  import {
18
- createGuardianBinding,
19
- revokeGuardianBinding,
20
18
  touchContactInteraction,
21
19
  upsertContactChannel,
22
20
  } from "../contacts/contacts-write.js";
@@ -998,28 +996,6 @@ export class RelayConnection {
998
996
  "Guardian voice verification succeeded",
999
997
  );
1000
998
 
1001
- // Create the guardian binding now that verification succeeded.
1002
- if (result.verificationType === "guardian") {
1003
- if (result.bindingConflict) {
1004
- log.warn(
1005
- {
1006
- callSessionId: this.callSessionId,
1007
- existingGuardian: result.bindingConflict.existingGuardian,
1008
- },
1009
- "Guardian binding conflict: another user already holds the voice binding",
1010
- );
1011
- } else {
1012
- revokeGuardianBinding("phone");
1013
- createGuardianBinding({
1014
- channel: "phone",
1015
- guardianExternalUserId: fromNumber,
1016
- guardianDeliveryChatId: fromNumber,
1017
- guardianPrincipalId: result.canonicalPrincipal!,
1018
- verifiedVia: "challenge",
1019
- });
1020
- }
1021
- }
1022
-
1023
999
  if (isOutbound) {
1024
1000
  // Keep the pointer message back to the initiating conversation
1025
1001
  const successSession = getCallSession(this.callSessionId);
@@ -210,44 +210,6 @@ export async function provisionPhoneNumber(
210
210
  };
211
211
  }
212
212
 
213
- /** Fetch the current status of a Twilio message by SID. */
214
- export async function fetchMessageStatus(
215
- accountSid: string,
216
- authToken: string,
217
- messageSid: string,
218
- ): Promise<{ status: string; errorCode?: string; errorMessage?: string }> {
219
- const res = await fetch(
220
- `${twilioBaseUrl(accountSid)}/Messages/${encodeURIComponent(
221
- messageSid,
222
- )}.json`,
223
- {
224
- method: "GET",
225
- headers: { Authorization: twilioAuthHeader(accountSid, authToken) },
226
- },
227
- );
228
-
229
- if (!res.ok) {
230
- const text = await res.text();
231
- throw new ProviderError(
232
- `Twilio API error ${res.status}: ${text}`,
233
- "twilio",
234
- res.status,
235
- );
236
- }
237
-
238
- const data = (await res.json()) as {
239
- status?: string;
240
- error_code?: number | null;
241
- error_message?: string | null;
242
- };
243
-
244
- return {
245
- status: data.status ?? "unknown",
246
- errorCode: data.error_code != null ? String(data.error_code) : undefined,
247
- errorMessage: data.error_message ?? undefined,
248
- };
249
- }
250
-
251
213
  export interface WebhookUrls {
252
214
  voiceUrl: string;
253
215
  statusCallbackUrl: string;
@@ -65,7 +65,7 @@ const log = getLogger("twilio-routes");
65
65
  * The gateway replaces this with a real JWT before returning TwiML to Twilio.
66
66
  * This keeps the signing key out of the daemon for voice webhook responses.
67
67
  */
68
- export const TWILIO_RELAY_TOKEN_PLACEHOLDER = "__VELLUM_RELAY_TOKEN__";
68
+ const TWILIO_RELAY_TOKEN_PLACEHOLDER = "__VELLUM_RELAY_TOKEN__";
69
69
 
70
70
  // ── Speech config type ───────────────────────────────────────────────
71
71
 
@@ -22,8 +22,7 @@ import type { Conversation } from "../daemon/conversation.js";
22
22
  import { resolveChannelCapabilities } from "../daemon/conversation-runtime-assembly.js";
23
23
  import type { ServerMessage } from "../daemon/message-protocol.js";
24
24
  import type { TrustContext } from "../daemon/trust-context.js";
25
- import { buildAssistantEvent } from "../runtime/assistant-event.js";
26
- import { assistantEventHub } from "../runtime/assistant-event-hub.js";
25
+ import { broadcastMessage } from "../runtime/assistant-event-hub.js";
27
26
  import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
28
27
  import * as pendingInteractions from "../runtime/pending-interactions.js";
29
28
  import { computeToolApprovalDigest } from "../security/tool-approval-digest.js";
@@ -418,34 +417,6 @@ export async function startVoiceTurn(
418
417
  );
419
418
  }
420
419
 
421
- // Serialized publish chain so hub subscribers observe events in order.
422
- let hubChain: Promise<void> = Promise.resolve();
423
- const publishToHub = (msg: ServerMessage): void => {
424
- // ServerMessage is a large union; conversationId exists on most but not all variants.
425
- const msgConversationId =
426
- "conversationId" in msg &&
427
- typeof (msg as { conversationId?: unknown }).conversationId === "string"
428
- ? (msg as { conversationId: string }).conversationId
429
- : undefined;
430
- const resolvedConversationId = msgConversationId ?? opts.conversationId;
431
- const event = buildAssistantEvent(
432
- DAEMON_INTERNAL_ASSISTANT_ID,
433
- msg,
434
- resolvedConversationId,
435
- );
436
- hubChain = (async () => {
437
- await hubChain;
438
- try {
439
- await assistantEventHub.publish(event);
440
- } catch (err) {
441
- log.warn(
442
- { err },
443
- "assistant-events hub subscriber threw during voice turn",
444
- );
445
- }
446
- })();
447
- };
448
-
449
420
  // Hook into conversation to intercept confirmation_request and secret_request events.
450
421
  // Voice auto-denies/auto-allows/auto-resolves these since there's no interactive UI.
451
422
  const autoDeny = !isGuardian;
@@ -455,7 +426,6 @@ export async function startVoiceTurn(
455
426
  if (msg.type === "confirmation_request") {
456
427
  if (usesLocalInteractiveApprovals) {
457
428
  pendingInteractions.register(msg.requestId, {
458
- conversation,
459
429
  conversationId: opts.conversationId,
460
430
  kind: "confirmation",
461
431
  confirmationDetails: {
@@ -470,7 +440,7 @@ export async function startVoiceTurn(
470
440
  acpOptions: msg.acpOptions,
471
441
  },
472
442
  });
473
- publishToHub(msg);
443
+ broadcastMessage(msg);
474
444
  return;
475
445
  }
476
446
  if (autoDeny) {
@@ -518,7 +488,7 @@ export async function startVoiceTurn(
518
488
  undefined,
519
489
  `Permission approved for "${msg.toolName}": guardian pre-approved via scoped grant.`,
520
490
  );
521
- publishToHub(msg);
491
+ broadcastMessage(msg);
522
492
  return;
523
493
  }
524
494
  } catch (err) {
@@ -539,7 +509,7 @@ export async function startVoiceTurn(
539
509
  undefined,
540
510
  `Permission denied for "${msg.toolName}": this voice call does not have interactive approval capabilities. Side-effect tools are not available for non-guardian voice callers. In your next assistant reply, explain briefly that this action requires guardian-level access and cannot be performed during this call.`,
541
511
  );
542
- publishToHub(msg);
512
+ broadcastMessage(msg);
543
513
  return;
544
514
  }
545
515
  if (autoAllow) {
@@ -554,7 +524,7 @@ export async function startVoiceTurn(
554
524
  undefined,
555
525
  `Permission approved for "${msg.toolName}": this is a verified guardian voice call.`,
556
526
  );
557
- publishToHub(msg);
527
+ broadcastMessage(msg);
558
528
  return;
559
529
  }
560
530
  } else if (msg.type === "secret_request") {
@@ -564,10 +534,9 @@ export async function startVoiceTurn(
564
534
  "Auto-resolving secret request for voice turn (no secret-entry UI)",
565
535
  );
566
536
  conversation.handleSecretResponse(msg.requestId, undefined, "store");
567
- publishToHub(msg);
568
537
  return;
569
538
  }
570
- publishToHub(msg);
539
+ broadcastMessage(msg);
571
540
  });
572
541
 
573
542
  // Fire-and-forget the agent loop
@@ -596,7 +565,7 @@ export async function startVoiceTurn(
596
565
  } else if (msg.type === "conversation_error") {
597
566
  lastError = msg.userMessage;
598
567
  }
599
- publishToHub(msg);
568
+ broadcastMessage(msg);
600
569
 
601
570
  // Forward voice-relevant events to the real-time event sink
602
571
  if (msg.type === "assistant_text_delta") {