@vellumai/assistant 0.11.2 → 0.11.3-staging.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (720) hide show
  1. package/ARCHITECTURE.md +58 -3
  2. package/docs/trusted-contact-access.md +9 -5
  3. package/docs/vellum-doctor.md +195 -0
  4. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +39 -0
  5. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
  6. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
  7. package/node_modules/@vellumai/ces-client/src/index.ts +1 -0
  8. package/node_modules/@vellumai/ces-client/src/rpc-client.ts +19 -2
  9. package/node_modules/@vellumai/environments/package.json +2 -1
  10. package/node_modules/@vellumai/environments/src/__tests__/cloud-assistant-hub-url.test.ts +38 -0
  11. package/node_modules/@vellumai/environments/src/__tests__/install-layout.test.ts +98 -0
  12. package/node_modules/@vellumai/environments/src/__tests__/package-boundary.test.ts +5 -5
  13. package/node_modules/@vellumai/environments/src/index.ts +17 -6
  14. package/node_modules/@vellumai/environments/src/install-layout.ts +49 -0
  15. package/node_modules/@vellumai/environments/src/seeds.ts +29 -0
  16. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +39 -0
  17. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
  18. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
  19. package/node_modules/@vellumai/gateway-client/src/index.ts +4 -0
  20. package/node_modules/@vellumai/gateway-client/src/verification-session-contract.ts +91 -6
  21. package/node_modules/@vellumai/ipc-server-utils/src/endpoint.test.ts +36 -0
  22. package/node_modules/@vellumai/ipc-server-utils/src/endpoint.ts +142 -0
  23. package/node_modules/@vellumai/ipc-server-utils/src/index.ts +2 -0
  24. package/node_modules/@vellumai/ipc-server-utils/src/listen-options.ts +3 -0
  25. package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.test.ts +15 -1
  26. package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.ts +17 -2
  27. package/node_modules/@vellumai/service-contracts/src/channels.ts +39 -0
  28. package/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
  29. package/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
  30. package/node_modules/@vellumai/slack-text/src/index.ts +16 -2
  31. package/openapi.yaml +589 -30
  32. package/package.json +1 -1
  33. package/src/__tests__/agent-image-optimize.test.ts +4 -4
  34. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +113 -66
  35. package/src/__tests__/agent-loop-override-profile.test.ts +38 -48
  36. package/src/__tests__/agent-loop-subagent-billing-headers.test.ts +166 -0
  37. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +1 -0
  38. package/src/__tests__/agent-wake-override-profile.test.ts +1 -0
  39. package/src/__tests__/answered-question-persistence.test.ts +240 -0
  40. package/src/__tests__/anthropic-provider.test.ts +165 -30
  41. package/src/__tests__/app-control-flow.test.ts +9 -8
  42. package/src/__tests__/assistant-event-hub.test.ts +48 -0
  43. package/src/__tests__/attachments-store-heic-normalize.test.ts +16 -12
  44. package/src/__tests__/attachments-store.test.ts +130 -68
  45. package/src/__tests__/attachments.test.ts +36 -36
  46. package/src/__tests__/background-workers-disk-pressure.test.ts +1 -1
  47. package/src/__tests__/call-start-guardian-guard.test.ts +18 -4
  48. package/src/__tests__/canned-reply-release.test.ts +86 -0
  49. package/src/__tests__/channel-guardian.test.ts +59 -29
  50. package/src/__tests__/channel-readiness-telegram-remote.test.ts +154 -0
  51. package/src/__tests__/channel-setup-panel-ack.test.ts +6 -5
  52. package/src/__tests__/client-os-metadata-persistence.test.ts +103 -4
  53. package/src/__tests__/compactor-image-manifest-trust.test.ts +1 -1
  54. package/src/__tests__/consult-deadline.test.ts +65 -0
  55. package/src/__tests__/conversation-agent-loop.test.ts +438 -2
  56. package/src/__tests__/conversation-disk-view-integration.test.ts +5 -1
  57. package/src/__tests__/conversation-disk-view.test.ts +4 -4
  58. package/src/__tests__/conversation-error.test.ts +22 -3
  59. package/src/__tests__/conversation-fork-crud.test.ts +5 -1
  60. package/src/__tests__/conversation-fork-referential.test.ts +352 -0
  61. package/src/__tests__/conversation-fork-retrospective.test.ts +5 -1
  62. package/src/__tests__/conversation-group-tools.test.ts +32 -2
  63. package/src/__tests__/conversation-inference-profile-route.test.ts +27 -1
  64. package/src/__tests__/conversation-initial-prompt.test.ts +51 -22
  65. package/src/__tests__/conversation-key-store-bootstrap-cleanup.test.ts +119 -0
  66. package/src/__tests__/conversation-key-store-origin.test.ts +105 -0
  67. package/src/__tests__/conversation-list-recency-ordering.test.ts +104 -0
  68. package/src/__tests__/conversation-origin-at-creation.test.ts +153 -0
  69. package/src/__tests__/conversation-origin-channel-filter.test.ts +95 -0
  70. package/src/__tests__/conversation-placement-promotion.test.ts +172 -0
  71. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +123 -0
  72. package/src/__tests__/conversation-queue.test.ts +433 -1
  73. package/src/__tests__/conversation-retry-route.test.ts +3 -1
  74. package/src/__tests__/conversation-routes-hidden-queue.test.ts +64 -1
  75. package/src/__tests__/conversation-store-ephemeral.test.ts +4 -0
  76. package/src/__tests__/conversation-store.test.ts +26 -10
  77. package/src/__tests__/conversation-summarize-route.test.ts +1 -1
  78. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +15 -6
  79. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +6 -5
  80. package/src/__tests__/conversation-surfaces-app-control.test.ts +12 -11
  81. package/src/__tests__/conversation-surfaces-app-open.test.ts +11 -5
  82. package/src/__tests__/conversation-surfaces-data-persist.test.ts +5 -4
  83. package/src/__tests__/conversation-surfaces-history-restored-completion.test.ts +967 -0
  84. package/src/__tests__/conversation-surfaces-persisted-info.test.ts +312 -0
  85. package/src/__tests__/conversation-surfaces-queued-emit.test.ts +6 -5
  86. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -8
  87. package/src/__tests__/conversation-surfaces-standalone.test.ts +21 -11
  88. package/src/__tests__/conversation-surfaces-state-update.test.ts +7 -11
  89. package/src/__tests__/conversation-surfaces-table-action.test.ts +7 -6
  90. package/src/__tests__/conversation-surfaces-task-progress.test.ts +11 -6
  91. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +9 -6
  92. package/src/__tests__/conversation-tool-setup-attribution.test.ts +70 -7
  93. package/src/__tests__/conversation-wait-for-idle.test.ts +6 -11
  94. package/src/__tests__/credential-prompt-route.test.ts +57 -7
  95. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  96. package/src/__tests__/cu-unified-flow.test.ts +89 -28
  97. package/src/__tests__/custom-group-listing-visibility.test.ts +1 -1
  98. package/src/__tests__/db-schedule-syntax-migration.test.ts +4 -1
  99. package/src/__tests__/discord-access-request-privacy.test.ts +366 -0
  100. package/src/__tests__/discord-requester-notice-privacy.test.ts +87 -0
  101. package/src/__tests__/disk-pressure-guard.test.ts +55 -55
  102. package/src/__tests__/disk-pressure-routes.test.ts +10 -10
  103. package/src/__tests__/disk-pressure-tools.test.ts +2 -2
  104. package/src/__tests__/disk-usage.test.ts +35 -20
  105. package/src/__tests__/document-sync-tags.test.ts +379 -0
  106. package/src/__tests__/document-update-default-surface.test.ts +28 -0
  107. package/src/__tests__/dynamic-skill-background-guard.test.ts +2 -2
  108. package/src/__tests__/emit-signal-routing-intent.test.ts +3 -4
  109. package/src/__tests__/ensure-conversation-exists.test.ts +8 -5
  110. package/src/__tests__/events-dev-bypass-actor.test.ts +183 -1
  111. package/src/__tests__/evict-conversations-for-reload.test.ts +90 -0
  112. package/src/__tests__/file-list-tool.test.ts +12 -10
  113. package/src/__tests__/file-ops-service.test.ts +151 -44
  114. package/src/__tests__/file-read-container-boundary.test.ts +137 -0
  115. package/src/__tests__/file-read-tool.test.ts +21 -9
  116. package/src/__tests__/file-url-path-guard.test.ts +83 -0
  117. package/src/__tests__/filesystem-tools.test.ts +82 -66
  118. package/src/__tests__/guardian-outbound-http.test.ts +8 -8
  119. package/src/__tests__/helpers/gateway-verification-sessions-stub.ts +14 -1
  120. package/src/__tests__/helpers/hub-clients.ts +42 -0
  121. package/src/__tests__/helpers/mock-conversation.ts +46 -0
  122. package/src/__tests__/helpers/verification-sessions-ipc-sim.ts +61 -57
  123. package/src/__tests__/history-repair.test.ts +112 -12
  124. package/src/__tests__/host-bash-proxy.test.ts +10 -5
  125. package/src/__tests__/host-bash-routes.test.ts +67 -0
  126. package/src/__tests__/host-browser-proxy.test.ts +2 -2
  127. package/src/__tests__/host-cu-proxy.test.ts +3 -7
  128. package/src/__tests__/host-file-proxy.test.ts +3 -7
  129. package/src/__tests__/host-file-read-tool.test.ts +5 -1
  130. package/src/__tests__/host-transfer-proxy-targeted.test.ts +6 -4
  131. package/src/__tests__/http-conversation-lineage.test.ts +2 -5
  132. package/src/__tests__/http-user-message-parity.test.ts +44 -0
  133. package/src/__tests__/identity-routes.test.ts +13 -13
  134. package/src/__tests__/image-conversion.test.ts +29 -26
  135. package/src/__tests__/image-source-path-reinject.test.ts +2 -2
  136. package/src/__tests__/inference-profile-session-handler.test.ts +95 -0
  137. package/src/__tests__/inference-profile-session-ipc.test.ts +25 -0
  138. package/src/__tests__/introduction-card-resolver.test.ts +6 -1
  139. package/src/__tests__/list-messages-attachments.test.ts +56 -32
  140. package/src/__tests__/list-messages-background-tool-completion.test.ts +4 -4
  141. package/src/__tests__/list-messages-client-message-id.test.ts +2 -2
  142. package/src/__tests__/list-messages-hidden-metadata.test.ts +16 -16
  143. package/src/__tests__/list-messages-page-latest.test.ts +61 -61
  144. package/src/__tests__/list-messages-provider-error.test.ts +6 -6
  145. package/src/__tests__/list-messages-queued.test.ts +49 -6
  146. package/src/__tests__/list-messages-system-card.test.ts +4 -4
  147. package/src/__tests__/list-messages-tool-merge.test.ts +9 -9
  148. package/src/__tests__/llm-resolver-override-or-default.test.ts +141 -0
  149. package/src/__tests__/llm-usage-store.test.ts +55 -0
  150. package/src/__tests__/manual-token-reconciliation.test.ts +45 -0
  151. package/src/__tests__/mcp-tool-annotations-risk.test.ts +133 -0
  152. package/src/__tests__/media-stream-server-integration.test.ts +36 -0
  153. package/src/__tests__/migration-export-http.test.ts +1 -1
  154. package/src/__tests__/migration-import-commit-http.test.ts +1 -1
  155. package/src/__tests__/migration-import-preflight-http.test.ts +1 -1
  156. package/src/__tests__/migration-validate-http.test.ts +1 -1
  157. package/src/__tests__/mtime-cache.test.ts +65 -3
  158. package/src/__tests__/notification-platform-adapter.test.ts +104 -0
  159. package/src/__tests__/notification-schedule-notify-dedup.test.ts +1 -1
  160. package/src/__tests__/oauth-provider-profiles.test.ts +4 -2
  161. package/src/__tests__/oauth-provider-seed-logos.test.ts +65 -0
  162. package/src/__tests__/oauth-provider-serializer.test.ts +17 -0
  163. package/src/__tests__/oauth-providers-routes.test.ts +1 -0
  164. package/src/__tests__/openai-responses-prompt-cache.test.ts +5 -2
  165. package/src/__tests__/path-policy.test.ts +164 -1
  166. package/src/__tests__/persist-media-references.test.ts +2 -2
  167. package/src/__tests__/persist-unsendable-image-downscale.test.ts +5 -5
  168. package/src/__tests__/persist-unsendable-image.test.ts +23 -23
  169. package/src/__tests__/persona-resolver.test.ts +154 -0
  170. package/src/__tests__/plugin-api-webhook-url.test.ts +170 -0
  171. package/src/__tests__/plugin-import-boundary-guard.test.ts +6 -0
  172. package/src/__tests__/processing-flag-persist-failure.test.ts +15 -10
  173. package/src/__tests__/profile-availability-incomplete.test.ts +113 -0
  174. package/src/__tests__/profiler-routes.test.ts +13 -13
  175. package/src/__tests__/prompt-cache-cross-turn-stability.test.ts +593 -0
  176. package/src/__tests__/proxy-approval-callback.test.ts +3 -3
  177. package/src/__tests__/queued-message-cancel-and-steer.test.ts +189 -0
  178. package/src/__tests__/queued-message-steer-actor-scoping.test.ts +164 -0
  179. package/src/__tests__/resolve-trust-class.test.ts +20 -0
  180. package/src/__tests__/run-conversation-turn-persistence.test.ts +1 -1
  181. package/src/__tests__/run-due-schedules.test.ts +174 -0
  182. package/src/__tests__/runtime-attachment-metadata.test.ts +15 -7
  183. package/src/__tests__/scaffold-managed-skill-tool.test.ts +166 -0
  184. package/src/__tests__/schedule-routes.test.ts +730 -8
  185. package/src/__tests__/schedule-store.test.ts +540 -0
  186. package/src/__tests__/schedule-tools.test.ts +103 -0
  187. package/src/__tests__/scheduler-wake.test.ts +5 -0
  188. package/src/__tests__/secret-routes-platform-proxy.test.ts +29 -1
  189. package/src/__tests__/secure-keys.test.ts +91 -0
  190. package/src/__tests__/server-history-render.test.ts +97 -7
  191. package/src/__tests__/size-guard.test.ts +8 -8
  192. package/src/__tests__/skill-docs-sync-guard.test.ts +3 -2
  193. package/src/__tests__/skill-tool-factory.test.ts +247 -0
  194. package/src/__tests__/skills-install-staging.test.ts +15 -6
  195. package/src/__tests__/slack-edit-ordering-characterization.test.ts +103 -0
  196. package/src/__tests__/slack-inbound-verification.test.ts +4 -1
  197. package/src/__tests__/slack-mention-binding-invariance.test.ts +103 -0
  198. package/src/__tests__/slack-mention-provider-leak-audit.test.ts +135 -0
  199. package/src/__tests__/starter-task-flow.test.ts +5 -4
  200. package/src/__tests__/steer-on-enqueue-question.test.ts +3 -2
  201. package/src/__tests__/stt-language-catalog-parity.test.ts +38 -0
  202. package/src/__tests__/subagent-allowlist-validation.test.ts +26 -4
  203. package/src/__tests__/subagent-cron-run-attribution.test.ts +301 -0
  204. package/src/__tests__/subagent-disposal.test.ts +10 -0
  205. package/src/__tests__/subagent-fork-notifications.test.ts +10 -0
  206. package/src/__tests__/subagent-fork-prompt-role.test.ts +85 -11
  207. package/src/__tests__/subagent-fork-spawn.test.ts +15 -7
  208. package/src/__tests__/subagent-manager-notify.test.ts +148 -0
  209. package/src/__tests__/subagent-notify-parent.test.ts +1 -1
  210. package/src/__tests__/subagent-persistence.test.ts +141 -0
  211. package/src/__tests__/subagent-role-registry.test.ts +172 -63
  212. package/src/__tests__/subagent-role-resolution.test.ts +88 -0
  213. package/src/__tests__/subagent-spawn-and-await.test.ts +48 -0
  214. package/src/__tests__/subagent-spawn-tool-fork.test.ts +111 -10
  215. package/src/__tests__/subagent-terminal-message.test.ts +88 -1
  216. package/src/__tests__/subagent-tool-gate-mode.test.ts +225 -10
  217. package/src/__tests__/subagent-tools.test.ts +1901 -108
  218. package/src/__tests__/surface-completion-compaction-boundary.test.ts +124 -0
  219. package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +298 -0
  220. package/src/__tests__/system-prompt.test.ts +82 -7
  221. package/src/__tests__/tool-grant-request-escalation.test.ts +40 -1
  222. package/src/__tests__/tool-result-spool.test.ts +74 -18
  223. package/src/__tests__/tool-side-effects-documents.test.ts +174 -0
  224. package/src/__tests__/tool-side-effects-hook-failures.test.ts +129 -0
  225. package/src/__tests__/tools-audio-read.test.ts +10 -10
  226. package/src/__tests__/tools-get-route.test.ts +85 -12
  227. package/src/__tests__/tools-list-cli.test.ts +171 -0
  228. package/src/__tests__/top-level-renderer.test.ts +54 -1
  229. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +68 -1
  230. package/src/__tests__/trusted-contact-multichannel.test.ts +4 -1
  231. package/src/__tests__/turn-tail-chain.test.ts +135 -0
  232. package/src/__tests__/ui-choice-copy-surfaces.test.ts +6 -4
  233. package/src/__tests__/ui-visual-surface.test.ts +5 -4
  234. package/src/__tests__/ui-work-result-surface.test.ts +5 -4
  235. package/src/__tests__/unified-turn-context-visible-app.test.ts +7 -8
  236. package/src/__tests__/usage-routes.test.ts +62 -0
  237. package/src/__tests__/verification-outbound-delivery.test.ts +176 -0
  238. package/src/__tests__/visible-app-context.test.ts +20 -4
  239. package/src/__tests__/web-search-history.test.ts +96 -0
  240. package/src/__tests__/workspace-migration-139-clear-renamed-cost-profile-label.test.ts +6 -6
  241. package/src/__tests__/workspace-migration-140-repair-seed-pinned-memory-v3-live.test.ts +330 -0
  242. package/src/acp/failure-error.ts +3 -5
  243. package/src/agent/attachments.ts +26 -24
  244. package/src/agent/history-repair/history-repair.ts +27 -26
  245. package/src/agent/image-optimize.ts +6 -6
  246. package/src/agent/loop.ts +40 -22
  247. package/src/agent/message-types.ts +3 -3
  248. package/src/api/constants/document-tools.ts +55 -0
  249. package/src/api/events/question-answered.ts +53 -0
  250. package/src/api/events/tool-result.ts +7 -0
  251. package/src/api/index.ts +13 -0
  252. package/src/api/responses/conversation-message.ts +11 -0
  253. package/src/api/surfaces-oauth-connect.test.ts +96 -0
  254. package/src/api/surfaces.ts +36 -8
  255. package/src/approvals/guardian-channel-delivery.ts +83 -0
  256. package/src/approvals/guardian-expiry-notifier.ts +13 -11
  257. package/src/approvals/guardian-request-resolvers.ts +222 -135
  258. package/src/calls/__tests__/voice-session-bridge.test.ts +50 -0
  259. package/src/calls/media-stream-server.ts +9 -1
  260. package/src/calls/voice-session-bridge.ts +38 -0
  261. package/src/channels/__tests__/gateway-verification-sessions.test.ts +3 -3
  262. package/src/channels/config.ts +7 -2
  263. package/src/channels/gateway-verification-sessions.ts +7 -2
  264. package/src/channels/types.ts +7 -1
  265. package/src/cli/commands/__tests__/cache.test.ts +7 -4
  266. package/src/cli/commands/__tests__/cli-test-harness.ts +82 -0
  267. package/src/cli/commands/__tests__/conversations-wake.test.ts +51 -6
  268. package/src/cli/commands/__tests__/inference-models.test.ts +14 -0
  269. package/src/cli/commands/__tests__/inference-profiles.test.ts +44 -1
  270. package/src/cli/commands/__tests__/inference-providers.test.ts +7 -0
  271. package/src/cli/commands/__tests__/plugins.test.ts +692 -0
  272. package/src/cli/commands/__tests__/schedules.test.ts +136 -37
  273. package/src/cli/commands/conversations.ts +7 -3
  274. package/src/cli/commands/credentials.help.ts +7 -0
  275. package/src/cli/commands/inference-profiles.ts +9 -3
  276. package/src/cli/commands/inference.help.ts +16 -2
  277. package/src/cli/commands/mcp.help.ts +4 -2
  278. package/src/cli/commands/memory/memory-retrospective.ts +18 -0
  279. package/src/cli/commands/notifications.ts +3 -6
  280. package/src/cli/commands/oauth/connect-surface-guidance.test.ts +16 -0
  281. package/src/cli/commands/oauth/connect-surface-guidance.ts +25 -7
  282. package/src/cli/commands/oauth/connect.test.ts +26 -1
  283. package/src/cli/commands/oauth/connect.ts +4 -1
  284. package/src/cli/commands/oauth/index.help.ts +3 -1
  285. package/src/cli/commands/oauth/providers.ts +3 -0
  286. package/src/cli/commands/plugins.help.ts +25 -2
  287. package/src/cli/commands/plugins.ts +289 -10
  288. package/src/cli/commands/schedules.help.ts +14 -12
  289. package/src/cli/commands/schedules.ts +19 -5
  290. package/src/cli/commands/tools.help.ts +4 -2
  291. package/src/cli/commands/tools.ts +38 -0
  292. package/src/cli/lib/__tests__/inspect-plugin.test.ts +1 -0
  293. package/src/cli/lib/__tests__/install-from-github.test.ts +79 -0
  294. package/src/cli/lib/__tests__/install-from-platform.test.ts +47 -1
  295. package/src/cli/lib/__tests__/plugin-surfaces.test.ts +86 -7
  296. package/src/cli/lib/__tests__/upgrade-plugin.test.ts +122 -0
  297. package/src/cli/lib/install-from-github.ts +61 -0
  298. package/src/cli/lib/install-from-platform.ts +13 -2
  299. package/src/cli/lib/plugin-surfaces.ts +124 -4
  300. package/src/cli/lib/upgrade-plugin.ts +18 -0
  301. package/src/cli.ts +1 -1
  302. package/src/config/__tests__/deployment-context-defaults.test.ts +73 -0
  303. package/src/config/__tests__/memory-retrospective-schema.test.ts +40 -0
  304. package/src/config/__tests__/plugin-updates-schema.test.ts +43 -0
  305. package/src/config/__tests__/profile-tool-support.test.ts +131 -0
  306. package/src/config/bundled-skills/AGENTS.md +1 -1
  307. package/src/config/bundled-skills/app-builder/SKILL.md +1 -1
  308. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +3 -3
  309. package/src/config/bundled-skills/schedule/SKILL.md +5 -1
  310. package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
  311. package/src/config/bundled-skills/settings/TOOLS.json +2 -2
  312. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +1 -0
  313. package/src/config/bundled-skills/subagent/SKILL.md +53 -22
  314. package/src/config/bundled-skills/subagent/TOOLS.json +14 -13
  315. package/src/config/bundled-skills/visualize/SKILL.md +1 -1
  316. package/src/config/default-profile-catalog.ts +6 -2
  317. package/src/config/feature-flag-registry.json +25 -17
  318. package/src/config/llm-resolver.ts +45 -15
  319. package/src/config/loader.ts +70 -1
  320. package/src/config/profile-tool-support.ts +110 -0
  321. package/src/config/sanitize-for-transfer.ts +11 -0
  322. package/src/config/schema.ts +4 -0
  323. package/src/config/schemas/__tests__/stt.test.ts +20 -5
  324. package/src/config/schemas/channels.ts +13 -0
  325. package/src/config/schemas/memory-retrospective.ts +25 -0
  326. package/src/config/schemas/plugin-updates.ts +55 -0
  327. package/src/config/schemas/services.ts +8 -4
  328. package/src/config/schemas/stt.ts +17 -5
  329. package/src/config/schemas/timeouts.ts +1 -1
  330. package/src/contacts/__tests__/guardian-delivery-reader.test.ts +16 -0
  331. package/src/contacts/guardian-delivery-reader.ts +29 -2
  332. package/src/context/compactor.ts +4 -4
  333. package/src/context/post-turn-tool-result-truncation.ts +32 -16
  334. package/src/context/strip-injections.ts +42 -0
  335. package/src/context/tool-result-spool.ts +32 -18
  336. package/src/credential-execution/ces-runtime.ts +3 -0
  337. package/src/credential-execution/client.ts +22 -1
  338. package/src/credential-execution/process-manager.test.ts +99 -0
  339. package/src/credential-execution/process-manager.ts +62 -16
  340. package/src/daemon/__tests__/abort-null-controller.test.ts +141 -5
  341. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +8 -12
  342. package/src/daemon/__tests__/install-assistant-command.test.ts +234 -0
  343. package/src/daemon/__tests__/turn-tail-assistant-reply-notify.test.ts +2 -4
  344. package/src/daemon/__tests__/turn-tail-deleted-conversation.test.ts +20 -29
  345. package/src/daemon/channel-ui-capability.ts +4 -4
  346. package/src/daemon/conversation-agent-loop-handlers.ts +117 -61
  347. package/src/daemon/conversation-agent-loop.ts +318 -148
  348. package/src/daemon/conversation-attachments.ts +1 -1
  349. package/src/daemon/conversation-error.ts +8 -1
  350. package/src/daemon/conversation-initial-prompt.ts +16 -38
  351. package/src/daemon/conversation-lifecycle.ts +154 -32
  352. package/src/daemon/conversation-messaging.ts +106 -43
  353. package/src/daemon/conversation-process.ts +131 -33
  354. package/src/daemon/conversation-queue-manager.ts +10 -0
  355. package/src/daemon/conversation-runtime-assembly.ts +9 -4
  356. package/src/daemon/conversation-store.ts +52 -3
  357. package/src/daemon/conversation-surface-state.ts +9 -0
  358. package/src/daemon/conversation-surfaces.ts +403 -210
  359. package/src/daemon/conversation-tool-setup.ts +56 -7
  360. package/src/daemon/conversation-turn-finalize.ts +134 -89
  361. package/src/daemon/conversation.ts +111 -27
  362. package/src/daemon/disk-pressure-guard-lifecycle.ts +2 -2
  363. package/src/daemon/disk-pressure-guard.ts +3 -3
  364. package/src/daemon/doordash-steps.ts +5 -5
  365. package/src/daemon/external-plugins-bootstrap.ts +7 -1
  366. package/src/daemon/handlers/config-channels.ts +48 -5
  367. package/src/daemon/handlers/conversation-history.ts +1 -1
  368. package/src/daemon/handlers/conversations.ts +62 -17
  369. package/src/daemon/handlers/shared.ts +12 -0
  370. package/src/daemon/handlers/skills.ts +11 -1
  371. package/src/daemon/identity-helpers.ts +38 -10
  372. package/src/daemon/install-assistant-command.ts +322 -0
  373. package/src/daemon/lifecycle.ts +14 -3
  374. package/src/daemon/message-types/conversations.ts +6 -7
  375. package/src/daemon/message-types/sync.ts +1 -0
  376. package/src/daemon/persist-media-references.ts +23 -14
  377. package/src/daemon/process-message.ts +6 -6
  378. package/src/daemon/tool-setup-types.ts +19 -122
  379. package/src/daemon/tool-side-effects.ts +17 -94
  380. package/src/daemon/trust-context-types.ts +39 -0
  381. package/src/daemon/trust-context.ts +14 -6
  382. package/src/daemon/turn-tail-chain.ts +73 -0
  383. package/src/daemon/web-search-history.ts +47 -33
  384. package/src/heartbeat/heartbeat-service.ts +6 -6
  385. package/src/ipc/__tests__/socket-path.test.ts +21 -0
  386. package/src/ipc/assistant-server.ts +17 -10
  387. package/src/ipc/cli-client.ts +10 -1
  388. package/src/ipc/routes/__tests__/documents-sync-ipc-routes.test.ts +56 -0
  389. package/src/ipc/routes/documents-sync-ipc-routes.ts +42 -0
  390. package/src/ipc/socket-cleanup.ts +9 -7
  391. package/src/ipc/socket-path.ts +4 -96
  392. package/src/live-voice/__tests__/live-voice-archive.test.ts +16 -16
  393. package/src/live-voice/__tests__/live-voice-attach-image.test.ts +209 -0
  394. package/src/live-voice/__tests__/live-voice-connection.test.ts +20 -0
  395. package/src/live-voice/__tests__/live-voice-integration.test.ts +7 -5
  396. package/src/live-voice/__tests__/live-voice-session-telemetry.test.ts +265 -0
  397. package/src/live-voice/__tests__/live-voice-stt.test.ts +6 -1
  398. package/src/live-voice/__tests__/live-voice-vad.test.ts +35 -15
  399. package/src/live-voice/__tests__/protocol.test.ts +52 -0
  400. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +3 -0
  401. package/src/live-voice/live-voice-archive.ts +13 -13
  402. package/src/live-voice/live-voice-connection.ts +7 -1
  403. package/src/live-voice/live-voice-photo.ts +169 -0
  404. package/src/live-voice/live-voice-session.ts +108 -4
  405. package/src/live-voice/protocol.ts +89 -1
  406. package/src/mcp/client.ts +10 -0
  407. package/src/messaging/providers/__tests__/callback-routing.test.ts +5 -1
  408. package/src/messaging/providers/__tests__/transport-dispatch.test.ts +66 -4
  409. package/src/messaging/providers/callback-routing.ts +1 -0
  410. package/src/messaging/providers/discord/api.ts +312 -0
  411. package/src/messaging/providers/discord/dm-delivery.test.ts +204 -0
  412. package/src/messaging/providers/discord/render.test.ts +204 -0
  413. package/src/messaging/providers/discord/render.ts +195 -0
  414. package/src/messaging/providers/discord/send.test.ts +179 -0
  415. package/src/messaging/providers/discord/send.ts +212 -0
  416. package/src/messaging/providers/discord/transport.ts +81 -0
  417. package/src/messaging/providers/index.ts +3 -1
  418. package/src/messaging/providers/retry-policy.test.ts +247 -0
  419. package/src/messaging/providers/retry-policy.ts +206 -0
  420. package/src/messaging/providers/slack/mention-source.test.ts +285 -0
  421. package/src/messaging/providers/slack/mention-source.ts +287 -0
  422. package/src/messaging/providers/telegram-bot/api.ts +47 -130
  423. package/src/messaging/providers/whatsapp/api.ts +47 -136
  424. package/src/monitoring/__tests__/db-integrity-sample.test.ts +4 -1
  425. package/src/monitoring/__tests__/plugin-auto-update.test.ts +332 -0
  426. package/src/monitoring/db-integrity-sample.ts +6 -1
  427. package/src/monitoring/plugin-auto-update.ts +359 -0
  428. package/src/monitoring/resource-sampler.ts +21 -5
  429. package/src/monitoring/worker.ts +13 -0
  430. package/src/notifications/__tests__/assistant-reply-producer.test.ts +375 -2
  431. package/src/notifications/__tests__/broadcaster.test.ts +37 -1
  432. package/src/notifications/__tests__/copy-composer.test.ts +165 -0
  433. package/src/notifications/__tests__/emit-signal-pipeline-failure.test.ts +205 -0
  434. package/src/notifications/__tests__/notification-utils.test.ts +249 -0
  435. package/src/notifications/adapters/platform.ts +31 -2
  436. package/src/notifications/assistant-reply-producer.ts +79 -32
  437. package/src/notifications/broadcaster.ts +30 -10
  438. package/src/notifications/copy-composer.ts +69 -0
  439. package/src/notifications/emit-signal.ts +82 -15
  440. package/src/notifications/events-store.ts +10 -2
  441. package/src/notifications/home-feed-side-effect.ts +6 -3
  442. package/src/notifications/notification-utils.ts +173 -5
  443. package/src/notifications/signal.ts +12 -0
  444. package/src/oauth/AGENTS.md +4 -2
  445. package/src/oauth/byo-connection.ts +6 -1
  446. package/src/oauth/credential-token-resolver.ts +3 -10
  447. package/src/oauth/manual-token-connection.ts +29 -64
  448. package/src/oauth/manual-token-providers.ts +62 -0
  449. package/src/oauth/provider-serializer.ts +13 -0
  450. package/src/oauth/seed-providers.ts +62 -11
  451. package/src/onboarding/onboarding-events-store.ts +91 -1
  452. package/src/permissions/question-prompter.test.ts +4 -0
  453. package/src/permissions/question-prompter.ts +21 -4
  454. package/src/persistence/__tests__/conversation-lineage.test.ts +248 -0
  455. package/src/persistence/attachments-store.ts +15 -15
  456. package/src/persistence/conversation-attention-store.ts +30 -10
  457. package/src/persistence/conversation-bootstrap.ts +17 -0
  458. package/src/persistence/conversation-crud.ts +363 -97
  459. package/src/persistence/conversation-group-migration.ts +1 -1
  460. package/src/persistence/conversation-key-store.ts +38 -10
  461. package/src/persistence/conversation-lineage.ts +226 -0
  462. package/src/persistence/conversation-plugin-facade.ts +28 -3
  463. package/src/persistence/conversation-queries.ts +207 -33
  464. package/src/persistence/conversation-types.ts +107 -1
  465. package/src/persistence/jobs-store.ts +32 -8
  466. package/src/persistence/llm-usage-store.ts +22 -0
  467. package/src/persistence/migrations/361-normalize-managed-connection-rows.test.ts +168 -0
  468. package/src/persistence/migrations/361-normalize-managed-connection-rows.ts +76 -0
  469. package/src/persistence/migrations/362-add-conversation-subagent-kind.test.ts +187 -0
  470. package/src/persistence/migrations/362-add-conversation-subagent-kind.ts +93 -0
  471. package/src/persistence/migrations/363-backfill-schedule-inference-profile.test.ts +229 -0
  472. package/src/persistence/migrations/363-backfill-schedule-inference-profile.ts +127 -0
  473. package/src/persistence/migrations/364-add-schedule-source-key.test.ts +120 -0
  474. package/src/persistence/migrations/364-add-schedule-source-key.ts +43 -0
  475. package/src/persistence/migrations/365-add-conversation-fork-strategy.ts +27 -0
  476. package/src/persistence/schema/conversations.ts +32 -0
  477. package/src/persistence/schema/infrastructure.ts +3 -0
  478. package/src/persistence/steps.ts +30 -0
  479. package/src/persistence/subagent-store.ts +148 -6
  480. package/src/platform/managed-speech.test.ts +20 -0
  481. package/src/platform/managed-speech.ts +9 -0
  482. package/src/plugin-api/index.ts +8 -0
  483. package/src/plugin-api/webhook-url.ts +151 -0
  484. package/src/plugins/__tests__/installed-plugin-dirs.test.ts +82 -0
  485. package/src/plugins/__tests__/source-fingerprint.test.ts +5 -1
  486. package/src/plugins/collect-source-versions.ts +4 -27
  487. package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +5 -5
  488. package/src/plugins/defaults/exploration-drift/package.json +1 -1
  489. package/src/plugins/defaults/image-recovery/hooks/post-model-call.ts +4 -2
  490. package/src/plugins/defaults/image-recovery/recover.ts +67 -57
  491. package/src/plugins/defaults/index.ts +1 -1
  492. package/src/plugins/defaults/memory/__tests__/conversation-queries.test.ts +64 -18
  493. package/src/plugins/defaults/memory/__tests__/jobs-worker-outcome-contract.test.ts +242 -0
  494. package/src/plugins/defaults/memory/__tests__/jobs-worker-retrospective-sweep.test.ts +24 -1
  495. package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +48 -3
  496. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +511 -19
  497. package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +39 -3
  498. package/src/plugins/defaults/memory/__tests__/memory-retrospective-provider-path.test.ts +493 -0
  499. package/src/plugins/defaults/memory/__tests__/memory-retrospective-wake-chain.test.ts +5 -4
  500. package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +5 -1
  501. package/src/plugins/defaults/memory/job-handlers.ts +87 -5
  502. package/src/plugins/defaults/memory/jobs-worker.ts +60 -6
  503. package/src/plugins/defaults/memory/memory-retrospective-constants.ts +11 -0
  504. package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +29 -0
  505. package/src/plugins/defaults/memory/memory-retrospective-job.ts +342 -60
  506. package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +23 -3
  507. package/src/plugins/defaults/memory/substrate/consolidation-lock.ts +9 -4
  508. package/src/plugins/defaults/memory/substrate/sweep-job.ts +7 -0
  509. package/src/plugins/defaults/memory/v1/graph/injection.ts +1 -1
  510. package/src/plugins/defaults/memory/v2/router.ts +8 -0
  511. package/src/plugins/defaults/turn-context/unified-turn-context.ts +1 -2
  512. package/src/plugins/external-plugin-loader.ts +17 -8
  513. package/src/plugins/installed-plugin-dirs.ts +101 -0
  514. package/src/plugins/mtime-cache.ts +34 -22
  515. package/src/plugins/types.ts +69 -8
  516. package/src/prompts/persona-resolver.ts +6 -2
  517. package/src/prompts/system-prompt.ts +72 -17
  518. package/src/providers/__tests__/inference.test.ts +40 -0
  519. package/src/providers/__tests__/preflight-resolved-config.test.ts +58 -1
  520. package/src/providers/__tests__/retry-callsite.test.ts +67 -0
  521. package/src/providers/__tests__/vellum-connection-routing.test.ts +42 -11
  522. package/src/providers/anthropic/client.ts +112 -95
  523. package/src/providers/connection-resolution.ts +35 -1
  524. package/src/providers/gemini/client.ts +5 -5
  525. package/src/providers/inference/adapter-factory.ts +16 -10
  526. package/src/providers/inference/auth.ts +16 -0
  527. package/src/providers/inference/connection-availability.ts +164 -12
  528. package/src/providers/inference/connections.ts +25 -1
  529. package/src/providers/media-resolve.ts +21 -11
  530. package/src/providers/model-catalog.ts +15 -0
  531. package/src/providers/openai/chat-completions-provider.ts +4 -4
  532. package/src/providers/openai/responses-provider.ts +12 -25
  533. package/src/providers/registry.ts +9 -4
  534. package/src/providers/retry.ts +25 -0
  535. package/src/providers/server-tool-pairing.ts +134 -0
  536. package/src/providers/speech-to-text/__tests__/resolve.test.ts +187 -6
  537. package/src/providers/speech-to-text/deepgram.ts +1 -0
  538. package/src/providers/speech-to-text/resolve.ts +80 -10
  539. package/src/providers/speech-to-text/vellum-managed.ts +7 -1
  540. package/src/providers/speech-to-text/vellum-speech-relay-connection.ts +3 -1
  541. package/src/providers/types.ts +26 -6
  542. package/src/providers/vellum-model-routing.ts +6 -7
  543. package/src/runtime/AGENTS.md +2 -0
  544. package/src/runtime/__tests__/agent-wake.test.ts +16 -16
  545. package/src/runtime/__tests__/background-job-runner.test.ts +0 -144
  546. package/src/runtime/__tests__/desktop-presence.test.ts +162 -0
  547. package/src/runtime/agent-wake.ts +63 -24
  548. package/src/runtime/assistant-event-hub.ts +87 -12
  549. package/src/runtime/auth/__tests__/guard-tests.test.ts +2 -0
  550. package/src/runtime/auth/__tests__/scopes.test.ts +20 -0
  551. package/src/runtime/auth/same-actor.ts +56 -8
  552. package/src/runtime/auth/scopes.ts +12 -0
  553. package/src/runtime/auth/types.ts +2 -0
  554. package/src/runtime/background-job-runner.ts +5 -27
  555. package/src/runtime/channel-readiness-service.ts +59 -3
  556. package/src/runtime/channel-readiness-types.ts +18 -0
  557. package/src/runtime/desktop-presence.ts +69 -0
  558. package/src/runtime/http-server.ts +12 -0
  559. package/src/runtime/local-actor-identity.ts +11 -9
  560. package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -0
  561. package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
  562. package/src/runtime/routes/__tests__/client-routes.test.ts +186 -14
  563. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +547 -1
  564. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +162 -7
  565. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +14 -10
  566. package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +340 -3
  567. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +28 -1
  568. package/src/runtime/routes/__tests__/plugins-routes.test.ts +173 -1
  569. package/src/runtime/routes/__tests__/question-routes.test.ts +64 -0
  570. package/src/runtime/routes/__tests__/retrospective-routes.test.ts +20 -0
  571. package/src/runtime/routes/__tests__/skill-history-route.test.ts +116 -0
  572. package/src/runtime/routes/__tests__/wake-conversation-routes.test.ts +60 -2
  573. package/src/runtime/routes/archive-utils.ts +16 -12
  574. package/src/runtime/routes/attachment-routes.ts +13 -6
  575. package/src/runtime/routes/canned-reply-release.ts +54 -0
  576. package/src/runtime/routes/channel-verification-routes.ts +2 -27
  577. package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +5 -0
  578. package/src/runtime/routes/client-routes.ts +114 -2
  579. package/src/runtime/routes/conversation-cli-routes.ts +10 -12
  580. package/src/runtime/routes/conversation-list-routes.ts +59 -10
  581. package/src/runtime/routes/conversation-management-routes.ts +47 -18
  582. package/src/runtime/routes/conversation-query-routes.ts +32 -53
  583. package/src/runtime/routes/conversation-routes.ts +360 -293
  584. package/src/runtime/routes/credential-prompt-routes.ts +23 -2
  585. package/src/runtime/routes/debug-routes.ts +4 -1
  586. package/src/runtime/routes/default-provider-routes.ts +7 -11
  587. package/src/runtime/routes/documents-routes.ts +44 -1
  588. package/src/runtime/routes/events-routes.ts +28 -1
  589. package/src/runtime/routes/host-app-control-routes.ts +2 -0
  590. package/src/runtime/routes/host-bash-routes.ts +2 -0
  591. package/src/runtime/routes/host-browser-routes.ts +2 -0
  592. package/src/runtime/routes/host-cu-routes.ts +2 -0
  593. package/src/runtime/routes/host-file-routes.ts +2 -0
  594. package/src/runtime/routes/host-transfer-routes.ts +4 -0
  595. package/src/runtime/routes/identity-routes.ts +6 -6
  596. package/src/runtime/routes/inbound-message-handler.ts +5 -5
  597. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +7 -3
  598. package/src/runtime/routes/inbound-stages/background-dispatch.ts +14 -0
  599. package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +2 -2
  600. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +14 -11
  601. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +14 -17
  602. package/src/runtime/routes/inference-profile-availability-guard.ts +171 -0
  603. package/src/runtime/routes/inference-profile-session-handler.ts +26 -2
  604. package/src/runtime/routes/inference-profile-session-routes.ts +2 -1
  605. package/src/runtime/routes/inference-profiles-routes.ts +152 -73
  606. package/src/runtime/routes/inference-provider-connection-routes.ts +0 -16
  607. package/src/runtime/routes/llm-call-sites-routes.ts +13 -0
  608. package/src/runtime/routes/log-export-routes.ts +1 -1
  609. package/src/runtime/routes/notification-routes.ts +0 -14
  610. package/src/runtime/routes/oauth-providers.ts +1 -0
  611. package/src/runtime/routes/plugins-routes.ts +106 -1
  612. package/src/runtime/routes/profiler-routes.ts +4 -2
  613. package/src/runtime/routes/question-routes.ts +28 -10
  614. package/src/runtime/routes/retrospective-routes.ts +9 -3
  615. package/src/runtime/routes/schedule-routes.ts +210 -12
  616. package/src/runtime/routes/secret-routes.ts +40 -23
  617. package/src/runtime/routes/settings-routes.ts +41 -13
  618. package/src/runtime/routes/skills-routes.ts +79 -0
  619. package/src/runtime/routes/ui-snapshot-routes.ts +1 -0
  620. package/src/runtime/routes/wake-conversation-routes.ts +23 -0
  621. package/src/runtime/services/__tests__/conversation-serializer.test.ts +1 -0
  622. package/src/runtime/services/conversation-serializer.ts +24 -9
  623. package/src/runtime/sync/documents-sidecar-publish.test.ts +101 -0
  624. package/src/runtime/sync/resource-sync-events.ts +79 -1
  625. package/src/runtime/sync/worker-daemon-notify.test.ts +34 -0
  626. package/src/runtime/sync/worker-daemon-notify.ts +44 -6
  627. package/src/runtime/verification-outbound-actions.ts +250 -222
  628. package/src/runtime/verification-templates.ts +41 -30
  629. package/src/schedule/__tests__/plugin-schedule-declarations.test.ts +614 -0
  630. package/src/schedule/__tests__/plugin-schedule-reconciler.test.ts +1066 -0
  631. package/src/schedule/inference-profile.ts +64 -3
  632. package/src/schedule/plugin-schedule-declarations.ts +518 -0
  633. package/src/schedule/plugin-schedule-reconciler.ts +605 -0
  634. package/src/schedule/plugin-schedules-gate.ts +23 -0
  635. package/src/schedule/schedule-store.ts +520 -26
  636. package/src/schedule/scheduler.ts +38 -0
  637. package/src/security/credential-backend.ts +51 -4
  638. package/src/security/encrypted-store.ts +64 -42
  639. package/src/security/secure-keys.ts +55 -7
  640. package/src/skills/catalog-install.ts +20 -7
  641. package/src/skills/inline-command-runner.ts +2 -7
  642. package/src/skills/skill-history.test.ts +269 -0
  643. package/src/skills/skill-history.ts +250 -0
  644. package/src/skills/skillssh-registry.ts +1 -1
  645. package/src/stt/daemon-batch-transcriber.ts +8 -6
  646. package/src/subagent/__tests__/consult-prompt.test.ts +25 -0
  647. package/src/subagent/consult-prompt.ts +3 -1
  648. package/src/subagent/consult-transcript.ts +1 -1
  649. package/src/subagent/manager.ts +304 -44
  650. package/src/subagent/progress-events.ts +35 -0
  651. package/src/subagent/role-resolution.ts +88 -0
  652. package/src/subagent/types.ts +302 -67
  653. package/src/subagent/validate-allowlists.ts +3 -4
  654. package/src/telegram/__tests__/webhook-health.test.ts +73 -1
  655. package/src/telegram/webhook-health.ts +101 -3
  656. package/src/telemetry/__tests__/telemetry-event-fixtures.ts +2 -0
  657. package/src/telemetry/activation-funnel.ts +6 -1
  658. package/src/telemetry/live-voice-funnel.ts +75 -0
  659. package/src/telemetry/telemetry-event-sources.ts +6 -0
  660. package/src/telemetry/telemetry-wire-source.json +1 -1
  661. package/src/telemetry/telemetry-wire.generated.ts +2 -0
  662. package/src/telemetry/types.ts +23 -4
  663. package/src/telemetry/usage-telemetry-reporter.test.ts +4 -0
  664. package/src/tools/__tests__/subagent-workflow-tool-input-schemas.test.ts +1 -1
  665. package/src/tools/ask-question/ask-question-tool.test.ts +118 -3
  666. package/src/tools/ask-question/ask-question-tool.ts +56 -2
  667. package/src/tools/browser/browser-execution.ts +1 -1
  668. package/src/tools/calls/call-start.ts +8 -5
  669. package/src/tools/conversation-groups/move_to_group.ts +10 -12
  670. package/src/tools/document/document-tool.ts +11 -4
  671. package/src/tools/execution-timeout.ts +9 -2
  672. package/src/tools/executor.ts +7 -6
  673. package/src/tools/filesystem/edit.ts +1 -1
  674. package/src/tools/filesystem/list.ts +1 -1
  675. package/src/tools/filesystem/read.ts +7 -13
  676. package/src/tools/filesystem/search.ts +23 -21
  677. package/src/tools/filesystem/write.ts +4 -1
  678. package/src/tools/host-filesystem/edit.ts +7 -2
  679. package/src/tools/host-filesystem/read.ts +21 -8
  680. package/src/tools/host-filesystem/write.ts +10 -2
  681. package/src/tools/host-terminal/host-shell.ts +2 -2
  682. package/src/tools/mcp/mcp-tool-factory.ts +25 -1
  683. package/src/tools/permission-checker.ts +8 -3
  684. package/src/tools/schedule/delete.ts +13 -1
  685. package/src/tools/schedule/list.ts +14 -3
  686. package/src/tools/schedule/update.ts +56 -33
  687. package/src/tools/shared/filesystem/audio-read.ts +6 -4
  688. package/src/tools/shared/filesystem/file-ops-service.ts +176 -116
  689. package/src/tools/shared/filesystem/image-read.ts +12 -12
  690. package/src/tools/shared/filesystem/path-policy.ts +70 -5
  691. package/src/tools/shared/filesystem/size-guard.ts +6 -6
  692. package/src/tools/shared/input-misuse.ts +72 -0
  693. package/src/tools/skills/scaffold-managed.ts +82 -0
  694. package/src/tools/skills/skill-tool-factory.ts +14 -1
  695. package/src/tools/subagent/consult-deadline.ts +12 -7
  696. package/src/tools/subagent/message.ts +3 -1
  697. package/src/tools/subagent/read.ts +66 -4
  698. package/src/tools/subagent/spawn.ts +500 -78
  699. package/src/tools/tool-approval-handler.ts +45 -4
  700. package/src/tools/types.ts +22 -3
  701. package/src/tools/ui-surface/surface-shape-docs.ts +1 -1
  702. package/src/tools/ui-surface/visual-validation.ts +2 -0
  703. package/src/usage/__tests__/subagent-attribution.test.ts +109 -0
  704. package/src/usage/subagent-attribution.ts +108 -0
  705. package/src/util/__tests__/sqlite-retry.test.ts +112 -0
  706. package/src/util/abort-reasons.ts +16 -0
  707. package/src/util/ansi.ts +44 -0
  708. package/src/util/disk-usage.ts +17 -13
  709. package/src/util/image-conversion.ts +20 -13
  710. package/src/util/schedule-source-key.ts +23 -0
  711. package/src/util/worker-process.ts +7 -1
  712. package/src/workspace/git-service.ts +33 -9
  713. package/src/workspace/migrations/140-repair-seed-pinned-memory-v3-live.ts +260 -0
  714. package/src/workspace/migrations/141-stt-english-default-to-multilingual.ts +111 -0
  715. package/src/workspace/migrations/__tests__/141-stt-english-default-to-multilingual.test.ts +126 -0
  716. package/src/workspace/migrations/registry.ts +4 -0
  717. package/src/workspace/top-level-renderer.ts +15 -2
  718. package/src/__tests__/tool-side-effects-slack-dm.test.ts +0 -357
  719. package/src/daemon/install-symlink.ts +0 -207
  720. package/src/notifications/deferred-emit.ts +0 -147
@@ -0,0 +1,134 @@
1
+ // Single source of truth for pairing server-side tool blocks (e.g. native
2
+ // web_search) across a message list. Pure leaf module: consumed by the
3
+ // provider formatter, load-time history repair, and any other pass that must
4
+ // distinguish a genuine orphan from a pair the provider manages itself.
5
+
6
+ /**
7
+ * Minimal structural message shape shared by daemon `Message[]` and
8
+ * `Anthropic.MessageParam[]`.
9
+ */
10
+ export interface ServerToolPairingMessage {
11
+ role: string;
12
+ content: string | ReadonlyArray<unknown>;
13
+ }
14
+
15
+ /** Type-guard for server_tool_use blocks. */
16
+ export function isServerToolUseBlock(
17
+ block: unknown,
18
+ ): block is { type: "server_tool_use"; id: string; name: string } {
19
+ return (
20
+ typeof block === "object" &&
21
+ block != null &&
22
+ (block as { type: string }).type === "server_tool_use"
23
+ );
24
+ }
25
+
26
+ /** Type-guard for web_search_tool_result blocks. */
27
+ export function isWebSearchToolResultBlock(block: unknown): block is {
28
+ type: "web_search_tool_result";
29
+ tool_use_id: string;
30
+ content: unknown;
31
+ } {
32
+ return (
33
+ typeof block === "object" &&
34
+ block != null &&
35
+ (block as { type: string }).type === "web_search_tool_result"
36
+ );
37
+ }
38
+
39
+ function isToolResultShapedBlock(block: unknown): boolean {
40
+ return (
41
+ typeof block === "object" &&
42
+ block != null &&
43
+ (block as { type?: string }).type === "tool_result"
44
+ );
45
+ }
46
+
47
+ function contentBlocks(msg: ServerToolPairingMessage): ReadonlyArray<unknown> {
48
+ return Array.isArray(msg.content) ? msg.content : [];
49
+ }
50
+
51
+ /**
52
+ * Pairing analysis for server-side tool blocks across the whole message list.
53
+ *
54
+ * Server-side tools are provider-executed, and the pair can legitimately span
55
+ * messages: when the model requests a server tool and a client tool in the
56
+ * same parallel tool-call group, the API defers the search (stop_reason
57
+ * `tool_use`, no result emitted) and executes it on the next request, placing
58
+ * the web_search_tool_result at the head of the next assistant message. Both
59
+ * the deferred tail and the resulting split pair must be sent back verbatim
60
+ * for the provider to pair and execute them.
61
+ */
62
+ export interface ServerToolPairing {
63
+ /**
64
+ * Ids with a complete use/result pair: the server_tool_use appears in the
65
+ * same message as its web_search_tool_result or in an earlier one.
66
+ */
67
+ resolvedPairIds: Set<string>;
68
+ /**
69
+ * Unanswered use ids in the final assistant message of an active tool-loop
70
+ * continuation (only user messages after it, carrying tool_result blocks or
71
+ * nothing at all). The provider executes these on this request.
72
+ */
73
+ deferredUseIds: Set<string>;
74
+ /** Ids whose use/result pair spans two messages. */
75
+ crossMessageIds: Set<string>;
76
+ }
77
+
78
+ export function analyzeServerToolPairing(
79
+ messages: ReadonlyArray<ServerToolPairingMessage>,
80
+ ): ServerToolPairing {
81
+ const useIndexById = new Map<string, number>();
82
+ const resultIndexById = new Map<string, number>();
83
+ let lastAssistantIndex = -1;
84
+
85
+ messages.forEach((msg, index) => {
86
+ if (msg.role !== "assistant") {
87
+ // Server-tool blocks legitimately live only in assistant messages; a
88
+ // stray result in a user message is a repair concern, not a pair.
89
+ return;
90
+ }
91
+ lastAssistantIndex = index;
92
+ for (const block of contentBlocks(msg)) {
93
+ if (isServerToolUseBlock(block) && !useIndexById.has(block.id)) {
94
+ useIndexById.set(block.id, index);
95
+ }
96
+ if (
97
+ isWebSearchToolResultBlock(block) &&
98
+ !resultIndexById.has(block.tool_use_id)
99
+ ) {
100
+ resultIndexById.set(block.tool_use_id, index);
101
+ }
102
+ }
103
+ });
104
+
105
+ const resolvedPairIds = new Set<string>();
106
+ const crossMessageIds = new Set<string>();
107
+ useIndexById.forEach((useIndex, id) => {
108
+ const resultIndex = resultIndexById.get(id);
109
+ if (resultIndex !== undefined && resultIndex >= useIndex) {
110
+ resolvedPairIds.add(id);
111
+ if (resultIndex > useIndex) {
112
+ crossMessageIds.add(id);
113
+ }
114
+ }
115
+ });
116
+
117
+ const deferredUseIds = new Set<string>();
118
+ if (lastAssistantIndex >= 0) {
119
+ const trailing = messages.slice(lastAssistantIndex + 1);
120
+ const trailingAllUser = trailing.every((m) => m.role === "user");
121
+ const trailingHasToolResult = trailing.some((m) =>
122
+ contentBlocks(m).some(isToolResultShapedBlock),
123
+ );
124
+ if (trailingAllUser && (trailing.length === 0 || trailingHasToolResult)) {
125
+ for (const block of contentBlocks(messages[lastAssistantIndex])) {
126
+ if (isServerToolUseBlock(block) && !resolvedPairIds.has(block.id)) {
127
+ deferredUseIds.add(block.id);
128
+ }
129
+ }
130
+ }
131
+ }
132
+
133
+ return { resolvedPairIds, deferredUseIds, crossMessageIds };
134
+ }
@@ -58,9 +58,27 @@ mock.module("../../../security/credential-key.js", () => ({
58
58
 
59
59
  let mockVellumAvailable = false;
60
60
 
61
+ /**
62
+ * Arguments the managed batch adapter was called with. The managed path has
63
+ * no constructor to spy on (the platform connection is the credential), so
64
+ * the language it forwards is observable only at the transcribe call.
65
+ */
66
+ const vellumManagedTranscribeCalls: Array<{
67
+ mimeType: string;
68
+ language: string | undefined;
69
+ }> = [];
70
+
61
71
  mock.module("../vellum-managed.js", () => ({
62
72
  vellumManagedSpeechAvailable: async () => mockVellumAvailable,
63
- vellumManagedTranscribe: async () => ({ text: "" }),
73
+ vellumManagedTranscribe: async (
74
+ _audio: Buffer,
75
+ mimeType: string,
76
+ _signal?: AbortSignal,
77
+ language?: string,
78
+ ) => {
79
+ vellumManagedTranscribeCalls.push({ mimeType, language });
80
+ return { text: "" };
81
+ },
64
82
  sttErrorFromManagedSpeech: (failure: unknown) => new Error(String(failure)),
65
83
  }));
66
84
 
@@ -172,6 +190,7 @@ mock.module("../xai-realtime.js", () => ({
172
190
  // ---------------------------------------------------------------------------
173
191
 
174
192
  const {
193
+ effectiveSttLanguage,
175
194
  resolveBatchTranscriber,
176
195
  sttCredentialGapReason,
177
196
  resolveConversationStreamingSttCapability,
@@ -1044,7 +1063,9 @@ describe("vellum managed resolution", () => {
1044
1063
  expect(vellumStreamCtorCalls).toEqual([
1045
1064
  {
1046
1065
  connection: mockVelayConnection,
1047
- options: { sampleRate: 24000 },
1066
+ // No language is configured here, so the managed default rides along
1067
+ // with the connection plumbing this test is about.
1068
+ options: { sampleRate: 24000, language: "multi" },
1048
1069
  },
1049
1070
  ]);
1050
1071
  });
@@ -1178,16 +1199,76 @@ describe("resolveStreamingTranscriber language plumbing", () => {
1178
1199
  expect(deepgramCtorCalls[0]?.options).toMatchObject({ language: "hi" });
1179
1200
  });
1180
1201
 
1181
- test("no configured language leaves the option off entirely", async () => {
1182
- // Regression guard for the default path: adapters must see no `language`
1183
- // key at all, so behavior for existing users is byte-identical.
1202
+ test("no configured language falls to multilingual on BYOK Deepgram", async () => {
1203
+ // Unset is not a neutral state on Deepgram: sending no language decodes
1204
+ // as English, so an unconfigured Hindi speaker gets English-sounding
1205
+ // nonsense. The default fills that gap with code-switching, which also
1206
+ // pins nova-3 the way any explicit language does.
1184
1207
  mockProviderKeys = { deepgram: "dg-key" };
1185
1208
  applyConfig({ provider: "deepgram" });
1186
1209
 
1187
1210
  await resolveStreamingTranscriber({ sampleRate: 16000 });
1188
1211
 
1189
1212
  expect(deepgramCtorCalls).toHaveLength(1);
1190
- expect(deepgramCtorCalls[0]?.options).not.toHaveProperty("language");
1213
+ expect(deepgramCtorCalls[0]?.options).toMatchObject({
1214
+ language: "multi",
1215
+ model: "nova-3",
1216
+ });
1217
+ });
1218
+
1219
+ test("no configured language falls to multilingual on the managed relay", async () => {
1220
+ // The relay dials Deepgram server-side, so it inherits the same English
1221
+ // default and needs the same fill-in.
1222
+ mockVellumAvailable = true;
1223
+ mockVelayConnection = {
1224
+ wsBaseUrl: "ws://gateway.test",
1225
+ httpBaseUrl: "http://gateway.test",
1226
+ mintServiceToken: () => "vk-test",
1227
+ };
1228
+ applyConfig({ provider: "vellum" });
1229
+
1230
+ await resolveStreamingTranscriber({ sampleRate: 24000 });
1231
+
1232
+ expect(vellumStreamCtorCalls).toEqual([
1233
+ {
1234
+ connection: mockVelayConnection,
1235
+ options: { sampleRate: 24000, language: "multi" },
1236
+ },
1237
+ ]);
1238
+ });
1239
+
1240
+ test("an explicitly configured language still wins over the default", async () => {
1241
+ // The default only fills the unset case: someone who picked Tamil (off
1242
+ // the code-switching roster entirely) must keep it.
1243
+ mockProviderKeys = { deepgram: "dg-key" };
1244
+ applyConfig({ provider: "deepgram", language: "ta" });
1245
+
1246
+ await resolveStreamingTranscriber({ sampleRate: 16000 });
1247
+
1248
+ expect(deepgramCtorCalls[0]?.options).toMatchObject({ language: "ta" });
1249
+ });
1250
+
1251
+ test("an explicit English pin is honored rather than treated as unset", async () => {
1252
+ // "en" is what the settings picker writes for a deliberate English pin,
1253
+ // so it must not collapse back into the multilingual default.
1254
+ mockProviderKeys = { deepgram: "dg-key" };
1255
+ applyConfig({ provider: "deepgram", language: "en" });
1256
+
1257
+ await resolveStreamingTranscriber({ sampleRate: 16000 });
1258
+
1259
+ expect(deepgramCtorCalls[0]?.options).toMatchObject({ language: "en" });
1260
+ });
1261
+
1262
+ test("providers that detect natively keep receiving no language when unset", async () => {
1263
+ // xAI reads unset as native auto-detection, so the multilingual default
1264
+ // would replace a broader capability with a ten-language one.
1265
+ mockProviderKeys = { xai: "xai-key" };
1266
+ applyConfig({ provider: "xai" });
1267
+
1268
+ await resolveStreamingTranscriber({ sampleRate: 16000 });
1269
+
1270
+ expect(xaiCtorCalls).toHaveLength(1);
1271
+ expect(xaiCtorCalls[0]?.options).not.toHaveProperty("language");
1191
1272
  });
1192
1273
 
1193
1274
  test("providers that auto-detect natively never receive a language", async () => {
@@ -1245,6 +1326,61 @@ describe("resolveStreamingTranscriber language plumbing", () => {
1245
1326
  model: "nova-3",
1246
1327
  });
1247
1328
  });
1329
+
1330
+ test("managed batch forwards the configured language to the platform", async () => {
1331
+ // The platform proxy passes it to Deepgram server-side, so a managed
1332
+ // voice note decodes in the same language the live session does.
1333
+ vellumManagedTranscribeCalls.length = 0;
1334
+ mockVellumAvailable = true;
1335
+ applyConfig({ provider: "vellum", language: "ta" });
1336
+
1337
+ const transcriber = await resolveBatchTranscriber();
1338
+ await transcriber!.transcribe({
1339
+ audio: Buffer.from("fake-audio"),
1340
+ mimeType: "audio/ogg",
1341
+ });
1342
+
1343
+ expect(vellumManagedTranscribeCalls).toHaveLength(1);
1344
+ expect(vellumManagedTranscribeCalls[0]?.language).toBe("ta");
1345
+ });
1346
+
1347
+ test("managed batch falls to multilingual when no language is configured", async () => {
1348
+ // The gap this closes: managed voice notes used to decode as English no
1349
+ // matter what the user had chosen, because nothing was forwarded.
1350
+ vellumManagedTranscribeCalls.length = 0;
1351
+ mockVellumAvailable = true;
1352
+ applyConfig({ provider: "vellum" });
1353
+
1354
+ const transcriber = await resolveBatchTranscriber();
1355
+ await transcriber!.transcribe({
1356
+ audio: Buffer.from("fake-audio"),
1357
+ mimeType: "audio/ogg",
1358
+ });
1359
+
1360
+ expect(vellumManagedTranscribeCalls).toHaveLength(1);
1361
+ expect(vellumManagedTranscribeCalls[0]?.language).toBe("multi");
1362
+ });
1363
+
1364
+ test("batch resolution falls to multilingual when no language is configured", async () => {
1365
+ // Dictation and voice notes ride the batch path, and they read the same
1366
+ // config the live session does. A user whose spoken language works in
1367
+ // voice mode must not find it broken in a voice note.
1368
+ deepgramBatchCtorCalls.length = 0;
1369
+ mockProviderKeys = { deepgram: "dg-key" };
1370
+ applyConfig({ provider: "deepgram" });
1371
+
1372
+ const transcriber = await resolveBatchTranscriber();
1373
+ await transcriber!.transcribe({
1374
+ audio: Buffer.from("fake-audio"),
1375
+ mimeType: "audio/ogg",
1376
+ });
1377
+
1378
+ expect(deepgramBatchCtorCalls).toHaveLength(1);
1379
+ expect(deepgramBatchCtorCalls[0]?.options).toMatchObject({
1380
+ language: "multi",
1381
+ model: "nova-3",
1382
+ });
1383
+ });
1248
1384
  });
1249
1385
 
1250
1386
  describe("sttCredentialGapReason", () => {
@@ -1254,3 +1390,48 @@ describe("sttCredentialGapReason", () => {
1254
1390
  expect(sttCredentialGapReason("deepgram")).toContain("API key");
1255
1391
  });
1256
1392
  });
1393
+
1394
+ describe("effectiveSttLanguage", () => {
1395
+ test("fills the unset case only where unset would mean English", () => {
1396
+ // Deepgram and the managed relay decode language-less audio as English,
1397
+ // so leaving them unset is a silent pin rather than a neutral state.
1398
+ expect(effectiveSttLanguage("deepgram", undefined)).toBe("multi");
1399
+ expect(effectiveSttLanguage("vellum", undefined)).toBe("multi");
1400
+ // Everyone else detects natively from the audio; filling in a ten-language
1401
+ // roster would narrow what they can already do.
1402
+ expect(effectiveSttLanguage("xai", undefined)).toBeUndefined();
1403
+ expect(effectiveSttLanguage("google-gemini", undefined)).toBeUndefined();
1404
+ expect(effectiveSttLanguage("openai-whisper", undefined)).toBeUndefined();
1405
+ });
1406
+
1407
+ test("a configured language always wins, including English", () => {
1408
+ // The default decides what happens when nobody has chosen, nothing more.
1409
+ expect(effectiveSttLanguage("deepgram", "ta")).toBe("ta");
1410
+ expect(effectiveSttLanguage("deepgram", "en")).toBe("en");
1411
+ expect(effectiveSttLanguage("vellum", "multi")).toBe("multi");
1412
+ expect(effectiveSttLanguage("xai", "hi")).toBe("hi");
1413
+ });
1414
+ });
1415
+
1416
+ describe("the multilingual default reaches configs with no stt block", () => {
1417
+ test("a config that omits services.stt entirely still resolves multilingual", () => {
1418
+ // The services-level default supplies the stt block for a fresh
1419
+ // workspace. Handing that default a literal would short-circuit the
1420
+ // inner parse and leave `language` undefined, so the block is parsed
1421
+ // through its own schema and the field default materializes.
1422
+ setConfig("services", {});
1423
+ expect(getConfig().services.stt.language).toBe("multi");
1424
+ });
1425
+
1426
+ test("a config that omits only the language gets it filled", () => {
1427
+ setConfig("services", { stt: { provider: "deepgram", providers: {} } });
1428
+ expect(getConfig().services.stt.language).toBe("multi");
1429
+ });
1430
+
1431
+ test("an explicit language is never overwritten by the default", () => {
1432
+ setConfig("services", {
1433
+ stt: { provider: "deepgram", language: "ta", providers: {} },
1434
+ });
1435
+ expect(getConfig().services.stt.language).toBe("ta");
1436
+ });
1437
+ });
@@ -105,6 +105,7 @@ export const DEEPGRAM_NOVA3_MONOLINGUAL_CODES = [
105
105
  "tl",
106
106
  "tr",
107
107
  "uk",
108
+ "ur",
108
109
  "vi",
109
110
  "zh",
110
111
  ] as const;
@@ -16,6 +16,64 @@ import {
16
16
 
17
17
  const log = getLogger("stt-resolver");
18
18
 
19
+ // ---------------------------------------------------------------------------
20
+ // Default spoken language
21
+ // ---------------------------------------------------------------------------
22
+
23
+ /**
24
+ * Providers that decode language-less audio as English rather than detecting
25
+ * the spoken language: Deepgram directly, and the managed relay, which dials
26
+ * Deepgram server-side. For these, an unset `services.stt.language` is not a
27
+ * neutral state: it is a silent English pin that returns non-English speech
28
+ * as English-sounding nonsense.
29
+ *
30
+ * Providers absent from this set need no default: xAI, Gemini and Whisper all
31
+ * detect natively from the audio when no language is sent.
32
+ */
33
+ const MULTILINGUAL_DEFAULT_PROVIDERS: ReadonlySet<SttProviderId> = new Set([
34
+ "deepgram",
35
+ "vellum",
36
+ ] as SttProviderId[]);
37
+
38
+ /**
39
+ * The language an unset config resolves to on the providers above: nova-3's
40
+ * code-switching mode, which follows a speaker between the ten languages of
41
+ * Deepgram's multi roster (`DEEPGRAM_MULTI_LANGUAGE_CODES` in `deepgram.ts`)
42
+ * without being told which one they are speaking. Chosen over an English pin
43
+ * because the failure it replaces is
44
+ * silent: a Hindi speaker under the English default gets fluent-looking
45
+ * garbage rather than an error, and has no way to tell recognition is
46
+ * misconfigured from the transcript alone.
47
+ *
48
+ * It is a default, not a ceiling. Speakers of the other 39 languages on the
49
+ * monolingual roster still pick theirs explicitly, and that pick continues to
50
+ * win here. This only decides what happens when nobody has chosen.
51
+ */
52
+ const DEFAULT_MULTILINGUAL_CODE = "multi";
53
+
54
+ /**
55
+ * The spoken language to transcribe with, given what config holds and which
56
+ * provider will receive it. Configured values always win; the default only
57
+ * fills the unset case, and only where unset would otherwise mean English.
58
+ *
59
+ * Applied inside the resolvers rather than at the config layer so config keeps
60
+ * recording what the user chose (or that they chose nothing). The settings
61
+ * surfaces read that distinction to show which rows are defaults, and the live
62
+ * session compares raw config values to decide whether a language change needs
63
+ * a re-dial.
64
+ */
65
+ export function effectiveSttLanguage(
66
+ providerId: SttProviderId,
67
+ configured: string | undefined,
68
+ ): string | undefined {
69
+ if (configured) {
70
+ return configured;
71
+ }
72
+ return MULTILINGUAL_DEFAULT_PROVIDERS.has(providerId)
73
+ ? DEFAULT_MULTILINGUAL_CODE
74
+ : undefined;
75
+ }
76
+
19
77
  // ---------------------------------------------------------------------------
20
78
  // Batch transcriber resolver (existing public API — unchanged contract)
21
79
  // ---------------------------------------------------------------------------
@@ -38,7 +96,10 @@ export async function resolveBatchTranscriber(): Promise<BatchTranscriber | null
38
96
  // change cannot pair one setting's old value with another's new value.
39
97
  const stt = getConfig().services.stt;
40
98
  const provider = stt.provider;
41
- const language = stt.language;
99
+ const language = effectiveSttLanguage(
100
+ provider as SttProviderId,
101
+ stt.language,
102
+ );
42
103
 
43
104
  // Look up credential provider via the catalog.
44
105
  const credentialProviderName = getCredentialProvider(
@@ -54,11 +115,12 @@ export async function resolveBatchTranscriber(): Promise<BatchTranscriber | null
54
115
  }
55
116
 
56
117
  if (provider === "vellum") {
57
- // Managed batch transcription rides the platform's speech proxy, which
58
- // accepts no language parameter, so `services.stt.language` does not
59
- // apply here; streaming is the path that honors it for managed speech.
118
+ // Managed batch rides the platform's speech proxy, which forwards the
119
+ // language to Deepgram server-side. A platform build predating that
120
+ // field ignores it rather than failing, so the daemon can send one
121
+ // before the platform side deploys.
60
122
  return (await sttProviderKeyResolves("vellum"))
61
- ? createDaemonBatchTranscriber(null, "vellum")
123
+ ? createDaemonBatchTranscriber(null, "vellum", language)
62
124
  : null;
63
125
  }
64
126
 
@@ -304,9 +366,11 @@ export interface ResolveStreamingTranscriberOptions {
304
366
  * Defaults to `services.stt.language`; pass explicitly to override the
305
367
  * config for a single session.
306
368
  *
307
- * See {@link CreateStreamingTranscriberOptions.language} for how each
308
- * provider treats it: notably, leaving it unset is not auto-detection on
309
- * Deepgram or the managed relay.
369
+ * Leaving both unset does not reach the adapters as "no language": on
370
+ * Deepgram and the managed relay, where that would mean English rather
371
+ * than detection, {@link effectiveSttLanguage} fills in code-switching
372
+ * first. See {@link CreateStreamingTranscriberOptions.language} for how
373
+ * each adapter treats what it finally receives.
310
374
  */
311
375
  language?: string;
312
376
  }
@@ -339,8 +403,14 @@ export async function resolveStreamingTranscriber(
339
403
  const provider = options.providerId ?? (stt.provider as SttProviderId);
340
404
  // Config-level language applies to every streaming caller (live voice,
341
405
  // dictation, telephony) unless one overrides it for a single session, so
342
- // the setting lands in one place rather than at each call site.
343
- const language = options.language ?? stt.language;
406
+ // the setting lands in one place rather than at each call site. An unset
407
+ // config falls to the provider's default (see `effectiveSttLanguage`),
408
+ // which is where a caller passing no language gets multilingual rather
409
+ // than a silent English pin.
410
+ const language = effectiveSttLanguage(
411
+ provider,
412
+ options.language ?? stt.language,
413
+ );
344
414
  const diarizePreference: DiarizePreference = options.diarize ?? "off";
345
415
 
346
416
  // Look up credential provider via the catalog.
@@ -95,8 +95,14 @@ export async function vellumManagedTranscribe(
95
95
  audio: Buffer,
96
96
  mimeType: string,
97
97
  signal?: AbortSignal,
98
+ language?: string,
98
99
  ): Promise<SttTranscribeResult> {
99
- const result = await managedSpeechTranscribe({ audio, mimeType, signal });
100
+ const result = await managedSpeechTranscribe({
101
+ audio,
102
+ mimeType,
103
+ signal,
104
+ language,
105
+ });
100
106
  if (!result.ok) {
101
107
  throw sttErrorFromManagedSpeech(result);
102
108
  }
@@ -59,7 +59,9 @@ export async function resolveSpeechRelayConnection(): Promise<SpeechRelayConnect
59
59
  mintToken({
60
60
  aud: "vellum-gateway",
61
61
  sub: DAEMON_SERVICE_SUB,
62
- scope_profile: "gateway_service_v1",
62
+ // Least-privilege (ATL-1033): this token rides in the dial URL, so it
63
+ // must open nothing but the speech relay.
64
+ scope_profile: "speech_relay_v1",
63
65
  policy_epoch: CURRENT_POLICY_EPOCH,
64
66
  ttlSeconds: RELAY_TOKEN_TTL_SECONDS,
65
67
  });
@@ -332,12 +332,32 @@ export interface SendMessageConfig {
332
332
  */
333
333
  logit_bias?: Record<string, number>;
334
334
  /**
335
- * When true, the most recent user message's content varies across
336
- * otherwise-identical turns (e.g. a per-turn memory block was injected into
337
- * it). The provider places the primary long-TTL cache breakpoint on the most
338
- * recent *stable* user message instead of the volatile latest one, so the
339
- * cached prefix stays reusable across turns. Default false — existing
340
- * behavior.
335
+ * When true, the TURN-STARTING user message carries content that will not
336
+ * recur byte-identically on the next turn, so a long-TTL breakpoint placed
337
+ * on it could never be read back across turns. The agent loop is the only
338
+ * producer: it sets the flag from the history it is about to send, when the
339
+ * turn-starting message carries a memory-v3 `<memory_spotlight>` block (the
340
+ * one injected block strip-and-replaced from every user message each turn).
341
+ *
342
+ * The flag describes the turn, not the request, so it holds for every
343
+ * request the turn makes, including tool-loop iterations, whose trailing
344
+ * tool-result message is user-role but carries no injected blocks.
345
+ *
346
+ * Consumed by the Anthropic client only, where it selects the TTL of the
347
+ * turn-start breakpoint: short instead of long. The block is still marked,
348
+ * so the turn's tool-loop iterations read the prefix back and each hit
349
+ * refreshes the entry; nothing is spent on a long-TTL entry whose bytes
350
+ * change before the next turn could reach it. Holding the flag steady across
351
+ * the turn is what keeps that one boundary on a single TTL; marking it at
352
+ * two would bill two writes for one reusable prefix.
353
+ *
354
+ * The OpenAI Responses transport ignores the flag and marks every markable
355
+ * user item: a volatile message is fixed within its own turn, so the write is
356
+ * prepaid once and read back by each tool-loop iteration.
357
+ *
358
+ * Default false. Providers that place no message-level breakpoints, or that
359
+ * key their cache on a request-level identifier rather than message bytes,
360
+ * can ignore it.
341
361
  */
342
362
  mutableLatestUserMessage?: boolean;
343
363
  /**
@@ -55,16 +55,15 @@ export const VELLUM_MANAGED_CONNECTION_NAME = "vellum";
55
55
 
56
56
  /**
57
57
  * Whether a connection is the provider-agnostic Vellum-managed connection.
58
+ * The provider column alone identifies the managed route: platform auth
59
+ * always accompanies it (auth derivation pairs them, the connection routes
60
+ * reject writes that split them, and DB migration 361 reconciles stored
61
+ * rows).
58
62
  * Structurally typed so this stays a pure module with no connection-schema
59
63
  * import.
60
64
  */
61
- export function isVellumManagedConnection(conn: {
62
- provider: string;
63
- auth: { type: string };
64
- }): boolean {
65
- return (
66
- conn.provider === VELLUM_MANAGED_PROVIDER && conn.auth.type === "platform"
67
- );
65
+ export function isVellumManagedConnection(conn: { provider: string }): boolean {
66
+ return conn.provider === VELLUM_MANAGED_PROVIDER;
68
67
  }
69
68
 
70
69
  export interface VellumModelRoute {
@@ -12,6 +12,8 @@ The single HTTP send endpoint is `POST /v1/messages`. Key behaviors:
12
12
 
13
13
  Do NOT add new send endpoints. All message ingress should go through `POST /v1/messages` (HTTP).
14
14
 
15
+ **A user interrupt ends the turn, not the queue.** `POST /v1/conversations/:id/cancel` (Stop / Esc, and the CLI's cancel signal file) aborts the turn in flight; anything the same user queued behind it survives and runs on that turn's drain, because the aborted loop reaches its `finally`, which calls `kickDrainQueue` like any other turn end. `abortConversation` discards the queue only for abort kinds where the conversation itself is going away (dispose, eviction, voice supersession, subagent teardown), and every discarded row a client is showing gets `message_queued_deleted` alongside `generation_cancelled` (echo-suppressed rows are skipped, since they never got a `message_queued` ack to close). Two invariants to keep: an unconditional `queue.clear()` emits no per-row terminal event, so clients keep rendering a queued row whose cancel/steer buttons are dead (DELETE 404s, steer reports `not_processing`) and whose message is silently lost on the next reload; and a teardown must discard even when the processing flag already reads idle, since a turn that cleared the flag can still be unwinding through its awaited turn-boundary commit with a `kickDrainQueue` ahead of it.
16
+
15
17
  ### Channel inbound honors "queue if busy" via defer-until-idle
16
18
 
17
19
  Channel inbound turns (Slack/Telegram/etc. — `processChannelMessageInBackground`) obey the same "process when the current turn completes" contract, but they do **not** route through the conversation's queue. A channel turn delivers its reply back through the provider callback URL (streaming session + `finalizeEventDelivery` + processed/delivery bookkeeping); the queue drain fans replies onto the SSE hub only and performs none of that. So a channel turn that arrives while the conversation is mid-turn is **deferred until the processing lock frees** (`withChannelTurnAdmission` in `routes/inbound-stages/channel-turn-admission.ts`: per-conversation single-flight for FIFO ordering + event-driven `waitForIdle`), then run with its delivery orchestration intact.