@vellumai/assistant 0.8.0 → 0.8.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 (692) hide show
  1. package/AGENTS.md +11 -0
  2. package/Dockerfile +5 -4
  3. package/README.md +2 -2
  4. package/docker-entrypoint.sh +16 -0
  5. package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +420 -0
  6. package/eslint-rules/cli-no-daemon-internals.js +283 -0
  7. package/eslint.config.mjs +12 -0
  8. package/knip.json +2 -1
  9. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -1
  10. package/openapi.yaml +4847 -1698
  11. package/package.json +3 -1
  12. package/scripts/generate-openapi.ts +52 -4
  13. package/scripts/sync-llm-catalog.ts +165 -0
  14. package/scripts/sync-web-search-catalog.ts +107 -0
  15. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +169 -0
  16. package/src/__tests__/agent-loop-override-profile.test.ts +26 -1
  17. package/src/__tests__/anthropic-provider.test.ts +92 -2
  18. package/src/__tests__/app-control-flow.test.ts +7 -0
  19. package/src/__tests__/assistant-events-sse-shed.test.ts +232 -0
  20. package/src/__tests__/avatar-identity-sync.test.ts +87 -0
  21. package/src/__tests__/background-workers-disk-pressure.test.ts +11 -22
  22. package/src/__tests__/btw-routes.test.ts +1 -0
  23. package/src/__tests__/call-site-routing-provider.test.ts +172 -45
  24. package/src/__tests__/cancel-resolves-conversation-key.test.ts +44 -3
  25. package/src/__tests__/channel-policy.test.ts +12 -0
  26. package/src/__tests__/checker.test.ts +89 -0
  27. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +35 -7
  28. package/src/__tests__/compact-event-conversation-id-guard.test.ts +33 -5
  29. package/src/__tests__/compaction-strip-metadata-clear.test.ts +26 -1
  30. package/src/__tests__/config-loader-backfill.test.ts +526 -102
  31. package/src/__tests__/config-loader-corrupt.test.ts +68 -0
  32. package/src/__tests__/config-loader-platform-defaults.test.ts +77 -23
  33. package/src/__tests__/config-schema-cmd.test.ts +63 -29
  34. package/src/__tests__/config-schema.test.ts +14 -3
  35. package/src/__tests__/config-set-platform-guard.test.ts +75 -152
  36. package/src/__tests__/config-set-route.test.ts +198 -0
  37. package/src/__tests__/config-watcher.test.ts +6 -0
  38. package/src/__tests__/contacts-tools.test.ts +51 -199
  39. package/src/__tests__/context-search-agent-protocol.test.ts +21 -2
  40. package/src/__tests__/context-search-agent-runner.test.ts +22 -138
  41. package/src/__tests__/context-search-conversations-source.test.ts +42 -16
  42. package/src/__tests__/context-search-fanout.test.ts +20 -157
  43. package/src/__tests__/context-search-memory-v2-source.test.ts +3 -3
  44. package/src/__tests__/context-search-types.test.ts +7 -2
  45. package/src/__tests__/context-window-manager.test.ts +389 -1
  46. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
  47. package/src/__tests__/conversation-crud-inference-profile.test.ts +100 -0
  48. package/src/__tests__/conversation-error.test.ts +38 -0
  49. package/src/__tests__/conversation-fork-crud.test.ts +241 -1
  50. package/src/__tests__/conversation-inference-profile-route.test.ts +14 -14
  51. package/src/__tests__/conversation-init.benchmark.test.ts +1 -0
  52. package/src/__tests__/conversation-lifecycle.test.ts +124 -0
  53. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +100 -1
  54. package/src/__tests__/conversation-process-callsite.test.ts +21 -1
  55. package/src/__tests__/conversation-runtime-assembly.test.ts +4 -4
  56. package/src/__tests__/conversation-slash-commands.test.ts +194 -2
  57. package/src/__tests__/conversation-surfaces-app-control.test.ts +323 -3
  58. package/src/__tests__/credential-security-invariants.test.ts +5 -6
  59. package/src/__tests__/daemon-credential-client.test.ts +56 -1
  60. package/src/__tests__/db-activation-state-fk-cascade.test.ts +132 -0
  61. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +37 -0
  62. package/src/__tests__/db-memory-graph-event-date-repair.test.ts +43 -20
  63. package/src/__tests__/db-proxy-transaction.test.ts +206 -0
  64. package/src/__tests__/external-plugin-loader.test.ts +458 -0
  65. package/src/__tests__/filing-service.test.ts +23 -3
  66. package/src/__tests__/fixtures/mock-chrome-extension.ts +5 -0
  67. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  68. package/src/__tests__/graph-extraction-event-date.test.ts +34 -0
  69. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +0 -8
  70. package/src/__tests__/heartbeat-disk-pressure.test.ts +21 -8
  71. package/src/__tests__/heartbeat-service.test.ts +50 -233
  72. package/src/__tests__/history-repair.test.ts +89 -0
  73. package/src/__tests__/host-app-control-proxy.test.ts +109 -1
  74. package/src/__tests__/host-app-control-routes.test.ts +247 -1
  75. package/src/__tests__/host-browser-proxy.test.ts +416 -20
  76. package/src/__tests__/host-browser-routes.test.ts +325 -33
  77. package/src/__tests__/host-proxy-preactivation.test.ts +211 -0
  78. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +246 -0
  79. package/src/__tests__/inference-profile-reaper.test.ts +154 -0
  80. package/src/__tests__/inference-profile-session-handler.test.ts +398 -0
  81. package/src/__tests__/inference-profile-session-ipc.test.ts +236 -0
  82. package/src/__tests__/inline-skill-load-permissions.test.ts +6 -1
  83. package/src/__tests__/install-skill-routing.test.ts +2 -2
  84. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +15 -0
  85. package/src/__tests__/llm-callsite-catalog.test.ts +20 -1
  86. package/src/__tests__/llm-catalog-parity.test.ts +146 -0
  87. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +188 -0
  88. package/src/__tests__/llm-request-log-source-factory.test.ts +124 -0
  89. package/src/__tests__/llm-resolver.test.ts +46 -0
  90. package/src/__tests__/managed-profile-guard.test.ts +131 -2
  91. package/src/__tests__/mcp-auth-routes.test.ts +1 -0
  92. package/src/__tests__/mcp-cli.test.ts +182 -220
  93. package/src/__tests__/mcp-health-check.test.ts +56 -27
  94. package/src/__tests__/memory-jobs-worker-lanes.test.ts +18 -11
  95. package/src/__tests__/message-complete-display-id.test.ts +175 -0
  96. package/src/__tests__/notification-platform-adapter.test.ts +229 -0
  97. package/src/__tests__/oauth-cli.test.ts +38 -2009
  98. package/src/__tests__/oauth-commands-routes.test.ts +711 -0
  99. package/src/__tests__/oauth-connect-routes.test.ts +174 -11
  100. package/src/__tests__/oauth-providers-routes.test.ts +14 -10
  101. package/src/__tests__/openai-responses-cutover-guard.test.ts +33 -12
  102. package/src/__tests__/openai-responses-provider.test.ts +17 -0
  103. package/src/__tests__/plugin-bootstrap.test.ts +31 -2
  104. package/src/__tests__/plugin-route-contribution.test.ts +31 -3
  105. package/src/__tests__/plugin-tool-contribution.test.ts +31 -3
  106. package/src/__tests__/plugin-types.test.ts +13 -11
  107. package/src/__tests__/process-message-background-slack.test.ts +46 -0
  108. package/src/__tests__/profile-entry-status.test.ts +43 -0
  109. package/src/__tests__/provider-managed-proxy-integration.test.ts +12 -4
  110. package/src/__tests__/provider-registry-ollama.test.ts +12 -4
  111. package/src/__tests__/provider-send-message-override-profile.test.ts +10 -4
  112. package/src/__tests__/relay-server.test.ts +118 -0
  113. package/src/__tests__/retry-thinking-tool-choice.test.ts +15 -0
  114. package/src/__tests__/schedule-retry.test.ts +56 -4
  115. package/src/__tests__/schedule-routes.test.ts +104 -0
  116. package/src/__tests__/scheduler-disk-pressure.test.ts +0 -4
  117. package/src/__tests__/scheduler-recurrence.test.ts +87 -34
  118. package/src/__tests__/scheduler-reuse-conversation.test.ts +161 -5
  119. package/src/__tests__/scheduler-wake.test.ts +0 -63
  120. package/src/__tests__/secret-allowlist.test.ts +1 -0
  121. package/src/__tests__/secret-routes-managed-proxy.test.ts +12 -4
  122. package/src/__tests__/shell-credential-ref.test.ts +95 -3
  123. package/src/__tests__/shell-tool-proxy-mode.test.ts +14 -0
  124. package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
  125. package/src/__tests__/skill-load-tool.test.ts +2 -4
  126. package/src/__tests__/subagent-call-site-routing.test.ts +78 -16
  127. package/src/__tests__/suggestion-routes.test.ts +3 -3
  128. package/src/__tests__/sync-message-contract.test.ts +63 -0
  129. package/src/__tests__/task-scheduler.test.ts +88 -23
  130. package/src/__tests__/update-bulletin-job.test.ts +96 -193
  131. package/src/__tests__/usage-cli.test.ts +11 -73
  132. package/src/__tests__/user-plugin-loader.test.ts +145 -0
  133. package/src/__tests__/vercel-config.test.ts +168 -0
  134. package/src/__tests__/web-search-catalog-parity.test.ts +86 -0
  135. package/src/__tests__/web-search.test.ts +303 -2
  136. package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +1 -21
  137. package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +58 -0
  138. package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +53 -20
  139. package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +191 -0
  140. package/src/__tests__/workspace-migration-076-drop-services-inference-mode.test.ts +211 -0
  141. package/src/__tests__/workspace-migration-077-seed-memory-router-callsite.test.ts +174 -0
  142. package/src/__tests__/workspace-migration-079-home-feed-notification-only.test.ts +323 -0
  143. package/src/__tests__/workspace-migration-080-restrict-vercel-api-token-metadata.test.ts +299 -0
  144. package/src/__tests__/workspace-migration-081-backfill-bash-allowed-tools.test.ts +410 -0
  145. package/src/__tests__/workspace-migration-082-backfill-managed-profile-labels.test.ts +268 -0
  146. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +3 -3
  147. package/src/__tests__/workspace-release-notes-feature-flag-guard.test.ts +115 -0
  148. package/src/acp/__tests__/helpers/which-stub.ts +4 -2
  149. package/src/acp/resolve-agent.test.ts +25 -0
  150. package/src/acp/resolve-agent.ts +13 -2
  151. package/src/acp/session-manager.ts +14 -0
  152. package/src/approvals/guardian-request-resolvers.ts +32 -87
  153. package/src/calls/relay-server.ts +35 -0
  154. package/src/calls/relay-setup-router.ts +36 -0
  155. package/src/calls/types.ts +1 -0
  156. package/src/calls/voice-session-bridge.ts +23 -4
  157. package/src/channels/config.ts +14 -1
  158. package/src/channels/types.ts +1 -0
  159. package/src/cli/AGENTS.md +164 -4
  160. package/src/cli/__tests__/notifications.test.ts +54 -0
  161. package/src/cli/commands/__tests__/avatar.test.ts +540 -0
  162. package/src/cli/commands/__tests__/backup.test.ts +236 -776
  163. package/src/cli/commands/__tests__/cache.test.ts +1 -1
  164. package/src/cli/commands/__tests__/changelog.test.ts +593 -0
  165. package/src/cli/commands/__tests__/channel-verification-sessions.test.ts +503 -0
  166. package/src/cli/commands/__tests__/conversations-import.test.ts +515 -0
  167. package/src/cli/commands/__tests__/domain-register.test.ts +140 -167
  168. package/src/cli/commands/__tests__/domain-status.test.ts +137 -76
  169. package/src/cli/commands/__tests__/email-attachment.test.ts +314 -337
  170. package/src/cli/commands/__tests__/email-core.test.ts +579 -0
  171. package/src/cli/commands/__tests__/image-generation.test.ts +87 -824
  172. package/src/cli/commands/__tests__/inference-send.test.ts +30 -266
  173. package/src/cli/commands/__tests__/inference-session.test.ts +423 -0
  174. package/src/cli/commands/__tests__/memory-v2.test.ts +81 -110
  175. package/src/cli/commands/__tests__/skills.test.ts +563 -0
  176. package/src/cli/commands/__tests__/status.test.ts +249 -0
  177. package/src/cli/commands/__tests__/stt.test.ts +320 -0
  178. package/src/cli/commands/__tests__/tts-synthesize.test.ts +4 -603
  179. package/src/cli/commands/__tests__/tts.test.ts +321 -0
  180. package/src/cli/commands/__tests__/webhooks.test.ts +86 -511
  181. package/src/cli/commands/attachment.ts +8 -3
  182. package/src/cli/commands/audit.ts +95 -64
  183. package/src/cli/commands/auth.ts +61 -58
  184. package/src/cli/commands/avatar.ts +276 -390
  185. package/src/cli/commands/backup.ts +409 -505
  186. package/src/cli/commands/bash.ts +9 -5
  187. package/src/cli/commands/browser.ts +28 -9
  188. package/src/cli/commands/cache.ts +9 -4
  189. package/src/cli/commands/changelog.ts +414 -0
  190. package/src/cli/commands/channel-verification-sessions.ts +238 -317
  191. package/src/cli/commands/clients.ts +8 -3
  192. package/src/cli/commands/completions.ts +9 -9
  193. package/src/cli/commands/config.ts +102 -72
  194. package/src/cli/commands/contacts.ts +575 -696
  195. package/src/cli/commands/conversations-defer.ts +17 -69
  196. package/src/cli/commands/conversations-import.ts +90 -253
  197. package/src/cli/commands/conversations.ts +346 -436
  198. package/src/cli/commands/credential-execution.ts +9 -6
  199. package/src/cli/commands/credentials.ts +456 -736
  200. package/src/cli/commands/domain.ts +128 -206
  201. package/src/cli/commands/email.ts +606 -794
  202. package/src/cli/commands/gateway.ts +8 -1
  203. package/src/cli/commands/image-generation.ts +157 -205
  204. package/src/cli/commands/inference-providers.ts +352 -0
  205. package/src/cli/commands/inference-session.ts +415 -0
  206. package/src/cli/commands/inference.ts +87 -65
  207. package/src/cli/commands/keys.ts +8 -3
  208. package/src/cli/commands/mcp.ts +103 -287
  209. package/src/cli/commands/memory-v2.ts +162 -516
  210. package/src/cli/commands/notifications.ts +33 -7
  211. package/src/cli/commands/oauth/apps.ts +292 -261
  212. package/src/cli/commands/oauth/connect.ts +176 -297
  213. package/src/cli/commands/oauth/disconnect.ts +16 -215
  214. package/src/cli/commands/oauth/index.ts +49 -45
  215. package/src/cli/commands/oauth/mode.ts +43 -199
  216. package/src/cli/commands/oauth/ping.ts +17 -125
  217. package/src/cli/commands/oauth/providers.ts +732 -921
  218. package/src/cli/commands/oauth/request.ts +60 -350
  219. package/src/cli/commands/oauth/shared.ts +11 -121
  220. package/src/cli/commands/oauth/status.ts +31 -121
  221. package/src/cli/commands/oauth/token.ts +13 -55
  222. package/src/cli/commands/pending.ts +19 -10
  223. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +133 -183
  224. package/src/cli/commands/platform/__tests__/connect.test.ts +66 -181
  225. package/src/cli/commands/platform/__tests__/disconnect.test.ts +71 -227
  226. package/src/cli/commands/platform/__tests__/status.test.ts +169 -287
  227. package/src/cli/commands/platform/connect.ts +16 -80
  228. package/src/cli/commands/platform/disconnect.ts +14 -112
  229. package/src/cli/commands/platform/index.ts +177 -246
  230. package/src/cli/commands/routes.ts +153 -336
  231. package/src/cli/commands/sequence.ts +316 -360
  232. package/src/cli/commands/skills.ts +449 -671
  233. package/src/cli/commands/status.ts +58 -37
  234. package/src/cli/commands/stt.ts +94 -262
  235. package/src/cli/commands/task.ts +14 -40
  236. package/src/cli/commands/trust.ts +8 -3
  237. package/src/cli/commands/tts.ts +162 -167
  238. package/src/cli/commands/ui.ts +35 -42
  239. package/src/cli/commands/usage.ts +188 -126
  240. package/src/cli/commands/watchers.ts +8 -3
  241. package/src/cli/commands/webhooks.ts +99 -193
  242. package/src/cli/lib/__tests__/register-command.test.ts +85 -0
  243. package/src/cli/lib/daemon-credential-client.ts +4 -5
  244. package/src/cli/lib/nested-value.ts +44 -0
  245. package/src/cli/lib/open-browser.ts +36 -0
  246. package/src/cli/lib/register-command.ts +19 -0
  247. package/src/cli/lib/time-ago.ts +34 -0
  248. package/src/cli/program.ts +2 -4
  249. package/src/cli/utils/__tests__/conversation-id.test.ts +66 -0
  250. package/src/cli/utils/__tests__/parse-duration.test.ts +49 -0
  251. package/src/cli/utils/conversation-id.ts +30 -0
  252. package/src/cli/utils/parse-duration.ts +41 -0
  253. package/src/config/acp-defaults.test.ts +5 -1
  254. package/src/config/acp-defaults.ts +11 -4
  255. package/src/config/bundled-skills/acp/TOOLS.json +2 -2
  256. package/src/config/bundled-skills/app-control/TOOLS.json +32 -0
  257. package/src/config/bundled-skills/contacts/SKILL.md +12 -45
  258. package/src/config/bundled-skills/contacts/TOOLS.json +0 -57
  259. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +0 -12
  260. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -58
  261. package/src/config/bundled-tool-registry.ts +0 -2
  262. package/src/config/feature-flag-registry.json +16 -0
  263. package/src/config/llm-resolver.ts +16 -1
  264. package/src/config/loader.ts +76 -14
  265. package/src/config/raw-config-utils.ts +2 -30
  266. package/src/config/schema.ts +4 -0
  267. package/src/config/schemas/__tests__/memory-v2.test.ts +49 -0
  268. package/src/config/schemas/call-site-catalog.ts +29 -7
  269. package/src/config/schemas/llm-request-logs.ts +57 -0
  270. package/src/config/schemas/llm.ts +52 -2
  271. package/src/config/schemas/memory-retrospective.ts +48 -0
  272. package/src/config/schemas/memory-v2.ts +32 -1
  273. package/src/config/schemas/memory.ts +4 -0
  274. package/src/config/schemas/services.ts +15 -12
  275. package/src/config/seed-inference-profiles.ts +195 -134
  276. package/src/contacts/contact-store.ts +0 -61
  277. package/src/context/window-manager.ts +191 -5
  278. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +79 -0
  279. package/src/daemon/__tests__/conversation-tool-setup.test.ts +109 -4
  280. package/src/daemon/__tests__/daemon-skill-host.test.ts +10 -4
  281. package/src/daemon/approval-generators.ts +23 -29
  282. package/src/daemon/config-watcher.ts +2 -0
  283. package/src/daemon/conversation-agent-loop-handlers.ts +24 -0
  284. package/src/daemon/conversation-agent-loop.ts +127 -97
  285. package/src/daemon/conversation-error.ts +21 -0
  286. package/src/daemon/conversation-lifecycle.ts +46 -5
  287. package/src/daemon/conversation-process.ts +36 -19
  288. package/src/daemon/conversation-runtime-assembly.ts +14 -5
  289. package/src/daemon/conversation-slash.ts +175 -23
  290. package/src/daemon/conversation-store.ts +17 -10
  291. package/src/daemon/conversation-surfaces.ts +76 -12
  292. package/src/daemon/conversation-tool-setup.ts +24 -14
  293. package/src/daemon/conversation.ts +48 -9
  294. package/src/daemon/external-plugins-bootstrap.ts +18 -8
  295. package/src/daemon/guardian-action-generators.ts +7 -22
  296. package/src/daemon/handlers/config-model.ts +8 -126
  297. package/src/daemon/handlers/config-slack-channel.ts +10 -7
  298. package/src/daemon/handlers/config-vercel.ts +3 -1
  299. package/src/daemon/handlers/skills.ts +84 -5
  300. package/src/daemon/history-repair.ts +33 -6
  301. package/src/daemon/host-app-control-proxy.ts +44 -19
  302. package/src/daemon/host-bash-proxy.ts +85 -158
  303. package/src/daemon/host-browser-proxy.ts +96 -35
  304. package/src/daemon/host-proxy-base.ts +13 -1
  305. package/src/daemon/host-proxy-preactivation.ts +25 -1
  306. package/src/daemon/identity-helpers.ts +19 -0
  307. package/src/daemon/lifecycle.ts +42 -43
  308. package/src/daemon/meet-host-supervisor.ts +15 -15
  309. package/src/daemon/memory-v2-startup.ts +9 -2
  310. package/src/daemon/message-protocol.ts +6 -0
  311. package/src/daemon/message-types/bookmarks.ts +18 -0
  312. package/src/daemon/message-types/conversations.ts +12 -9
  313. package/src/daemon/message-types/messages.ts +9 -1
  314. package/src/daemon/message-types/sync.ts +60 -0
  315. package/src/daemon/pkb-reminder-builder.test.ts +54 -13
  316. package/src/daemon/pkb-reminder-builder.ts +21 -7
  317. package/src/daemon/process-message.ts +56 -23
  318. package/src/daemon/server.ts +23 -18
  319. package/src/daemon/shutdown-handlers.ts +0 -2
  320. package/src/daemon/tool-setup-types.ts +9 -0
  321. package/src/daemon/tool-side-effects.ts +6 -4
  322. package/src/daemon/wake-target-adapter.ts +11 -0
  323. package/src/export/transcript-formatter.ts +61 -2
  324. package/src/filing/filing-service.ts +40 -53
  325. package/src/heartbeat/__tests__/heartbeat-service.test.ts +359 -0
  326. package/src/heartbeat/heartbeat-run-store.ts +2 -1
  327. package/src/heartbeat/heartbeat-service.ts +148 -127
  328. package/src/home/__tests__/feed-types.test.ts +63 -131
  329. package/src/home/__tests__/feed-writer.test.ts +77 -278
  330. package/src/home/__tests__/post-connect-feed.test.ts +9 -12
  331. package/src/home/feed-types.ts +19 -73
  332. package/src/home/feed-writer.ts +25 -156
  333. package/src/home/post-connect-feed.ts +1 -3
  334. package/src/ipc/__tests__/cli-ipc.test.ts +2 -0
  335. package/src/ipc/__tests__/email-ipc.test.ts +506 -0
  336. package/src/ipc/__tests__/exit-helper.test.ts +104 -0
  337. package/src/ipc/__tests__/streaming-client.test.ts +237 -0
  338. package/src/ipc/__tests__/streaming-framing.test.ts +142 -0
  339. package/src/ipc/assistant-server.ts +55 -6
  340. package/src/ipc/cli-client.ts +370 -50
  341. package/src/ipc/routes/db-proxy-transaction.ts +151 -0
  342. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +60 -0
  343. package/src/ipc/skill-routes/events.ts +30 -3
  344. package/src/live-voice/__tests__/live-voice-session-manager.test.ts +46 -0
  345. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +1 -0
  346. package/src/live-voice/live-voice-session-manager.ts +11 -4
  347. package/src/live-voice/live-voice-session.ts +14 -6
  348. package/src/memory/__tests__/bookmark-crud.test.ts +258 -0
  349. package/src/memory/__tests__/bookmark-schema.test.ts +181 -0
  350. package/src/memory/__tests__/conversation-types.test.ts +36 -0
  351. package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +130 -0
  352. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +177 -0
  353. package/src/memory/__tests__/memory-retrospective-job.test.ts +328 -0
  354. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +213 -0
  355. package/src/memory/__tests__/memory-retrospective-trigger-check.test.ts +90 -0
  356. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +69 -0
  357. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -0
  358. package/src/memory/bookmark-crud.ts +179 -0
  359. package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +31 -9
  360. package/src/memory/context-search/agent-protocol.ts +5 -1
  361. package/src/memory/context-search/agent-runner.ts +60 -85
  362. package/src/memory/context-search/limits.ts +1 -4
  363. package/src/memory/context-search/search.ts +23 -113
  364. package/src/memory/context-search/sources/conversations.ts +18 -6
  365. package/src/memory/context-search/sources/memory-v2.ts +39 -14
  366. package/src/memory/context-search/sources/memory.ts +7 -0
  367. package/src/memory/context-search/sources/workspace.ts +13 -10
  368. package/src/memory/context-search/types.ts +1 -1
  369. package/src/memory/conversation-bootstrap.ts +11 -0
  370. package/src/memory/conversation-crud.ts +312 -10
  371. package/src/memory/conversation-queries.ts +9 -5
  372. package/src/memory/conversation-title-service.ts +1 -0
  373. package/src/memory/conversation-types.ts +16 -0
  374. package/src/memory/db-init.ts +14 -0
  375. package/src/memory/embedding-backend.ts +2 -1
  376. package/src/memory/embedding-runtime-manager.ts +1 -2
  377. package/src/memory/graph/__tests__/remember-description.test.ts +55 -0
  378. package/src/memory/graph/conversation-graph-memory.ts +76 -5
  379. package/src/memory/graph/extraction.ts +4 -0
  380. package/src/memory/graph/graph-memory-state-store.ts +16 -3
  381. package/src/memory/graph/tool-handlers.ts +17 -7
  382. package/src/memory/graph/tools.ts +44 -5
  383. package/src/memory/indexer.ts +17 -0
  384. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +13 -15
  385. package/src/memory/jobs/embed-concept-page.ts +45 -9
  386. package/src/memory/jobs-store.ts +51 -1
  387. package/src/memory/jobs-worker.ts +52 -3
  388. package/src/memory/llm-request-log-source-clickhouse.ts +317 -0
  389. package/src/memory/llm-request-log-source-local.ts +26 -0
  390. package/src/memory/llm-request-log-source.ts +97 -0
  391. package/src/memory/llm-request-log-store.ts +1 -1
  392. package/src/memory/memory-retrospective-constants.ts +13 -0
  393. package/src/memory/memory-retrospective-enqueue.ts +114 -0
  394. package/src/memory/memory-retrospective-job.ts +351 -0
  395. package/src/memory/memory-retrospective-startup-cleanup.ts +108 -0
  396. package/src/memory/memory-retrospective-state.ts +162 -0
  397. package/src/memory/memory-retrospective-trigger-check.ts +91 -0
  398. package/src/memory/memory-v2-activation-log-store.ts +49 -5
  399. package/src/memory/memory-v2-concept-frequency.ts +4 -0
  400. package/src/memory/message-content.ts +38 -1
  401. package/src/memory/migrations/227-add-conversation-inference-profile.ts +6 -1
  402. package/src/memory/migrations/228-rename-inference-profile-snake-case.ts +20 -7
  403. package/src/memory/migrations/229-delete-private-conversations.test.ts +70 -1
  404. package/src/memory/migrations/229-delete-private-conversations.ts +12 -0
  405. package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +16 -2
  406. package/src/memory/migrations/240-conversation-inference-profile-session.ts +25 -0
  407. package/src/memory/migrations/241-activation-state-fk-cascade.ts +50 -0
  408. package/src/memory/migrations/242-message-bookmarks.ts +38 -0
  409. package/src/memory/migrations/243-provider-connections.ts +68 -0
  410. package/src/memory/migrations/244-provider-connection-status-label.ts +23 -0
  411. package/src/memory/migrations/245-memory-retrospective-state.ts +36 -0
  412. package/src/memory/migrations/246-backfill-provider-connection-label.ts +81 -0
  413. package/src/memory/migrations/__tests__/244-provider-connection-status-label.test.ts +84 -0
  414. package/src/memory/migrations/__tests__/245-memory-retrospective-state.test.ts +125 -0
  415. package/src/memory/migrations/__tests__/246-backfill-provider-connection-label.test.ts +192 -0
  416. package/src/memory/migrations/index.ts +7 -0
  417. package/src/memory/published-pages-store.ts +16 -0
  418. package/src/memory/schema/bookmarks.ts +38 -0
  419. package/src/memory/schema/conversations.ts +2 -0
  420. package/src/memory/schema/index.ts +2 -0
  421. package/src/memory/schema/inference.ts +29 -0
  422. package/src/memory/schema/memory-core.ts +9 -0
  423. package/src/memory/search/semantic.ts +1 -4
  424. package/src/memory/v2/__tests__/__snapshots__/prompts-router.test.ts.snap +27 -0
  425. package/src/memory/v2/__tests__/activation-store.test.ts +5 -5
  426. package/src/memory/v2/__tests__/activation.test.ts +11 -4
  427. package/src/memory/v2/__tests__/backfill-jobs.test.ts +38 -21
  428. package/src/memory/v2/__tests__/consolidation-job.test.ts +123 -135
  429. package/src/memory/v2/__tests__/edge-index.test.ts +1 -1
  430. package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +111 -0
  431. package/src/memory/v2/__tests__/injection.test.ts +628 -10
  432. package/src/memory/v2/__tests__/migration.test.ts +7 -3
  433. package/src/memory/v2/__tests__/page-index.test.ts +277 -0
  434. package/src/memory/v2/__tests__/page-store.test.ts +14 -1
  435. package/src/memory/v2/__tests__/prompts-router.test.ts +257 -0
  436. package/src/memory/v2/__tests__/qdrant.test.ts +72 -0
  437. package/src/memory/v2/__tests__/reranker.test.ts +4 -4
  438. package/src/memory/v2/__tests__/router.test.ts +516 -0
  439. package/src/memory/v2/__tests__/sim.test.ts +45 -1
  440. package/src/memory/v2/__tests__/skill-store.test.ts +58 -3
  441. package/src/memory/v2/__tests__/static-context.test.ts +7 -22
  442. package/src/memory/v2/__tests__/sweep-job.test.ts +95 -0
  443. package/src/memory/v2/activation-store.ts +34 -5
  444. package/src/memory/v2/activation.ts +40 -27
  445. package/src/memory/v2/backfill-jobs.ts +17 -84
  446. package/src/memory/v2/consolidation-job.ts +85 -78
  447. package/src/memory/v2/frontmatter-sweep.ts +91 -0
  448. package/src/memory/v2/injection.ts +440 -109
  449. package/src/memory/v2/migration.ts +117 -20
  450. package/src/memory/v2/page-index.ts +191 -0
  451. package/src/memory/v2/page-store.ts +3 -0
  452. package/src/memory/v2/prompts/consolidation.ts +9 -7
  453. package/src/memory/v2/prompts/router.ts +192 -0
  454. package/src/memory/v2/qdrant.ts +100 -87
  455. package/src/memory/v2/reranker.ts +14 -7
  456. package/src/memory/v2/router.ts +322 -0
  457. package/src/memory/v2/sim.ts +25 -12
  458. package/src/memory/v2/skill-store.ts +118 -29
  459. package/src/memory/v2/static-context.ts +16 -9
  460. package/src/memory/v2/sweep-job.ts +122 -96
  461. package/src/memory/v2/types.ts +10 -6
  462. package/src/memory/validation.ts +13 -0
  463. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +182 -0
  464. package/src/notifications/__tests__/home-feed-side-effect.test.ts +199 -0
  465. package/src/notifications/__tests__/signal-registry.test.ts +17 -0
  466. package/src/notifications/adapters/platform.ts +171 -0
  467. package/src/notifications/conversation-pairing.ts +2 -2
  468. package/src/notifications/copy-composer.ts +15 -0
  469. package/src/notifications/destination-resolver.ts +21 -0
  470. package/src/notifications/emit-signal.ts +28 -1
  471. package/src/notifications/home-feed-side-effect.ts +111 -0
  472. package/src/notifications/signal.ts +5 -0
  473. package/src/permissions/checker.ts +12 -0
  474. package/src/permissions/ipc-risk-types.ts +2 -0
  475. package/src/plugin-api/index.ts +13 -0
  476. package/src/plugin-api/package.json +12 -0
  477. package/src/plugin-api/types.ts +62 -0
  478. package/src/plugins/defaults/injectors.ts +19 -3
  479. package/src/plugins/external-plugin-loader.ts +294 -0
  480. package/src/plugins/types.ts +46 -30
  481. package/src/plugins/user-loader.ts +64 -41
  482. package/src/proactive-artifact/job.test.ts +12 -4
  483. package/src/proactive-artifact/job.ts +4 -0
  484. package/src/proactive-artifact/trigger-state.test.ts +9 -0
  485. package/src/proactive-artifact/trigger-state.ts +4 -0
  486. package/src/prompts/__tests__/system-prompt.test.ts +105 -0
  487. package/src/prompts/system-prompt.ts +22 -1
  488. package/src/prompts/update-bulletin-job.ts +61 -73
  489. package/src/providers/__tests__/dispatch-connection-routing.test.ts +279 -0
  490. package/src/providers/__tests__/inference.test.ts +288 -0
  491. package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
  492. package/src/providers/__tests__/provider-secret-catalog.test.ts +6 -0
  493. package/src/providers/__tests__/retry-callsite.test.ts +14 -32
  494. package/src/providers/__tests__/satellite-connection-routing.test.ts +510 -0
  495. package/src/providers/__tests__/search-provider-catalog.test.ts +80 -0
  496. package/src/providers/anthropic/client.ts +95 -26
  497. package/src/providers/call-site-routing.ts +94 -16
  498. package/src/providers/connection-resolution.ts +163 -0
  499. package/src/providers/inference/__tests__/connections-status-label.test.ts +250 -0
  500. package/src/providers/inference/adapter-factory.ts +173 -0
  501. package/src/providers/inference/auth.ts +112 -0
  502. package/src/providers/inference/backfill.ts +196 -0
  503. package/src/providers/inference/connections.ts +356 -0
  504. package/src/providers/inference/resolve-auth.ts +65 -0
  505. package/src/providers/model-catalog.ts +104 -6
  506. package/src/providers/openai/responses-provider.ts +4 -2
  507. package/src/providers/provider-env-vars.ts +17 -7
  508. package/src/providers/provider-secret-catalog.ts +49 -30
  509. package/src/providers/provider-send-message.ts +41 -20
  510. package/src/providers/registry.ts +143 -159
  511. package/src/providers/retry.ts +18 -10
  512. package/src/providers/search-provider-catalog.ts +121 -0
  513. package/src/runtime/AGENTS.md +18 -5
  514. package/src/runtime/__tests__/background-job-runner.test.ts +357 -0
  515. package/src/runtime/__tests__/pre-first-message-gate.test.ts +82 -0
  516. package/src/runtime/actor-trust-resolver.ts +32 -10
  517. package/src/runtime/agent-wake.ts +35 -6
  518. package/src/runtime/assistant-event-hub.ts +3 -85
  519. package/src/runtime/auth/route-policy.ts +303 -8
  520. package/src/runtime/auth/same-actor.ts +2 -0
  521. package/src/runtime/background-job-runner.ts +339 -0
  522. package/src/runtime/btw-sidechain.ts +1 -0
  523. package/src/runtime/http-router.ts +36 -1
  524. package/src/runtime/http-server.ts +31 -5
  525. package/src/runtime/http-types.ts +2 -0
  526. package/src/runtime/middleware/__tests__/request-logger.test.ts +162 -0
  527. package/src/runtime/middleware/request-logger.ts +62 -1
  528. package/src/runtime/pre-first-message-gate.ts +83 -0
  529. package/src/runtime/routes/__tests__/backup-routes.test.ts +8 -1
  530. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +251 -0
  531. package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +142 -0
  532. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +315 -0
  533. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +189 -0
  534. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +15 -136
  535. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +736 -0
  536. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +4 -4
  537. package/src/runtime/routes/__tests__/stt-routes.test.ts +5 -1
  538. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +384 -0
  539. package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
  540. package/src/runtime/routes/acp-routes.ts +10 -8
  541. package/src/runtime/routes/app-management-routes.ts +228 -3
  542. package/src/runtime/routes/approval-routes.ts +0 -18
  543. package/src/runtime/routes/audit-routes.ts +43 -0
  544. package/src/runtime/routes/auth-routes.ts +72 -0
  545. package/src/runtime/routes/avatar-routes.ts +273 -20
  546. package/src/runtime/routes/backup-routes.ts +406 -2
  547. package/src/runtime/routes/bookmark-routes.ts +154 -0
  548. package/src/runtime/routes/channel-verification-routes.ts +2 -1
  549. package/src/runtime/routes/contact-routes.ts +0 -160
  550. package/src/runtime/routes/conversation-cli-routes.ts +192 -0
  551. package/src/runtime/routes/conversation-management-routes.ts +30 -43
  552. package/src/runtime/routes/conversation-query-routes.ts +334 -86
  553. package/src/runtime/routes/conversation-routes.ts +31 -10
  554. package/src/runtime/routes/conversations-import-routes.ts +229 -0
  555. package/src/runtime/routes/credential-routes.ts +540 -0
  556. package/src/runtime/routes/debug-routes.ts +2 -2
  557. package/src/runtime/routes/document-pdf-renderer.ts +5 -1
  558. package/src/runtime/routes/domain-routes.ts +167 -0
  559. package/src/runtime/routes/email-routes.ts +603 -0
  560. package/src/runtime/routes/errors.ts +2 -2
  561. package/src/runtime/routes/events-routes.ts +192 -0
  562. package/src/runtime/routes/home-feed-routes.ts +6 -78
  563. package/src/runtime/routes/host-app-control-routes.ts +44 -2
  564. package/src/runtime/routes/host-browser-routes.ts +103 -22
  565. package/src/runtime/routes/http-adapter.ts +2 -0
  566. package/src/runtime/routes/identity-routes.ts +5 -0
  567. package/src/runtime/routes/image-generation-routes.ts +99 -0
  568. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +137 -1
  569. package/src/runtime/routes/inbound-stages/background-dispatch.ts +87 -7
  570. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +156 -0
  571. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +22 -4
  572. package/src/runtime/routes/index.ts +36 -0
  573. package/src/runtime/routes/inference-profile-session-handler.ts +312 -0
  574. package/src/runtime/routes/inference-profile-session-reaper.ts +98 -0
  575. package/src/runtime/routes/inference-profile-session-routes.ts +146 -0
  576. package/src/runtime/routes/inference-provider-connection-routes.ts +317 -0
  577. package/src/runtime/routes/inference-send-routes.ts +115 -0
  578. package/src/runtime/routes/integrations/twilio.ts +1 -0
  579. package/src/runtime/routes/mcp-auth-routes.ts +283 -9
  580. package/src/runtime/routes/memory-v2-routes.ts +13 -398
  581. package/src/runtime/routes/notification-routes.ts +2 -0
  582. package/src/runtime/routes/oauth-apps.ts +112 -7
  583. package/src/runtime/routes/oauth-commands-routes.ts +1007 -0
  584. package/src/runtime/routes/oauth-connect-routes.ts +67 -5
  585. package/src/runtime/routes/oauth-providers.ts +298 -8
  586. package/src/runtime/routes/platform-routes.ts +336 -0
  587. package/src/runtime/routes/playground/inject-failures.ts +2 -1
  588. package/src/runtime/routes/playground/reset-circuit.ts +2 -1
  589. package/src/runtime/routes/playground/state.ts +2 -1
  590. package/src/runtime/routes/publish-routes.ts +221 -0
  591. package/src/runtime/routes/schedule-routes.ts +82 -0
  592. package/src/runtime/routes/sequence-routes.ts +291 -0
  593. package/src/runtime/routes/settings-routes.ts +2 -10
  594. package/src/runtime/routes/skills-routes.ts +31 -1
  595. package/src/runtime/routes/stt-routes.ts +240 -3
  596. package/src/runtime/routes/surface-action-routes.ts +43 -7
  597. package/src/runtime/routes/tts-routes.ts +67 -0
  598. package/src/runtime/routes/types.ts +32 -0
  599. package/src/runtime/routes/user-routes-cli.ts +243 -0
  600. package/src/runtime/routes/webhook-routes.ts +165 -0
  601. package/src/runtime/sync/resource-sync-events.ts +25 -0
  602. package/src/runtime/sync/sync-publisher.test.ts +105 -0
  603. package/src/runtime/sync/sync-publisher.ts +21 -0
  604. package/src/schedule/scheduler.ts +200 -123
  605. package/src/security/__tests__/provider-key-env-fallback.test.ts +12 -6
  606. package/src/security/secret-patterns.ts +3 -0
  607. package/src/sequence/engine.ts +38 -40
  608. package/src/subagent/manager.ts +20 -15
  609. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +206 -0
  610. package/src/tools/browser/browser-execution.ts +15 -4
  611. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +174 -0
  612. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +16 -13
  613. package/src/tools/browser/cdp-client/extension-cdp-client.ts +24 -1
  614. package/src/tools/browser/cdp-client/factory.ts +66 -5
  615. package/src/tools/browser/runtime-check.ts +77 -0
  616. package/src/tools/memory/register.test.ts +3 -3
  617. package/src/tools/memory/register.ts +9 -1
  618. package/src/tools/network/__tests__/web-search.test.ts +156 -0
  619. package/src/tools/network/web-search.ts +280 -37
  620. package/src/tools/permission-checker.ts +13 -5
  621. package/src/tools/subagent/spawn.ts +3 -3
  622. package/src/tools/terminal/shell.ts +44 -0
  623. package/src/usage/attribution.ts +3 -2
  624. package/src/util/pricing.ts +86 -160
  625. package/src/watcher/__tests__/engine.test.ts +301 -0
  626. package/src/watcher/constants.ts +7 -0
  627. package/src/watcher/engine.ts +90 -90
  628. package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +6 -9
  629. package/src/workspace/migrations/054-seed-recall-callsite.ts +10 -1
  630. package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +28 -4
  631. package/src/workspace/migrations/069-seed-onboarding-threads.ts +8 -2
  632. package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +104 -0
  633. package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +93 -0
  634. package/src/workspace/migrations/074-drop-deprecated-secret-detection-keys.ts +117 -0
  635. package/src/workspace/migrations/075-memory-v2-bm25-b-default-reembed.ts +61 -0
  636. package/src/workspace/migrations/076-drop-services-inference-mode.ts +62 -0
  637. package/src/workspace/migrations/077-seed-memory-router-callsite.ts +89 -0
  638. package/src/workspace/migrations/078-release-notes-tavily-web-search.ts +66 -0
  639. package/src/workspace/migrations/079-home-feed-notification-only.ts +197 -0
  640. package/src/workspace/migrations/080-restrict-vercel-api-token-metadata.ts +182 -0
  641. package/src/workspace/migrations/081-backfill-bash-allowed-tools-for-injection-credentials.ts +160 -0
  642. package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +154 -0
  643. package/src/workspace/migrations/registry.ts +22 -0
  644. package/src/workspace/migrations/runner.ts +13 -2
  645. package/src/workspace/migrations/types.ts +13 -3
  646. package/src/workspace/provider-commit-message-generator.ts +3 -2
  647. package/src/__tests__/context-search-pkb-source.test.ts +0 -498
  648. package/src/__tests__/credentials-cli.test.ts +0 -1225
  649. package/src/__tests__/memory-admin-recall.test.ts +0 -213
  650. package/src/approvals/__tests__/guardian-feed-event.test.ts +0 -303
  651. package/src/cli/commands/__tests__/email-download.test.ts +0 -260
  652. package/src/cli/commands/__tests__/email-list.test.ts +0 -216
  653. package/src/cli/commands/__tests__/email-register.test.ts +0 -186
  654. package/src/cli/commands/__tests__/email-send.test.ts +0 -416
  655. package/src/cli/commands/__tests__/email-status.test.ts +0 -185
  656. package/src/cli/commands/__tests__/email-unregister.test.ts +0 -168
  657. package/src/cli/commands/__tests__/routes.test.ts +0 -562
  658. package/src/cli/commands/__tests__/stt-transcribe.test.ts +0 -454
  659. package/src/cli/commands/autonomy.ts +0 -365
  660. package/src/cli/commands/memory.ts +0 -424
  661. package/src/cli/commands/oauth/__tests__/connect.test.ts +0 -947
  662. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +0 -686
  663. package/src/cli/commands/oauth/__tests__/mode.test.ts +0 -632
  664. package/src/cli/commands/oauth/__tests__/ping.test.ts +0 -631
  665. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +0 -573
  666. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +0 -330
  667. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +0 -521
  668. package/src/cli/commands/oauth/__tests__/status.test.ts +0 -551
  669. package/src/cli/commands/oauth/__tests__/token.test.ts +0 -420
  670. package/src/cli/lib/daemon-avatar-client.ts +0 -37
  671. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -87
  672. package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +0 -207
  673. package/src/daemon/__tests__/conversation-feed-event.test.ts +0 -304
  674. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +0 -233
  675. package/src/home/__tests__/assistant-feed-authoring.test.ts +0 -156
  676. package/src/home/__tests__/emit-feed-event.test.ts +0 -169
  677. package/src/home/__tests__/feed-population-integration.test.ts +0 -312
  678. package/src/home/__tests__/feed-scheduler.test.ts +0 -222
  679. package/src/home/__tests__/phase5-exit-criteria.test.ts +0 -229
  680. package/src/home/__tests__/platform-gmail-digest.test.ts +0 -222
  681. package/src/home/__tests__/rollup-producer.test.ts +0 -507
  682. package/src/home/assistant-feed-authoring.ts +0 -135
  683. package/src/home/emit-feed-event.ts +0 -169
  684. package/src/home/feed-scheduler.ts +0 -281
  685. package/src/home/platform-gmail-digest.ts +0 -163
  686. package/src/home/rewrite-command-preview.ts +0 -66
  687. package/src/home/rewrite-feed-title.ts +0 -58
  688. package/src/home/rollup-producer.ts +0 -426
  689. package/src/memory/admin.ts +0 -326
  690. package/src/memory/context-search/sources/pkb.ts +0 -476
  691. package/src/memory/graph/compaction.ts +0 -299
  692. /package/src/cli/{commands → lib}/cache-fs.ts +0 -0
@@ -0,0 +1,115 @@
1
+ import { readdirSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { describe, expect, test } from "bun:test";
4
+
5
+ type Registry = {
6
+ flags: Array<{
7
+ key: string;
8
+ scope: string;
9
+ defaultEnabled: boolean;
10
+ }>;
11
+ };
12
+
13
+ const LEGACY_FLAGGED_RELEASE_NOTE_ALLOWLIST = new Map<string, string>([
14
+ [
15
+ "045-release-notes-meet-avatar.ts",
16
+ "Historical bulletin that already shipped before this guard existed.",
17
+ ],
18
+ ]);
19
+
20
+ const FLAGGED_FEATURE_LANGUAGE_PATTERNS: Array<{
21
+ label: string;
22
+ pattern: RegExp;
23
+ }> = [
24
+ { label: "feature flag", pattern: /\bfeature[- ]flag(?:ged)?\b/i },
25
+ { label: "rollout flag", pattern: /\brollout flag\b/i },
26
+ { label: "behind ... flag", pattern: /\bbehind\b[^\n.]{0,120}\bflag\b/i },
27
+ { label: "gated on", pattern: /\bgated on\b/i },
28
+ { label: "when enabled", pattern: /\bwhen enabled\b/i },
29
+ ];
30
+
31
+ function getRepoRoot(): string {
32
+ return join(process.cwd(), "..");
33
+ }
34
+
35
+ function getReleaseNoteMigrationFiles(): string[] {
36
+ const migrationsDir = join(process.cwd(), "src", "workspace", "migrations");
37
+ return readdirSync(migrationsDir)
38
+ .filter((fileName) => /^\d+-release-notes-[a-z0-9-]+\.ts$/.test(fileName))
39
+ .sort();
40
+ }
41
+
42
+ function loadDefaultDisabledAssistantFlagKeys(): string[] {
43
+ const registryPath = join(
44
+ getRepoRoot(),
45
+ "meta",
46
+ "feature-flags",
47
+ "feature-flag-registry.json",
48
+ );
49
+ const registry = JSON.parse(readFileSync(registryPath, "utf-8")) as Registry;
50
+ return registry.flags
51
+ .filter((flag) => flag.scope === "assistant" && !flag.defaultEnabled)
52
+ .map((flag) => flag.key)
53
+ .sort();
54
+ }
55
+
56
+ function escapeRegExp(value: string): string {
57
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
58
+ }
59
+
60
+ function featureFlagKeyPattern(key: string): RegExp {
61
+ const escaped = escapeRegExp(key);
62
+ if (key.includes("-")) {
63
+ return new RegExp(`(?:^|[^a-z0-9-])${escaped}(?:$|[^a-z0-9-])`, "i");
64
+ }
65
+
66
+ return new RegExp("[`'\"]" + escaped + "[`'\"]", "i");
67
+ }
68
+
69
+ describe("workspace release-note migrations feature flag guard", () => {
70
+ test("new release-note migrations do not announce default-disabled feature-flagged work", () => {
71
+ const migrationsDir = join(process.cwd(), "src", "workspace", "migrations");
72
+ const defaultDisabledFlagKeys = loadDefaultDisabledAssistantFlagKeys();
73
+ const violations: string[] = [];
74
+
75
+ for (const fileName of getReleaseNoteMigrationFiles()) {
76
+ if (LEGACY_FLAGGED_RELEASE_NOTE_ALLOWLIST.has(fileName)) {
77
+ continue;
78
+ }
79
+
80
+ const content = readFileSync(join(migrationsDir, fileName), "utf-8");
81
+
82
+ for (const { label, pattern } of FLAGGED_FEATURE_LANGUAGE_PATTERNS) {
83
+ if (pattern.test(content)) {
84
+ violations.push(
85
+ `${fileName}: contains flagged-feature language "${label}"`,
86
+ );
87
+ }
88
+ }
89
+
90
+ for (const key of defaultDisabledFlagKeys) {
91
+ if (featureFlagKeyPattern(key).test(content)) {
92
+ violations.push(
93
+ `${fileName}: references default-disabled assistant feature flag "${key}"`,
94
+ );
95
+ }
96
+ }
97
+ }
98
+
99
+ if (violations.length > 0) {
100
+ const message = [
101
+ "Release-note migrations write to UPDATES.md, which is processed without checking feature flags.",
102
+ "Do not announce features that are still behind default-disabled assistant flags or rollout flags.",
103
+ "Wait until GA and add a new append-only release-note migration with a new marker.",
104
+ "",
105
+ "Violations:",
106
+ ...violations.map((violation) => ` - ${violation}`),
107
+ "",
108
+ "If this is an already-shipped historical bulletin, add a narrow entry to",
109
+ "LEGACY_FLAGGED_RELEASE_NOTE_ALLOWLIST in workspace-release-notes-feature-flag-guard.test.ts.",
110
+ ].join("\n");
111
+
112
+ expect(violations, message).toEqual([]);
113
+ }
114
+ });
115
+ });
@@ -11,7 +11,8 @@
11
11
  * in `afterAll` so the swap doesn't leak into other files.
12
12
  */
13
13
 
14
- type WhichStub = (command: string) => string | null;
14
+ type WhichOptions = { PATH?: string; cwd?: string };
15
+ type WhichStub = (command: string, options?: WhichOptions) => string | null;
15
16
 
16
17
  /**
17
18
  * Installs a process-global stub for Bun.which. Returns helpers to drive and
@@ -30,7 +31,8 @@ export function installWhichStub(): {
30
31
  const originalWhich = Bun.which;
31
32
  let whichStub: WhichStub = () => null;
32
33
 
33
- (Bun as unknown as { which: WhichStub }).which = (cmd) => whichStub(cmd);
34
+ (Bun as unknown as { which: WhichStub }).which = (cmd, options) =>
35
+ whichStub(cmd, options);
34
36
 
35
37
  function setWhich(arg: Record<string, string | null> | WhichStub): void {
36
38
  whichStub = typeof arg === "function" ? arg : (cmd) => arg[cmd] ?? null;
@@ -161,6 +161,31 @@ describe("resolveAcpAgent", () => {
161
161
  expect(result.hint).toBe("npm i -g @zed-industries/codex-acp");
162
162
  });
163
163
 
164
+ test("binary preflight honors agent.env.PATH override (matches spawn env)", () => {
165
+ // The actual spawn merges `agentConfig.env` into the child env, so a
166
+ // per-agent PATH override wins over the daemon's PATH. The preflight
167
+ // must use the same PATH or it will reject configs that would have
168
+ // spawned successfully.
169
+ config.setConfig({
170
+ agents: {
171
+ custom: {
172
+ command: "my-binary",
173
+ args: [],
174
+ env: { PATH: "/opt/custom/bin" },
175
+ },
176
+ },
177
+ });
178
+ which.setWhich((cmd, options) =>
179
+ cmd === "my-binary" && options?.PATH === "/opt/custom/bin"
180
+ ? "/opt/custom/bin/my-binary"
181
+ : null,
182
+ );
183
+
184
+ const result = resolveAcpAgent("custom");
185
+
186
+ expect(result.ok).toBe(true);
187
+ });
188
+
164
189
  test("ok result when user config provides agent and binary is on PATH", () => {
165
190
  config.setConfig({
166
191
  agents: {
@@ -65,6 +65,17 @@ function installHintFor(command: string): string {
65
65
  : `Install '${command}' and ensure it is on PATH.`;
66
66
  }
67
67
 
68
+ /**
69
+ * Resolve the binary using the same PATH the spawn will see. `AcpAgentProcess`
70
+ * spawns with `{ ...process.env, ...config.env }`, so a per-agent `env.PATH`
71
+ * override wins over the daemon's PATH. Mirror that here so a config that
72
+ * relies on a custom PATH to locate the binary doesn't fail preflight.
73
+ */
74
+ function findAgentBinary(agent: AcpAgentConfig): string | null {
75
+ const PATH = agent.env?.PATH ?? process.env.PATH;
76
+ return Bun.which(agent.command, PATH ? { PATH } : undefined);
77
+ }
78
+
68
79
  /**
69
80
  * Resolve an id against user config first, then bundled defaults. Returns the
70
81
  * resolved entry plus a `source` label so callers can surface "user override
@@ -122,7 +133,7 @@ export function resolveAcpAgent(id: string): ResolveAcpAgentResult {
122
133
  }
123
134
 
124
135
  const { agent } = found;
125
- if (!Bun.which(agent.command)) {
136
+ if (!findAgentBinary(agent)) {
126
137
  return {
127
138
  ok: false,
128
139
  reason: "binary_not_found",
@@ -157,7 +168,7 @@ export function listAcpAgents(): {
157
168
  const agents: AcpAgentEntry[] = mergedAgentIds(userAgents).map((id) => {
158
169
  // Non-null: ids come from `mergedAgentIds` so the lookup always resolves.
159
170
  const { agent, source } = lookupAgent(userAgents, id)!;
160
- const available = Bun.which(agent.command) !== null;
171
+ const available = findAgentBinary(agent) !== null;
161
172
  const entry: AcpAgentEntry = {
162
173
  id,
163
174
  command: agent.command,
@@ -278,12 +278,26 @@ export class AcpSessionManager {
278
278
 
279
279
  /**
280
280
  * Kills the agent process and removes the session from tracking.
281
+ *
282
+ * Persists the buffered event log first so abort paths
283
+ * (`executeAcpAbort`, daemon shutdown) don't drop history. If the
284
+ * session is still in a non-terminal state, mark it cancelled so the
285
+ * persisted row reflects reality. The in-flight prompt's then/catch
286
+ * handler will short-circuit after teardown removes the entry.
281
287
  */
282
288
  close(acpSessionId: string): void {
283
289
  const entry = this.sessions.get(acpSessionId);
284
290
  if (!entry) {
285
291
  throw new Error(`ACP session "${acpSessionId}" not found`);
286
292
  }
293
+ if (
294
+ entry.state.status === "running" ||
295
+ entry.state.status === "initializing"
296
+ ) {
297
+ entry.state.status = "cancelled";
298
+ entry.state.completedAt = Date.now();
299
+ }
300
+ this.persistTerminal(acpSessionId, entry);
287
301
  this.teardownSession(acpSessionId, entry);
288
302
  }
289
303
 
@@ -13,8 +13,8 @@
13
13
 
14
14
  import { answerCall } from "../calls/call-domain.js";
15
15
  import { findContactChannel } from "../contacts/contact-store.js";
16
+ import { upsertContactChannel } from "../contacts/contacts-write.js";
16
17
  import { findConversation } from "../daemon/conversation-store.js";
17
- import { emitFeedEvent } from "../home/emit-feed-event.js";
18
18
  import {
19
19
  type CanonicalGuardianRequest,
20
20
  getCanonicalGuardianRequest,
@@ -119,6 +119,12 @@ export type ResolverResult =
119
119
  applied: true;
120
120
  grantMinted?: boolean;
121
121
  guardianReplyText?: string;
122
+ activatedContact?: {
123
+ sourceChannel: string;
124
+ externalUserId: string;
125
+ externalChatId?: string;
126
+ displayName?: string;
127
+ };
122
128
  }
123
129
  | { ok: false; reason: string };
124
130
 
@@ -206,21 +212,6 @@ const pendingInteractionResolver: GuardianRequestResolver = {
206
212
  ctx.emissionContext,
207
213
  );
208
214
 
209
- const approved = decision.action !== "reject";
210
- void emitFeedEvent({
211
- source: "assistant",
212
- title: approved ? "Tool Request Approved" : "Tool Request Denied",
213
- summary: `${approved ? "Approved" : "Denied"} access to ${request.toolName ?? "unknown tool"}.`,
214
- dedupKey: `guardian-approval:${request.id}`,
215
- urgency: approved ? undefined : "medium",
216
- detailPanel: { kind: "toolPermission" },
217
- }).catch((err) => {
218
- log.warn(
219
- { err, requestId: request.id },
220
- "Failed to emit guardian approval feed event",
221
- );
222
- });
223
-
224
215
  log.info(
225
216
  {
226
217
  event: "resolver_tool_approval_applied",
@@ -467,20 +458,6 @@ const accessRequestResolver: GuardianRequestResolver = {
467
458
  }
468
459
  }
469
460
 
470
- void emitFeedEvent({
471
- source: "assistant",
472
- title: "Access Request Denied",
473
- summary: `Denied access request.`,
474
- dedupKey: `guardian-access:${request.id}`,
475
- urgency: "medium",
476
- detailPanel: { kind: "permissionChat" },
477
- }).catch((err) => {
478
- log.warn(
479
- { err, requestId: request.id },
480
- "Failed to emit access request feed event",
481
- );
482
- });
483
-
484
461
  return {
485
462
  ok: true,
486
463
  applied: true,
@@ -496,6 +473,21 @@ const accessRequestResolver: GuardianRequestResolver = {
496
473
  // a verification session. The caller is already on the line and the
497
474
  // relay server's in-call wait loop will detect the approved status.
498
475
  if (channel === "phone") {
476
+ try {
477
+ upsertContactChannel({
478
+ sourceChannel: "phone",
479
+ externalUserId: requesterExternalUserId,
480
+ externalChatId: requesterChatId,
481
+ status: "active",
482
+ policy: "allow",
483
+ });
484
+ } catch (err) {
485
+ log.error(
486
+ { err, requesterExternalUserId },
487
+ "Access request resolver: failed to activate voice caller as trusted contact",
488
+ );
489
+ }
490
+
499
491
  log.info(
500
492
  {
501
493
  event: "resolver_access_request_voice_approved",
@@ -506,21 +498,16 @@ const accessRequestResolver: GuardianRequestResolver = {
506
498
  "Access request resolver: voice approval — direct trusted-contact activation (no verification session)",
507
499
  );
508
500
 
509
- void emitFeedEvent({
510
- source: "assistant",
511
- title: "Access Request Approved",
512
- summary: `Granted access request.`,
513
- dedupKey: `guardian-access:${request.id}`,
514
- urgency: undefined,
515
- detailPanel: { kind: "permissionChat" },
516
- }).catch((err) => {
517
- log.warn(
518
- { err, requestId: request.id },
519
- "Failed to emit access request feed event",
520
- );
521
- });
522
-
523
- return { ok: true, applied: true };
501
+ return {
502
+ ok: true,
503
+ applied: true,
504
+ activatedContact: {
505
+ sourceChannel: "phone",
506
+ externalUserId: requesterExternalUserId,
507
+ ...(requesterChatId ? { externalChatId: requesterChatId } : {}),
508
+ ...(requesterDisplayName ? { displayName: requesterDisplayName } : {}),
509
+ },
510
+ };
524
511
  }
525
512
 
526
513
  // Non-voice approvals: mint an identity-bound verification session so the
@@ -738,20 +725,6 @@ const accessRequestResolver: GuardianRequestResolver = {
738
725
  ? `Access approved for ${requesterLabel}. Give them this verification code: \`${session.secret}\`. The code expires in 10 minutes.`
739
726
  : `Access approved for ${requesterLabel}. Give them this verification code: \`${session.secret}\`. The code expires in 10 minutes. I could not notify them automatically, so please tell them to send the code manually.`;
740
727
 
741
- void emitFeedEvent({
742
- source: "assistant",
743
- title: "Access Request Approved",
744
- summary: `Granted access request.`,
745
- dedupKey: `guardian-access:${request.id}`,
746
- urgency: undefined,
747
- detailPanel: { kind: "permissionChat" },
748
- }).catch((err) => {
749
- log.warn(
750
- { err, requestId: request.id },
751
- "Failed to emit access request feed event",
752
- );
753
- });
754
-
755
728
  return {
756
729
  ok: true,
757
730
  applied: true,
@@ -825,20 +798,6 @@ const toolGrantRequestResolver: GuardianRequestResolver = {
825
798
  }
826
799
  }
827
800
 
828
- void emitFeedEvent({
829
- source: "assistant",
830
- title: "Tool Grant Denied",
831
- summary: `Denied grant request for ${request.toolName ?? "unknown tool"}.`,
832
- dedupKey: `guardian-grant:${request.id}`,
833
- urgency: "medium",
834
- detailPanel: { kind: "toolPermission" },
835
- }).catch((err) => {
836
- log.warn(
837
- { err, requestId: request.id },
838
- "Failed to emit tool grant denial feed event",
839
- );
840
- });
841
-
842
801
  return { ok: true, applied: true };
843
802
  }
844
803
 
@@ -936,20 +895,6 @@ const toolGrantRequestResolver: GuardianRequestResolver = {
936
895
  }
937
896
  }
938
897
 
939
- void emitFeedEvent({
940
- source: "assistant",
941
- title: "Tool Grant Approved",
942
- summary: `Approved grant request for ${request.toolName ?? "unknown tool"}.`,
943
- dedupKey: `guardian-grant:${request.id}`,
944
- urgency: undefined,
945
- detailPanel: { kind: "toolPermission" },
946
- }).catch((err) => {
947
- log.warn(
948
- { err, requestId: request.id },
949
- "Failed to emit tool grant approval feed event",
950
- );
951
- });
952
-
953
898
  return { ok: true, applied: true, grantMinted: false };
954
899
  },
955
900
  };
@@ -612,6 +612,12 @@ export class RelayConnection {
612
612
  );
613
613
  this.startNameCapture(outcome.assistantId, outcome.fromNumber);
614
614
  return;
615
+ case "unverified_caller":
616
+ await this.handleUnverifiedCaller(
617
+ outcome.displayName,
618
+ outcome.isGuardian,
619
+ );
620
+ return;
615
621
  case "verification":
616
622
  if (this.controller && resolved.actorTrust.trustClass !== "unknown") {
617
623
  this.controller.setTrustContext(
@@ -669,6 +675,35 @@ export class RelayConnection {
669
675
  });
670
676
  }
671
677
 
678
+ /** Speak verification guidance to a known-but-unverified caller, then disconnect. */
679
+ private async handleUnverifiedCaller(
680
+ displayName: string,
681
+ isGuardian: boolean,
682
+ ): Promise<void> {
683
+ recordCallEvent(this.callSessionId, "inbound_acl_unverified_caller", {
684
+ callSessionId: this.callSessionId,
685
+ isGuardian,
686
+ });
687
+ this.connectionState = "disconnecting";
688
+ updateCallSession(this.callSessionId, {
689
+ status: "failed",
690
+ endedAt: Date.now(),
691
+ lastError: "Inbound voice ACL: caller channel unverified",
692
+ });
693
+ const action = isGuardian
694
+ ? `To verify, open your assistant's contacts page, click Verify next to the phone channel, ` +
695
+ `and follow the prompts. Then call back once the verification session is active.`
696
+ : `Please reach out to the account guardian to start a new verification session, ` +
697
+ `then call back once the verification session is active.`;
698
+ const message =
699
+ `This number is registered as ${displayName}'s phone but has not been verified yet. ` +
700
+ action;
701
+ await speakSystemPrompt(this, message);
702
+ setTimeout(() => {
703
+ this.endSession("Inbound voice ACL: caller channel unverified");
704
+ }, getTtsPlaybackDelayMs());
705
+ }
706
+
672
707
  /** Deny an inbound call with a TTS message and schedule disconnect. */
673
708
  private async denyInboundCall(
674
709
  from: string,
@@ -56,6 +56,13 @@ type SetupOutcome =
56
56
  guardianName: string | null;
57
57
  }
58
58
  | { action: "name_capture"; assistantId: string; fromNumber: string }
59
+ | {
60
+ action: "unverified_caller";
61
+ assistantId: string;
62
+ fromNumber: string;
63
+ displayName: string;
64
+ isGuardian: boolean;
65
+ }
59
66
  | { action: "deny"; message: string; logReason: string };
60
67
 
61
68
  // ── Resolved context produced alongside the outcome ──────────────────
@@ -234,6 +241,35 @@ export function routeSetup(ctx: SetupContext): {
234
241
  };
235
242
  }
236
243
 
244
+ // Known caller whose channel hasn't passed verification yet —
245
+ // mirrors the gateway's pre-intercept (twilio-voice-webhook.ts) so
246
+ // calls slipping past it (e.g. canonicalization mismatch between
247
+ // gateway and assistant DBs) still get useful guidance instead of
248
+ // the "I don't recognize this number" name-capture script.
249
+ const unverifiedStatuses = new Set(["unverified", "pending"]);
250
+ const memberChannel = actorTrust.memberRecord?.channel;
251
+ if (memberChannel && unverifiedStatuses.has(memberChannel.status)) {
252
+ log.info(
253
+ {
254
+ callSessionId: ctx.callSessionId,
255
+ from: ctx.from,
256
+ channelId: memberChannel.id,
257
+ channelStatus: memberChannel.status,
258
+ },
259
+ "Inbound voice ACL: known but unverified caller — returning verification guidance",
260
+ );
261
+ return {
262
+ outcome: {
263
+ action: "unverified_caller",
264
+ assistantId,
265
+ fromNumber: ctx.from,
266
+ displayName: actorTrust.memberRecord!.contact.displayName,
267
+ isGuardian: actorTrust.memberRecord!.contact.role === "guardian",
268
+ },
269
+ resolved,
270
+ };
271
+ }
272
+
237
273
  // Unknown caller — name capture flow
238
274
  log.info(
239
275
  {
@@ -33,6 +33,7 @@ export type CallEventType =
33
33
  | "inbound_acl_name_capture_started"
34
34
  | "inbound_acl_name_captured"
35
35
  | "inbound_acl_name_capture_timeout"
36
+ | "inbound_acl_unverified_caller"
36
37
  | "inbound_acl_access_approved"
37
38
  | "inbound_acl_access_denied"
38
39
  | "inbound_acl_access_timeout"
@@ -293,7 +293,11 @@ export async function startVoiceTurn(
293
293
  onMessageComplete: (msg) => {
294
294
  opts.onComplete?.();
295
295
  opts.callbacks?.message_complete?.(msg);
296
- if (msg.type === "message_complete" && msg.messageId) {
296
+ if (
297
+ msg.type === "message_complete" &&
298
+ msg.messageId &&
299
+ msg.source !== "aux"
300
+ ) {
297
301
  try {
298
302
  opts.callbacks?.persisted_assistant_message_id?.(msg.messageId);
299
303
  } catch (err) {
@@ -314,7 +318,8 @@ export async function startVoiceTurn(
314
318
 
315
319
  // Phone voice has no interactive permission/secret UI, so apply explicit
316
320
  // per-role policies by default. Local live voice opts into the normal
317
- // client approval path instead.
321
+ // client approval path instead. Side-effect double-defense is wired
322
+ // below at the conversation-configure point.
318
323
  const trustClass = opts.trustContext?.trustClass;
319
324
  const isGuardian = trustClass === "guardian";
320
325
  const approvalMode = opts.approvalMode ?? "phone-call";
@@ -386,7 +391,13 @@ export async function startVoiceTurn(
386
391
  }
387
392
  }
388
393
 
389
- // Configure conversation for this voice turn
394
+ // Non-guardian phone voice forces side-effect tools to prompt so the
395
+ // auto-deny handler below reliably sees a confirmation_request. Without
396
+ // this, a broad allow trust rule (e.g. wildcard bash) would let
397
+ // side-effect tools execute without ever emitting an event for the
398
+ // auto-deny / scoped-grant handler to intercept.
399
+ conversation.forcePromptSideEffects =
400
+ !isGuardian && !usesLocalInteractiveApprovals;
390
401
  conversation.setAssistantId(opts.assistantId ?? DAEMON_INTERNAL_ASSISTANT_ID);
391
402
  conversation.callSessionId = voiceSessionId;
392
403
  conversation.setTrustContext(opts.trustContext ?? null);
@@ -528,7 +539,14 @@ export async function startVoiceTurn(
528
539
  return;
529
540
  }
530
541
  } else if (msg.type === "secret_request") {
531
- // Voice has no secret-entry UI, so resolve immediately
542
+ if (usesLocalInteractiveApprovals) {
543
+ // Local live voice runs alongside the desktop client, which has a
544
+ // secret-entry UI (SecretPromptManager). Forward the broadcast and
545
+ // let the prompter's existing registration handle the response.
546
+ broadcastMessage(msg);
547
+ return;
548
+ }
549
+ // Phone voice has no secret-entry UI, so resolve immediately.
532
550
  log.info(
533
551
  { turnId, service: msg.service, field: msg.field },
534
552
  "Auto-resolving secret request for voice turn (no secret-entry UI)",
@@ -549,6 +567,7 @@ export async function startVoiceTurn(
549
567
  conversation.setAssistantId("self");
550
568
  conversation.setVoiceCallControlPrompt(null);
551
569
  conversation.callSessionId = undefined;
570
+ conversation.forcePromptSideEffects = false;
552
571
  // Reset the conversation's client callback to a no-op so the stale
553
572
  // closure doesn't intercept events from future turns on the same conversation.
554
573
  conversation.updateClient(() => {}, true);
@@ -11,7 +11,8 @@ import type { ChannelId } from "./types.js";
11
11
  export type ConversationStrategy =
12
12
  | "start_new_conversation"
13
13
  | "continue_existing_conversation"
14
- | "not_deliverable";
14
+ | "not_deliverable"
15
+ | "push_only";
15
16
 
16
17
  export interface ChannelInvitePolicy {
17
18
  /** Whether inbound invite code redemption is supported on this channel. */
@@ -72,6 +73,18 @@ const CHANNEL_POLICIES = {
72
73
  codeRedemptionEnabled: true,
73
74
  },
74
75
  },
76
+ platform: {
77
+ notification: {
78
+ deliveryEnabled: true,
79
+ // Platform is a push-only relay — conversations are owned by the vellum
80
+ // channel. push_only skips pairDeliveryWithConversation without implying
81
+ // the channel is non-deliverable (which not_deliverable would).
82
+ conversationStrategy: "push_only",
83
+ },
84
+ invite: {
85
+ codeRedemptionEnabled: false,
86
+ },
87
+ },
75
88
  phone: {
76
89
  notification: {
77
90
  deliveryEnabled: false,
@@ -5,6 +5,7 @@ export const CHANNEL_IDS = [
5
5
  "whatsapp",
6
6
  "slack",
7
7
  "email",
8
+ "platform",
8
9
  ] as const;
9
10
 
10
11
  export type ChannelId = (typeof CHANNEL_IDS)[number];