@vellumai/assistant 0.11.2 → 0.11.3-dev.202608080427.92f668a

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 (826) hide show
  1. package/ARCHITECTURE.md +69 -9
  2. package/docs/flux-turn-detection-spike.md +243 -0
  3. package/docs/stt-provider-onboarding.md +3 -1
  4. package/docs/trusted-contact-access.md +9 -5
  5. package/docs/vellum-doctor.md +195 -0
  6. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +50 -0
  7. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
  8. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
  9. package/node_modules/@vellumai/ces-client/src/index.ts +1 -0
  10. package/node_modules/@vellumai/ces-client/src/rpc-client.ts +19 -2
  11. package/node_modules/@vellumai/environments/package.json +2 -1
  12. package/node_modules/@vellumai/environments/src/__tests__/cloud-assistant-hub-url.test.ts +38 -0
  13. package/node_modules/@vellumai/environments/src/__tests__/install-layout.test.ts +98 -0
  14. package/node_modules/@vellumai/environments/src/__tests__/package-boundary.test.ts +5 -5
  15. package/node_modules/@vellumai/environments/src/index.ts +17 -6
  16. package/node_modules/@vellumai/environments/src/install-layout.ts +49 -0
  17. package/node_modules/@vellumai/environments/src/seeds.ts +29 -0
  18. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +50 -0
  19. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
  20. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
  21. package/node_modules/@vellumai/gateway-client/src/index.ts +4 -0
  22. package/node_modules/@vellumai/gateway-client/src/verification-session-contract.ts +91 -6
  23. package/node_modules/@vellumai/ipc-server-utils/src/endpoint.test.ts +36 -0
  24. package/node_modules/@vellumai/ipc-server-utils/src/endpoint.ts +142 -0
  25. package/node_modules/@vellumai/ipc-server-utils/src/index.ts +2 -0
  26. package/node_modules/@vellumai/ipc-server-utils/src/listen-options.ts +3 -0
  27. package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.test.ts +15 -1
  28. package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.ts +17 -2
  29. package/node_modules/@vellumai/service-contracts/src/channels.ts +50 -0
  30. package/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
  31. package/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
  32. package/node_modules/@vellumai/slack-text/src/index.ts +16 -2
  33. package/openapi.yaml +619 -47
  34. package/package.json +1 -1
  35. package/scripts/voice-ttft-spike.ts +3 -3
  36. package/src/__tests__/agent-image-optimize.test.ts +4 -4
  37. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +113 -66
  38. package/src/__tests__/agent-loop-override-profile.test.ts +38 -48
  39. package/src/__tests__/agent-loop-subagent-billing-headers.test.ts +166 -0
  40. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +1 -0
  41. package/src/__tests__/agent-wake-override-profile.test.ts +1 -0
  42. package/src/__tests__/answered-question-persistence.test.ts +240 -0
  43. package/src/__tests__/anthropic-provider.test.ts +165 -30
  44. package/src/__tests__/app-control-flow.test.ts +9 -8
  45. package/src/__tests__/assistant-event-hub.test.ts +48 -0
  46. package/src/__tests__/attachments-store-heic-normalize.test.ts +16 -12
  47. package/src/__tests__/attachments-store.test.ts +130 -68
  48. package/src/__tests__/attachments.test.ts +36 -36
  49. package/src/__tests__/background-workers-disk-pressure.test.ts +1 -1
  50. package/src/__tests__/call-controller.test.ts +120 -0
  51. package/src/__tests__/call-start-guardian-guard.test.ts +18 -4
  52. package/src/__tests__/canned-reply-release.test.ts +86 -0
  53. package/src/__tests__/channel-availability-routes.test.ts +14 -1
  54. package/src/__tests__/channel-guardian.test.ts +59 -29
  55. package/src/__tests__/channel-readiness-telegram-remote.test.ts +154 -0
  56. package/src/__tests__/channel-setup-panel-ack.test.ts +6 -5
  57. package/src/__tests__/client-os-metadata-persistence.test.ts +103 -4
  58. package/src/__tests__/compactor-image-manifest-trust.test.ts +1 -1
  59. package/src/__tests__/config-loader-backfill.test.ts +19 -0
  60. package/src/__tests__/config-schema.test.ts +150 -7
  61. package/src/__tests__/consult-deadline.test.ts +65 -0
  62. package/src/__tests__/conversation-agent-loop.test.ts +438 -2
  63. package/src/__tests__/conversation-disk-view-integration.test.ts +5 -1
  64. package/src/__tests__/conversation-disk-view.test.ts +4 -4
  65. package/src/__tests__/conversation-error.test.ts +22 -3
  66. package/src/__tests__/conversation-fork-crud.test.ts +5 -1
  67. package/src/__tests__/conversation-fork-referential.test.ts +352 -0
  68. package/src/__tests__/conversation-fork-retrospective.test.ts +5 -1
  69. package/src/__tests__/conversation-group-tools.test.ts +32 -2
  70. package/src/__tests__/conversation-inference-profile-route.test.ts +27 -1
  71. package/src/__tests__/conversation-initial-prompt.test.ts +51 -22
  72. package/src/__tests__/conversation-key-store-bootstrap-cleanup.test.ts +119 -0
  73. package/src/__tests__/conversation-key-store-origin.test.ts +105 -0
  74. package/src/__tests__/conversation-list-recency-ordering.test.ts +104 -0
  75. package/src/__tests__/conversation-origin-at-creation.test.ts +153 -0
  76. package/src/__tests__/conversation-origin-channel-filter.test.ts +95 -0
  77. package/src/__tests__/conversation-placement-promotion.test.ts +172 -0
  78. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +123 -0
  79. package/src/__tests__/conversation-queue.test.ts +433 -1
  80. package/src/__tests__/conversation-retry-route.test.ts +3 -1
  81. package/src/__tests__/conversation-routes-hidden-queue.test.ts +64 -1
  82. package/src/__tests__/conversation-store-ephemeral.test.ts +4 -0
  83. package/src/__tests__/conversation-store.test.ts +26 -10
  84. package/src/__tests__/conversation-summarize-route.test.ts +1 -1
  85. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +15 -6
  86. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +6 -5
  87. package/src/__tests__/conversation-surfaces-app-control.test.ts +12 -11
  88. package/src/__tests__/conversation-surfaces-app-open.test.ts +11 -5
  89. package/src/__tests__/conversation-surfaces-data-persist.test.ts +5 -4
  90. package/src/__tests__/conversation-surfaces-history-restored-completion.test.ts +967 -0
  91. package/src/__tests__/conversation-surfaces-persisted-info.test.ts +312 -0
  92. package/src/__tests__/conversation-surfaces-queued-emit.test.ts +6 -5
  93. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -8
  94. package/src/__tests__/conversation-surfaces-standalone.test.ts +21 -11
  95. package/src/__tests__/conversation-surfaces-state-update.test.ts +7 -11
  96. package/src/__tests__/conversation-surfaces-table-action.test.ts +7 -6
  97. package/src/__tests__/conversation-surfaces-task-progress.test.ts +11 -6
  98. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +9 -6
  99. package/src/__tests__/conversation-tool-setup-attribution.test.ts +70 -7
  100. package/src/__tests__/conversation-wait-for-idle.test.ts +6 -11
  101. package/src/__tests__/credential-prompt-route.test.ts +54 -7
  102. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  103. package/src/__tests__/cu-unified-flow.test.ts +89 -28
  104. package/src/__tests__/custom-group-listing-visibility.test.ts +1 -1
  105. package/src/__tests__/db-schedule-syntax-migration.test.ts +4 -1
  106. package/src/__tests__/discord-access-request-privacy.test.ts +366 -0
  107. package/src/__tests__/discord-requester-notice-privacy.test.ts +87 -0
  108. package/src/__tests__/disk-pressure-guard.test.ts +55 -55
  109. package/src/__tests__/disk-pressure-routes.test.ts +10 -10
  110. package/src/__tests__/disk-pressure-tools.test.ts +2 -2
  111. package/src/__tests__/disk-usage.test.ts +35 -20
  112. package/src/__tests__/document-sync-tags.test.ts +379 -0
  113. package/src/__tests__/document-update-default-surface.test.ts +28 -0
  114. package/src/__tests__/dynamic-skill-background-guard.test.ts +2 -2
  115. package/src/__tests__/emit-signal-routing-intent.test.ts +3 -4
  116. package/src/__tests__/ensure-conversation-exists.test.ts +8 -5
  117. package/src/__tests__/events-dev-bypass-actor.test.ts +294 -1
  118. package/src/__tests__/evict-conversations-for-reload.test.ts +90 -0
  119. package/src/__tests__/file-list-tool.test.ts +12 -10
  120. package/src/__tests__/file-ops-service.test.ts +151 -44
  121. package/src/__tests__/file-read-container-boundary.test.ts +137 -0
  122. package/src/__tests__/file-read-tool.test.ts +21 -9
  123. package/src/__tests__/file-url-path-guard.test.ts +83 -0
  124. package/src/__tests__/filesystem-tools.test.ts +82 -66
  125. package/src/__tests__/guardian-outbound-http.test.ts +8 -8
  126. package/src/__tests__/helpers/gateway-verification-sessions-stub.ts +14 -1
  127. package/src/__tests__/helpers/hub-clients.ts +42 -0
  128. package/src/__tests__/helpers/mock-conversation.ts +46 -0
  129. package/src/__tests__/helpers/verification-sessions-ipc-sim.ts +61 -57
  130. package/src/__tests__/history-repair.test.ts +112 -12
  131. package/src/__tests__/host-bash-proxy.test.ts +10 -5
  132. package/src/__tests__/host-bash-routes.test.ts +67 -0
  133. package/src/__tests__/host-browser-proxy.test.ts +2 -2
  134. package/src/__tests__/host-cu-proxy.test.ts +3 -7
  135. package/src/__tests__/host-file-proxy.test.ts +3 -7
  136. package/src/__tests__/host-file-read-tool.test.ts +5 -1
  137. package/src/__tests__/host-transfer-proxy-targeted.test.ts +6 -4
  138. package/src/__tests__/http-conversation-lineage.test.ts +2 -5
  139. package/src/__tests__/http-user-message-parity.test.ts +44 -0
  140. package/src/__tests__/identity-routes.test.ts +13 -13
  141. package/src/__tests__/image-conversion.test.ts +29 -26
  142. package/src/__tests__/image-source-path-reinject.test.ts +2 -2
  143. package/src/__tests__/inference-profile-session-handler.test.ts +95 -0
  144. package/src/__tests__/inference-profile-session-ipc.test.ts +25 -0
  145. package/src/__tests__/introduction-card-resolver.test.ts +6 -1
  146. package/src/__tests__/list-messages-attachments.test.ts +56 -32
  147. package/src/__tests__/list-messages-background-tool-completion.test.ts +4 -4
  148. package/src/__tests__/list-messages-client-message-id.test.ts +2 -2
  149. package/src/__tests__/list-messages-hidden-metadata.test.ts +16 -16
  150. package/src/__tests__/list-messages-page-latest.test.ts +61 -61
  151. package/src/__tests__/list-messages-provider-error.test.ts +6 -6
  152. package/src/__tests__/list-messages-queued.test.ts +49 -6
  153. package/src/__tests__/list-messages-system-card.test.ts +4 -4
  154. package/src/__tests__/list-messages-tool-merge.test.ts +9 -9
  155. package/src/__tests__/llm-resolver-override-or-default.test.ts +141 -0
  156. package/src/__tests__/llm-usage-store.test.ts +55 -0
  157. package/src/__tests__/manual-token-reconciliation.test.ts +45 -0
  158. package/src/__tests__/mcp-list-plugin-servers.test.ts +250 -0
  159. package/src/__tests__/mcp-tool-annotations-risk.test.ts +133 -0
  160. package/src/__tests__/media-stream-output.test.ts +175 -0
  161. package/src/__tests__/media-stream-server-integration.test.ts +36 -0
  162. package/src/__tests__/media-stream-stt-session.test.ts +67 -0
  163. package/src/__tests__/migration-export-http.test.ts +1 -1
  164. package/src/__tests__/migration-import-commit-http.test.ts +1 -1
  165. package/src/__tests__/migration-import-preflight-http.test.ts +1 -1
  166. package/src/__tests__/migration-validate-http.test.ts +1 -1
  167. package/src/__tests__/mtime-cache.test.ts +65 -3
  168. package/src/__tests__/notification-platform-adapter.test.ts +104 -0
  169. package/src/__tests__/notification-schedule-notify-dedup.test.ts +1 -1
  170. package/src/__tests__/oauth-provider-profiles.test.ts +4 -2
  171. package/src/__tests__/oauth-provider-seed-logos.test.ts +65 -0
  172. package/src/__tests__/oauth-provider-serializer.test.ts +17 -0
  173. package/src/__tests__/oauth-providers-routes.test.ts +1 -0
  174. package/src/__tests__/openai-responses-prompt-cache.test.ts +5 -2
  175. package/src/__tests__/path-policy.test.ts +164 -1
  176. package/src/__tests__/persist-media-references.test.ts +2 -2
  177. package/src/__tests__/persist-unsendable-image-downscale.test.ts +5 -5
  178. package/src/__tests__/persist-unsendable-image.test.ts +23 -23
  179. package/src/__tests__/persona-resolver.test.ts +154 -0
  180. package/src/__tests__/plugin-api-webhook-url.test.ts +170 -0
  181. package/src/__tests__/plugin-import-boundary-guard.test.ts +6 -0
  182. package/src/__tests__/processing-flag-persist-failure.test.ts +15 -10
  183. package/src/__tests__/profile-availability-incomplete.test.ts +113 -0
  184. package/src/__tests__/profiler-routes.test.ts +13 -13
  185. package/src/__tests__/prompt-cache-cross-turn-stability.test.ts +593 -0
  186. package/src/__tests__/proxy-approval-callback.test.ts +3 -3
  187. package/src/__tests__/queued-message-cancel-and-steer.test.ts +189 -0
  188. package/src/__tests__/queued-message-steer-actor-scoping.test.ts +164 -0
  189. package/src/__tests__/resolve-trust-class.test.ts +20 -0
  190. package/src/__tests__/run-conversation-turn-persistence.test.ts +1 -1
  191. package/src/__tests__/run-due-schedules.test.ts +174 -0
  192. package/src/__tests__/runtime-attachment-metadata.test.ts +15 -7
  193. package/src/__tests__/scaffold-managed-skill-tool.test.ts +166 -0
  194. package/src/__tests__/schedule-routes.test.ts +730 -8
  195. package/src/__tests__/schedule-store.test.ts +540 -0
  196. package/src/__tests__/schedule-tools.test.ts +103 -0
  197. package/src/__tests__/scheduler-wake.test.ts +5 -0
  198. package/src/__tests__/secret-routes-platform-proxy.test.ts +29 -1
  199. package/src/__tests__/secure-keys.test.ts +91 -0
  200. package/src/__tests__/server-history-render.test.ts +97 -7
  201. package/src/__tests__/size-guard.test.ts +8 -8
  202. package/src/__tests__/skill-docs-sync-guard.test.ts +3 -2
  203. package/src/__tests__/skill-tool-factory.test.ts +247 -0
  204. package/src/__tests__/skills-install-staging.test.ts +15 -6
  205. package/src/__tests__/skills.test.ts +32 -0
  206. package/src/__tests__/slack-edit-ordering-characterization.test.ts +103 -0
  207. package/src/__tests__/slack-inbound-verification.test.ts +4 -1
  208. package/src/__tests__/slack-mention-binding-invariance.test.ts +103 -0
  209. package/src/__tests__/slack-mention-provider-leak-audit.test.ts +135 -0
  210. package/src/__tests__/starter-task-flow.test.ts +5 -4
  211. package/src/__tests__/steer-on-enqueue-question.test.ts +3 -2
  212. package/src/__tests__/stt-language-catalog-parity.test.ts +38 -0
  213. package/src/__tests__/subagent-allowlist-validation.test.ts +26 -4
  214. package/src/__tests__/subagent-cron-run-attribution.test.ts +301 -0
  215. package/src/__tests__/subagent-disposal.test.ts +10 -0
  216. package/src/__tests__/subagent-fork-notifications.test.ts +10 -0
  217. package/src/__tests__/subagent-fork-prompt-role.test.ts +85 -11
  218. package/src/__tests__/subagent-fork-spawn.test.ts +15 -7
  219. package/src/__tests__/subagent-manager-notify.test.ts +148 -0
  220. package/src/__tests__/subagent-notify-parent.test.ts +1 -1
  221. package/src/__tests__/subagent-persistence.test.ts +141 -0
  222. package/src/__tests__/subagent-role-registry.test.ts +172 -63
  223. package/src/__tests__/subagent-role-resolution.test.ts +88 -0
  224. package/src/__tests__/subagent-spawn-and-await.test.ts +48 -0
  225. package/src/__tests__/subagent-spawn-tool-fork.test.ts +111 -10
  226. package/src/__tests__/subagent-terminal-message.test.ts +88 -1
  227. package/src/__tests__/subagent-tool-gate-mode.test.ts +225 -10
  228. package/src/__tests__/subagent-tools.test.ts +1901 -108
  229. package/src/__tests__/surface-completion-compaction-boundary.test.ts +124 -0
  230. package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +298 -0
  231. package/src/__tests__/system-prompt.test.ts +82 -7
  232. package/src/__tests__/tool-grant-request-escalation.test.ts +40 -1
  233. package/src/__tests__/tool-result-spool.test.ts +74 -18
  234. package/src/__tests__/tool-side-effects-documents.test.ts +174 -0
  235. package/src/__tests__/tool-side-effects-hook-failures.test.ts +129 -0
  236. package/src/__tests__/tools-audio-read.test.ts +10 -10
  237. package/src/__tests__/tools-get-route.test.ts +85 -12
  238. package/src/__tests__/tools-list-cli.test.ts +171 -0
  239. package/src/__tests__/top-level-renderer.test.ts +54 -1
  240. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +68 -1
  241. package/src/__tests__/trusted-contact-multichannel.test.ts +4 -1
  242. package/src/__tests__/turn-tail-chain.test.ts +135 -0
  243. package/src/__tests__/ui-choice-copy-surfaces.test.ts +6 -4
  244. package/src/__tests__/ui-visual-surface.test.ts +5 -4
  245. package/src/__tests__/ui-work-result-surface.test.ts +5 -4
  246. package/src/__tests__/unified-turn-context-visible-app.test.ts +7 -8
  247. package/src/__tests__/usage-routes.test.ts +62 -0
  248. package/src/__tests__/verification-outbound-delivery.test.ts +176 -0
  249. package/src/__tests__/visible-app-context.test.ts +20 -4
  250. package/src/__tests__/web-search-history.test.ts +96 -0
  251. package/src/__tests__/workspace-migration-139-clear-renamed-cost-profile-label.test.ts +6 -6
  252. package/src/__tests__/workspace-migration-140-repair-seed-pinned-memory-v3-live.test.ts +330 -0
  253. package/src/__tests__/workspace-migration-142-consolidate-voice-front-door.test.ts +150 -0
  254. package/src/acp/failure-error.ts +3 -5
  255. package/src/agent/attachments.ts +26 -24
  256. package/src/agent/history-repair/history-repair.ts +27 -26
  257. package/src/agent/image-optimize.ts +6 -6
  258. package/src/agent/loop.ts +40 -22
  259. package/src/agent/message-types.ts +3 -3
  260. package/src/api/constants/document-tools.ts +55 -0
  261. package/src/api/events/question-answered.ts +53 -0
  262. package/src/api/events/tool-result.ts +7 -0
  263. package/src/api/index.ts +13 -0
  264. package/src/api/responses/conversation-message.ts +11 -0
  265. package/src/api/surfaces-oauth-connect.test.ts +96 -0
  266. package/src/api/surfaces.ts +36 -8
  267. package/src/approvals/guardian-channel-delivery.ts +83 -0
  268. package/src/approvals/guardian-expiry-notifier.ts +13 -11
  269. package/src/approvals/guardian-request-resolvers.ts +222 -135
  270. package/src/calls/__tests__/tts-text-sanitizer.test.ts +13 -0
  271. package/src/calls/__tests__/voice-session-bridge.test.ts +131 -12
  272. package/src/calls/__tests__/voice-triage-escalate.test.ts +106 -0
  273. package/src/calls/call-controller.ts +30 -2
  274. package/src/calls/call-speech-output.ts +12 -4
  275. package/src/calls/call-transport.ts +18 -1
  276. package/src/calls/media-stream-output.ts +53 -5
  277. package/src/calls/media-stream-server.ts +21 -1
  278. package/src/calls/media-stream-stt-session.ts +49 -0
  279. package/src/calls/telephony-synthesis-language.ts +84 -0
  280. package/src/calls/tts-text-sanitizer.ts +12 -5
  281. package/src/calls/voice-session-bridge.ts +86 -17
  282. package/src/calls/voice-triage-escalate.ts +54 -7
  283. package/src/channels/__tests__/gateway-verification-sessions.test.ts +3 -3
  284. package/src/channels/__tests__/plugin-channel-declarations.test.ts +161 -0
  285. package/src/channels/config.ts +20 -2
  286. package/src/channels/gateway-verification-sessions.ts +7 -2
  287. package/src/channels/plugin-channel-declarations.ts +108 -0
  288. package/src/channels/types.ts +37 -1
  289. package/src/cli/AGENTS.md +5 -2
  290. package/src/cli/commands/__tests__/cache.test.ts +7 -4
  291. package/src/cli/commands/__tests__/cli-test-harness.ts +82 -0
  292. package/src/cli/commands/__tests__/conversations-wake.test.ts +51 -6
  293. package/src/cli/commands/__tests__/inference-models.test.ts +14 -0
  294. package/src/cli/commands/__tests__/inference-profiles.test.ts +44 -1
  295. package/src/cli/commands/__tests__/inference-providers.test.ts +7 -0
  296. package/src/cli/commands/__tests__/plugins.test.ts +692 -0
  297. package/src/cli/commands/__tests__/schedules.test.ts +136 -37
  298. package/src/cli/commands/conversations.ts +7 -3
  299. package/src/cli/commands/credentials.help.ts +7 -0
  300. package/src/cli/commands/inference-profiles.ts +9 -3
  301. package/src/cli/commands/inference.help.ts +16 -2
  302. package/src/cli/commands/mcp.help.ts +17 -6
  303. package/src/cli/commands/mcp.ts +9 -0
  304. package/src/cli/commands/memory/memory-retrospective.ts +18 -0
  305. package/src/cli/commands/notifications.ts +3 -6
  306. package/src/cli/commands/oauth/connect-surface-guidance.test.ts +16 -0
  307. package/src/cli/commands/oauth/connect-surface-guidance.ts +25 -7
  308. package/src/cli/commands/oauth/connect.test.ts +26 -1
  309. package/src/cli/commands/oauth/connect.ts +4 -1
  310. package/src/cli/commands/oauth/index.help.ts +3 -1
  311. package/src/cli/commands/oauth/providers.ts +3 -0
  312. package/src/cli/commands/plugins.help.ts +25 -2
  313. package/src/cli/commands/plugins.ts +289 -10
  314. package/src/cli/commands/schedules.help.ts +14 -12
  315. package/src/cli/commands/schedules.ts +19 -5
  316. package/src/cli/commands/stt.help.ts +27 -2
  317. package/src/cli/commands/tools.help.ts +4 -2
  318. package/src/cli/commands/tools.ts +38 -0
  319. package/src/cli/lib/__tests__/inspect-plugin.test.ts +1 -0
  320. package/src/cli/lib/__tests__/install-from-github.test.ts +79 -0
  321. package/src/cli/lib/__tests__/install-from-platform.test.ts +47 -1
  322. package/src/cli/lib/__tests__/plugin-surfaces.test.ts +86 -7
  323. package/src/cli/lib/__tests__/upgrade-plugin.test.ts +161 -0
  324. package/src/cli/lib/install-from-github.ts +61 -0
  325. package/src/cli/lib/install-from-platform.ts +13 -2
  326. package/src/cli/lib/plugin-surfaces.ts +124 -4
  327. package/src/cli/lib/upgrade-plugin.ts +60 -0
  328. package/src/cli.ts +1 -1
  329. package/src/config/__tests__/default-profile-catalog.test.ts +11 -1
  330. package/src/config/__tests__/deployment-context-defaults.test.ts +73 -0
  331. package/src/config/__tests__/memory-retrospective-schema.test.ts +40 -0
  332. package/src/config/__tests__/plugin-updates-schema.test.ts +43 -0
  333. package/src/config/__tests__/profile-tool-support.test.ts +131 -0
  334. package/src/config/bundled-skills/AGENTS.md +1 -1
  335. package/src/config/bundled-skills/acp/SKILL.md +6 -7
  336. package/src/config/bundled-skills/app-builder/SKILL.md +1 -1
  337. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +3 -3
  338. package/src/config/bundled-skills/media-processing/services/preprocess.ts +14 -4
  339. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +15 -15
  340. package/src/config/bundled-skills/schedule/SKILL.md +5 -1
  341. package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
  342. package/src/config/bundled-skills/settings/TOOLS.json +3 -3
  343. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +1 -0
  344. package/src/config/bundled-skills/subagent/SKILL.md +53 -22
  345. package/src/config/bundled-skills/subagent/TOOLS.json +14 -13
  346. package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +22 -1
  347. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +9 -2
  348. package/src/config/bundled-skills/visualize/SKILL.md +1 -1
  349. package/src/config/call-site-defaults.ts +4 -5
  350. package/src/config/default-profile-catalog.ts +9 -5
  351. package/src/config/feature-flag-registry.json +25 -17
  352. package/src/config/llm-resolver.ts +45 -15
  353. package/src/config/loader.ts +75 -1
  354. package/src/config/profile-tool-support.ts +110 -0
  355. package/src/config/sanitize-for-transfer.ts +11 -0
  356. package/src/config/schema.ts +4 -0
  357. package/src/config/schemas/__tests__/live-voice.test.ts +142 -4
  358. package/src/config/schemas/__tests__/stt.test.ts +20 -5
  359. package/src/config/schemas/call-site-catalog.ts +4 -4
  360. package/src/config/schemas/calls.ts +0 -4
  361. package/src/config/schemas/channels.ts +13 -0
  362. package/src/config/schemas/live-voice.ts +82 -23
  363. package/src/config/schemas/llm.ts +1 -1
  364. package/src/config/schemas/memory-retrospective.ts +25 -0
  365. package/src/config/schemas/plugin-updates.ts +59 -0
  366. package/src/config/schemas/services.ts +8 -4
  367. package/src/config/schemas/stt.ts +18 -5
  368. package/src/config/schemas/timeouts.ts +1 -1
  369. package/src/config/schemas/tts.ts +63 -0
  370. package/src/contacts/__tests__/guardian-delivery-reader.test.ts +16 -0
  371. package/src/contacts/guardian-delivery-reader.ts +29 -2
  372. package/src/context/compactor.ts +4 -4
  373. package/src/context/post-turn-tool-result-truncation.ts +32 -16
  374. package/src/context/strip-injections.ts +42 -0
  375. package/src/context/tool-result-spool.ts +32 -18
  376. package/src/credential-execution/ces-runtime.ts +3 -0
  377. package/src/credential-execution/client.ts +22 -1
  378. package/src/credential-execution/process-manager.test.ts +99 -0
  379. package/src/credential-execution/process-manager.ts +62 -16
  380. package/src/daemon/__tests__/abort-null-controller.test.ts +141 -5
  381. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +8 -12
  382. package/src/daemon/__tests__/install-assistant-command.test.ts +234 -0
  383. package/src/daemon/__tests__/turn-tail-assistant-reply-notify.test.ts +2 -4
  384. package/src/daemon/__tests__/turn-tail-deleted-conversation.test.ts +20 -29
  385. package/src/daemon/channel-ui-capability.ts +4 -4
  386. package/src/daemon/conversation-agent-loop-handlers.ts +117 -61
  387. package/src/daemon/conversation-agent-loop.ts +318 -148
  388. package/src/daemon/conversation-attachments.ts +1 -1
  389. package/src/daemon/conversation-error.ts +8 -1
  390. package/src/daemon/conversation-initial-prompt.ts +16 -38
  391. package/src/daemon/conversation-lifecycle.ts +154 -32
  392. package/src/daemon/conversation-messaging.ts +106 -43
  393. package/src/daemon/conversation-process.ts +131 -33
  394. package/src/daemon/conversation-queue-manager.ts +10 -0
  395. package/src/daemon/conversation-runtime-assembly.ts +9 -4
  396. package/src/daemon/conversation-store.ts +52 -3
  397. package/src/daemon/conversation-surface-state.ts +9 -0
  398. package/src/daemon/conversation-surfaces.ts +403 -210
  399. package/src/daemon/conversation-tool-setup.ts +56 -7
  400. package/src/daemon/conversation-turn-finalize.ts +134 -89
  401. package/src/daemon/conversation.ts +111 -27
  402. package/src/daemon/disk-pressure-guard-lifecycle.ts +2 -2
  403. package/src/daemon/disk-pressure-guard.ts +3 -3
  404. package/src/daemon/doordash-steps.ts +5 -5
  405. package/src/daemon/external-plugins-bootstrap.ts +7 -1
  406. package/src/daemon/handlers/config-channels.ts +48 -5
  407. package/src/daemon/handlers/conversation-history.ts +1 -1
  408. package/src/daemon/handlers/conversations.ts +62 -17
  409. package/src/daemon/handlers/shared.ts +12 -0
  410. package/src/daemon/handlers/skills.ts +11 -1
  411. package/src/daemon/identity-helpers.ts +38 -10
  412. package/src/daemon/install-assistant-command.ts +322 -0
  413. package/src/daemon/lifecycle.ts +14 -3
  414. package/src/daemon/message-types/conversations.ts +6 -7
  415. package/src/daemon/message-types/sync.ts +1 -0
  416. package/src/daemon/persist-media-references.ts +23 -14
  417. package/src/daemon/process-message.ts +6 -6
  418. package/src/daemon/tool-setup-types.ts +19 -122
  419. package/src/daemon/tool-side-effects.ts +17 -94
  420. package/src/daemon/trust-context-types.ts +39 -0
  421. package/src/daemon/trust-context.ts +14 -6
  422. package/src/daemon/turn-tail-chain.ts +73 -0
  423. package/src/daemon/web-search-history.ts +47 -33
  424. package/src/heartbeat/heartbeat-service.ts +6 -6
  425. package/src/inbound/__tests__/oauth-callback-url.test.ts +83 -0
  426. package/src/inbound/oauth-callback-url.ts +61 -0
  427. package/src/ipc/__tests__/socket-path.test.ts +21 -0
  428. package/src/ipc/assistant-server.ts +17 -10
  429. package/src/ipc/cli-client.ts +10 -1
  430. package/src/ipc/routes/__tests__/documents-sync-ipc-routes.test.ts +56 -0
  431. package/src/ipc/routes/documents-sync-ipc-routes.ts +42 -0
  432. package/src/ipc/socket-cleanup.ts +9 -7
  433. package/src/ipc/socket-path.ts +4 -96
  434. package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +1 -104
  435. package/src/live-voice/__tests__/live-voice-archive.test.ts +16 -16
  436. package/src/live-voice/__tests__/live-voice-attach-image.test.ts +209 -0
  437. package/src/live-voice/__tests__/live-voice-connection.test.ts +20 -0
  438. package/src/live-voice/__tests__/live-voice-events.test.ts +7 -8
  439. package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +932 -0
  440. package/src/live-voice/__tests__/live-voice-integration.test.ts +12 -5
  441. package/src/live-voice/__tests__/live-voice-metrics.test.ts +115 -8
  442. package/src/live-voice/__tests__/live-voice-photo.test.ts +100 -0
  443. package/src/live-voice/__tests__/live-voice-progress.test.ts +179 -146
  444. package/src/live-voice/__tests__/live-voice-session-telemetry.test.ts +265 -0
  445. package/src/live-voice/__tests__/live-voice-stt.test.ts +324 -2
  446. package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +131 -2
  447. package/src/live-voice/__tests__/live-voice-tts-session.test.ts +0 -483
  448. package/src/live-voice/__tests__/live-voice-tts.test.ts +148 -2
  449. package/src/live-voice/__tests__/live-voice-vad.test.ts +313 -32
  450. package/src/live-voice/__tests__/progress-narration.test.ts +214 -0
  451. package/src/live-voice/__tests__/progress-phrases.test.ts +167 -0
  452. package/src/live-voice/__tests__/protocol.test.ts +52 -0
  453. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +3 -0
  454. package/src/live-voice/live-voice-archive.ts +13 -13
  455. package/src/live-voice/live-voice-connection.ts +7 -1
  456. package/src/live-voice/live-voice-metrics.ts +57 -32
  457. package/src/live-voice/live-voice-photo.ts +168 -0
  458. package/src/live-voice/live-voice-session.ts +1137 -351
  459. package/src/live-voice/live-voice-tts.ts +18 -2
  460. package/src/live-voice/progress-narration.ts +277 -0
  461. package/src/live-voice/progress-phrases.ts +105 -2
  462. package/src/live-voice/protocol.ts +110 -2
  463. package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +0 -1
  464. package/src/mcp/__tests__/mcp-oauth-client-registration.test.ts +196 -0
  465. package/src/mcp/__tests__/mcp-oauth-provider.test.ts +9 -9
  466. package/src/mcp/client.ts +14 -7
  467. package/src/mcp/mcp-auth-orchestrator.ts +13 -22
  468. package/src/mcp/mcp-oauth-provider.ts +195 -240
  469. package/src/messaging/providers/__tests__/callback-routing.test.ts +5 -1
  470. package/src/messaging/providers/__tests__/transport-dispatch.test.ts +66 -4
  471. package/src/messaging/providers/callback-routing.ts +1 -0
  472. package/src/messaging/providers/discord/api.ts +312 -0
  473. package/src/messaging/providers/discord/dm-delivery.test.ts +204 -0
  474. package/src/messaging/providers/discord/render.test.ts +204 -0
  475. package/src/messaging/providers/discord/render.ts +195 -0
  476. package/src/messaging/providers/discord/send.test.ts +179 -0
  477. package/src/messaging/providers/discord/send.ts +212 -0
  478. package/src/messaging/providers/discord/transport.ts +81 -0
  479. package/src/messaging/providers/index.ts +3 -1
  480. package/src/messaging/providers/retry-policy.test.ts +247 -0
  481. package/src/messaging/providers/retry-policy.ts +206 -0
  482. package/src/messaging/providers/slack/mention-source.test.ts +285 -0
  483. package/src/messaging/providers/slack/mention-source.ts +287 -0
  484. package/src/messaging/providers/telegram-bot/api.ts +47 -130
  485. package/src/messaging/providers/whatsapp/api.ts +47 -136
  486. package/src/monitoring/__tests__/db-integrity-sample.test.ts +4 -1
  487. package/src/monitoring/__tests__/plugin-auto-update.test.ts +495 -0
  488. package/src/monitoring/db-integrity-sample.ts +6 -1
  489. package/src/monitoring/plugin-auto-update.ts +463 -0
  490. package/src/monitoring/resource-sampler.ts +21 -5
  491. package/src/monitoring/worker.ts +13 -0
  492. package/src/notifications/__tests__/assistant-reply-producer.test.ts +375 -2
  493. package/src/notifications/__tests__/broadcaster.test.ts +37 -1
  494. package/src/notifications/__tests__/copy-composer.test.ts +165 -0
  495. package/src/notifications/__tests__/emit-signal-pipeline-failure.test.ts +205 -0
  496. package/src/notifications/__tests__/notification-utils.test.ts +249 -0
  497. package/src/notifications/adapters/platform.ts +31 -2
  498. package/src/notifications/assistant-reply-producer.ts +79 -32
  499. package/src/notifications/broadcaster.ts +30 -10
  500. package/src/notifications/copy-composer.ts +69 -0
  501. package/src/notifications/emit-signal.ts +82 -15
  502. package/src/notifications/events-store.ts +10 -2
  503. package/src/notifications/home-feed-side-effect.ts +6 -3
  504. package/src/notifications/notification-utils.ts +173 -5
  505. package/src/notifications/signal.ts +13 -0
  506. package/src/oauth/AGENTS.md +4 -2
  507. package/src/oauth/byo-connection.ts +6 -1
  508. package/src/oauth/credential-token-resolver.ts +3 -10
  509. package/src/oauth/manual-token-connection.ts +29 -64
  510. package/src/oauth/manual-token-providers.ts +62 -0
  511. package/src/oauth/provider-serializer.ts +13 -0
  512. package/src/oauth/seed-providers.ts +62 -11
  513. package/src/onboarding/onboarding-events-store.ts +91 -1
  514. package/src/permissions/question-prompter.test.ts +4 -0
  515. package/src/permissions/question-prompter.ts +21 -4
  516. package/src/persistence/__tests__/conversation-lineage.test.ts +248 -0
  517. package/src/persistence/attachments-store.ts +15 -15
  518. package/src/persistence/conversation-attention-store.ts +30 -10
  519. package/src/persistence/conversation-bootstrap.ts +17 -0
  520. package/src/persistence/conversation-crud.ts +363 -97
  521. package/src/persistence/conversation-group-migration.ts +1 -1
  522. package/src/persistence/conversation-key-store.ts +38 -10
  523. package/src/persistence/conversation-lineage.ts +226 -0
  524. package/src/persistence/conversation-plugin-facade.ts +28 -3
  525. package/src/persistence/conversation-queries.ts +207 -33
  526. package/src/persistence/conversation-types.ts +107 -1
  527. package/src/persistence/jobs-store.ts +32 -8
  528. package/src/persistence/llm-usage-store.ts +22 -0
  529. package/src/persistence/migrations/361-normalize-managed-connection-rows.test.ts +168 -0
  530. package/src/persistence/migrations/361-normalize-managed-connection-rows.ts +76 -0
  531. package/src/persistence/migrations/362-add-conversation-subagent-kind.test.ts +187 -0
  532. package/src/persistence/migrations/362-add-conversation-subagent-kind.ts +93 -0
  533. package/src/persistence/migrations/363-backfill-schedule-inference-profile.test.ts +229 -0
  534. package/src/persistence/migrations/363-backfill-schedule-inference-profile.ts +127 -0
  535. package/src/persistence/migrations/364-add-schedule-source-key.test.ts +120 -0
  536. package/src/persistence/migrations/364-add-schedule-source-key.ts +43 -0
  537. package/src/persistence/migrations/365-add-conversation-fork-strategy.ts +27 -0
  538. package/src/persistence/schema/conversations.ts +32 -0
  539. package/src/persistence/schema/infrastructure.ts +3 -0
  540. package/src/persistence/steps.ts +30 -0
  541. package/src/persistence/subagent-store.ts +148 -6
  542. package/src/platform/managed-speech.test.ts +20 -0
  543. package/src/platform/managed-speech.ts +9 -0
  544. package/src/plugin-api/__tests__/oauth-callback-url-export.test.ts +29 -0
  545. package/src/plugin-api/index.ts +28 -5
  546. package/src/plugin-api/webhook-url.ts +151 -0
  547. package/src/plugins/__tests__/installed-plugin-dirs.test.ts +82 -0
  548. package/src/plugins/__tests__/mcp-servers.test.ts +370 -0
  549. package/src/plugins/__tests__/source-fingerprint.test.ts +5 -1
  550. package/src/plugins/collect-source-versions.ts +4 -27
  551. package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +5 -5
  552. package/src/plugins/defaults/exploration-drift/package.json +1 -1
  553. package/src/plugins/defaults/image-recovery/hooks/post-model-call.ts +4 -2
  554. package/src/plugins/defaults/image-recovery/recover.ts +67 -57
  555. package/src/plugins/defaults/index.ts +1 -1
  556. package/src/plugins/defaults/memory/__tests__/conversation-queries.test.ts +64 -18
  557. package/src/plugins/defaults/memory/__tests__/jobs-worker-outcome-contract.test.ts +242 -0
  558. package/src/plugins/defaults/memory/__tests__/jobs-worker-retrospective-sweep.test.ts +24 -1
  559. package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +48 -3
  560. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +511 -19
  561. package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +39 -3
  562. package/src/plugins/defaults/memory/__tests__/memory-retrospective-provider-path.test.ts +493 -0
  563. package/src/plugins/defaults/memory/__tests__/memory-retrospective-wake-chain.test.ts +5 -4
  564. package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +5 -1
  565. package/src/plugins/defaults/memory/job-handlers.ts +87 -5
  566. package/src/plugins/defaults/memory/jobs-worker.ts +60 -6
  567. package/src/plugins/defaults/memory/memory-retrospective-constants.ts +11 -0
  568. package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +29 -0
  569. package/src/plugins/defaults/memory/memory-retrospective-job.ts +342 -60
  570. package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +23 -3
  571. package/src/plugins/defaults/memory/substrate/consolidation-lock.ts +9 -4
  572. package/src/plugins/defaults/memory/substrate/skill-content.ts +8 -1
  573. package/src/plugins/defaults/memory/substrate/sweep-job.ts +7 -0
  574. package/src/plugins/defaults/memory/v1/graph/injection.ts +1 -1
  575. package/src/plugins/defaults/memory/v2/router.ts +8 -0
  576. package/src/plugins/defaults/turn-context/unified-turn-context.ts +1 -2
  577. package/src/plugins/external-plugin-loader.ts +64 -8
  578. package/src/plugins/installed-plugin-dirs.ts +101 -0
  579. package/src/plugins/mcp-servers.ts +343 -0
  580. package/src/plugins/mtime-cache.ts +34 -22
  581. package/src/plugins/types.ts +69 -8
  582. package/src/prompts/persona-resolver.ts +6 -2
  583. package/src/prompts/system-prompt.ts +72 -17
  584. package/src/providers/__tests__/inference.test.ts +40 -0
  585. package/src/providers/__tests__/preflight-resolved-config.test.ts +58 -1
  586. package/src/providers/__tests__/retry-callsite.test.ts +72 -2
  587. package/src/providers/__tests__/vellum-connection-routing.test.ts +42 -11
  588. package/src/providers/anthropic/client.ts +112 -95
  589. package/src/providers/connection-resolution.ts +35 -1
  590. package/src/providers/gemini/client.ts +5 -5
  591. package/src/providers/inference/adapter-factory.ts +16 -10
  592. package/src/providers/inference/auth.ts +16 -0
  593. package/src/providers/inference/connection-availability.ts +164 -12
  594. package/src/providers/inference/connections.ts +25 -1
  595. package/src/providers/media-resolve.ts +21 -11
  596. package/src/providers/model-catalog.ts +15 -0
  597. package/src/providers/openai/chat-completions-provider.ts +4 -4
  598. package/src/providers/openai/responses-provider.ts +12 -25
  599. package/src/providers/registry.ts +9 -4
  600. package/src/providers/retry.ts +25 -0
  601. package/src/providers/server-tool-pairing.ts +134 -0
  602. package/src/providers/speech-to-text/__tests__/deepgram-flux-frames.test.ts +433 -0
  603. package/src/providers/speech-to-text/__tests__/deepgram-flux-realtime.test.ts +620 -0
  604. package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +34 -0
  605. package/src/providers/speech-to-text/__tests__/resolve.test.ts +472 -12
  606. package/src/providers/speech-to-text/deepgram-flux-frames.ts +395 -0
  607. package/src/providers/speech-to-text/deepgram-flux-realtime.ts +719 -0
  608. package/src/providers/speech-to-text/deepgram-realtime.test.ts +283 -1
  609. package/src/providers/speech-to-text/deepgram-realtime.ts +117 -3
  610. package/src/providers/speech-to-text/deepgram.ts +1 -0
  611. package/src/providers/speech-to-text/provider-catalog.ts +137 -8
  612. package/src/providers/speech-to-text/resolve.ts +105 -12
  613. package/src/providers/speech-to-text/vellum-managed.ts +7 -1
  614. package/src/providers/speech-to-text/vellum-speech-relay-connection.ts +3 -1
  615. package/src/providers/types.ts +26 -6
  616. package/src/providers/vellum-model-routing.ts +6 -7
  617. package/src/runtime/AGENTS.md +2 -0
  618. package/src/runtime/__tests__/agent-wake.test.ts +16 -16
  619. package/src/runtime/__tests__/background-job-runner.test.ts +0 -144
  620. package/src/runtime/__tests__/desktop-presence.test.ts +162 -0
  621. package/src/runtime/__tests__/local-actor-identity-force-refresh.test.ts +104 -0
  622. package/src/runtime/agent-wake.ts +63 -24
  623. package/src/runtime/assistant-event-hub.ts +110 -12
  624. package/src/runtime/auth/__tests__/guard-tests.test.ts +2 -0
  625. package/src/runtime/auth/__tests__/scopes.test.ts +20 -0
  626. package/src/runtime/auth/same-actor.ts +56 -8
  627. package/src/runtime/auth/scopes.ts +12 -0
  628. package/src/runtime/auth/types.ts +2 -0
  629. package/src/runtime/background-job-runner.ts +5 -27
  630. package/src/runtime/channel-readiness-service.ts +59 -3
  631. package/src/runtime/channel-readiness-types.ts +18 -0
  632. package/src/runtime/desktop-presence.ts +69 -0
  633. package/src/runtime/http-server.ts +12 -0
  634. package/src/runtime/local-actor-identity.ts +29 -14
  635. package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -0
  636. package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
  637. package/src/runtime/routes/__tests__/client-routes.test.ts +186 -14
  638. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +547 -1
  639. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +162 -7
  640. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +14 -10
  641. package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +340 -3
  642. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +28 -1
  643. package/src/runtime/routes/__tests__/plugins-routes.test.ts +217 -1
  644. package/src/runtime/routes/__tests__/question-routes.test.ts +64 -0
  645. package/src/runtime/routes/__tests__/retrospective-routes.test.ts +20 -0
  646. package/src/runtime/routes/__tests__/skill-history-route.test.ts +116 -0
  647. package/src/runtime/routes/__tests__/sse-actor-principal-heal.test.ts +165 -0
  648. package/src/runtime/routes/__tests__/stt-routes.test.ts +25 -0
  649. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +2 -0
  650. package/src/runtime/routes/__tests__/wake-conversation-routes.test.ts +60 -2
  651. package/src/runtime/routes/archive-utils.ts +16 -12
  652. package/src/runtime/routes/attachment-routes.ts +13 -6
  653. package/src/runtime/routes/canned-reply-release.ts +54 -0
  654. package/src/runtime/routes/channel-availability-routes.ts +32 -14
  655. package/src/runtime/routes/channel-verification-routes.ts +2 -27
  656. package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +5 -0
  657. package/src/runtime/routes/client-routes.ts +114 -2
  658. package/src/runtime/routes/conversation-cli-routes.ts +10 -12
  659. package/src/runtime/routes/conversation-list-routes.ts +59 -10
  660. package/src/runtime/routes/conversation-management-routes.ts +47 -18
  661. package/src/runtime/routes/conversation-query-routes.ts +32 -53
  662. package/src/runtime/routes/conversation-routes.ts +360 -293
  663. package/src/runtime/routes/credential-prompt-routes.ts +20 -2
  664. package/src/runtime/routes/debug-routes.ts +4 -1
  665. package/src/runtime/routes/default-provider-routes.ts +7 -11
  666. package/src/runtime/routes/documents-routes.ts +44 -1
  667. package/src/runtime/routes/events-routes.ts +29 -1
  668. package/src/runtime/routes/host-app-control-routes.ts +2 -0
  669. package/src/runtime/routes/host-bash-routes.ts +2 -0
  670. package/src/runtime/routes/host-browser-routes.ts +2 -0
  671. package/src/runtime/routes/host-cu-routes.ts +2 -0
  672. package/src/runtime/routes/host-file-routes.ts +2 -0
  673. package/src/runtime/routes/host-transfer-routes.ts +4 -0
  674. package/src/runtime/routes/identity-routes.ts +6 -6
  675. package/src/runtime/routes/inbound-message-handler.ts +5 -5
  676. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +7 -3
  677. package/src/runtime/routes/inbound-stages/background-dispatch.ts +14 -0
  678. package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +2 -2
  679. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +14 -11
  680. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +14 -17
  681. package/src/runtime/routes/inference-profile-availability-guard.ts +171 -0
  682. package/src/runtime/routes/inference-profile-session-handler.ts +26 -2
  683. package/src/runtime/routes/inference-profile-session-routes.ts +2 -1
  684. package/src/runtime/routes/inference-profiles-routes.ts +152 -73
  685. package/src/runtime/routes/inference-provider-connection-routes.ts +0 -16
  686. package/src/runtime/routes/llm-call-sites-routes.ts +13 -0
  687. package/src/runtime/routes/log-export-routes.ts +1 -1
  688. package/src/runtime/routes/mcp-auth-routes.ts +141 -57
  689. package/src/runtime/routes/notification-routes.ts +0 -14
  690. package/src/runtime/routes/oauth-providers.ts +1 -0
  691. package/src/runtime/routes/plugins-routes.ts +127 -4
  692. package/src/runtime/routes/profiler-routes.ts +4 -2
  693. package/src/runtime/routes/question-routes.ts +28 -10
  694. package/src/runtime/routes/retrospective-routes.ts +9 -3
  695. package/src/runtime/routes/schedule-routes.ts +210 -12
  696. package/src/runtime/routes/secret-routes.ts +40 -23
  697. package/src/runtime/routes/settings-routes.ts +41 -13
  698. package/src/runtime/routes/skills-routes.ts +79 -0
  699. package/src/runtime/routes/sse-actor-principal-heal.ts +113 -0
  700. package/src/runtime/routes/stt-routes.ts +31 -25
  701. package/src/runtime/routes/ui-snapshot-routes.ts +1 -0
  702. package/src/runtime/routes/wake-conversation-routes.ts +23 -0
  703. package/src/runtime/services/__tests__/conversation-serializer.test.ts +1 -0
  704. package/src/runtime/services/conversation-serializer.ts +24 -9
  705. package/src/runtime/sync/documents-sidecar-publish.test.ts +101 -0
  706. package/src/runtime/sync/resource-sync-events.ts +79 -1
  707. package/src/runtime/sync/worker-daemon-notify.test.ts +34 -0
  708. package/src/runtime/sync/worker-daemon-notify.ts +44 -6
  709. package/src/runtime/verification-outbound-actions.ts +250 -222
  710. package/src/runtime/verification-templates.ts +41 -30
  711. package/src/schedule/__tests__/plugin-schedule-declarations.test.ts +614 -0
  712. package/src/schedule/__tests__/plugin-schedule-reconciler.test.ts +1066 -0
  713. package/src/schedule/inference-profile.ts +64 -3
  714. package/src/schedule/plugin-schedule-declarations.ts +518 -0
  715. package/src/schedule/plugin-schedule-reconciler.ts +605 -0
  716. package/src/schedule/plugin-schedules-gate.ts +23 -0
  717. package/src/schedule/schedule-store.ts +520 -26
  718. package/src/schedule/scheduler.ts +38 -0
  719. package/src/security/credential-backend.ts +51 -4
  720. package/src/security/encrypted-store.ts +64 -42
  721. package/src/security/oauth2.ts +6 -22
  722. package/src/security/secure-keys.ts +55 -7
  723. package/src/skills/catalog-install.ts +20 -7
  724. package/src/skills/inline-command-runner.ts +2 -7
  725. package/src/skills/skill-history.test.ts +269 -0
  726. package/src/skills/skill-history.ts +250 -0
  727. package/src/skills/skillssh-registry.ts +1 -1
  728. package/src/stt/__tests__/daemon-batch-transcriber.test.ts +22 -0
  729. package/src/stt/__tests__/language-metadata.test.ts +85 -0
  730. package/src/stt/__tests__/speech-energy.test.ts +79 -0
  731. package/src/stt/__tests__/types.test.ts +94 -0
  732. package/src/stt/daemon-batch-transcriber.ts +18 -6
  733. package/src/stt/language-metadata.ts +65 -0
  734. package/src/stt/speech-energy.ts +115 -12
  735. package/src/stt/stt-stream-session.ts +8 -4
  736. package/src/stt/types.ts +119 -0
  737. package/src/subagent/__tests__/consult-prompt.test.ts +25 -0
  738. package/src/subagent/consult-prompt.ts +3 -1
  739. package/src/subagent/consult-transcript.ts +1 -1
  740. package/src/subagent/manager.ts +304 -44
  741. package/src/subagent/progress-events.ts +35 -0
  742. package/src/subagent/role-resolution.ts +88 -0
  743. package/src/subagent/types.ts +303 -67
  744. package/src/subagent/validate-allowlists.ts +3 -4
  745. package/src/telegram/__tests__/webhook-health.test.ts +73 -1
  746. package/src/telegram/webhook-health.ts +101 -3
  747. package/src/telemetry/__tests__/telemetry-event-fixtures.ts +2 -0
  748. package/src/telemetry/activation-funnel.ts +6 -1
  749. package/src/telemetry/live-voice-funnel.ts +75 -0
  750. package/src/telemetry/telemetry-event-sources.ts +6 -0
  751. package/src/telemetry/telemetry-wire-source.json +1 -1
  752. package/src/telemetry/telemetry-wire.generated.ts +2 -0
  753. package/src/telemetry/types.ts +23 -4
  754. package/src/telemetry/usage-telemetry-reporter.test.ts +4 -0
  755. package/src/tools/__tests__/subagent-workflow-tool-input-schemas.test.ts +1 -1
  756. package/src/tools/ask-question/ask-question-tool.test.ts +118 -3
  757. package/src/tools/ask-question/ask-question-tool.ts +56 -2
  758. package/src/tools/browser/browser-execution.ts +1 -1
  759. package/src/tools/calls/call-start.ts +8 -5
  760. package/src/tools/conversation-groups/move_to_group.ts +10 -12
  761. package/src/tools/document/document-tool.ts +11 -4
  762. package/src/tools/execution-timeout.ts +9 -2
  763. package/src/tools/executor.ts +7 -6
  764. package/src/tools/filesystem/edit.ts +1 -1
  765. package/src/tools/filesystem/list.ts +1 -1
  766. package/src/tools/filesystem/read.ts +7 -13
  767. package/src/tools/filesystem/search.ts +23 -21
  768. package/src/tools/filesystem/write.ts +4 -1
  769. package/src/tools/host-filesystem/edit.ts +7 -2
  770. package/src/tools/host-filesystem/read.ts +21 -8
  771. package/src/tools/host-filesystem/write.ts +10 -2
  772. package/src/tools/host-terminal/host-shell.ts +2 -2
  773. package/src/tools/mcp/mcp-tool-factory.ts +25 -1
  774. package/src/tools/permission-checker.ts +8 -3
  775. package/src/tools/schedule/delete.ts +13 -1
  776. package/src/tools/schedule/list.ts +14 -3
  777. package/src/tools/schedule/update.ts +56 -33
  778. package/src/tools/shared/filesystem/audio-read.ts +6 -4
  779. package/src/tools/shared/filesystem/file-ops-service.ts +176 -116
  780. package/src/tools/shared/filesystem/image-read.ts +12 -12
  781. package/src/tools/shared/filesystem/path-policy.ts +70 -5
  782. package/src/tools/shared/filesystem/size-guard.ts +6 -6
  783. package/src/tools/shared/input-misuse.ts +72 -0
  784. package/src/tools/skills/scaffold-managed.ts +82 -0
  785. package/src/tools/skills/skill-tool-factory.ts +14 -1
  786. package/src/tools/subagent/consult-deadline.ts +12 -7
  787. package/src/tools/subagent/message.ts +3 -1
  788. package/src/tools/subagent/read.ts +66 -4
  789. package/src/tools/subagent/spawn.ts +500 -78
  790. package/src/tools/tool-approval-handler.ts +45 -4
  791. package/src/tools/types.ts +22 -3
  792. package/src/tools/ui-surface/surface-shape-docs.ts +1 -1
  793. package/src/tools/ui-surface/visual-validation.ts +2 -0
  794. package/src/tts/__tests__/provider-adapters.test.ts +147 -0
  795. package/src/tts/__tests__/speakable-segments.test.ts +470 -0
  796. package/src/tts/language-voices.ts +23 -0
  797. package/src/tts/providers/deepgram-provider.ts +3 -1
  798. package/src/tts/providers/elevenlabs-provider.ts +73 -1
  799. package/src/tts/providers/xai-provider.ts +28 -2
  800. package/src/tts/speakable-segments.ts +293 -23
  801. package/src/tts/synthesis-stream.ts +7 -0
  802. package/src/tts/types.ts +7 -0
  803. package/src/usage/__tests__/subagent-attribution.test.ts +109 -0
  804. package/src/usage/subagent-attribution.ts +108 -0
  805. package/src/util/__tests__/language-subtag.test.ts +54 -0
  806. package/src/util/__tests__/sqlite-retry.test.ts +112 -0
  807. package/src/util/abort-reasons.ts +16 -0
  808. package/src/util/ansi.ts +44 -0
  809. package/src/util/disk-usage.ts +17 -13
  810. package/src/util/image-conversion.ts +20 -13
  811. package/src/util/language-subtag.ts +43 -0
  812. package/src/util/schedule-source-key.ts +23 -0
  813. package/src/util/unicode.ts +1 -1
  814. package/src/util/worker-process.ts +7 -1
  815. package/src/workspace/git-service.ts +33 -9
  816. package/src/workspace/migrations/140-repair-seed-pinned-memory-v3-live.ts +260 -0
  817. package/src/workspace/migrations/141-stt-english-default-to-multilingual.ts +111 -0
  818. package/src/workspace/migrations/142-consolidate-voice-front-door.ts +70 -0
  819. package/src/workspace/migrations/__tests__/141-stt-english-default-to-multilingual.test.ts +116 -0
  820. package/src/workspace/migrations/registry.ts +6 -0
  821. package/src/workspace/top-level-renderer.ts +15 -2
  822. package/src/__tests__/tool-side-effects-slack-dm.test.ts +0 -357
  823. package/src/daemon/install-symlink.ts +0 -207
  824. package/src/live-voice/__tests__/front-decision.test.ts +0 -525
  825. package/src/live-voice/front-decision.ts +0 -429
  826. package/src/notifications/deferred-emit.ts +0 -147
@@ -1,6 +1,7 @@
1
1
  import { beforeEach, describe, expect, mock, test } from "bun:test";
2
2
 
3
3
  import type { BatchTranscriber } from "../../../../stt/types.js";
4
+ import { SttError } from "../../../../stt/types.js";
4
5
  import type { ToolContext } from "../../../../tools/types.js";
5
6
 
6
7
  // ---------------------------------------------------------------------------
@@ -8,9 +9,15 @@ import type { ToolContext } from "../../../../tools/types.js";
8
9
  // ---------------------------------------------------------------------------
9
10
 
10
11
  let mockTranscriber: BatchTranscriber | null = null;
12
+ let mockResolveError: Error | null = null;
11
13
 
12
14
  mock.module("../../../../providers/speech-to-text/resolve.js", () => ({
13
- resolveBatchTranscriber: async () => mockTranscriber,
15
+ resolveBatchTranscriber: async () => {
16
+ if (mockResolveError) {
17
+ throw mockResolveError;
18
+ }
19
+ return mockTranscriber;
20
+ },
14
21
  }));
15
22
 
16
23
  // Track calls to spawnWithTimeout so we can simulate ffmpeg/ffprobe results.
@@ -103,6 +110,7 @@ function makeMockTranscriber(
103
110
  describe("transcribe_media tool", () => {
104
111
  beforeEach(() => {
105
112
  mockTranscriber = null;
113
+ mockResolveError = null;
106
114
  spawnResults = {};
107
115
  accessiblePaths = new Set();
108
116
  mockFileContents = {};
@@ -119,6 +127,19 @@ describe("transcribe_media tool", () => {
119
127
  "No speech-to-text provider is configured",
120
128
  );
121
129
  });
130
+
131
+ test("surfaces a resolver error verbatim rather than the not-configured copy", async () => {
132
+ const reason =
133
+ 'Deepgram Flux is streaming-only. Batch transcription requires the deepgram provider: set services.stt.provider to "deepgram".';
134
+ mockResolveError = new SttError("provider-error", reason, {
135
+ userFacing: true,
136
+ });
137
+
138
+ const result = await run({ file_path: "/tmp/test.mp3" }, makeContext());
139
+
140
+ expect(result.isError).toBe(true);
141
+ expect(result.content).toBe(reason);
142
+ });
122
143
  });
123
144
 
124
145
  describe("input validation", () => {
@@ -234,8 +234,15 @@ export async function run(
234
234
  };
235
235
  }
236
236
 
237
- // Resolve the configured STT provider
238
- const transcriber = await resolveBatchTranscriber();
237
+ // Resolve the configured STT provider. A typed resolver error already names
238
+ // the mismatch (e.g. a streaming-only provider) and its fix, so it reaches
239
+ // the model verbatim rather than as the "nothing configured" copy below.
240
+ let transcriber: BatchTranscriber | null;
241
+ try {
242
+ transcriber = await resolveBatchTranscriber();
243
+ } catch (err) {
244
+ return { content: (err as Error).message, isError: true };
245
+ }
239
246
  if (!transcriber) {
240
247
  return {
241
248
  content:
@@ -67,7 +67,7 @@ Semantic tokens flip automatically between light and dark. Use them for every su
67
67
  - Surfaces: --surface-base (page), --surface-lift (card), --surface-overlay, --surface-sunken (recessed tile), --surface-hover, --surface-active.
68
68
  - Text, strongest to faintest: --content-emphasised, --content-strong, --content-default (body), --content-secondary (labels and any text under 14px), --content-tertiary (14px and up only), --content-quiet, --content-faint, --content-disabled, --content-inset (on inverted fills). Text at 11 to 13px always takes --content-secondary or stronger.
69
69
  - Borders: --border-base (hairline), --border-subtle, --border-element (visible control edge), --border-hover, --border-active, --border-disabled.
70
- - Status pairs: --system-positive-strong/-weak, --system-negative-strong/-weak (and --system-negative-hover), --system-mid-strong/-weak, --system-info-strong/-weak.
70
+ - Status pairs: --system-positive-strong/-weak, --system-negative-strong/-weak (and --system-negative-hover), --system-mid-strong/-weak, --system-info-strong/-weak. A non-text glyph sitting on its own -weak fill takes --system-positive-on-weak or --system-negative-on-weak; those clear the 3:1 that non-text indicators need, which --system-negative-strong misses on --system-negative-weak in the dark theme. Text on a -weak fill needs 4.5:1 and takes --content-default or stronger; --content-tertiary misses that on both fills in the light and dark themes, and --content-secondary misses it on the negative fill in light.
71
71
  - Type: --font-sans (default), --font-mono (identifiers, code, tabular numbers only), --font-serif (editorial pull-quotes only).
72
72
  - Radius: --radius-xs 2, --radius-sm 4, --radius-md 8, --radius-lg 12, --radius-xl 16, --radius-xxl 20, --radius-pill 999.
73
73
 
@@ -121,22 +121,21 @@ export const CALL_SITE_DEFAULTS: Record<LLMCallSite, CallSiteDefaultConfig> = {
121
121
  effort: "low",
122
122
  thinking: { enabled: false },
123
123
  },
124
- // Endpoint decisions gate live-voice turn-end latency, and `cost-optimized`'s
125
- // upstream cannot fit any usable decision budget (~1s+ per forced tool call).
124
+ // Progress narration only helps when it arrives before the next real output.
126
125
  // `latency-optimized` is the latency-class profile (see
127
126
  // default-profile-catalog.ts): managed installs get the pinned latency model,
128
127
  // BYOK installs resolve their own provider's latency model through the intent
129
128
  // table rather than a model id they may hold no credential for. The profile
130
129
  // is user-facing ("Speed"), so a user edit to it moves this call site too.
131
- voiceFrontDecision: {
130
+ voiceProgressNarration: {
132
131
  profile: "latency-optimized",
133
132
  effort: "low",
134
133
  thinking: { enabled: false },
135
134
  },
136
135
  // The front-door leg fronts EVERY unified live-voice turn and its leading
137
136
  // tokens ARE the endpointing/triage verdict, so both TTFT variance and
138
- // judgment quality gate the whole call. Same latency class as the endpoint
139
- // decider: live drives showed the cost-optimized upstream with multi-second
137
+ // judgment quality gate the whole call. Live drives showed the
138
+ // cost-optimized upstream with multi-second
140
139
  // cross-session TTFT tails and over-escalation of small talk under open-task
141
140
  // context pressure.
142
141
  voiceFrontDoor: {
@@ -135,7 +135,11 @@ const VELLUM_PROFILE_IMPLS: ProfileImpls = {
135
135
  label: "Speed",
136
136
  description: "Fastest responses, with reasoning turned off",
137
137
  maxTokens: 8192,
138
- effort: "low",
138
+ // Explicit reasoning opt-out, matching `cost-optimized` above: this
139
+ // profile advertises reasoning as off, and OpenAI-compat APIs default
140
+ // reasoning to "medium" when the field is omitted, so the opt-out has to
141
+ // be stated rather than implied.
142
+ effort: "none",
139
143
  thinking: { enabled: false, streamThinking: false },
140
144
  contextWindow: {
141
145
  maxInputTokens: DEFAULT_CONTEXT_WINDOW_MAX_INPUT_TOKENS,
@@ -194,7 +198,7 @@ const BYOK_PROFILE_IMPLS: Record<
194
198
  label: "Speed",
195
199
  description: "Fastest responses, with reasoning turned off",
196
200
  maxTokens: 8192,
197
- effort: "low",
201
+ effort: "none",
198
202
  thinking: { enabled: false, streamThinking: false },
199
203
  contextWindow: { maxInputTokens: DEFAULT_CONTEXT_WINDOW_MAX_INPUT_TOKENS },
200
204
  },
@@ -298,9 +302,9 @@ export const OS_BETA_PROFILE_TEMPLATE: DefaultProfileTemplate = {
298
302
  /**
299
303
  * Profiles whose body is code-owned outright: no workspace overlay, and no
300
304
  * user-owned shadow. The shadow rule below lets a user replace a default they
301
- * can select, but `latency-optimized` fronts every live-voice turn through
302
- * `voiceFrontDecision`/`voiceFrontDoor`, where a model outside the latency
303
- * envelope is audible dead air rather than a slow reply. A same-named
305
+ * can select, but `latency-optimized` serves `voiceFrontDoor` and
306
+ * `voiceProgressNarration`, where a model outside the latency envelope is
307
+ * audible dead air rather than a slow reply. A same-named
304
308
  * workspace entry stays on disk and stays listed; it just never governs what
305
309
  * this name resolves to.
306
310
  */
@@ -101,6 +101,14 @@
101
101
  "description": "Enable the Quick Input popover on right-click of the menu bar icon",
102
102
  "defaultEnabled": false
103
103
  },
104
+ {
105
+ "id": "companion-surface",
106
+ "scope": "client",
107
+ "key": "companion-surface",
108
+ "label": "Companion Surface",
109
+ "description": "Show the macOS companion surface: the floating avatar that carries Talk, Type and the running call, and its tray item. Read in the Electron main process, which decides whether the window opens at all",
110
+ "defaultEnabled": false
111
+ },
104
112
  {
105
113
  "id": "expand-completed-steps",
106
114
  "scope": "client",
@@ -197,14 +205,6 @@
197
205
  "description": "Show the Velvet theme option in the macOS appearance settings. Velvet is a dark-mode variant with red/pink accent colors.",
198
206
  "defaultEnabled": false
199
207
  },
200
- {
201
- "id": "queue-steering",
202
- "scope": "assistant",
203
- "key": "queue-steering",
204
- "label": "Queue Steering",
205
- "description": "Enable the 'Push to agent' button on queued messages, allowing users to steer the assistant to a specific queued message by aborting the current generation and promoting the message to the head of the queue.",
206
- "defaultEnabled": false
207
- },
208
208
  {
209
209
  "id": "chat-pull-to-refresh-enabled",
210
210
  "scope": "client",
@@ -213,14 +213,6 @@
213
213
  "description": "Enable pull-to-refresh gesture in the chat view.",
214
214
  "defaultEnabled": false
215
215
  },
216
- {
217
- "id": "platform-notifications",
218
- "scope": "client",
219
- "key": "platform-notifications",
220
- "label": "Platform Notifications",
221
- "description": "Enable the Notifications tab in settings.",
222
- "defaultEnabled": false
223
- },
224
216
  {
225
217
  "id": "centralized-assistant-status",
226
218
  "scope": "client",
@@ -346,7 +338,7 @@
346
338
  "scope": "client",
347
339
  "key": "assistant-switcher",
348
340
  "label": "Assistant Switcher",
349
- "description": "Show the Switch Assistant section in General settings (local mode only), linking to the assistant chooser.",
341
+ "description": "Show the Switch Assistant section in General settings, linking to the assistant chooser. Covers local clients, signed-in cloud-hub users, remote-gateway origins, and native mobile shells; remote-gateway desktop browsers hand off to the hub chooser with a self-registration param. Also makes the chooser's selection authoritative for the app's active assistant on every surface including the platform hub, a job that previously belonged to multi-platform-assistant alone.",
350
342
  "defaultEnabled": false
351
343
  },
352
344
  {
@@ -364,6 +356,22 @@
364
356
  "label": "Assistant Reply Push",
365
357
  "description": "Gates the `chat.assistant_reply` push notification the assistant sends at the end of a user-initiated turn whose reply the user has not seen. On by default; turn it off to silence the push without disabling the rest of the notification pipeline.",
366
358
  "defaultEnabled": true
359
+ },
360
+ {
361
+ "id": "desktop-presence-suppression",
362
+ "scope": "assistant",
363
+ "key": "desktop-presence-suppression",
364
+ "label": "Desktop Presence Suppression",
365
+ "description": "Gates whether a `chat.assistant_reply` push is suppressed while a Mac desktop client reports itself attended. On by default; turn it off to restore unconditional reply pushes.",
366
+ "defaultEnabled": true
367
+ },
368
+ {
369
+ "id": "plugin-schedules",
370
+ "scope": "assistant",
371
+ "key": "plugin-schedules",
372
+ "label": "Plugin Schedules",
373
+ "description": "Plugins declare recurring schedules as files that register and run automatically",
374
+ "defaultEnabled": false
367
375
  }
368
376
  ]
369
377
  }
@@ -40,7 +40,7 @@ import {
40
40
  * 3. `llm.callSites[callSite].profile` (the call site's named profile)
41
41
  * 4. `CALL_SITE_DEFAULTS[callSite].profile` intent resolved through
42
42
  * `llm.defaultProvider`
43
- * 5. balanced intent through `llm.defaultProvider` — the code-owned anchor
43
+ * 5. balanced intent through `llm.defaultProvider`: the code-owned anchor
44
44
  * for profileless call sites, or when nothing above is usable
45
45
  *
46
46
  * A winner must carry its own `provider` AND `model`: the base layer's schema
@@ -157,9 +157,11 @@ export function resolveCallSiteConfig(
157
157
  //
158
158
  // The request config is the base + winner + site-tweak composition:
159
159
  // code-owned schema defaults, then the single winning profile, then the call
160
- // site's own tuning fragment. Selection is pure either/or — no profile ever
161
- // contributes a field to another profile; `deepMerge` here only makes nested
162
- // tweaks (`thinking.enabled`) combine leaf-wise instead of wiping siblings.
160
+ // site's own tuning fragment (its shipped `CALL_SITE_DEFAULTS` tuning with
161
+ // the workspace `llm.callSites` entry layered over it, field by field).
162
+ // Selection is pure either/or: no profile ever contributes a field to
163
+ // another profile, and `deepMerge` only makes nested tweaks
164
+ // (`thinking.enabled`) combine leaf-wise instead of wiping siblings.
163
165
  // `temperature`/`topP` come from the winner (or an explicit tweak);
164
166
  // `logitBias` only ever from the winner.
165
167
  // `forceOverrideProfile` is a no-op here (the override is already first).
@@ -221,8 +223,9 @@ export function selectWinningProfile(
221
223
  }
222
224
  // Anchor: profileless call sites (`vision`, `workflowLeaf`) and any
223
225
  // resolution whose every named rung was unusable land on balanced intent
224
- // through the default provider. `profileName` stays null — the anchor is
225
- // not a selection.
226
+ // through the default provider, bottoming out on the code-owned catalog,
227
+ // so it always resolves. `profileName` stays null on the catalog path:
228
+ // the anchor itself is not a selection.
226
229
  return {
227
230
  profileName: null,
228
231
  source: "default",
@@ -380,15 +383,10 @@ function resolveOverrideOrDefault(
380
383
  const winnerFragment: Mergeable =
381
384
  selection.entry == null ? {} : winnerConfigFragment(selection.entry);
382
385
 
383
- // The call site's own tweak fragment: the workspace override replaces the
384
- // code default wholesale. `profile` is the selection discriminator and
385
- // `logitBias` is winner-owned, so neither enters the merge.
386
- const site = llm.callSites?.[callSite] ?? CALL_SITE_DEFAULTS[callSite];
387
- const {
388
- profile: _siteProfile,
389
- logitBias: _siteBias,
390
- ...tweak
391
- } = (site ?? {}) as Record<string, unknown>;
386
+ const tweak = composeCallSiteTweak(
387
+ CALL_SITE_DEFAULTS[callSite] as Mergeable | undefined,
388
+ llm.callSites?.[callSite] as Mergeable | undefined,
389
+ );
392
390
 
393
391
  // Direct call-site model overrides are fragments by design: when the tweak
394
392
  // pins a model the winner's provider does not serve, stamp the catalog
@@ -471,6 +469,38 @@ function winnerConfigFragment(entry: ProfileEntry): Mergeable {
471
469
 
472
470
  type Mergeable = Record<string, unknown>;
473
471
 
472
+ /**
473
+ * The call site's tuning fragment: its shipped `CALL_SITE_DEFAULTS` tuning
474
+ * with the workspace `llm.callSites` entry layered over it, field by field.
475
+ * An entry that only names a profile therefore repoints the selection while
476
+ * the tuning the call site ships with still applies, and a field the entry
477
+ * sets wins for that field alone.
478
+ *
479
+ * `profile` is the selection discriminator and `logitBias` is winner-owned,
480
+ * so neither survives into the fragment. A workspace entry also owns the
481
+ * selection for its own call site: when one exists the shipped layer
482
+ * contributes tuning only, so a shipped `provider`/`model` pin can never
483
+ * override the profile or the custom model the user chose there. With no
484
+ * workspace entry the shipped fragment applies whole, pin included.
485
+ */
486
+ export function composeCallSiteTweak(
487
+ shipped: Mergeable | undefined,
488
+ workspace: Mergeable | undefined,
489
+ ): Mergeable {
490
+ const {
491
+ provider: _shippedProvider,
492
+ model: _shippedModel,
493
+ ...shippedTuning
494
+ } = shipped ?? {};
495
+ const shippedLayer = workspace == null ? (shipped ?? {}) : shippedTuning;
496
+ const {
497
+ profile: _siteProfile,
498
+ logitBias: _siteBias,
499
+ ...tweak
500
+ } = deepMerge(shippedLayer, workspace ?? {});
501
+ return tweak;
502
+ }
503
+
474
504
  /**
475
505
  * FNV-1a 32-bit string hash → unit float in [0, 1). Deterministic and stable
476
506
  * across runtimes — the mix-pick contract depends on identical output for
@@ -1,12 +1,13 @@
1
1
  import {
2
2
  existsSync,
3
3
  mkdirSync,
4
+ readdirSync,
4
5
  readFileSync,
5
6
  renameSync,
6
7
  rmSync,
7
8
  writeFileSync,
8
9
  } from "node:fs";
9
- import { dirname, join } from "node:path";
10
+ import { basename, dirname, join } from "node:path";
10
11
 
11
12
  import { safeStatSync } from "../util/fs.js";
12
13
  import { getLogger } from "../util/logger.js";
@@ -319,6 +320,53 @@ function writeQuarantineNotice(
319
320
  }
320
321
  }
321
322
 
323
+ /**
324
+ * Whether the newest quarantined config next to `configPath`
325
+ * (`config.json.corrupt-*.json`, written by {@link quarantineCorruptConfig})
326
+ * carried `memory.v3.live: true`. Quarantine filenames embed a
327
+ * filesystem-safe ISO timestamp, so a lexicographic sort is chronological.
328
+ *
329
+ * The first-launch seed asks this so a quarantine-reseed carries the memory
330
+ * tier forward: without it, reseeding an existing memory-v3 assistant
331
+ * silently demotes it to v2: the reseeded file records no `live` decision,
332
+ * migration 105 is already checkpointed on an existing workspace and never
333
+ * re-runs, and the schema default is `false`. Only `true` is ever salvaged:
334
+ * carrying `false` forward would re-pin a workspace to the schema default,
335
+ * the exact bug the seed's absent-leaf contract exists to prevent.
336
+ *
337
+ * A quarantined file usually fails `JSON.parse` (that is why it was
338
+ * quarantined); every config writer serializes via
339
+ * `JSON.stringify(config, null, 2)` and `memory.v3.live` is the only config
340
+ * key named `"live"`, so a literal `"live": true` match on the raw text is
341
+ * an unambiguous fallback for truncated files.
342
+ */
343
+ function quarantinedConfigSaidMemoryV3Live(configPath: string): boolean {
344
+ try {
345
+ const dir = dirname(configPath);
346
+ const prefix = `${basename(configPath)}.corrupt-`;
347
+ const quarantines = readdirSync(dir)
348
+ .filter((name) => name.startsWith(prefix) && name.endsWith(".json"))
349
+ .sort();
350
+ const newest = quarantines[quarantines.length - 1];
351
+ if (!newest) {
352
+ return false;
353
+ }
354
+ const raw = readFileSync(join(dir, newest), "utf-8");
355
+ try {
356
+ const parsed: unknown = JSON.parse(raw);
357
+ if (!isPlainObject(parsed) || !isPlainObject(parsed.memory)) {
358
+ return false;
359
+ }
360
+ const v3 = parsed.memory.v3;
361
+ return isPlainObject(v3) && v3.live === true;
362
+ } catch {
363
+ return /"live"\s*:\s*true/.test(raw);
364
+ }
365
+ } catch {
366
+ return false;
367
+ }
368
+ }
369
+
322
370
  /** Minimal structural view of the Zod issues the recovery ladder consumes. */
323
371
  type ValidationIssue = { path: PropertyKey[]; message: string };
324
372
 
@@ -719,6 +767,11 @@ const DEPRECATED_FIELDS: Record<string, string> = {
719
767
  "daemon.reapOrphanedSubprocesses has been removed. The daemon now reaps " +
720
768
  "orphaned subprocesses automatically whenever it runs as PID 1 on Linux. " +
721
769
  "The field will be removed from your config file.",
770
+ "calls.voice.language":
771
+ "calls.voice.language has been removed; it had no effect. Use " +
772
+ "services.stt.language for the spoken language and " +
773
+ "services.tts.providers.<id>.languageVoices for per-language voices. " +
774
+ "The field will be removed from your config file.",
722
775
  };
723
776
 
724
777
  /**
@@ -1137,6 +1190,27 @@ export function loadConfig(): AssistantConfig {
1137
1190
  // `memory.v3.live=false` override still wins by merging after
1138
1191
  // migrations.
1139
1192
  seed.memory.v3 = {} as (typeof seed.memory)["v3"];
1193
+ // Exception: a quarantine-reseed carries the memory tier forward.
1194
+ // When the missing config.json is explained by a quarantined
1195
+ // predecessor that had `live: true`, this is an EXISTING memory-v3
1196
+ // assistant being reseeded, not a first launch: migration 105 is
1197
+ // already checkpointed here and never re-runs, so leaving the leaf
1198
+ // absent would silently demote the assistant to v2. Persist the
1199
+ // carried value and apply it to this load's effective config so the
1200
+ // current boot already runs v3.
1201
+ if (quarantinedConfigSaidMemoryV3Live(configPath)) {
1202
+ seed.memory.v3 = { live: true } as (typeof seed.memory)["v3"];
1203
+ config.memory.v3.live = true;
1204
+ // Refresh the last-known-good safety net (mirrors the
1205
+ // deployment-context refresh above): its snapshot was taken before
1206
+ // the carry, so a later in-process validation recovery would
1207
+ // otherwise restore live=false and demote the assistant in memory
1208
+ // despite the reseeded file on disk carrying true.
1209
+ lastKnownGoodConfig = structuredClone(config);
1210
+ log.info(
1211
+ "Carried memory.v3.live=true forward from the quarantined config",
1212
+ );
1213
+ }
1140
1214
  // Strip dataDir (runtime-derived) from the persisted config
1141
1215
  const { dataDir: _, ...persistable } = seed;
1142
1216
  writeFileSync(configPath, JSON.stringify(persistable, null, 2) + "\n");
@@ -0,0 +1,110 @@
1
+ import type { z } from "zod";
2
+
3
+ import { PROVIDER_CATALOG } from "../providers/model-catalog.js";
4
+ import { resolveDefaultProfileForProvider } from "./default-profile-catalog.js";
5
+ import { selectWinningProfile } from "./llm-resolver.js";
6
+ import type { AssistantConfig } from "./schema.js";
7
+ import type { LLMSchema } from "./schemas/llm.js";
8
+
9
+ /**
10
+ * Whether a named inference profile is KNOWN to support tool calling.
11
+ *
12
+ * Tri-state on purpose. The model catalog is not exhaustive: BYOK installs
13
+ * point profiles at models the catalog has never heard of, and a
14
+ * `supportsToolUse` flag it does not carry is not evidence of anything. So
15
+ * only `false` is a verdict:
16
+ * - `true` the catalog states the model supports tool use
17
+ * - `false` the catalog states the model does NOT support tool use
18
+ * - `undefined` the model is unknown to the catalog, or the catalog entry
19
+ * is silent on tool use
20
+ *
21
+ * A `mix` profile is answered across ALL of its arms rather than by expanding
22
+ * it, because the arm a mix lands on is a function of the running
23
+ * conversation's `selectionSeed` and no such conversation exists at probe
24
+ * time. A verdict is only returned when it holds for every arm: all-denied is
25
+ * `false`, all-capable is `true`, and a mix of the two is `undefined` (which
26
+ * arm runs is unknowable here, so there is no honest verdict).
27
+ *
28
+ * Callers gate on `=== false` so an unknown model is never punished (fail
29
+ * open).
30
+ */
31
+ export function profileSupportsTools(
32
+ profileKey: string,
33
+ config: AssistantConfig,
34
+ ): boolean | undefined {
35
+ const arms = mixArms(profileKey, config.llm);
36
+ if (arms == null) {
37
+ return concreteProfileSupportsTools(profileKey, config);
38
+ }
39
+ const verdicts = arms.map((arm) => concreteProfileSupportsTools(arm, config));
40
+ if (verdicts.length === 0) {
41
+ return undefined;
42
+ }
43
+ if (verdicts.every((verdict) => verdict === false)) {
44
+ return false;
45
+ }
46
+ if (verdicts.every((verdict) => verdict === true)) {
47
+ return true;
48
+ }
49
+ return undefined;
50
+ }
51
+
52
+ /** The arm profile names of a `mix` profile, or `undefined` if not a mix. */
53
+ function mixArms(
54
+ profileKey: string,
55
+ llm: z.infer<typeof LLMSchema>,
56
+ ): string[] | undefined {
57
+ const entry = resolveDefaultProfileForProvider(
58
+ llm.profiles,
59
+ profileKey,
60
+ llm.defaultProvider ?? null,
61
+ );
62
+ return entry?.mix?.map((arm) => arm.profile);
63
+ }
64
+
65
+ /**
66
+ * Verdict for a profile expected to name one concrete model. A key that is
67
+ * itself a mix yields no verdict: `LLMSchema.superRefine` forbids nesting, so
68
+ * this is only reachable from a hand-written config that never went through
69
+ * the schema, and expanding it would reintroduce the unseeded random pick.
70
+ */
71
+ function concreteProfileSupportsTools(
72
+ profileKey: string,
73
+ config: AssistantConfig,
74
+ ): boolean | undefined {
75
+ if (mixArms(profileKey, config.llm) != null) {
76
+ return undefined;
77
+ }
78
+ // Run the profile through the real resolver so a catalog default and a
79
+ // workspace shadow alike yield the model the child would actually run on.
80
+ // Feeding the key in as the override rung means a profile the resolver
81
+ // cannot use falls through to a different rung, and a non-`override` winner
82
+ // tells us the key never resolved: unknown, so no verdict.
83
+ const winner = selectWinningProfile("subagentSpawn", config.llm, {
84
+ overrideProfile: profileKey,
85
+ });
86
+ if (winner.source !== "override") {
87
+ return undefined;
88
+ }
89
+ const model = winner.entry?.model;
90
+ return model == null ? undefined : modelSupportsTools(model);
91
+ }
92
+
93
+ /**
94
+ * Look a model id up across every catalog provider. A model offered by more
95
+ * than one provider (e.g. the same id direct and through OpenRouter) is
96
+ * matched several times; any entry claiming tool support settles it, keeping
97
+ * the answer on the fail-open side.
98
+ */
99
+ function modelSupportsTools(modelId: string): boolean | undefined {
100
+ const matches = PROVIDER_CATALOG.flatMap((provider) =>
101
+ provider.models.filter((model) => model.id === modelId),
102
+ );
103
+ if (matches.some((model) => model.supportsToolUse === true)) {
104
+ return true;
105
+ }
106
+ if (matches.some((model) => model.supportsToolUse === false)) {
107
+ return false;
108
+ }
109
+ return undefined;
110
+ }
@@ -6,6 +6,7 @@
6
6
  * - `ingress.publicBaseUrl` → set to `""`
7
7
  * - `ingress.enabled` → deleted
8
8
  * - `ingress.publicBaseUrlManagedBy` → deleted
9
+ * - `telegram.registeredWebhookUrl` → deleted
9
10
  * - `daemon` → deleted entirely
10
11
  * - `skills.load.extraDirs` → set to `[]`
11
12
  * - `hostBrowser.cdpInspect.desktopAuto` → deleted **only when the source
@@ -45,6 +46,16 @@ export function sanitizeConfigForTransfer(configJson: string): string {
45
46
  delete ingress.publicBaseUrlManagedBy;
46
47
  }
47
48
 
49
+ // Strip the recorded Telegram webhook URL. It records where *this*
50
+ // deployment pointed Telegram, so carrying it across a teleport would have
51
+ // the destination compare its own registration against the source's address
52
+ // and report a mismatch on a channel that is fine. Absent, the health sweep
53
+ // reports unverified until the destination reconciles and records its own.
54
+ if (config.telegram && typeof config.telegram === "object") {
55
+ const telegram = config.telegram as Record<string, unknown>;
56
+ delete telegram.registeredWebhookUrl;
57
+ }
58
+
48
59
  // Strip daemon entirely
49
60
  delete config.daemon;
50
61
 
@@ -50,6 +50,7 @@ import {
50
50
  PlatformConfigSchema,
51
51
  UiConfigSchema,
52
52
  } from "./schemas/platform.js";
53
+ import { PluginUpdatesConfigSchema } from "./schemas/plugin-updates.js";
53
54
  import { SecretDetectionConfigSchema } from "./schemas/security.js";
54
55
  import { ServicesSchema } from "./schemas/services.js";
55
56
  import { SkillsConfigSchema } from "./schemas/skills.js";
@@ -142,6 +143,9 @@ export const AssistantConfigSchema = z.object({
142
143
  .describe(
143
144
  "Per-plugin configuration keyed by plugin name. Validated downstream by each plugin's manifest.config validator at bootstrap.",
144
145
  ),
146
+ pluginUpdates: PluginUpdatesConfigSchema.default(
147
+ PluginUpdatesConfigSchema.parse({}),
148
+ ),
145
149
  legacyTelemetryOptOut: z
146
150
  .boolean()
147
151
  .optional()