@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
@@ -1,36 +1,61 @@
1
1
  /**
2
2
  * Shared availability computation for a (provider, connection) pair: whether
3
3
  * the connection exists, carries a usable credential, and can actually serve
4
- * the provider. The status is reported, never enforced — a dangling or
4
+ * the provider.
5
+ *
6
+ * On read paths the status is reported, not enforced — a dangling or
5
7
  * uncredentialed connection is a valid persisted state that surfaces an
6
- * explainable error at dispatch time.
8
+ * explainable error at dispatch time. The dedicated inference-profile write
9
+ * routes (create / update / set-active / conversation-scoped pin) are the
10
+ * exception: they refuse to persist a selection that provably cannot dispatch,
11
+ * because those writes are what a chat turn resolves through. Generic
12
+ * `config set` writes and dispatch itself stay report-only.
7
13
  *
8
14
  * Consumed by the default-provider status route (`llm.defaultProvider`) and
9
- * the inference-profile list route (per-profile `provider_connection`) so the
10
- * two never drift.
15
+ * the inference-profile routes (per-profile availability) so the two never
16
+ * drift.
11
17
  */
12
18
 
13
19
  import { getDb } from "../../persistence/db-connection.js";
14
20
  import { credentialKey } from "../../security/credential-key.js";
15
21
  import { getSecureKeyResultAsync } from "../../security/secure-keys.js";
22
+ import {
23
+ describeSubscriptionModelIncompatibility,
24
+ isConnectionCompatibleWithModel,
25
+ } from "../connection-model-compat.js";
16
26
  import { PROVIDER_CATALOG } from "../model-catalog.js";
17
27
  import { resolveManagedProxyContext } from "../platform-proxy/context.js";
28
+ import {
29
+ ConnectionResolutionError,
30
+ resolveRoutingIdentity,
31
+ } from "../routing-identity.js";
18
32
  import {
19
33
  isVellumManagedConnection,
20
34
  MANAGED_ROUTABLE_PROVIDERS,
21
35
  VELLUM_MANAGED_CONNECTION_NAME,
22
36
  VELLUM_MANAGED_PROVIDER,
23
37
  } from "../vellum-model-routing.js";
24
- import { getConnection } from "./connections.js";
38
+ import { ROUTING_IDENTITY_PROVIDERS } from "./auth.js";
39
+ import { getConnection, listConnections } from "./connections.js";
40
+
41
+ /**
42
+ * Every availability verdict, in one place. Route schemas build their zod
43
+ * enums from this rather than restating it, so a new status reaches the wire
44
+ * for every surface at once instead of drifting between them.
45
+ */
46
+ export const CONNECTION_AVAILABILITY_STATUSES = [
47
+ "ok",
48
+ "incomplete",
49
+ "missing_connection",
50
+ "missing_credential",
51
+ "provider_mismatch",
52
+ "unsupported_auth",
53
+ "vellum_unauthenticated",
54
+ "unknown",
55
+ ] as const;
25
56
 
26
57
  export type ConnectionAvailabilityStatus =
27
- | "ok"
28
- | "missing_connection"
29
- | "missing_credential"
30
- | "provider_mismatch"
31
- | "unsupported_auth"
32
- | "vellum_unauthenticated"
33
- | "unknown";
58
+ (typeof CONNECTION_AVAILABILITY_STATUSES)[number];
34
59
 
35
60
  export interface ConnectionAvailability {
36
61
  status: ConnectionAvailabilityStatus;
@@ -204,3 +229,130 @@ export async function computeConnectionAvailability(
204
229
  }
205
230
  }
206
231
  }
232
+
233
+ /**
234
+ * Statuses that mean a profile provably cannot serve a request. `unknown` is
235
+ * excluded on purpose: it means the credential store could not be reached, not
236
+ * that the credential is absent, and treating a CES outage as a broken profile
237
+ * would block writes that are actually fine.
238
+ */
239
+ const UNAVAILABLE_STATUSES: ReadonlySet<ConnectionAvailabilityStatus> = new Set(
240
+ [
241
+ // A profile with no provider and model of its own is skipped by the
242
+ // resolver on every turn, so it provably cannot serve a request. It
243
+ // belongs here for the same reason the connection failures do: pinning
244
+ // one silently runs a different profile than the user selected.
245
+ "incomplete",
246
+ "missing_connection",
247
+ "missing_credential",
248
+ "provider_mismatch",
249
+ "unsupported_auth",
250
+ "vellum_unauthenticated",
251
+ ],
252
+ );
253
+
254
+ /** Whether an availability verdict means dispatch would provably fail. */
255
+ export function isUnavailable(
256
+ availability: ConnectionAvailability | null,
257
+ ): boolean {
258
+ return availability !== null && UNAVAILABLE_STATUSES.has(availability.status);
259
+ }
260
+
261
+ /**
262
+ * Availability of a whole effective profile entry, judged the way dispatch
263
+ * judges it:
264
+ *
265
+ * - routing identities (`vellum`, `chatgpt`) resolve to their canonical row
266
+ * and derived upstream;
267
+ * - a pinned `provider_connection` is judged directly;
268
+ * - a provider with no pinned connection is judged against the connection
269
+ * dispatch would auto-resolve (an active, model-compatible row for that
270
+ * provider) — with no such row, the profile cannot serve requests.
271
+ *
272
+ * Returns null when there is nothing to judge: a mix carries no provider or
273
+ * model of its own, because the resolver expands it to a seeded arm and
274
+ * judges that arm instead.
275
+ */
276
+ export async function computeProfileAvailability(
277
+ entry: Record<string, unknown>,
278
+ ): Promise<ConnectionAvailability | null> {
279
+ const provider = entry.provider;
280
+ const model = typeof entry.model === "string" ? entry.model : undefined;
281
+
282
+ // A rung only wins if its profile carries BOTH a provider and a model (see
283
+ // `usableEntry` in config/llm-resolver.ts); one without them is skipped as
284
+ // "incomplete" and the call site quietly resolves elsewhere. Report that so
285
+ // clients can show it rather than presenting the profile as healthy.
286
+ if (typeof provider !== "string" || model === undefined) {
287
+ if (entry.mix != null) {
288
+ return null;
289
+ }
290
+ const missing =
291
+ typeof provider !== "string"
292
+ ? model === undefined
293
+ ? "a provider and a model"
294
+ : "a provider"
295
+ : "a model";
296
+ // Which profile a call site falls back to depends on the call site (its
297
+ // shipped intent, then the balanced anchor), so this names the effect
298
+ // without claiming a destination it cannot know.
299
+ return {
300
+ status: "incomplete",
301
+ message: `Missing ${missing}, so actions using it fall back to another profile.`,
302
+ };
303
+ }
304
+
305
+ // Routing-identity profiles carry no provider_connection. A model the
306
+ // identity cannot route reports as a mismatch rather than throwing —
307
+ // availability annotates, it must not fail the profiles read.
308
+ if (ROUTING_IDENTITY_PROVIDERS.has(provider)) {
309
+ try {
310
+ const identity = resolveRoutingIdentity(provider, model);
311
+ if (!identity) {
312
+ return null;
313
+ }
314
+ return await computeConnectionAvailability(
315
+ identity.expectedProvider,
316
+ identity.connectionName,
317
+ );
318
+ } catch (err) {
319
+ return {
320
+ status: "provider_mismatch",
321
+ message:
322
+ err instanceof ConnectionResolutionError
323
+ ? err.message
324
+ : `Model "${model ?? "<unset>"}" cannot be routed by provider "${provider}".`,
325
+ };
326
+ }
327
+ }
328
+
329
+ const pinned = entry.provider_connection;
330
+ if (typeof pinned === "string") {
331
+ return computeConnectionAvailability(provider, pinned);
332
+ }
333
+
334
+ // Mirror the dispatch-time auto-resolve (`resolveConfiguredProvider`): with
335
+ // no pinned connection, the first active model-compatible row for the
336
+ // provider serves the request, and none means dispatch returns no provider.
337
+ let candidates;
338
+ try {
339
+ candidates = listConnections(getDb(), { provider });
340
+ } catch {
341
+ return {
342
+ status: "unknown",
343
+ message: `Connections for provider "${provider}" could not be looked up. Try again shortly.`,
344
+ };
345
+ }
346
+ const active = candidates.find((candidate) =>
347
+ isConnectionCompatibleWithModel(candidate, model),
348
+ );
349
+ if (active) {
350
+ return computeConnectionAvailability(provider, active.name);
351
+ }
352
+ return {
353
+ status: "missing_connection",
354
+ message:
355
+ describeSubscriptionModelIncompatibility(candidates, model) ??
356
+ `Provider "${provider}" is a valid provider id, but no ${provider} connection/API key is configured, so this profile cannot serve requests.`,
357
+ };
358
+ }
@@ -163,6 +163,14 @@ export type CreateConnectionInput = {
163
163
 
164
164
  export type UpdateConnectionInput = {
165
165
  auth: Auth;
166
+ /**
167
+ * Optional provider correction. The HTTP PATCH route never passes this
168
+ * (provider is immutable there); it exists for owners of well-known rows
169
+ * to keep the provider truthful when they rewrite the auth, e.g. the
170
+ * ChatGPT sign-in flow stamping "openai" on the subscription row so a
171
+ * claiming row with a different provider cannot strand the fresh token.
172
+ */
173
+ provider?: string;
166
174
  label?: string | null;
167
175
  baseUrl?: string | null;
168
176
  models?: ConnectionModel[] | null;
@@ -178,6 +186,7 @@ export type ConnectionCreateError =
178
186
  export type ConnectionUpdateError =
179
187
  | { code: "not_found" }
180
188
  | { code: "invalid_auth" }
189
+ | { code: "invalid_provider"; provider: string }
181
190
  | { code: "base_url_required" }
182
191
  | { code: "models_required" };
183
192
 
@@ -278,12 +287,23 @@ export function updateConnection(
278
287
  return { ok: false, error: { code: "invalid_auth" } };
279
288
  }
280
289
 
290
+ if (
291
+ input.provider !== undefined &&
292
+ !VALID_CONNECTION_PROVIDERS.includes(input.provider as never)
293
+ ) {
294
+ return {
295
+ ok: false,
296
+ error: { code: "invalid_provider", provider: input.provider },
297
+ };
298
+ }
299
+ const nextProvider = input.provider ?? existing.provider;
300
+
281
301
  const nextBaseUrl =
282
302
  input.baseUrl !== undefined ? input.baseUrl : existing.baseUrl;
283
303
  const nextModels =
284
304
  input.models !== undefined ? input.models : existing.models;
285
305
 
286
- if (PROVIDERS_REQUIRING_BASE_URL_AND_MODELS.has(existing.provider)) {
306
+ if (PROVIDERS_REQUIRING_BASE_URL_AND_MODELS.has(nextProvider)) {
287
307
  if (!nextBaseUrl) {
288
308
  return { ok: false, error: { code: "base_url_required" } };
289
309
  }
@@ -296,10 +316,14 @@ export function updateConnection(
296
316
  const setClause: {
297
317
  auth: string;
298
318
  updatedAt: number;
319
+ provider?: string;
299
320
  label?: string | null;
300
321
  baseUrl?: string | null;
301
322
  models?: string | null;
302
323
  } = { auth: JSON.stringify(auth), updatedAt: now };
324
+ if (input.provider !== undefined) {
325
+ setClause.provider = input.provider;
326
+ }
303
327
  if (input.label !== undefined) {
304
328
  setClause.label = input.label;
305
329
  }
@@ -96,7 +96,7 @@ export function resolveMediaSourceData(
96
96
  return { data: bytes.toString("base64"), media_type: source.media_type };
97
97
  }
98
98
 
99
- function resolveImageBlock(block: ImageContent): ContentBlock {
99
+ async function resolveImageBlock(block: ImageContent): Promise<ContentBlock> {
100
100
  if (block.source.type === "base64") {
101
101
  return block;
102
102
  }
@@ -113,7 +113,7 @@ function resolveImageBlock(block: ImageContent): ContentBlock {
113
113
  }
114
114
  // Apply the same transport optimization the inline-base64 path used, so a
115
115
  // reloaded (reference) turn sends the model the same bytes a live turn would.
116
- const { data, mediaType } = optimizeImageForTransport(
116
+ const { data, mediaType } = await optimizeImageForTransport(
117
117
  bytes.toString("base64"),
118
118
  block.source.media_type,
119
119
  );
@@ -161,7 +161,7 @@ function resolveFileBlock(block: FileContent): ContentBlock {
161
161
  };
162
162
  }
163
163
 
164
- function resolveBlock(block: ContentBlock): ContentBlock {
164
+ async function resolveBlock(block: ContentBlock): Promise<ContentBlock> {
165
165
  switch (block.type) {
166
166
  case "image":
167
167
  return resolveImageBlock(block);
@@ -172,7 +172,10 @@ function resolveBlock(block: ContentBlock): ContentBlock {
172
172
  if (!block.contentBlocks?.length) {
173
173
  return block;
174
174
  }
175
- return { ...block, contentBlocks: block.contentBlocks.map(resolveBlock) };
175
+ return {
176
+ ...block,
177
+ contentBlocks: await Promise.all(block.contentBlocks.map(resolveBlock)),
178
+ };
176
179
  }
177
180
  default:
178
181
  return block;
@@ -197,11 +200,18 @@ function contentHasReference(content: ContentBlock[]): boolean {
197
200
  * (same object reference) so the common all-base64 live turn does no allocation
198
201
  * or disk I/O.
199
202
  */
200
- export function resolveMediaReferences(messages: Message[]): Message[] {
201
- return messages.map((message) => {
202
- if (!contentHasReference(message.content)) {
203
- return message;
204
- }
205
- return { ...message, content: message.content.map(resolveBlock) };
206
- });
203
+ export function resolveMediaReferences(
204
+ messages: Message[],
205
+ ): Promise<Message[]> {
206
+ return Promise.all(
207
+ messages.map(async (message) => {
208
+ if (!contentHasReference(message.content)) {
209
+ return message;
210
+ }
211
+ return {
212
+ ...message,
213
+ content: await Promise.all(message.content.map(resolveBlock)),
214
+ };
215
+ }),
216
+ );
207
217
  }
@@ -2233,6 +2233,21 @@ export function getCatalogProviderForModel(
2233
2233
  ?.id;
2234
2234
  }
2235
2235
 
2236
+ /**
2237
+ * Human-readable display name for a model id, from the first catalog entry
2238
+ * that serves it (a model carries the same display name under every provider
2239
+ * that offers it). Undefined for uncataloged ids.
2240
+ */
2241
+ export function getModelDisplayName(modelId: string): string | undefined {
2242
+ for (const provider of PROVIDER_CATALOG) {
2243
+ const match = provider.models.find((m) => m.id === modelId);
2244
+ if (match) {
2245
+ return match.displayName;
2246
+ }
2247
+ }
2248
+ return undefined;
2249
+ }
2250
+
2236
2251
  /**
2237
2252
  * Whether the given model only supports adaptive (always-on) thinking, driven
2238
2253
  * by the `adaptiveThinkingOnly` capability in the catalog. Matches the model ID
@@ -383,7 +383,7 @@ export class OpenAIChatCompletionsProvider implements Provider {
383
383
  const coercedObjectKeys = new Map<string, string[]>();
384
384
 
385
385
  try {
386
- const openaiMessages = this.toOpenAIMessages(
386
+ const openaiMessages = await this.toOpenAIMessages(
387
387
  messages,
388
388
  systemPrompt,
389
389
  modelSupportsAudioInput(modelOverride ?? this.model),
@@ -940,14 +940,14 @@ export class OpenAIChatCompletionsProvider implements Provider {
940
940
  }
941
941
 
942
942
  /** Convert neutral messages + system prompt to OpenAI message format. */
943
- private toOpenAIMessages(
943
+ private async toOpenAIMessages(
944
944
  messages: Message[],
945
945
  systemPrompt?: string,
946
946
  audioInputEnabled = false,
947
- ): OpenAI.Chat.Completions.ChatCompletionMessageParam[] {
947
+ ): Promise<OpenAI.Chat.Completions.ChatCompletionMessageParam[]> {
948
948
  // Swap any persisted attachment references back to inline base64 before
949
949
  // serializing, so the block transforms below can read `source.data`.
950
- messages = resolveMediaReferences(messages);
950
+ messages = await resolveMediaReferences(messages);
951
951
  const result: OpenAI.Chat.Completions.ChatCompletionMessageParam[] = [];
952
952
 
953
953
  if (systemPrompt) {
@@ -231,8 +231,6 @@ export class OpenAIResponsesProvider implements Provider {
231
231
  const usageAttributionHeaders = configObj?.usageAttributionHeaders as
232
232
  | Record<string, string>
233
233
  | undefined;
234
- const mutableLatestUserMessage =
235
- configObj?.mutableLatestUserMessage === true;
236
234
  const disableCache = configObj?.disableCache === true;
237
235
  const disableTurnStartCache = configObj?.disableTurnStartCache === true;
238
236
  const promptCacheKey =
@@ -244,7 +242,7 @@ export class OpenAIResponsesProvider implements Provider {
244
242
  try {
245
243
  const effectiveModel = modelOverride ?? this.model;
246
244
  recordProviderRequestDiagnostics({ model_id: effectiveModel });
247
- const input = this.toResponsesInput(messages);
245
+ const input = await this.toResponsesInput(messages);
248
246
 
249
247
  const params: Record<string, unknown> = {
250
248
  model: effectiveModel,
@@ -273,8 +271,8 @@ export class OpenAIResponsesProvider implements Provider {
273
271
 
274
272
  // Explicit prompt-cache mode (GPT-5.6+ semantics, direct API only).
275
273
  // Explicit mode disables the implicit latest-message breakpoint — under
276
- // implicit mode a volatile latest user message (mutableLatestUserMessage)
277
- // makes every cached entry end at content that never recurs: zero reads
274
+ // implicit mode a volatile latest user message makes every cached entry
275
+ // end at content that never recurs across turns: zero reads
278
276
  // plus a full-prompt 1.25x write per turn. With explicit markers we
279
277
  // choose the stable boundaries ourselves. Under `disableCache` we still
280
278
  // send explicit mode but stamp no markers: a request with no explicit
@@ -288,10 +286,7 @@ export class OpenAIResponsesProvider implements Provider {
288
286
  ) {
289
287
  params.prompt_cache_options = { mode: "explicit" };
290
288
  if (!disableCache) {
291
- this.applyPromptCacheBreakpoints(input, {
292
- mutableLatestUserMessage,
293
- disableTurnStartCache,
294
- });
289
+ this.applyPromptCacheBreakpoints(input, { disableTurnStartCache });
295
290
  }
296
291
  }
297
292
 
@@ -753,10 +748,10 @@ export class OpenAIResponsesProvider implements Provider {
753
748
  *
754
749
  * System prompt is NOT included here — it goes into the `instructions` param.
755
750
  */
756
- private toResponsesInput(messages: Message[]): unknown[] {
751
+ private async toResponsesInput(messages: Message[]): Promise<unknown[]> {
757
752
  // Swap any persisted attachment references back to inline base64 before
758
753
  // serializing, so the block transforms below can read `source.data`.
759
- messages = resolveMediaReferences(messages);
754
+ messages = await resolveMediaReferences(messages);
760
755
  const result: unknown[] = [];
761
756
 
762
757
  // `call_id`s emitted as `function_call` items earlier in this request.
@@ -788,8 +783,11 @@ export class OpenAIResponsesProvider implements Provider {
788
783
  * historical user-message boundaries makes the newest still-matching one
789
784
  * the read point; in the volatile-latest-message flow that is typically
790
785
  * the previous turn's user message once it re-renders without its
791
- * injected block. Marking the volatile latest item itself prepays its
792
- * write so in-turn tool-loop iterations read it back. The ladder is
786
+ * injected block. Every markable item is marked, including a volatile
787
+ * latest user message that is the only one on a first turn: a volatile
788
+ * message is still fixed within its own turn, so marking it prepays one
789
+ * write that every in-turn tool-loop iteration reads back, and cross-turn
790
+ * the ladder re-marks whichever boundaries recur. The ladder is
793
791
  * cost-safe: OpenAI writes at most the latest four unmatched marked
794
792
  * boundaries per request and considers up to the latest 50 markers for
795
793
  * reads. All breakpoints share the fixed 30m TTL (no `ttl` field is
@@ -811,7 +809,7 @@ export class OpenAIResponsesProvider implements Provider {
811
809
  */
812
810
  private applyPromptCacheBreakpoints(
813
811
  input: unknown[],
814
- opts: { mutableLatestUserMessage: boolean; disableTurnStartCache: boolean },
812
+ opts: { disableTurnStartCache: boolean },
815
813
  ): void {
816
814
  const items = input as ResponsesMessageItem[];
817
815
 
@@ -866,17 +864,6 @@ export class OpenAIResponsesProvider implements Provider {
866
864
  return;
867
865
  }
868
866
 
869
- // A volatile latest user message with no prior user message to anchor
870
- // on: every marker would be a write whose prefix never recurs across
871
- // turns — skip caching entirely for this request.
872
- if (
873
- opts.mutableLatestUserMessage &&
874
- candidates.length === 1 &&
875
- candidates[0] === items.length - 1
876
- ) {
877
- return;
878
- }
879
-
880
867
  for (const idx of candidates) {
881
868
  // `disableTurnStartCache` suppresses the marker on the turn-start
882
869
  // (newest user) item — one-shot call sites whose prompts never
@@ -17,7 +17,10 @@ import {
17
17
  // Per-connection provider cache (mix-and-match support)
18
18
  // ---------------------------------------------------------------------------
19
19
  import type { ProviderConnection } from "./inference/auth.js";
20
- import { ROUTING_IDENTITY_PROVIDERS } from "./inference/auth.js";
20
+ import {
21
+ effectiveConnectionAuth,
22
+ ROUTING_IDENTITY_PROVIDERS,
23
+ } from "./inference/auth.js";
21
24
  import { resolveAuth } from "./inference/resolve-auth.js";
22
25
  import { isModelInCatalog, PROVIDER_CATALOG } from "./model-catalog.js";
23
26
  import { getProviderDefaultModel } from "./model-intents.js";
@@ -333,9 +336,11 @@ export async function resolveProviderFromConnection(
333
336
  // re-read from the store below, so a key rotated since the entry was cached
334
337
  // is picked up here rather than served stale forever.
335
338
 
336
- const authResult = await resolveAuth(connection.auth, effectiveProvider, {
337
- baseUrl: connection.baseUrl,
338
- });
339
+ const authResult = await resolveAuth(
340
+ effectiveConnectionAuth(connection),
341
+ effectiveProvider,
342
+ { baseUrl: connection.baseUrl },
343
+ );
339
344
  if (!authResult.ok) {
340
345
  const err = authResult.error;
341
346
  if (err.code === "not_implemented") {
@@ -4,6 +4,7 @@ import {
4
4
  resolveUsageAttribution,
5
5
  sanitizeUsageMetadataValue,
6
6
  } from "../usage/attribution.js";
7
+ import { resolveSubagentAttribution } from "../usage/subagent-attribution.js";
7
8
  import {
8
9
  type ProviderCredentialSource,
9
10
  ProviderError,
@@ -49,6 +50,12 @@ const USAGE_ATTRIBUTION_HEADER_NAMES = {
49
50
  resolvedProvider: "X-Vellum-Resolved-Provider",
50
51
  resolvedModel: "X-Vellum-Resolved-Model",
51
52
  resolvedMixArm: "X-Vellum-Resolved-Mix-Arm",
53
+ // Delegated-work attribution. Every subagent variety shares
54
+ // `llm_call_site = "subagentSpawn"`, so on the authoritative billing path
55
+ // these two orthogonal dimensions are the only way to tell an advisor
56
+ // consult from a fork from a regular spawn.
57
+ subagentRole: "X-Vellum-Subagent-Role",
58
+ subagentSpawnMode: "X-Vellum-Subagent-Spawn-Mode",
52
59
  } as const;
53
60
 
54
61
  /** Providers whose transports consume `promptCacheKey` (OpenAI Responses
@@ -422,6 +429,10 @@ function normalizeSendMessageOptions(
422
429
  // downstream as a wire-format field.
423
430
  delete nextConfig.callSite;
424
431
  if (normalizeOptions.forwardUsageAttributionHeaders === true) {
432
+ // Read from the conversation row rather than the live SubagentManager:
433
+ // the row is durable and the lookup is a memoized primary-key read that
434
+ // can never throw, so billing attribution cannot destabilize dispatch.
435
+ const subagent = resolveSubagentAttribution(config.conversationId);
425
436
  const usageAttributionHeaders = buildUsageAttributionHeaders({
426
437
  callSite: attribution.callSite,
427
438
  appliedProfile: attribution.appliedProfile,
@@ -429,6 +440,8 @@ function normalizeSendMessageOptions(
429
440
  resolvedProvider: attribution.resolvedProvider,
430
441
  resolvedModel: attribution.resolvedModel,
431
442
  resolvedMixArm: attribution.resolvedMixArm,
443
+ subagentRole: subagent.subagentRole,
444
+ subagentSpawnMode: subagent.subagentSpawnMode,
432
445
  });
433
446
  if (Object.keys(usageAttributionHeaders).length > 0) {
434
447
  nextConfig.usageAttributionHeaders = usageAttributionHeaders;
@@ -769,6 +782,8 @@ function buildUsageAttributionHeaders(input: {
769
782
  resolvedProvider: string;
770
783
  resolvedModel: string;
771
784
  resolvedMixArm: string | null;
785
+ subagentRole: string | null;
786
+ subagentSpawnMode: string | null;
772
787
  }): Record<string, string> {
773
788
  const headers: Record<string, string> = {};
774
789
  addSanitizedHeader(
@@ -803,6 +818,16 @@ function buildUsageAttributionHeaders(input: {
803
818
  USAGE_ATTRIBUTION_HEADER_NAMES.resolvedMixArm,
804
819
  input.resolvedMixArm,
805
820
  );
821
+ addSanitizedHeader(
822
+ headers,
823
+ USAGE_ATTRIBUTION_HEADER_NAMES.subagentRole,
824
+ input.subagentRole,
825
+ );
826
+ addSanitizedHeader(
827
+ headers,
828
+ USAGE_ATTRIBUTION_HEADER_NAMES.subagentSpawnMode,
829
+ input.subagentSpawnMode,
830
+ );
806
831
  return headers;
807
832
  }
808
833