@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
@@ -27,6 +27,9 @@ mock.module("../registry.js", () => ({
27
27
  // ── Imports (after mocks) ───────────────────────────────────────────────────
28
28
 
29
29
  import { CODE_DEFAULT_PROFILE_ENTRIES } from "../../config/default-profile-catalog.js";
30
+ import { getDb } from "../../persistence/db-connection.js";
31
+ import { initializeDb } from "../../persistence/db-init.js";
32
+ import { resetSubagentAttributionCacheForTests } from "../../usage/subagent-attribution.js";
30
33
  import { RetryProvider } from "../retry.js";
31
34
  import type {
32
35
  Message,
@@ -188,6 +191,70 @@ describe("RetryProvider — callSite resolution", () => {
188
191
  ).toBeUndefined();
189
192
  });
190
193
 
194
+ // Delegated-work attribution on the authoritative billing path. Every
195
+ // subagent variety shares `llm_call_site = "subagentSpawn"`, so these two
196
+ // orthogonal headers are what let rated usage be decomposed by variety.
197
+ test("forwards subagent role and spawn mode headers for a subagent conversation", async () => {
198
+ await initializeDb();
199
+ resetSubagentAttributionCacheForTests();
200
+ getDb().run(
201
+ `INSERT INTO conversations (id, conversation_type, created_at, updated_at, subagent_role, subagent_spawn_mode)
202
+ VALUES ('conv-retry-advisor', 'background', 1000, 1000, 'advisor', 'advisor_consult')`,
203
+ );
204
+ setLlmConfig({
205
+ callSites: { subagentSpawn: { provider: "openai", model: "gpt-sub" } },
206
+ });
207
+
208
+ let seen: SendMessageOptions | undefined;
209
+ const wrapped = new RetryProvider(
210
+ makeProvider("openai", (options) => {
211
+ seen = options;
212
+ }),
213
+ { forwardUsageAttributionHeaders: true },
214
+ );
215
+
216
+ await wrapped.sendMessage(DUMMY_MESSAGES, {
217
+ config: {
218
+ callSite: "subagentSpawn",
219
+ conversationId: "conv-retry-advisor",
220
+ },
221
+ });
222
+
223
+ const headers = (seen?.config as Record<string, unknown>)
224
+ .usageAttributionHeaders as Record<string, string>;
225
+ expect(headers["X-Vellum-Subagent-Role"]).toBe("advisor");
226
+ expect(headers["X-Vellum-Subagent-Spawn-Mode"]).toBe("advisor_consult");
227
+ });
228
+
229
+ test("omits subagent headers for a conversation that is not a subagent", async () => {
230
+ await initializeDb();
231
+ resetSubagentAttributionCacheForTests();
232
+ getDb().run(
233
+ `INSERT INTO conversations (id, conversation_type, created_at, updated_at)
234
+ VALUES ('conv-retry-plain', 'standard', 1000, 1000)`,
235
+ );
236
+ setLlmConfig({
237
+ callSites: { subagentSpawn: { provider: "openai", model: "gpt-sub" } },
238
+ });
239
+
240
+ let seen: SendMessageOptions | undefined;
241
+ const wrapped = new RetryProvider(
242
+ makeProvider("openai", (options) => {
243
+ seen = options;
244
+ }),
245
+ { forwardUsageAttributionHeaders: true },
246
+ );
247
+
248
+ await wrapped.sendMessage(DUMMY_MESSAGES, {
249
+ config: { callSite: "subagentSpawn", conversationId: "conv-retry-plain" },
250
+ });
251
+
252
+ const headers = (seen?.config as Record<string, unknown>)
253
+ .usageAttributionHeaders as Record<string, string>;
254
+ expect(headers["X-Vellum-Subagent-Role"]).toBeUndefined();
255
+ expect(headers["X-Vellum-Subagent-Spawn-Mode"]).toBeUndefined();
256
+ });
257
+
191
258
  test("omits attribution headers by default for direct provider transports", async () => {
192
259
  setLlmConfig({
193
260
  callSites: {
@@ -9,8 +9,9 @@ import { migrateProviderConnectionStatusLabel } from "../../persistence/migratio
9
9
  import { migrateProviderConnectionBaseUrlAndModels } from "../../persistence/migrations/250-provider-connection-base-url-and-models.js";
10
10
  import * as schema from "../../persistence/schema/index.js";
11
11
  import { createAdapterFromConnection } from "../inference/adapter-factory.js";
12
- import type { ProviderConnection } from "../inference/auth.js";
12
+ import type { Auth, ProviderConnection } from "../inference/auth.js";
13
13
  import type { ResolvedAuth } from "../inference/auth.js";
14
+ import { effectiveConnectionAuth } from "../inference/auth.js";
14
15
  import {
15
16
  createConnection,
16
17
  getConnection,
@@ -44,16 +45,11 @@ const resolvedAuth: ResolvedAuth = {
44
45
  describe("vellum connection routing", () => {
45
46
  test("isVellumManagedConnection identifies the sentinel connection", () => {
46
47
  expect(isVellumManagedConnection(vellumConnection)).toBe(true);
47
- expect(
48
- isVellumManagedConnection({
49
- provider: "fireworks",
50
- auth: { type: "platform" },
51
- }),
52
- ).toBe(false);
53
- // `vellum` provider with non-platform auth is not a managed vellum route.
54
- expect(
55
- isVellumManagedConnection({ provider: "vellum", auth: { type: "none" } }),
56
- ).toBe(false);
48
+ // The provider column alone decides: a concrete provider is never the
49
+ // managed route (platform auth always pairs with provider "vellum";
50
+ // DB migration 361 reconciles stored rows).
51
+ expect(isVellumManagedConnection({ provider: "fireworks" })).toBe(false);
52
+ expect(isVellumManagedConnection({ provider: "vellum" })).toBe(true);
57
53
  });
58
54
 
59
55
  test("the vellum sentinel is not a real provider without an override", () => {
@@ -82,6 +78,41 @@ describe("vellum connection routing", () => {
82
78
  });
83
79
  });
84
80
 
81
+ describe("effectiveConnectionAuth", () => {
82
+ test("a vellum row dispatches on platform auth regardless of the stored variant", () => {
83
+ for (const stored of [
84
+ { type: "api_key", credential: "vault/x" },
85
+ { type: "none" },
86
+ { type: "platform" },
87
+ ] as Auth[]) {
88
+ expect(
89
+ effectiveConnectionAuth({ provider: "vellum", auth: stored }),
90
+ ).toEqual({ type: "platform" });
91
+ }
92
+ });
93
+
94
+ test("payload-carrying rows keep their stored auth verbatim", () => {
95
+ const keyed: Auth = { type: "api_key", credential: "vault/anthropic" };
96
+ expect(
97
+ effectiveConnectionAuth({ provider: "anthropic", auth: keyed }),
98
+ ).toBe(keyed);
99
+ const subscription: Auth = { type: "oauth_subscription" } as Auth;
100
+ expect(
101
+ effectiveConnectionAuth({ provider: "openai", auth: subscription }),
102
+ ).toBe(subscription);
103
+ });
104
+
105
+ test("a deliberately keyed keyless provider keeps its key", () => {
106
+ // Keyless means no key REQUIRED, not no key possible: the ollama adapter
107
+ // accepts one, so stored api_key auth on an ollama row is payload and
108
+ // must never be derived away.
109
+ const keyed: Auth = { type: "api_key", credential: "vault/ollama" };
110
+ expect(effectiveConnectionAuth({ provider: "ollama", auth: keyed })).toBe(
111
+ keyed,
112
+ );
113
+ });
114
+ });
115
+
85
116
  describe("vellum connection persistence (DB round-trip)", () => {
86
117
  // Guards the P1: a persisted `provider: "vellum"` row must survive the DB
87
118
  // loaders and create route, which validate against VALID_CONNECTION_PROVIDERS.
@@ -18,6 +18,12 @@ import {
18
18
  PLACEHOLDER_EMPTY_TURN,
19
19
  } from "../placeholder-sentinels.js";
20
20
  import { recordProviderRequestDiagnostics } from "../request-diagnostics.js";
21
+ import {
22
+ analyzeServerToolPairing,
23
+ isServerToolUseBlock,
24
+ isWebSearchToolResultBlock,
25
+ type ServerToolPairing,
26
+ } from "../server-tool-pairing.js";
21
27
  import { createStreamTimeout } from "../stream-timeout.js";
22
28
  import type {
23
29
  ContentBlock,
@@ -489,73 +495,54 @@ function normalizeFollowingUserContent(
489
495
  };
490
496
  }
491
497
 
492
- /** Type-guard for server_tool_use blocks. */
493
- function isServerToolUseBlock(
494
- block: unknown,
495
- ): block is { type: "server_tool_use"; id: string; name: string } {
496
- return (
497
- typeof block === "object" &&
498
- block != null &&
499
- (block as { type: string }).type === "server_tool_use"
500
- );
501
- }
502
-
503
- /** Type-guard for web_search_tool_result blocks. */
504
- function isWebSearchToolResultBlock(block: unknown): block is {
505
- type: "web_search_tool_result";
506
- tool_use_id: string;
507
- content: unknown;
508
- } {
509
- return (
510
- typeof block === "object" &&
511
- block != null &&
512
- (block as { type: string }).type === "web_search_tool_result"
513
- );
514
- }
515
-
516
498
  /**
517
- * Repair orphaned server-side tool blocks within assistant messages. Server-
518
- * side tools (e.g. web_search) are self-paired: the assistant message should
519
- * contain both server_tool_use and its matching web_search_tool_result. Either
520
- * side can go missing a partial stream may drop the result, or a downstream
521
- * step (history reload, message split, compaction) may drop the use block.
522
- * Both cases trigger an Anthropic 400 on the next request, so this function
523
- * handles both directions:
499
+ * Repair orphaned server-side tool blocks within assistant messages, using the
500
+ * cross-message pairing from {@link analyzeServerToolPairing}. A pair can go
501
+ * missing on either side: a partial stream may drop the result, or a
502
+ * downstream step (history reload, message split, compaction) may drop the use
503
+ * block. Both cases trigger an Anthropic 400 on the next request, so this
504
+ * function handles both directions:
524
505
  *
525
- * - server_tool_use without paired result: inject a synthetic error result.
526
- * - web_search_tool_result without paired server_tool_use: downgrade to a
506
+ * - server_tool_use without a paired result: inject a synthetic error
507
+ * result.
508
+ * - web_search_tool_result without a paired server_tool_use: downgrade to a
527
509
  * text block describing what was found so the model retains context.
510
+ *
511
+ * Deferred use blocks (see {@link ServerToolPairing.deferredUseIds}) are not
512
+ * orphans: they are left intact so the provider executes the search on this
513
+ * request instead of seeing a synthetic failure.
528
514
  */
529
515
  function repairOrphanedServerToolBlocks(
530
516
  messages: Anthropic.MessageParam[],
517
+ pairing: ServerToolPairing,
531
518
  ): Anthropic.MessageParam[] {
519
+ if (pairing.deferredUseIds.size > 0) {
520
+ log.info(
521
+ { deferredIds: Array.from(pairing.deferredUseIds) },
522
+ "Preserving deferred server_tool_use blocks for provider-side execution",
523
+ );
524
+ }
532
525
  return messages.map((msg) => {
533
526
  if (msg.role !== "assistant") {
534
527
  return msg;
535
528
  }
536
529
  const content = Array.isArray(msg.content) ? msg.content : [];
537
530
 
538
- const serverToolUseIds = new Set<string>();
539
- const webSearchResultIds = new Set<string>();
540
- for (const block of content) {
541
- if (isServerToolUseBlock(block)) {
542
- serverToolUseIds.add(block.id);
543
- }
544
- if (isWebSearchToolResultBlock(block)) {
545
- webSearchResultIds.add(block.tool_use_id);
546
- }
547
- }
548
-
549
531
  const orphanServerToolUseIds = new Set<string>();
550
- for (const id of serverToolUseIds) {
551
- if (!webSearchResultIds.has(id)) {
552
- orphanServerToolUseIds.add(id);
553
- }
554
- }
555
532
  const orphanWebSearchResultIds = new Set<string>();
556
- for (const id of webSearchResultIds) {
557
- if (!serverToolUseIds.has(id)) {
558
- orphanWebSearchResultIds.add(id);
533
+ for (const block of content) {
534
+ if (
535
+ isServerToolUseBlock(block) &&
536
+ !pairing.resolvedPairIds.has(block.id) &&
537
+ !pairing.deferredUseIds.has(block.id)
538
+ ) {
539
+ orphanServerToolUseIds.add(block.id);
540
+ }
541
+ if (
542
+ isWebSearchToolResultBlock(block) &&
543
+ !pairing.resolvedPairIds.has(block.tool_use_id)
544
+ ) {
545
+ orphanWebSearchResultIds.add(block.tool_use_id);
559
546
  }
560
547
  }
561
548
 
@@ -709,9 +696,18 @@ function findActiveToolUseContinuationStart(
709
696
 
710
697
  function ensureToolPairing(
711
698
  messages: Anthropic.MessageParam[],
699
+ pairing: ServerToolPairing,
712
700
  ): Anthropic.MessageParam[] {
713
701
  const result: Anthropic.MessageParam[] = [];
714
702
 
703
+ // Messages carrying a deferred or cross-message-paired server tool block
704
+ // must go out verbatim: the provider pairs and executes these blocks across
705
+ // messages itself, and reordering or splitting them breaks that pairing.
706
+ const verbatimIds = new Set([
707
+ ...pairing.deferredUseIds,
708
+ ...pairing.crossMessageIds,
709
+ ]);
710
+
715
711
  let i = 0;
716
712
  while (i < messages.length) {
717
713
  const msg = messages[i];
@@ -724,8 +720,23 @@ function ensureToolPairing(
724
720
 
725
721
  const content = Array.isArray(msg.content) ? msg.content : [];
726
722
 
723
+ const hasVerbatimServerBlock =
724
+ verbatimIds.size > 0 &&
725
+ content.some(
726
+ (block) =>
727
+ (isServerToolUseBlock(block) && verbatimIds.has(block.id)) ||
728
+ (isWebSearchToolResultBlock(block) &&
729
+ verbatimIds.has(block.tool_use_id)),
730
+ );
731
+
727
732
  const { pairedContent, carryoverContent, toolUseIds } =
728
- splitAssistantForToolPairing(content);
733
+ hasVerbatimServerBlock
734
+ ? {
735
+ pairedContent: content,
736
+ carryoverContent: [] as Anthropic.ContentBlockParam[],
737
+ toolUseIds: getOrderedToolUseIds(content),
738
+ }
739
+ : splitAssistantForToolPairing(content);
729
740
 
730
741
  if (toolUseIds.length === 0) {
731
742
  result.push(msg);
@@ -976,7 +987,7 @@ export class AnthropicProvider implements Provider {
976
987
  // edge LB, NAT idle) — only the latter should be retried.
977
988
  let innerTimeoutSignal: AbortSignal | undefined;
978
989
  try {
979
- sentMessages = this.buildSentMessages(messages);
990
+ sentMessages = await this.buildSentMessages(messages);
980
991
  const {
981
992
  effort,
982
993
  speed,
@@ -1169,7 +1180,10 @@ export class AnthropicProvider implements Provider {
1169
1180
  }
1170
1181
  return -1;
1171
1182
  };
1172
- const applyCacheControlToLastBlock = (msgIdx: number): void => {
1183
+ const applyCacheControlToLastBlock = (
1184
+ msgIdx: number,
1185
+ control: typeof cacheControl | typeof tailCacheControl = cacheControl,
1186
+ ): void => {
1173
1187
  const content = msgs[msgIdx].content;
1174
1188
  if (!Array.isArray(content) || content.length === 0) {
1175
1189
  return;
@@ -1177,27 +1191,30 @@ export class AnthropicProvider implements Provider {
1177
1191
  const lastBlock = content[content.length - 1];
1178
1192
  if (typeof lastBlock !== "string") {
1179
1193
  (lastBlock as unknown as Record<string, unknown>).cache_control =
1180
- cacheControl;
1194
+ control;
1181
1195
  }
1182
1196
  };
1183
1197
  const turnStartIdx = findUserTextMsgIdx(msgs.length - 1);
1184
- // When the latest user message is volatile (`mutableLatestUserMessage`)
1185
- // and it is itself the turn-start (first-of-turn, no tool-use loop yet),
1186
- // skip the long-TTL anchor here it would land on per-turn-varying
1187
- // content and never hit again. The previous-turn anchor below becomes the
1188
- // primary stable breakpoint. During tool-use loops (`turnStartIdx <
1189
- // msgs.length - 1`) the turn-start block is fixed within the turn, so
1190
- // behavior is unchanged. Independent from `disableTurnStartCache`, which
1191
- // expresses a different intent (one-shot callers with no future hit).
1192
- const skipVolatileTurnStartAnchor =
1193
- mutableLatestUserMessage && turnStartIdx === msgs.length - 1;
1194
- if (
1195
- turnStartIdx >= 0 &&
1196
- !disableCache &&
1197
- !disableTurnStartCache &&
1198
- !skipVolatileTurnStartAnchor
1199
- ) {
1200
- applyCacheControlToLastBlock(turnStartIdx);
1198
+ // Turn-start anchor. A volatile turn start (`mutableLatestUserMessage`:
1199
+ // the message carries a per-turn block that will not recur next turn)
1200
+ // takes the SHORT TTL instead of the long one. The long TTL would buy
1201
+ // nothing: the bytes change next turn, so that entry can never be read
1202
+ // across turns, and the only reads it can serve are this turn's tool-loop
1203
+ // iterations, which the short TTL already serves, refreshing on each
1204
+ // hit. Marking the same boundary at two different TTLs across a turn
1205
+ // bills two writes for one reusable prefix, the long one at the higher
1206
+ // write multiplier.
1207
+ //
1208
+ // The signal is turn-scoped, not request-scoped: it describes the
1209
+ // turn-starting user message, so it holds for every request in the turn
1210
+ // and the TTL chosen here stays consistent as the tool loop advances.
1211
+ // `disableTurnStartCache` is independent: it expresses a different
1212
+ // intent (one-shot callers with no future hit).
1213
+ if (turnStartIdx >= 0 && !disableCache && !disableTurnStartCache) {
1214
+ applyCacheControlToLastBlock(
1215
+ turnStartIdx,
1216
+ mutableLatestUserMessage ? tailCacheControl : cacheControl,
1217
+ );
1201
1218
  }
1202
1219
 
1203
1220
  // Previous-turn anchor: when this request is the first of a new turn
@@ -1223,26 +1240,19 @@ export class AnthropicProvider implements Provider {
1223
1240
 
1224
1241
  // Advancing tail: place a short-lived 5m cache breakpoint on the last
1225
1242
  // block of the last message. This caches the growing tail cheaply
1226
- // without conflicting with the 1h breakpoints above. It fires during
1227
- // tool-use loops (the tail falls after the turn-starting user message)
1228
- // and also on a first-of-turn request whose volatile turn-start anchor
1229
- // was skipped while a previous-turn anchor exists: there the latest
1230
- // message would otherwise carry no breakpoint, so the next request's
1231
- // anchor can land far ahead of the previous-turn anchor and Anthropic's
1232
- // ~20-block cache lookback can't bridge the gap forcing a full
1233
- // re-creation of the prefix. The 5m breakpoint gives the next call an
1234
- // exact, reachable boundary; cross-turn it expires harmlessly. The
1235
- // first-of-turn bridge lands on the turn-start block, so it honors
1236
- // `disableTurnStartCache` like the long-TTL anchor above. Skip
1243
+ // without conflicting with the long-TTL breakpoints above. It fires
1244
+ // during tool-use loops, where the tail falls after the turn-starting
1245
+ // user message: without it the next iteration's anchor can land far
1246
+ // ahead of the last written boundary and Anthropic's ~20-block cache
1247
+ // lookback can't bridge the gap, forcing a full re-creation of the
1248
+ // prefix. On a first-of-turn request the tail IS the turn-start message,
1249
+ // which the anchor above already marks, so no bridge is needed. Skip
1237
1250
  // thinking/redacted_thinking blocks — Anthropic doesn't allow
1238
1251
  // cache_control on those types.
1239
1252
  if (
1240
1253
  !disableCache &&
1241
1254
  turnStartIdx >= 0 &&
1242
- (turnStartIdx < sentMessages.length - 1 ||
1243
- (skipVolatileTurnStartAnchor &&
1244
- turnStartIdx > 0 &&
1245
- !disableTurnStartCache))
1255
+ turnStartIdx < sentMessages.length - 1
1246
1256
  ) {
1247
1257
  const lastMsg = sentMessages[sentMessages.length - 1];
1248
1258
  if (Array.isArray(lastMsg.content) && lastMsg.content.length > 0) {
@@ -1272,10 +1282,11 @@ export class AnthropicProvider implements Provider {
1272
1282
  // system is a single block or absent) + at most two message anchors
1273
1283
  // ≤ 4 — Anthropic's per-request cap. The two message anchors are
1274
1284
  // turn-start + prev-turn-anchor (first-of-turn), turn-start + tail
1275
- // (tool-use loop), or prev-turn-anchor + tail (first-of-turn with the
1285
+ // (tool-use loop), prev-turn-anchor + tail (first-of-turn with the
1276
1286
  // volatile turn-start anchor skipped — the freed turn-start slot covers
1277
- // the tail). At most two message-level breakpoints are placed, so the
1278
- // total can't drift past 4.
1287
+ // the tail), or the tail alone (volatile first turn, where no
1288
+ // previous turn exists to anchor). At most two message-level
1289
+ // breakpoints are placed, so the total can't drift past 4.
1279
1290
 
1280
1291
  // Strip orphaned UTF-16 surrogates so the Anthropic JSON parser never
1281
1292
  // sees invalid strings produced by upstream surrogate-splitting `.slice()` calls.
@@ -1801,7 +1812,7 @@ export class AnthropicProvider implements Provider {
1801
1812
  systemPrompt: string,
1802
1813
  tools?: ToolDefinition[],
1803
1814
  ): Promise<number> {
1804
- const sentMessages = this.buildSentMessages(messages);
1815
+ const sentMessages = await this.buildSentMessages(messages);
1805
1816
 
1806
1817
  const system = systemPrompt
1807
1818
  ? systemPrompt
@@ -1837,10 +1848,12 @@ export class AnthropicProvider implements Provider {
1837
1848
  * `cache_control` breakpoints (which don't affect token counts) are the
1838
1849
  * only thing layered on top in `sendMessage`.
1839
1850
  */
1840
- private buildSentMessages(messages: Message[]): Anthropic.MessageParam[] {
1851
+ private async buildSentMessages(
1852
+ messages: Message[],
1853
+ ): Promise<Anthropic.MessageParam[]> {
1841
1854
  // Swap any persisted attachment references back to inline base64 before
1842
1855
  // serializing, so the block transforms below can read `source.data`.
1843
- messages = resolveMediaReferences(messages);
1856
+ messages = await resolveMediaReferences(messages);
1844
1857
  const formatted = messages
1845
1858
  .map((m) => {
1846
1859
  // Track whether an unknown block was dropped during filtering
@@ -2014,7 +2027,11 @@ export class AnthropicProvider implements Provider {
2014
2027
  formatted[i] = { ...msg, content: stripped };
2015
2028
  }
2016
2029
 
2017
- return ensureToolPairing(repairOrphanedServerToolBlocks(formatted));
2030
+ const serverToolPairing = analyzeServerToolPairing(formatted);
2031
+ return ensureToolPairing(
2032
+ repairOrphanedServerToolBlocks(formatted, serverToolPairing),
2033
+ serverToolPairing,
2034
+ );
2018
2035
  }
2019
2036
 
2020
2037
  /**
@@ -27,6 +27,7 @@
27
27
  * a conversation offline.
28
28
  */
29
29
 
30
+ import { getIsPlatform } from "../config/env-registry.js";
30
31
  import {
31
32
  resolveCallSiteConfig,
32
33
  selectWinningProfile,
@@ -468,7 +469,40 @@ export async function preflightResolvedConfig(
468
469
  errorOptions,
469
470
  );
470
471
  }
471
- if ((await platformLoginPresence()) === "unauthenticated") {
472
+ const presence = await platformLoginPresence();
473
+ if (presence === "ok") {
474
+ return;
475
+ }
476
+ if (getIsPlatform()) {
477
+ // A platform-managed assistant cannot present a login screen or switch
478
+ // providers, so the login-or-switch wording never fits. An unreachable
479
+ // store is transient and recovers on its own, so it reads as a retry. A
480
+ // reachable but empty store can only be fixed by re-provisioning the
481
+ // credential platform-side.
482
+ if (presence === "indeterminate") {
483
+ throw new ConnectionResolutionError(
484
+ connectionName,
485
+ "platform_unauthenticated",
486
+ "The assistant's platform credentials are temporarily unavailable; retrying automatically.",
487
+ errorOptions,
488
+ );
489
+ }
490
+ log.error(
491
+ {
492
+ connectionName,
493
+ model: resolved.model,
494
+ profileName: attribution.profileName,
495
+ },
496
+ "Managed platform credential is missing and must be re-provisioned",
497
+ );
498
+ throw new ConnectionResolutionError(
499
+ connectionName,
500
+ "platform_unauthenticated",
501
+ "This assistant's platform credential is missing and must be re-provisioned on the Vellum platform.",
502
+ errorOptions,
503
+ );
504
+ }
505
+ if (presence === "unauthenticated") {
472
506
  throw new ConnectionResolutionError(
473
507
  connectionName,
474
508
  "platform_unauthenticated",
@@ -434,7 +434,7 @@ export class GeminiProvider implements Provider {
434
434
 
435
435
  try {
436
436
  recordProviderRequestDiagnostics({ model_id: activeModel });
437
- const geminiContents = this.toGeminiContents(messages, activeModel);
437
+ const geminiContents = await this.toGeminiContents(messages, activeModel);
438
438
 
439
439
  const geminiConfig: genai.GenerateContentConfig = {};
440
440
 
@@ -658,7 +658,7 @@ export class GeminiProvider implements Provider {
658
658
  systemPrompt: string,
659
659
  tools?: ToolDefinition[],
660
660
  ): Promise<number> {
661
- const contents = this.toGeminiContents(messages, this.model);
661
+ const contents = await this.toGeminiContents(messages, this.model);
662
662
  const config: genai.CountTokensConfig = {};
663
663
  if (systemPrompt) {
664
664
  config.systemInstruction = systemPrompt.replaceAll(
@@ -689,13 +689,13 @@ export class GeminiProvider implements Provider {
689
689
  }
690
690
 
691
691
  /** Convert neutral messages to Gemini Content[] format. */
692
- private toGeminiContents(
692
+ private async toGeminiContents(
693
693
  messages: Message[],
694
694
  model: string,
695
- ): genai.Content[] {
695
+ ): Promise<genai.Content[]> {
696
696
  // Swap any persisted attachment references back to inline base64 before
697
697
  // building parts, so the transforms below can read `source.data`.
698
- messages = resolveMediaReferences(messages);
698
+ messages = await resolveMediaReferences(messages);
699
699
  const result: genai.Content[] = [];
700
700
 
701
701
  // Build a map from tool_use id → function name so tool_result blocks
@@ -34,9 +34,11 @@ import { RetryProvider } from "../retry.js";
34
34
  import { TogetherProvider } from "../together/client.js";
35
35
  import type { Provider } from "../types.js";
36
36
  import { UsageTrackingProvider } from "../usage-tracking.js";
37
+ import { isVellumManagedConnection } from "../vellum-model-routing.js";
37
38
  import { VercelAIGatewayProvider } from "../vercel-ai-gateway/client.js";
38
39
  import type { ResolvedAuth } from "./auth.js";
39
40
  import type { ProviderConnection } from "./auth.js";
41
+ import { effectiveConnectionAuth } from "./auth.js";
40
42
  import { resolveAuth } from "./resolve-auth.js";
41
43
 
42
44
  /** Unified construction opts. Adapters ignore fields they don't consume. */
@@ -244,9 +246,11 @@ export function createAdapterFromConnection(
244
246
  function makeCredentialRefresher(): () => Promise<Provider | null> {
245
247
  let lastAuth = JSON.stringify(resolvedAuth);
246
248
  return async (): Promise<Provider | null> => {
247
- const refreshedAuth = await resolveAuth(connection.auth, provider, {
248
- baseUrl: connection.baseUrl,
249
- });
249
+ const refreshedAuth = await resolveAuth(
250
+ effectiveConnectionAuth(connection),
251
+ provider,
252
+ { baseUrl: connection.baseUrl },
253
+ );
250
254
  if (!refreshedAuth.ok) {
251
255
  return null;
252
256
  }
@@ -262,19 +266,20 @@ export function createAdapterFromConnection(
262
266
  // Usage-attribution headers (`X-Vellum-*`) are only meaningful when the
263
267
  // request is routed through the Vellum-managed proxy. They carry billing
264
268
  // metadata for our own backend. Forwarding them to a third-party endpoint
265
- // would leak internal Vellum metadata, so gate on the auth type:
266
- // `platform` is the only auth that flows through our proxy.
267
- const isManagedProxy = connection.auth.type === "platform";
269
+ // would leak internal Vellum metadata, so gate on the managed connection
270
+ // identity, the only route that flows through our proxy.
271
+ const isManagedProxy = isVellumManagedConnection(connection);
272
+ const effectiveAuth = effectiveConnectionAuth(connection);
268
273
  return new UsageTrackingProvider(
269
274
  new RetryProvider(adapter, {
270
275
  forwardUsageAttributionHeaders: isManagedProxy,
271
276
  credentialSource: isManagedProxy
272
277
  ? "vellum-managed"
273
- : connection.auth.type === "api_key"
278
+ : effectiveAuth.type === "api_key"
274
279
  ? "byok"
275
- : connection.auth.type === "oauth_subscription"
280
+ : effectiveAuth.type === "oauth_subscription"
276
281
  ? "oauth-subscription"
277
- : connection.auth.type === "none"
282
+ : effectiveAuth.type === "none"
278
283
  ? "no-auth"
279
284
  : undefined,
280
285
  connectionName: connection.name,
@@ -320,7 +325,8 @@ function buildConnectionAdapter(
320
325
  : undefined;
321
326
 
322
327
  const codexSubscription =
323
- connection.auth.type === "oauth_subscription" && provider === "openai";
328
+ effectiveConnectionAuth(connection).type === "oauth_subscription" &&
329
+ provider === "openai";
324
330
 
325
331
  const adapter = buildProviderAdapter(provider, {
326
332
  apiKey,
@@ -72,6 +72,22 @@ export function deriveAuthForProvider(
72
72
  return credential ? { type: "api_key", credential } : null;
73
73
  }
74
74
 
75
+ /**
76
+ * The auth a connection dispatches with. The stored auth object is
77
+ * authoritative only where it carries a payload (an api_key credential ref,
78
+ * the oauth_subscription marker, a deliberately keyed keyless provider);
79
+ * the vellum provider IS the managed route, so its auth derives from the
80
+ * provider and the stored value can never mislead dispatch.
81
+ */
82
+ export function effectiveConnectionAuth(connection: {
83
+ provider: string;
84
+ auth: Auth;
85
+ }): Auth {
86
+ return connection.provider === VELLUM_MANAGED_PROVIDER
87
+ ? { type: "platform" }
88
+ : connection.auth;
89
+ }
90
+
75
91
  // ---------------------------------------------------------------------------
76
92
  // ResolvedAuth — what the dispatcher hands to each adapter
77
93
  // ---------------------------------------------------------------------------