@vellumai/assistant 0.11.2 → 0.11.3-staging.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (720) hide show
  1. package/ARCHITECTURE.md +58 -3
  2. package/docs/trusted-contact-access.md +9 -5
  3. package/docs/vellum-doctor.md +195 -0
  4. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +39 -0
  5. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
  6. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
  7. package/node_modules/@vellumai/ces-client/src/index.ts +1 -0
  8. package/node_modules/@vellumai/ces-client/src/rpc-client.ts +19 -2
  9. package/node_modules/@vellumai/environments/package.json +2 -1
  10. package/node_modules/@vellumai/environments/src/__tests__/cloud-assistant-hub-url.test.ts +38 -0
  11. package/node_modules/@vellumai/environments/src/__tests__/install-layout.test.ts +98 -0
  12. package/node_modules/@vellumai/environments/src/__tests__/package-boundary.test.ts +5 -5
  13. package/node_modules/@vellumai/environments/src/index.ts +17 -6
  14. package/node_modules/@vellumai/environments/src/install-layout.ts +49 -0
  15. package/node_modules/@vellumai/environments/src/seeds.ts +29 -0
  16. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +39 -0
  17. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
  18. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
  19. package/node_modules/@vellumai/gateway-client/src/index.ts +4 -0
  20. package/node_modules/@vellumai/gateway-client/src/verification-session-contract.ts +91 -6
  21. package/node_modules/@vellumai/ipc-server-utils/src/endpoint.test.ts +36 -0
  22. package/node_modules/@vellumai/ipc-server-utils/src/endpoint.ts +142 -0
  23. package/node_modules/@vellumai/ipc-server-utils/src/index.ts +2 -0
  24. package/node_modules/@vellumai/ipc-server-utils/src/listen-options.ts +3 -0
  25. package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.test.ts +15 -1
  26. package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.ts +17 -2
  27. package/node_modules/@vellumai/service-contracts/src/channels.ts +39 -0
  28. package/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
  29. package/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
  30. package/node_modules/@vellumai/slack-text/src/index.ts +16 -2
  31. package/openapi.yaml +589 -30
  32. package/package.json +1 -1
  33. package/src/__tests__/agent-image-optimize.test.ts +4 -4
  34. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +113 -66
  35. package/src/__tests__/agent-loop-override-profile.test.ts +38 -48
  36. package/src/__tests__/agent-loop-subagent-billing-headers.test.ts +166 -0
  37. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +1 -0
  38. package/src/__tests__/agent-wake-override-profile.test.ts +1 -0
  39. package/src/__tests__/answered-question-persistence.test.ts +240 -0
  40. package/src/__tests__/anthropic-provider.test.ts +165 -30
  41. package/src/__tests__/app-control-flow.test.ts +9 -8
  42. package/src/__tests__/assistant-event-hub.test.ts +48 -0
  43. package/src/__tests__/attachments-store-heic-normalize.test.ts +16 -12
  44. package/src/__tests__/attachments-store.test.ts +130 -68
  45. package/src/__tests__/attachments.test.ts +36 -36
  46. package/src/__tests__/background-workers-disk-pressure.test.ts +1 -1
  47. package/src/__tests__/call-start-guardian-guard.test.ts +18 -4
  48. package/src/__tests__/canned-reply-release.test.ts +86 -0
  49. package/src/__tests__/channel-guardian.test.ts +59 -29
  50. package/src/__tests__/channel-readiness-telegram-remote.test.ts +154 -0
  51. package/src/__tests__/channel-setup-panel-ack.test.ts +6 -5
  52. package/src/__tests__/client-os-metadata-persistence.test.ts +103 -4
  53. package/src/__tests__/compactor-image-manifest-trust.test.ts +1 -1
  54. package/src/__tests__/consult-deadline.test.ts +65 -0
  55. package/src/__tests__/conversation-agent-loop.test.ts +438 -2
  56. package/src/__tests__/conversation-disk-view-integration.test.ts +5 -1
  57. package/src/__tests__/conversation-disk-view.test.ts +4 -4
  58. package/src/__tests__/conversation-error.test.ts +22 -3
  59. package/src/__tests__/conversation-fork-crud.test.ts +5 -1
  60. package/src/__tests__/conversation-fork-referential.test.ts +352 -0
  61. package/src/__tests__/conversation-fork-retrospective.test.ts +5 -1
  62. package/src/__tests__/conversation-group-tools.test.ts +32 -2
  63. package/src/__tests__/conversation-inference-profile-route.test.ts +27 -1
  64. package/src/__tests__/conversation-initial-prompt.test.ts +51 -22
  65. package/src/__tests__/conversation-key-store-bootstrap-cleanup.test.ts +119 -0
  66. package/src/__tests__/conversation-key-store-origin.test.ts +105 -0
  67. package/src/__tests__/conversation-list-recency-ordering.test.ts +104 -0
  68. package/src/__tests__/conversation-origin-at-creation.test.ts +153 -0
  69. package/src/__tests__/conversation-origin-channel-filter.test.ts +95 -0
  70. package/src/__tests__/conversation-placement-promotion.test.ts +172 -0
  71. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +123 -0
  72. package/src/__tests__/conversation-queue.test.ts +433 -1
  73. package/src/__tests__/conversation-retry-route.test.ts +3 -1
  74. package/src/__tests__/conversation-routes-hidden-queue.test.ts +64 -1
  75. package/src/__tests__/conversation-store-ephemeral.test.ts +4 -0
  76. package/src/__tests__/conversation-store.test.ts +26 -10
  77. package/src/__tests__/conversation-summarize-route.test.ts +1 -1
  78. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +15 -6
  79. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +6 -5
  80. package/src/__tests__/conversation-surfaces-app-control.test.ts +12 -11
  81. package/src/__tests__/conversation-surfaces-app-open.test.ts +11 -5
  82. package/src/__tests__/conversation-surfaces-data-persist.test.ts +5 -4
  83. package/src/__tests__/conversation-surfaces-history-restored-completion.test.ts +967 -0
  84. package/src/__tests__/conversation-surfaces-persisted-info.test.ts +312 -0
  85. package/src/__tests__/conversation-surfaces-queued-emit.test.ts +6 -5
  86. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -8
  87. package/src/__tests__/conversation-surfaces-standalone.test.ts +21 -11
  88. package/src/__tests__/conversation-surfaces-state-update.test.ts +7 -11
  89. package/src/__tests__/conversation-surfaces-table-action.test.ts +7 -6
  90. package/src/__tests__/conversation-surfaces-task-progress.test.ts +11 -6
  91. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +9 -6
  92. package/src/__tests__/conversation-tool-setup-attribution.test.ts +70 -7
  93. package/src/__tests__/conversation-wait-for-idle.test.ts +6 -11
  94. package/src/__tests__/credential-prompt-route.test.ts +57 -7
  95. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  96. package/src/__tests__/cu-unified-flow.test.ts +89 -28
  97. package/src/__tests__/custom-group-listing-visibility.test.ts +1 -1
  98. package/src/__tests__/db-schedule-syntax-migration.test.ts +4 -1
  99. package/src/__tests__/discord-access-request-privacy.test.ts +366 -0
  100. package/src/__tests__/discord-requester-notice-privacy.test.ts +87 -0
  101. package/src/__tests__/disk-pressure-guard.test.ts +55 -55
  102. package/src/__tests__/disk-pressure-routes.test.ts +10 -10
  103. package/src/__tests__/disk-pressure-tools.test.ts +2 -2
  104. package/src/__tests__/disk-usage.test.ts +35 -20
  105. package/src/__tests__/document-sync-tags.test.ts +379 -0
  106. package/src/__tests__/document-update-default-surface.test.ts +28 -0
  107. package/src/__tests__/dynamic-skill-background-guard.test.ts +2 -2
  108. package/src/__tests__/emit-signal-routing-intent.test.ts +3 -4
  109. package/src/__tests__/ensure-conversation-exists.test.ts +8 -5
  110. package/src/__tests__/events-dev-bypass-actor.test.ts +183 -1
  111. package/src/__tests__/evict-conversations-for-reload.test.ts +90 -0
  112. package/src/__tests__/file-list-tool.test.ts +12 -10
  113. package/src/__tests__/file-ops-service.test.ts +151 -44
  114. package/src/__tests__/file-read-container-boundary.test.ts +137 -0
  115. package/src/__tests__/file-read-tool.test.ts +21 -9
  116. package/src/__tests__/file-url-path-guard.test.ts +83 -0
  117. package/src/__tests__/filesystem-tools.test.ts +82 -66
  118. package/src/__tests__/guardian-outbound-http.test.ts +8 -8
  119. package/src/__tests__/helpers/gateway-verification-sessions-stub.ts +14 -1
  120. package/src/__tests__/helpers/hub-clients.ts +42 -0
  121. package/src/__tests__/helpers/mock-conversation.ts +46 -0
  122. package/src/__tests__/helpers/verification-sessions-ipc-sim.ts +61 -57
  123. package/src/__tests__/history-repair.test.ts +112 -12
  124. package/src/__tests__/host-bash-proxy.test.ts +10 -5
  125. package/src/__tests__/host-bash-routes.test.ts +67 -0
  126. package/src/__tests__/host-browser-proxy.test.ts +2 -2
  127. package/src/__tests__/host-cu-proxy.test.ts +3 -7
  128. package/src/__tests__/host-file-proxy.test.ts +3 -7
  129. package/src/__tests__/host-file-read-tool.test.ts +5 -1
  130. package/src/__tests__/host-transfer-proxy-targeted.test.ts +6 -4
  131. package/src/__tests__/http-conversation-lineage.test.ts +2 -5
  132. package/src/__tests__/http-user-message-parity.test.ts +44 -0
  133. package/src/__tests__/identity-routes.test.ts +13 -13
  134. package/src/__tests__/image-conversion.test.ts +29 -26
  135. package/src/__tests__/image-source-path-reinject.test.ts +2 -2
  136. package/src/__tests__/inference-profile-session-handler.test.ts +95 -0
  137. package/src/__tests__/inference-profile-session-ipc.test.ts +25 -0
  138. package/src/__tests__/introduction-card-resolver.test.ts +6 -1
  139. package/src/__tests__/list-messages-attachments.test.ts +56 -32
  140. package/src/__tests__/list-messages-background-tool-completion.test.ts +4 -4
  141. package/src/__tests__/list-messages-client-message-id.test.ts +2 -2
  142. package/src/__tests__/list-messages-hidden-metadata.test.ts +16 -16
  143. package/src/__tests__/list-messages-page-latest.test.ts +61 -61
  144. package/src/__tests__/list-messages-provider-error.test.ts +6 -6
  145. package/src/__tests__/list-messages-queued.test.ts +49 -6
  146. package/src/__tests__/list-messages-system-card.test.ts +4 -4
  147. package/src/__tests__/list-messages-tool-merge.test.ts +9 -9
  148. package/src/__tests__/llm-resolver-override-or-default.test.ts +141 -0
  149. package/src/__tests__/llm-usage-store.test.ts +55 -0
  150. package/src/__tests__/manual-token-reconciliation.test.ts +45 -0
  151. package/src/__tests__/mcp-tool-annotations-risk.test.ts +133 -0
  152. package/src/__tests__/media-stream-server-integration.test.ts +36 -0
  153. package/src/__tests__/migration-export-http.test.ts +1 -1
  154. package/src/__tests__/migration-import-commit-http.test.ts +1 -1
  155. package/src/__tests__/migration-import-preflight-http.test.ts +1 -1
  156. package/src/__tests__/migration-validate-http.test.ts +1 -1
  157. package/src/__tests__/mtime-cache.test.ts +65 -3
  158. package/src/__tests__/notification-platform-adapter.test.ts +104 -0
  159. package/src/__tests__/notification-schedule-notify-dedup.test.ts +1 -1
  160. package/src/__tests__/oauth-provider-profiles.test.ts +4 -2
  161. package/src/__tests__/oauth-provider-seed-logos.test.ts +65 -0
  162. package/src/__tests__/oauth-provider-serializer.test.ts +17 -0
  163. package/src/__tests__/oauth-providers-routes.test.ts +1 -0
  164. package/src/__tests__/openai-responses-prompt-cache.test.ts +5 -2
  165. package/src/__tests__/path-policy.test.ts +164 -1
  166. package/src/__tests__/persist-media-references.test.ts +2 -2
  167. package/src/__tests__/persist-unsendable-image-downscale.test.ts +5 -5
  168. package/src/__tests__/persist-unsendable-image.test.ts +23 -23
  169. package/src/__tests__/persona-resolver.test.ts +154 -0
  170. package/src/__tests__/plugin-api-webhook-url.test.ts +170 -0
  171. package/src/__tests__/plugin-import-boundary-guard.test.ts +6 -0
  172. package/src/__tests__/processing-flag-persist-failure.test.ts +15 -10
  173. package/src/__tests__/profile-availability-incomplete.test.ts +113 -0
  174. package/src/__tests__/profiler-routes.test.ts +13 -13
  175. package/src/__tests__/prompt-cache-cross-turn-stability.test.ts +593 -0
  176. package/src/__tests__/proxy-approval-callback.test.ts +3 -3
  177. package/src/__tests__/queued-message-cancel-and-steer.test.ts +189 -0
  178. package/src/__tests__/queued-message-steer-actor-scoping.test.ts +164 -0
  179. package/src/__tests__/resolve-trust-class.test.ts +20 -0
  180. package/src/__tests__/run-conversation-turn-persistence.test.ts +1 -1
  181. package/src/__tests__/run-due-schedules.test.ts +174 -0
  182. package/src/__tests__/runtime-attachment-metadata.test.ts +15 -7
  183. package/src/__tests__/scaffold-managed-skill-tool.test.ts +166 -0
  184. package/src/__tests__/schedule-routes.test.ts +730 -8
  185. package/src/__tests__/schedule-store.test.ts +540 -0
  186. package/src/__tests__/schedule-tools.test.ts +103 -0
  187. package/src/__tests__/scheduler-wake.test.ts +5 -0
  188. package/src/__tests__/secret-routes-platform-proxy.test.ts +29 -1
  189. package/src/__tests__/secure-keys.test.ts +91 -0
  190. package/src/__tests__/server-history-render.test.ts +97 -7
  191. package/src/__tests__/size-guard.test.ts +8 -8
  192. package/src/__tests__/skill-docs-sync-guard.test.ts +3 -2
  193. package/src/__tests__/skill-tool-factory.test.ts +247 -0
  194. package/src/__tests__/skills-install-staging.test.ts +15 -6
  195. package/src/__tests__/slack-edit-ordering-characterization.test.ts +103 -0
  196. package/src/__tests__/slack-inbound-verification.test.ts +4 -1
  197. package/src/__tests__/slack-mention-binding-invariance.test.ts +103 -0
  198. package/src/__tests__/slack-mention-provider-leak-audit.test.ts +135 -0
  199. package/src/__tests__/starter-task-flow.test.ts +5 -4
  200. package/src/__tests__/steer-on-enqueue-question.test.ts +3 -2
  201. package/src/__tests__/stt-language-catalog-parity.test.ts +38 -0
  202. package/src/__tests__/subagent-allowlist-validation.test.ts +26 -4
  203. package/src/__tests__/subagent-cron-run-attribution.test.ts +301 -0
  204. package/src/__tests__/subagent-disposal.test.ts +10 -0
  205. package/src/__tests__/subagent-fork-notifications.test.ts +10 -0
  206. package/src/__tests__/subagent-fork-prompt-role.test.ts +85 -11
  207. package/src/__tests__/subagent-fork-spawn.test.ts +15 -7
  208. package/src/__tests__/subagent-manager-notify.test.ts +148 -0
  209. package/src/__tests__/subagent-notify-parent.test.ts +1 -1
  210. package/src/__tests__/subagent-persistence.test.ts +141 -0
  211. package/src/__tests__/subagent-role-registry.test.ts +172 -63
  212. package/src/__tests__/subagent-role-resolution.test.ts +88 -0
  213. package/src/__tests__/subagent-spawn-and-await.test.ts +48 -0
  214. package/src/__tests__/subagent-spawn-tool-fork.test.ts +111 -10
  215. package/src/__tests__/subagent-terminal-message.test.ts +88 -1
  216. package/src/__tests__/subagent-tool-gate-mode.test.ts +225 -10
  217. package/src/__tests__/subagent-tools.test.ts +1901 -108
  218. package/src/__tests__/surface-completion-compaction-boundary.test.ts +124 -0
  219. package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +298 -0
  220. package/src/__tests__/system-prompt.test.ts +82 -7
  221. package/src/__tests__/tool-grant-request-escalation.test.ts +40 -1
  222. package/src/__tests__/tool-result-spool.test.ts +74 -18
  223. package/src/__tests__/tool-side-effects-documents.test.ts +174 -0
  224. package/src/__tests__/tool-side-effects-hook-failures.test.ts +129 -0
  225. package/src/__tests__/tools-audio-read.test.ts +10 -10
  226. package/src/__tests__/tools-get-route.test.ts +85 -12
  227. package/src/__tests__/tools-list-cli.test.ts +171 -0
  228. package/src/__tests__/top-level-renderer.test.ts +54 -1
  229. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +68 -1
  230. package/src/__tests__/trusted-contact-multichannel.test.ts +4 -1
  231. package/src/__tests__/turn-tail-chain.test.ts +135 -0
  232. package/src/__tests__/ui-choice-copy-surfaces.test.ts +6 -4
  233. package/src/__tests__/ui-visual-surface.test.ts +5 -4
  234. package/src/__tests__/ui-work-result-surface.test.ts +5 -4
  235. package/src/__tests__/unified-turn-context-visible-app.test.ts +7 -8
  236. package/src/__tests__/usage-routes.test.ts +62 -0
  237. package/src/__tests__/verification-outbound-delivery.test.ts +176 -0
  238. package/src/__tests__/visible-app-context.test.ts +20 -4
  239. package/src/__tests__/web-search-history.test.ts +96 -0
  240. package/src/__tests__/workspace-migration-139-clear-renamed-cost-profile-label.test.ts +6 -6
  241. package/src/__tests__/workspace-migration-140-repair-seed-pinned-memory-v3-live.test.ts +330 -0
  242. package/src/acp/failure-error.ts +3 -5
  243. package/src/agent/attachments.ts +26 -24
  244. package/src/agent/history-repair/history-repair.ts +27 -26
  245. package/src/agent/image-optimize.ts +6 -6
  246. package/src/agent/loop.ts +40 -22
  247. package/src/agent/message-types.ts +3 -3
  248. package/src/api/constants/document-tools.ts +55 -0
  249. package/src/api/events/question-answered.ts +53 -0
  250. package/src/api/events/tool-result.ts +7 -0
  251. package/src/api/index.ts +13 -0
  252. package/src/api/responses/conversation-message.ts +11 -0
  253. package/src/api/surfaces-oauth-connect.test.ts +96 -0
  254. package/src/api/surfaces.ts +36 -8
  255. package/src/approvals/guardian-channel-delivery.ts +83 -0
  256. package/src/approvals/guardian-expiry-notifier.ts +13 -11
  257. package/src/approvals/guardian-request-resolvers.ts +222 -135
  258. package/src/calls/__tests__/voice-session-bridge.test.ts +50 -0
  259. package/src/calls/media-stream-server.ts +9 -1
  260. package/src/calls/voice-session-bridge.ts +38 -0
  261. package/src/channels/__tests__/gateway-verification-sessions.test.ts +3 -3
  262. package/src/channels/config.ts +7 -2
  263. package/src/channels/gateway-verification-sessions.ts +7 -2
  264. package/src/channels/types.ts +7 -1
  265. package/src/cli/commands/__tests__/cache.test.ts +7 -4
  266. package/src/cli/commands/__tests__/cli-test-harness.ts +82 -0
  267. package/src/cli/commands/__tests__/conversations-wake.test.ts +51 -6
  268. package/src/cli/commands/__tests__/inference-models.test.ts +14 -0
  269. package/src/cli/commands/__tests__/inference-profiles.test.ts +44 -1
  270. package/src/cli/commands/__tests__/inference-providers.test.ts +7 -0
  271. package/src/cli/commands/__tests__/plugins.test.ts +692 -0
  272. package/src/cli/commands/__tests__/schedules.test.ts +136 -37
  273. package/src/cli/commands/conversations.ts +7 -3
  274. package/src/cli/commands/credentials.help.ts +7 -0
  275. package/src/cli/commands/inference-profiles.ts +9 -3
  276. package/src/cli/commands/inference.help.ts +16 -2
  277. package/src/cli/commands/mcp.help.ts +4 -2
  278. package/src/cli/commands/memory/memory-retrospective.ts +18 -0
  279. package/src/cli/commands/notifications.ts +3 -6
  280. package/src/cli/commands/oauth/connect-surface-guidance.test.ts +16 -0
  281. package/src/cli/commands/oauth/connect-surface-guidance.ts +25 -7
  282. package/src/cli/commands/oauth/connect.test.ts +26 -1
  283. package/src/cli/commands/oauth/connect.ts +4 -1
  284. package/src/cli/commands/oauth/index.help.ts +3 -1
  285. package/src/cli/commands/oauth/providers.ts +3 -0
  286. package/src/cli/commands/plugins.help.ts +25 -2
  287. package/src/cli/commands/plugins.ts +289 -10
  288. package/src/cli/commands/schedules.help.ts +14 -12
  289. package/src/cli/commands/schedules.ts +19 -5
  290. package/src/cli/commands/tools.help.ts +4 -2
  291. package/src/cli/commands/tools.ts +38 -0
  292. package/src/cli/lib/__tests__/inspect-plugin.test.ts +1 -0
  293. package/src/cli/lib/__tests__/install-from-github.test.ts +79 -0
  294. package/src/cli/lib/__tests__/install-from-platform.test.ts +47 -1
  295. package/src/cli/lib/__tests__/plugin-surfaces.test.ts +86 -7
  296. package/src/cli/lib/__tests__/upgrade-plugin.test.ts +122 -0
  297. package/src/cli/lib/install-from-github.ts +61 -0
  298. package/src/cli/lib/install-from-platform.ts +13 -2
  299. package/src/cli/lib/plugin-surfaces.ts +124 -4
  300. package/src/cli/lib/upgrade-plugin.ts +18 -0
  301. package/src/cli.ts +1 -1
  302. package/src/config/__tests__/deployment-context-defaults.test.ts +73 -0
  303. package/src/config/__tests__/memory-retrospective-schema.test.ts +40 -0
  304. package/src/config/__tests__/plugin-updates-schema.test.ts +43 -0
  305. package/src/config/__tests__/profile-tool-support.test.ts +131 -0
  306. package/src/config/bundled-skills/AGENTS.md +1 -1
  307. package/src/config/bundled-skills/app-builder/SKILL.md +1 -1
  308. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +3 -3
  309. package/src/config/bundled-skills/schedule/SKILL.md +5 -1
  310. package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
  311. package/src/config/bundled-skills/settings/TOOLS.json +2 -2
  312. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +1 -0
  313. package/src/config/bundled-skills/subagent/SKILL.md +53 -22
  314. package/src/config/bundled-skills/subagent/TOOLS.json +14 -13
  315. package/src/config/bundled-skills/visualize/SKILL.md +1 -1
  316. package/src/config/default-profile-catalog.ts +6 -2
  317. package/src/config/feature-flag-registry.json +25 -17
  318. package/src/config/llm-resolver.ts +45 -15
  319. package/src/config/loader.ts +70 -1
  320. package/src/config/profile-tool-support.ts +110 -0
  321. package/src/config/sanitize-for-transfer.ts +11 -0
  322. package/src/config/schema.ts +4 -0
  323. package/src/config/schemas/__tests__/stt.test.ts +20 -5
  324. package/src/config/schemas/channels.ts +13 -0
  325. package/src/config/schemas/memory-retrospective.ts +25 -0
  326. package/src/config/schemas/plugin-updates.ts +55 -0
  327. package/src/config/schemas/services.ts +8 -4
  328. package/src/config/schemas/stt.ts +17 -5
  329. package/src/config/schemas/timeouts.ts +1 -1
  330. package/src/contacts/__tests__/guardian-delivery-reader.test.ts +16 -0
  331. package/src/contacts/guardian-delivery-reader.ts +29 -2
  332. package/src/context/compactor.ts +4 -4
  333. package/src/context/post-turn-tool-result-truncation.ts +32 -16
  334. package/src/context/strip-injections.ts +42 -0
  335. package/src/context/tool-result-spool.ts +32 -18
  336. package/src/credential-execution/ces-runtime.ts +3 -0
  337. package/src/credential-execution/client.ts +22 -1
  338. package/src/credential-execution/process-manager.test.ts +99 -0
  339. package/src/credential-execution/process-manager.ts +62 -16
  340. package/src/daemon/__tests__/abort-null-controller.test.ts +141 -5
  341. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +8 -12
  342. package/src/daemon/__tests__/install-assistant-command.test.ts +234 -0
  343. package/src/daemon/__tests__/turn-tail-assistant-reply-notify.test.ts +2 -4
  344. package/src/daemon/__tests__/turn-tail-deleted-conversation.test.ts +20 -29
  345. package/src/daemon/channel-ui-capability.ts +4 -4
  346. package/src/daemon/conversation-agent-loop-handlers.ts +117 -61
  347. package/src/daemon/conversation-agent-loop.ts +318 -148
  348. package/src/daemon/conversation-attachments.ts +1 -1
  349. package/src/daemon/conversation-error.ts +8 -1
  350. package/src/daemon/conversation-initial-prompt.ts +16 -38
  351. package/src/daemon/conversation-lifecycle.ts +154 -32
  352. package/src/daemon/conversation-messaging.ts +106 -43
  353. package/src/daemon/conversation-process.ts +131 -33
  354. package/src/daemon/conversation-queue-manager.ts +10 -0
  355. package/src/daemon/conversation-runtime-assembly.ts +9 -4
  356. package/src/daemon/conversation-store.ts +52 -3
  357. package/src/daemon/conversation-surface-state.ts +9 -0
  358. package/src/daemon/conversation-surfaces.ts +403 -210
  359. package/src/daemon/conversation-tool-setup.ts +56 -7
  360. package/src/daemon/conversation-turn-finalize.ts +134 -89
  361. package/src/daemon/conversation.ts +111 -27
  362. package/src/daemon/disk-pressure-guard-lifecycle.ts +2 -2
  363. package/src/daemon/disk-pressure-guard.ts +3 -3
  364. package/src/daemon/doordash-steps.ts +5 -5
  365. package/src/daemon/external-plugins-bootstrap.ts +7 -1
  366. package/src/daemon/handlers/config-channels.ts +48 -5
  367. package/src/daemon/handlers/conversation-history.ts +1 -1
  368. package/src/daemon/handlers/conversations.ts +62 -17
  369. package/src/daemon/handlers/shared.ts +12 -0
  370. package/src/daemon/handlers/skills.ts +11 -1
  371. package/src/daemon/identity-helpers.ts +38 -10
  372. package/src/daemon/install-assistant-command.ts +322 -0
  373. package/src/daemon/lifecycle.ts +14 -3
  374. package/src/daemon/message-types/conversations.ts +6 -7
  375. package/src/daemon/message-types/sync.ts +1 -0
  376. package/src/daemon/persist-media-references.ts +23 -14
  377. package/src/daemon/process-message.ts +6 -6
  378. package/src/daemon/tool-setup-types.ts +19 -122
  379. package/src/daemon/tool-side-effects.ts +17 -94
  380. package/src/daemon/trust-context-types.ts +39 -0
  381. package/src/daemon/trust-context.ts +14 -6
  382. package/src/daemon/turn-tail-chain.ts +73 -0
  383. package/src/daemon/web-search-history.ts +47 -33
  384. package/src/heartbeat/heartbeat-service.ts +6 -6
  385. package/src/ipc/__tests__/socket-path.test.ts +21 -0
  386. package/src/ipc/assistant-server.ts +17 -10
  387. package/src/ipc/cli-client.ts +10 -1
  388. package/src/ipc/routes/__tests__/documents-sync-ipc-routes.test.ts +56 -0
  389. package/src/ipc/routes/documents-sync-ipc-routes.ts +42 -0
  390. package/src/ipc/socket-cleanup.ts +9 -7
  391. package/src/ipc/socket-path.ts +4 -96
  392. package/src/live-voice/__tests__/live-voice-archive.test.ts +16 -16
  393. package/src/live-voice/__tests__/live-voice-attach-image.test.ts +209 -0
  394. package/src/live-voice/__tests__/live-voice-connection.test.ts +20 -0
  395. package/src/live-voice/__tests__/live-voice-integration.test.ts +7 -5
  396. package/src/live-voice/__tests__/live-voice-session-telemetry.test.ts +265 -0
  397. package/src/live-voice/__tests__/live-voice-stt.test.ts +6 -1
  398. package/src/live-voice/__tests__/live-voice-vad.test.ts +35 -15
  399. package/src/live-voice/__tests__/protocol.test.ts +52 -0
  400. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +3 -0
  401. package/src/live-voice/live-voice-archive.ts +13 -13
  402. package/src/live-voice/live-voice-connection.ts +7 -1
  403. package/src/live-voice/live-voice-photo.ts +169 -0
  404. package/src/live-voice/live-voice-session.ts +108 -4
  405. package/src/live-voice/protocol.ts +89 -1
  406. package/src/mcp/client.ts +10 -0
  407. package/src/messaging/providers/__tests__/callback-routing.test.ts +5 -1
  408. package/src/messaging/providers/__tests__/transport-dispatch.test.ts +66 -4
  409. package/src/messaging/providers/callback-routing.ts +1 -0
  410. package/src/messaging/providers/discord/api.ts +312 -0
  411. package/src/messaging/providers/discord/dm-delivery.test.ts +204 -0
  412. package/src/messaging/providers/discord/render.test.ts +204 -0
  413. package/src/messaging/providers/discord/render.ts +195 -0
  414. package/src/messaging/providers/discord/send.test.ts +179 -0
  415. package/src/messaging/providers/discord/send.ts +212 -0
  416. package/src/messaging/providers/discord/transport.ts +81 -0
  417. package/src/messaging/providers/index.ts +3 -1
  418. package/src/messaging/providers/retry-policy.test.ts +247 -0
  419. package/src/messaging/providers/retry-policy.ts +206 -0
  420. package/src/messaging/providers/slack/mention-source.test.ts +285 -0
  421. package/src/messaging/providers/slack/mention-source.ts +287 -0
  422. package/src/messaging/providers/telegram-bot/api.ts +47 -130
  423. package/src/messaging/providers/whatsapp/api.ts +47 -136
  424. package/src/monitoring/__tests__/db-integrity-sample.test.ts +4 -1
  425. package/src/monitoring/__tests__/plugin-auto-update.test.ts +332 -0
  426. package/src/monitoring/db-integrity-sample.ts +6 -1
  427. package/src/monitoring/plugin-auto-update.ts +359 -0
  428. package/src/monitoring/resource-sampler.ts +21 -5
  429. package/src/monitoring/worker.ts +13 -0
  430. package/src/notifications/__tests__/assistant-reply-producer.test.ts +375 -2
  431. package/src/notifications/__tests__/broadcaster.test.ts +37 -1
  432. package/src/notifications/__tests__/copy-composer.test.ts +165 -0
  433. package/src/notifications/__tests__/emit-signal-pipeline-failure.test.ts +205 -0
  434. package/src/notifications/__tests__/notification-utils.test.ts +249 -0
  435. package/src/notifications/adapters/platform.ts +31 -2
  436. package/src/notifications/assistant-reply-producer.ts +79 -32
  437. package/src/notifications/broadcaster.ts +30 -10
  438. package/src/notifications/copy-composer.ts +69 -0
  439. package/src/notifications/emit-signal.ts +82 -15
  440. package/src/notifications/events-store.ts +10 -2
  441. package/src/notifications/home-feed-side-effect.ts +6 -3
  442. package/src/notifications/notification-utils.ts +173 -5
  443. package/src/notifications/signal.ts +12 -0
  444. package/src/oauth/AGENTS.md +4 -2
  445. package/src/oauth/byo-connection.ts +6 -1
  446. package/src/oauth/credential-token-resolver.ts +3 -10
  447. package/src/oauth/manual-token-connection.ts +29 -64
  448. package/src/oauth/manual-token-providers.ts +62 -0
  449. package/src/oauth/provider-serializer.ts +13 -0
  450. package/src/oauth/seed-providers.ts +62 -11
  451. package/src/onboarding/onboarding-events-store.ts +91 -1
  452. package/src/permissions/question-prompter.test.ts +4 -0
  453. package/src/permissions/question-prompter.ts +21 -4
  454. package/src/persistence/__tests__/conversation-lineage.test.ts +248 -0
  455. package/src/persistence/attachments-store.ts +15 -15
  456. package/src/persistence/conversation-attention-store.ts +30 -10
  457. package/src/persistence/conversation-bootstrap.ts +17 -0
  458. package/src/persistence/conversation-crud.ts +363 -97
  459. package/src/persistence/conversation-group-migration.ts +1 -1
  460. package/src/persistence/conversation-key-store.ts +38 -10
  461. package/src/persistence/conversation-lineage.ts +226 -0
  462. package/src/persistence/conversation-plugin-facade.ts +28 -3
  463. package/src/persistence/conversation-queries.ts +207 -33
  464. package/src/persistence/conversation-types.ts +107 -1
  465. package/src/persistence/jobs-store.ts +32 -8
  466. package/src/persistence/llm-usage-store.ts +22 -0
  467. package/src/persistence/migrations/361-normalize-managed-connection-rows.test.ts +168 -0
  468. package/src/persistence/migrations/361-normalize-managed-connection-rows.ts +76 -0
  469. package/src/persistence/migrations/362-add-conversation-subagent-kind.test.ts +187 -0
  470. package/src/persistence/migrations/362-add-conversation-subagent-kind.ts +93 -0
  471. package/src/persistence/migrations/363-backfill-schedule-inference-profile.test.ts +229 -0
  472. package/src/persistence/migrations/363-backfill-schedule-inference-profile.ts +127 -0
  473. package/src/persistence/migrations/364-add-schedule-source-key.test.ts +120 -0
  474. package/src/persistence/migrations/364-add-schedule-source-key.ts +43 -0
  475. package/src/persistence/migrations/365-add-conversation-fork-strategy.ts +27 -0
  476. package/src/persistence/schema/conversations.ts +32 -0
  477. package/src/persistence/schema/infrastructure.ts +3 -0
  478. package/src/persistence/steps.ts +30 -0
  479. package/src/persistence/subagent-store.ts +148 -6
  480. package/src/platform/managed-speech.test.ts +20 -0
  481. package/src/platform/managed-speech.ts +9 -0
  482. package/src/plugin-api/index.ts +8 -0
  483. package/src/plugin-api/webhook-url.ts +151 -0
  484. package/src/plugins/__tests__/installed-plugin-dirs.test.ts +82 -0
  485. package/src/plugins/__tests__/source-fingerprint.test.ts +5 -1
  486. package/src/plugins/collect-source-versions.ts +4 -27
  487. package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +5 -5
  488. package/src/plugins/defaults/exploration-drift/package.json +1 -1
  489. package/src/plugins/defaults/image-recovery/hooks/post-model-call.ts +4 -2
  490. package/src/plugins/defaults/image-recovery/recover.ts +67 -57
  491. package/src/plugins/defaults/index.ts +1 -1
  492. package/src/plugins/defaults/memory/__tests__/conversation-queries.test.ts +64 -18
  493. package/src/plugins/defaults/memory/__tests__/jobs-worker-outcome-contract.test.ts +242 -0
  494. package/src/plugins/defaults/memory/__tests__/jobs-worker-retrospective-sweep.test.ts +24 -1
  495. package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +48 -3
  496. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +511 -19
  497. package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +39 -3
  498. package/src/plugins/defaults/memory/__tests__/memory-retrospective-provider-path.test.ts +493 -0
  499. package/src/plugins/defaults/memory/__tests__/memory-retrospective-wake-chain.test.ts +5 -4
  500. package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +5 -1
  501. package/src/plugins/defaults/memory/job-handlers.ts +87 -5
  502. package/src/plugins/defaults/memory/jobs-worker.ts +60 -6
  503. package/src/plugins/defaults/memory/memory-retrospective-constants.ts +11 -0
  504. package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +29 -0
  505. package/src/plugins/defaults/memory/memory-retrospective-job.ts +342 -60
  506. package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +23 -3
  507. package/src/plugins/defaults/memory/substrate/consolidation-lock.ts +9 -4
  508. package/src/plugins/defaults/memory/substrate/sweep-job.ts +7 -0
  509. package/src/plugins/defaults/memory/v1/graph/injection.ts +1 -1
  510. package/src/plugins/defaults/memory/v2/router.ts +8 -0
  511. package/src/plugins/defaults/turn-context/unified-turn-context.ts +1 -2
  512. package/src/plugins/external-plugin-loader.ts +17 -8
  513. package/src/plugins/installed-plugin-dirs.ts +101 -0
  514. package/src/plugins/mtime-cache.ts +34 -22
  515. package/src/plugins/types.ts +69 -8
  516. package/src/prompts/persona-resolver.ts +6 -2
  517. package/src/prompts/system-prompt.ts +72 -17
  518. package/src/providers/__tests__/inference.test.ts +40 -0
  519. package/src/providers/__tests__/preflight-resolved-config.test.ts +58 -1
  520. package/src/providers/__tests__/retry-callsite.test.ts +67 -0
  521. package/src/providers/__tests__/vellum-connection-routing.test.ts +42 -11
  522. package/src/providers/anthropic/client.ts +112 -95
  523. package/src/providers/connection-resolution.ts +35 -1
  524. package/src/providers/gemini/client.ts +5 -5
  525. package/src/providers/inference/adapter-factory.ts +16 -10
  526. package/src/providers/inference/auth.ts +16 -0
  527. package/src/providers/inference/connection-availability.ts +164 -12
  528. package/src/providers/inference/connections.ts +25 -1
  529. package/src/providers/media-resolve.ts +21 -11
  530. package/src/providers/model-catalog.ts +15 -0
  531. package/src/providers/openai/chat-completions-provider.ts +4 -4
  532. package/src/providers/openai/responses-provider.ts +12 -25
  533. package/src/providers/registry.ts +9 -4
  534. package/src/providers/retry.ts +25 -0
  535. package/src/providers/server-tool-pairing.ts +134 -0
  536. package/src/providers/speech-to-text/__tests__/resolve.test.ts +187 -6
  537. package/src/providers/speech-to-text/deepgram.ts +1 -0
  538. package/src/providers/speech-to-text/resolve.ts +80 -10
  539. package/src/providers/speech-to-text/vellum-managed.ts +7 -1
  540. package/src/providers/speech-to-text/vellum-speech-relay-connection.ts +3 -1
  541. package/src/providers/types.ts +26 -6
  542. package/src/providers/vellum-model-routing.ts +6 -7
  543. package/src/runtime/AGENTS.md +2 -0
  544. package/src/runtime/__tests__/agent-wake.test.ts +16 -16
  545. package/src/runtime/__tests__/background-job-runner.test.ts +0 -144
  546. package/src/runtime/__tests__/desktop-presence.test.ts +162 -0
  547. package/src/runtime/agent-wake.ts +63 -24
  548. package/src/runtime/assistant-event-hub.ts +87 -12
  549. package/src/runtime/auth/__tests__/guard-tests.test.ts +2 -0
  550. package/src/runtime/auth/__tests__/scopes.test.ts +20 -0
  551. package/src/runtime/auth/same-actor.ts +56 -8
  552. package/src/runtime/auth/scopes.ts +12 -0
  553. package/src/runtime/auth/types.ts +2 -0
  554. package/src/runtime/background-job-runner.ts +5 -27
  555. package/src/runtime/channel-readiness-service.ts +59 -3
  556. package/src/runtime/channel-readiness-types.ts +18 -0
  557. package/src/runtime/desktop-presence.ts +69 -0
  558. package/src/runtime/http-server.ts +12 -0
  559. package/src/runtime/local-actor-identity.ts +11 -9
  560. package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -0
  561. package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
  562. package/src/runtime/routes/__tests__/client-routes.test.ts +186 -14
  563. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +547 -1
  564. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +162 -7
  565. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +14 -10
  566. package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +340 -3
  567. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +28 -1
  568. package/src/runtime/routes/__tests__/plugins-routes.test.ts +173 -1
  569. package/src/runtime/routes/__tests__/question-routes.test.ts +64 -0
  570. package/src/runtime/routes/__tests__/retrospective-routes.test.ts +20 -0
  571. package/src/runtime/routes/__tests__/skill-history-route.test.ts +116 -0
  572. package/src/runtime/routes/__tests__/wake-conversation-routes.test.ts +60 -2
  573. package/src/runtime/routes/archive-utils.ts +16 -12
  574. package/src/runtime/routes/attachment-routes.ts +13 -6
  575. package/src/runtime/routes/canned-reply-release.ts +54 -0
  576. package/src/runtime/routes/channel-verification-routes.ts +2 -27
  577. package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +5 -0
  578. package/src/runtime/routes/client-routes.ts +114 -2
  579. package/src/runtime/routes/conversation-cli-routes.ts +10 -12
  580. package/src/runtime/routes/conversation-list-routes.ts +59 -10
  581. package/src/runtime/routes/conversation-management-routes.ts +47 -18
  582. package/src/runtime/routes/conversation-query-routes.ts +32 -53
  583. package/src/runtime/routes/conversation-routes.ts +360 -293
  584. package/src/runtime/routes/credential-prompt-routes.ts +23 -2
  585. package/src/runtime/routes/debug-routes.ts +4 -1
  586. package/src/runtime/routes/default-provider-routes.ts +7 -11
  587. package/src/runtime/routes/documents-routes.ts +44 -1
  588. package/src/runtime/routes/events-routes.ts +28 -1
  589. package/src/runtime/routes/host-app-control-routes.ts +2 -0
  590. package/src/runtime/routes/host-bash-routes.ts +2 -0
  591. package/src/runtime/routes/host-browser-routes.ts +2 -0
  592. package/src/runtime/routes/host-cu-routes.ts +2 -0
  593. package/src/runtime/routes/host-file-routes.ts +2 -0
  594. package/src/runtime/routes/host-transfer-routes.ts +4 -0
  595. package/src/runtime/routes/identity-routes.ts +6 -6
  596. package/src/runtime/routes/inbound-message-handler.ts +5 -5
  597. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +7 -3
  598. package/src/runtime/routes/inbound-stages/background-dispatch.ts +14 -0
  599. package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +2 -2
  600. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +14 -11
  601. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +14 -17
  602. package/src/runtime/routes/inference-profile-availability-guard.ts +171 -0
  603. package/src/runtime/routes/inference-profile-session-handler.ts +26 -2
  604. package/src/runtime/routes/inference-profile-session-routes.ts +2 -1
  605. package/src/runtime/routes/inference-profiles-routes.ts +152 -73
  606. package/src/runtime/routes/inference-provider-connection-routes.ts +0 -16
  607. package/src/runtime/routes/llm-call-sites-routes.ts +13 -0
  608. package/src/runtime/routes/log-export-routes.ts +1 -1
  609. package/src/runtime/routes/notification-routes.ts +0 -14
  610. package/src/runtime/routes/oauth-providers.ts +1 -0
  611. package/src/runtime/routes/plugins-routes.ts +106 -1
  612. package/src/runtime/routes/profiler-routes.ts +4 -2
  613. package/src/runtime/routes/question-routes.ts +28 -10
  614. package/src/runtime/routes/retrospective-routes.ts +9 -3
  615. package/src/runtime/routes/schedule-routes.ts +210 -12
  616. package/src/runtime/routes/secret-routes.ts +40 -23
  617. package/src/runtime/routes/settings-routes.ts +41 -13
  618. package/src/runtime/routes/skills-routes.ts +79 -0
  619. package/src/runtime/routes/ui-snapshot-routes.ts +1 -0
  620. package/src/runtime/routes/wake-conversation-routes.ts +23 -0
  621. package/src/runtime/services/__tests__/conversation-serializer.test.ts +1 -0
  622. package/src/runtime/services/conversation-serializer.ts +24 -9
  623. package/src/runtime/sync/documents-sidecar-publish.test.ts +101 -0
  624. package/src/runtime/sync/resource-sync-events.ts +79 -1
  625. package/src/runtime/sync/worker-daemon-notify.test.ts +34 -0
  626. package/src/runtime/sync/worker-daemon-notify.ts +44 -6
  627. package/src/runtime/verification-outbound-actions.ts +250 -222
  628. package/src/runtime/verification-templates.ts +41 -30
  629. package/src/schedule/__tests__/plugin-schedule-declarations.test.ts +614 -0
  630. package/src/schedule/__tests__/plugin-schedule-reconciler.test.ts +1066 -0
  631. package/src/schedule/inference-profile.ts +64 -3
  632. package/src/schedule/plugin-schedule-declarations.ts +518 -0
  633. package/src/schedule/plugin-schedule-reconciler.ts +605 -0
  634. package/src/schedule/plugin-schedules-gate.ts +23 -0
  635. package/src/schedule/schedule-store.ts +520 -26
  636. package/src/schedule/scheduler.ts +38 -0
  637. package/src/security/credential-backend.ts +51 -4
  638. package/src/security/encrypted-store.ts +64 -42
  639. package/src/security/secure-keys.ts +55 -7
  640. package/src/skills/catalog-install.ts +20 -7
  641. package/src/skills/inline-command-runner.ts +2 -7
  642. package/src/skills/skill-history.test.ts +269 -0
  643. package/src/skills/skill-history.ts +250 -0
  644. package/src/skills/skillssh-registry.ts +1 -1
  645. package/src/stt/daemon-batch-transcriber.ts +8 -6
  646. package/src/subagent/__tests__/consult-prompt.test.ts +25 -0
  647. package/src/subagent/consult-prompt.ts +3 -1
  648. package/src/subagent/consult-transcript.ts +1 -1
  649. package/src/subagent/manager.ts +304 -44
  650. package/src/subagent/progress-events.ts +35 -0
  651. package/src/subagent/role-resolution.ts +88 -0
  652. package/src/subagent/types.ts +302 -67
  653. package/src/subagent/validate-allowlists.ts +3 -4
  654. package/src/telegram/__tests__/webhook-health.test.ts +73 -1
  655. package/src/telegram/webhook-health.ts +101 -3
  656. package/src/telemetry/__tests__/telemetry-event-fixtures.ts +2 -0
  657. package/src/telemetry/activation-funnel.ts +6 -1
  658. package/src/telemetry/live-voice-funnel.ts +75 -0
  659. package/src/telemetry/telemetry-event-sources.ts +6 -0
  660. package/src/telemetry/telemetry-wire-source.json +1 -1
  661. package/src/telemetry/telemetry-wire.generated.ts +2 -0
  662. package/src/telemetry/types.ts +23 -4
  663. package/src/telemetry/usage-telemetry-reporter.test.ts +4 -0
  664. package/src/tools/__tests__/subagent-workflow-tool-input-schemas.test.ts +1 -1
  665. package/src/tools/ask-question/ask-question-tool.test.ts +118 -3
  666. package/src/tools/ask-question/ask-question-tool.ts +56 -2
  667. package/src/tools/browser/browser-execution.ts +1 -1
  668. package/src/tools/calls/call-start.ts +8 -5
  669. package/src/tools/conversation-groups/move_to_group.ts +10 -12
  670. package/src/tools/document/document-tool.ts +11 -4
  671. package/src/tools/execution-timeout.ts +9 -2
  672. package/src/tools/executor.ts +7 -6
  673. package/src/tools/filesystem/edit.ts +1 -1
  674. package/src/tools/filesystem/list.ts +1 -1
  675. package/src/tools/filesystem/read.ts +7 -13
  676. package/src/tools/filesystem/search.ts +23 -21
  677. package/src/tools/filesystem/write.ts +4 -1
  678. package/src/tools/host-filesystem/edit.ts +7 -2
  679. package/src/tools/host-filesystem/read.ts +21 -8
  680. package/src/tools/host-filesystem/write.ts +10 -2
  681. package/src/tools/host-terminal/host-shell.ts +2 -2
  682. package/src/tools/mcp/mcp-tool-factory.ts +25 -1
  683. package/src/tools/permission-checker.ts +8 -3
  684. package/src/tools/schedule/delete.ts +13 -1
  685. package/src/tools/schedule/list.ts +14 -3
  686. package/src/tools/schedule/update.ts +56 -33
  687. package/src/tools/shared/filesystem/audio-read.ts +6 -4
  688. package/src/tools/shared/filesystem/file-ops-service.ts +176 -116
  689. package/src/tools/shared/filesystem/image-read.ts +12 -12
  690. package/src/tools/shared/filesystem/path-policy.ts +70 -5
  691. package/src/tools/shared/filesystem/size-guard.ts +6 -6
  692. package/src/tools/shared/input-misuse.ts +72 -0
  693. package/src/tools/skills/scaffold-managed.ts +82 -0
  694. package/src/tools/skills/skill-tool-factory.ts +14 -1
  695. package/src/tools/subagent/consult-deadline.ts +12 -7
  696. package/src/tools/subagent/message.ts +3 -1
  697. package/src/tools/subagent/read.ts +66 -4
  698. package/src/tools/subagent/spawn.ts +500 -78
  699. package/src/tools/tool-approval-handler.ts +45 -4
  700. package/src/tools/types.ts +22 -3
  701. package/src/tools/ui-surface/surface-shape-docs.ts +1 -1
  702. package/src/tools/ui-surface/visual-validation.ts +2 -0
  703. package/src/usage/__tests__/subagent-attribution.test.ts +109 -0
  704. package/src/usage/subagent-attribution.ts +108 -0
  705. package/src/util/__tests__/sqlite-retry.test.ts +112 -0
  706. package/src/util/abort-reasons.ts +16 -0
  707. package/src/util/ansi.ts +44 -0
  708. package/src/util/disk-usage.ts +17 -13
  709. package/src/util/image-conversion.ts +20 -13
  710. package/src/util/schedule-source-key.ts +23 -0
  711. package/src/util/worker-process.ts +7 -1
  712. package/src/workspace/git-service.ts +33 -9
  713. package/src/workspace/migrations/140-repair-seed-pinned-memory-v3-live.ts +260 -0
  714. package/src/workspace/migrations/141-stt-english-default-to-multilingual.ts +111 -0
  715. package/src/workspace/migrations/__tests__/141-stt-english-default-to-multilingual.test.ts +126 -0
  716. package/src/workspace/migrations/registry.ts +4 -0
  717. package/src/workspace/top-level-renderer.ts +15 -2
  718. package/src/__tests__/tool-side-effects-slack-dm.test.ts +0 -357
  719. package/src/daemon/install-symlink.ts +0 -207
  720. package/src/notifications/deferred-emit.ts +0 -147
@@ -0,0 +1,330 @@
1
+ /**
2
+ * Tests for workspace migration `140-repair-seed-pinned-memory-v3-live`.
3
+ *
4
+ * The pre-#39847 first-launch seed persisted `memory.v3.live = false` before
5
+ * migration 105 could record the real decision, stranding brand-new
6
+ * assistants on v2 and demoting existing v3 assistants whose config.json was
7
+ * quarantined and reseeded. The repair flips `live` back to true only for
8
+ * those two victim classes and never over a deliberate opt-out.
9
+ */
10
+
11
+ import {
12
+ existsSync,
13
+ mkdirSync,
14
+ mkdtempSync,
15
+ readFileSync,
16
+ rmSync,
17
+ writeFileSync,
18
+ } from "node:fs";
19
+ import { tmpdir } from "node:os";
20
+ import { join } from "node:path";
21
+ import { Database } from "bun:sqlite";
22
+ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
23
+
24
+ import { repairSeedPinnedMemoryV3LiveMigration } from "../workspace/migrations/140-repair-seed-pinned-memory-v3-live.js";
25
+ import { WORKSPACE_MIGRATIONS } from "../workspace/migrations/registry.js";
26
+ import type { MigrationRunContext } from "../workspace/migrations/types.js";
27
+
28
+ const NEW_WORKSPACE_CTX: MigrationRunContext = { isNewWorkspace: true };
29
+ const UPGRADE_CTX: MigrationRunContext = { isNewWorkspace: false };
30
+
31
+ let workspaceDir: string;
32
+ let configPath: string;
33
+
34
+ beforeEach(() => {
35
+ workspaceDir = mkdtempSync(join(tmpdir(), "vellum-migration-140-test-"));
36
+ configPath = join(workspaceDir, "config.json");
37
+ mkdirSync(join(workspaceDir, "data", "db"), { recursive: true });
38
+ });
39
+
40
+ afterEach(() => {
41
+ if (existsSync(workspaceDir)) {
42
+ rmSync(workspaceDir, { recursive: true, force: true });
43
+ }
44
+ });
45
+
46
+ function readConfig(): Record<string, unknown> {
47
+ return JSON.parse(readFileSync(configPath, "utf-8"));
48
+ }
49
+
50
+ function readLive(): unknown {
51
+ const memory = (readConfig().memory ?? {}) as Record<string, unknown>;
52
+ const v3 = (memory.v3 ?? {}) as Record<string, unknown>;
53
+ return v3.live;
54
+ }
55
+
56
+ function writeConfig(config: Record<string, unknown>): void {
57
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
58
+ }
59
+
60
+ /** A checkpoint file whose 105 entry ran `gapMs` after the earliest entry. */
61
+ function writeCheckpoints(gapMs: number): void {
62
+ const base = Date.parse("2026-06-20T12:00:00.000Z");
63
+ writeFileSync(
64
+ join(workspaceDir, "data", ".workspace-migrations.json"),
65
+ JSON.stringify(
66
+ {
67
+ applied: {
68
+ "001-avatar-rename": {
69
+ appliedAt: new Date(base).toISOString(),
70
+ status: "completed",
71
+ },
72
+ "105-enable-memory-v3-live-for-new-workspaces": {
73
+ appliedAt: new Date(base + gapMs).toISOString(),
74
+ status: "completed",
75
+ },
76
+ },
77
+ },
78
+ null,
79
+ 2,
80
+ ) + "\n",
81
+ );
82
+ }
83
+
84
+ const FIRST_BOOT_GAP_MS = 5_000;
85
+ const UPGRADE_SWEEP_GAP_MS = 30 * 24 * 60 * 60 * 1000;
86
+
87
+ function writeSelectionRows(file: string): void {
88
+ const db = new Database(join(workspaceDir, "data", "db", file));
89
+ db.exec(`
90
+ CREATE TABLE memory_v3_selections (
91
+ conversation_id TEXT NOT NULL,
92
+ turn INTEGER NOT NULL,
93
+ slug TEXT NOT NULL,
94
+ source TEXT NOT NULL,
95
+ pinned INTEGER NOT NULL DEFAULT 0
96
+ );
97
+ INSERT INTO memory_v3_selections (conversation_id, turn, slug, source)
98
+ VALUES ('conv-1', 1, 'some-page', 'needle');
99
+ `);
100
+ db.close();
101
+ }
102
+
103
+ describe("140-repair-seed-pinned-memory-v3-live migration", () => {
104
+ test("has correct id and is registered last", () => {
105
+ expect(repairSeedPinnedMemoryV3LiveMigration.id).toBe(
106
+ "140-repair-seed-pinned-memory-v3-live",
107
+ );
108
+ expect(repairSeedPinnedMemoryV3LiveMigration.description).toContain(
109
+ "memory.v3.live",
110
+ );
111
+ // getLastWorkspaceMigrationId() reports the final entry as the registry
112
+ // ceiling, so ordering matters: this must be registered, and everything
113
+ // after it must carry a higher id. Asserting it stays literally last
114
+ // would break on every migration appended after it.
115
+ const index = WORKSPACE_MIGRATIONS.findIndex(
116
+ (migration) => migration.id === "140-repair-seed-pinned-memory-v3-live",
117
+ );
118
+ expect(index).toBeGreaterThan(-1);
119
+ for (const later of WORKSPACE_MIGRATIONS.slice(index + 1)) {
120
+ expect(later.id > "140").toBe(true);
121
+ }
122
+ });
123
+
124
+ test("flips a seed-race victim: born in the 105 era, live=false, v3 never ran", () => {
125
+ writeConfig({
126
+ memory: { v2: { enabled: true }, v3: { live: false } },
127
+ llm: { activeProfile: "balanced" },
128
+ });
129
+ writeCheckpoints(FIRST_BOOT_GAP_MS);
130
+
131
+ repairSeedPinnedMemoryV3LiveMigration.run(workspaceDir, UPGRADE_CTX);
132
+
133
+ expect(readLive()).toBe(true);
134
+ // The rest of the config is untouched.
135
+ const config = readConfig();
136
+ expect((config.llm as Record<string, unknown>).activeProfile).toBe(
137
+ "balanced",
138
+ );
139
+ expect(
140
+ ((config.memory as Record<string, unknown>).v2 as Record<string, unknown>)
141
+ .enabled,
142
+ ).toBe(true);
143
+ });
144
+
145
+ test("skips new workspaces so a hatch-time opt-out override wins", () => {
146
+ writeConfig({ memory: { v3: { live: false } } });
147
+ writeCheckpoints(FIRST_BOOT_GAP_MS);
148
+
149
+ repairSeedPinnedMemoryV3LiveMigration.run(workspaceDir, NEW_WORKSPACE_CTX);
150
+
151
+ expect(readLive()).toBe(false);
152
+ });
153
+
154
+ test("leaves an absent leaf alone: pre-105 assistants stay on the manual-upgrade path", () => {
155
+ writeConfig({ memory: { v2: { enabled: true } } });
156
+ writeCheckpoints(UPGRADE_SWEEP_GAP_MS);
157
+
158
+ repairSeedPinnedMemoryV3LiveMigration.run(workspaceDir, UPGRADE_CTX);
159
+
160
+ expect(readLive()).toBeUndefined();
161
+ });
162
+
163
+ test("leaves live=true alone (idempotent after its own repair)", () => {
164
+ writeConfig({ memory: { v3: { live: false } } });
165
+ writeCheckpoints(FIRST_BOOT_GAP_MS);
166
+
167
+ repairSeedPinnedMemoryV3LiveMigration.run(workspaceDir, UPGRADE_CTX);
168
+ expect(readLive()).toBe(true);
169
+ const afterFirstRun = readFileSync(configPath, "utf-8");
170
+
171
+ repairSeedPinnedMemoryV3LiveMigration.run(workspaceDir, UPGRADE_CTX);
172
+ expect(readFileSync(configPath, "utf-8")).toBe(afterFirstRun);
173
+ });
174
+
175
+ test("skips a live=false workspace that was NOT born in the 105 era", () => {
176
+ writeConfig({ memory: { v3: { live: false } } });
177
+ writeCheckpoints(UPGRADE_SWEEP_GAP_MS);
178
+
179
+ repairSeedPinnedMemoryV3LiveMigration.run(workspaceDir, UPGRADE_CTX);
180
+
181
+ expect(readLive()).toBe(false);
182
+ });
183
+
184
+ test("skips when the checkpoint file is missing (no era evidence)", () => {
185
+ writeConfig({ memory: { v3: { live: false } } });
186
+
187
+ repairSeedPinnedMemoryV3LiveMigration.run(workspaceDir, UPGRADE_CTX);
188
+
189
+ expect(readLive()).toBe(false);
190
+ });
191
+
192
+ test("respects a hatch-time opt-out recorded in the archived default overlay", () => {
193
+ writeConfig({ memory: { v3: { live: false } } });
194
+ writeCheckpoints(FIRST_BOOT_GAP_MS);
195
+ writeFileSync(
196
+ join(workspaceDir, "default-config.json"),
197
+ JSON.stringify({ memory: { v3: { live: false } } }, null, 2),
198
+ );
199
+
200
+ repairSeedPinnedMemoryV3LiveMigration.run(workspaceDir, UPGRADE_CTX);
201
+
202
+ expect(readLive()).toBe(false);
203
+ });
204
+
205
+ test("an archived overlay without a memory.v3.live opt-out does not block repair", () => {
206
+ writeConfig({ memory: { v3: { live: false } } });
207
+ writeCheckpoints(FIRST_BOOT_GAP_MS);
208
+ writeFileSync(
209
+ join(workspaceDir, "default-config.json"),
210
+ JSON.stringify({ llm: { activeProfile: "balanced" } }, null, 2),
211
+ );
212
+
213
+ repairSeedPinnedMemoryV3LiveMigration.run(workspaceDir, UPGRADE_CTX);
214
+
215
+ expect(readLive()).toBe(true);
216
+ });
217
+
218
+ test("respects a deliberate opt-out: v3 selection rows exist", () => {
219
+ writeConfig({ memory: { v3: { live: false } } });
220
+ writeCheckpoints(FIRST_BOOT_GAP_MS);
221
+ writeSelectionRows("assistant-memory.db");
222
+
223
+ repairSeedPinnedMemoryV3LiveMigration.run(workspaceDir, UPGRADE_CTX);
224
+
225
+ expect(readLive()).toBe(false);
226
+ });
227
+
228
+ test("finds selection rows staged under the __relocating name mid-drain", () => {
229
+ writeConfig({ memory: { v3: { live: false } } });
230
+ writeCheckpoints(FIRST_BOOT_GAP_MS);
231
+ const db = new Database(join(workspaceDir, "data", "db", "assistant.db"));
232
+ db.exec(`
233
+ CREATE TABLE memory_v3_selections__relocating (
234
+ conversation_id TEXT NOT NULL,
235
+ turn INTEGER NOT NULL,
236
+ slug TEXT NOT NULL,
237
+ source TEXT NOT NULL
238
+ );
239
+ INSERT INTO memory_v3_selections__relocating
240
+ (conversation_id, turn, slug, source)
241
+ VALUES ('conv-1', 1, 'some-page', 'needle');
242
+ `);
243
+ db.close();
244
+
245
+ repairSeedPinnedMemoryV3LiveMigration.run(workspaceDir, UPGRADE_CTX);
246
+
247
+ expect(readLive()).toBe(false);
248
+ });
249
+
250
+ test("finds selection rows in the pre-relocation assistant.db too", () => {
251
+ writeConfig({ memory: { v3: { live: false } } });
252
+ writeCheckpoints(FIRST_BOOT_GAP_MS);
253
+ writeSelectionRows("assistant.db");
254
+
255
+ repairSeedPinnedMemoryV3LiveMigration.run(workspaceDir, UPGRADE_CTX);
256
+
257
+ expect(readLive()).toBe(false);
258
+ });
259
+
260
+ test("an empty selections table is not usage evidence", () => {
261
+ writeConfig({ memory: { v3: { live: false } } });
262
+ writeCheckpoints(FIRST_BOOT_GAP_MS);
263
+ const db = new Database(
264
+ join(workspaceDir, "data", "db", "assistant-memory.db"),
265
+ );
266
+ db.exec(
267
+ `CREATE TABLE memory_v3_selections (conversation_id TEXT, turn INTEGER)`,
268
+ );
269
+ db.close();
270
+
271
+ repairSeedPinnedMemoryV3LiveMigration.run(workspaceDir, UPGRADE_CTX);
272
+
273
+ expect(readLive()).toBe(true);
274
+ });
275
+
276
+ test("quarantine carry-forward flips a demoted v3 assistant even with usage rows and an old workspace", () => {
277
+ writeConfig({ memory: { v3: { live: false } } });
278
+ writeCheckpoints(UPGRADE_SWEEP_GAP_MS);
279
+ writeSelectionRows("assistant-memory.db");
280
+ writeFileSync(
281
+ join(workspaceDir, "config.json.corrupt-2026-08-01T10-00-00.000Z.json"),
282
+ JSON.stringify({ memory: { v3: { live: true } } }, null, 2),
283
+ );
284
+
285
+ repairSeedPinnedMemoryV3LiveMigration.run(workspaceDir, UPGRADE_CTX);
286
+
287
+ expect(readLive()).toBe(true);
288
+ });
289
+
290
+ test("salvages live=true from a truncated (unparseable) quarantined config", () => {
291
+ writeConfig({ memory: { v3: { live: false } } });
292
+ writeCheckpoints(UPGRADE_SWEEP_GAP_MS);
293
+ writeFileSync(
294
+ join(workspaceDir, "config.json.corrupt-2026-08-01T10-00-00.000Z.json"),
295
+ `{\n "memory": {\n "v3": {\n "live": true\n }\n },\n "llm": {\n "activeProf`,
296
+ );
297
+
298
+ repairSeedPinnedMemoryV3LiveMigration.run(workspaceDir, UPGRADE_CTX);
299
+
300
+ expect(readLive()).toBe(true);
301
+ });
302
+
303
+ test("the NEWEST quarantined config wins", () => {
304
+ writeConfig({ memory: { v3: { live: false } } });
305
+ writeCheckpoints(UPGRADE_SWEEP_GAP_MS);
306
+ writeFileSync(
307
+ join(workspaceDir, "config.json.corrupt-2026-07-01T10-00-00.000Z.json"),
308
+ JSON.stringify({ memory: { v3: { live: true } } }),
309
+ );
310
+ writeFileSync(
311
+ join(workspaceDir, "config.json.corrupt-2026-08-01T10-00-00.000Z.json"),
312
+ JSON.stringify({ memory: { v3: { live: false } } }),
313
+ );
314
+
315
+ repairSeedPinnedMemoryV3LiveMigration.run(workspaceDir, UPGRADE_CTX);
316
+
317
+ expect(readLive()).toBe(false);
318
+ });
319
+
320
+ test("no-ops when config.json is missing or corrupt", () => {
321
+ // Missing.
322
+ repairSeedPinnedMemoryV3LiveMigration.run(workspaceDir, UPGRADE_CTX);
323
+ expect(existsSync(configPath)).toBe(false);
324
+
325
+ // Corrupt.
326
+ writeFileSync(configPath, "{ not json");
327
+ repairSeedPinnedMemoryV3LiveMigration.run(workspaceDir, UPGRADE_CTX);
328
+ expect(readFileSync(configPath, "utf-8")).toBe("{ not json");
329
+ });
330
+ });
@@ -6,15 +6,13 @@
6
6
  * `{"error":{"message":"..."}}`. This picks the most specific signal available:
7
7
  * a structured stderr error, else the last stderr line, else the ack message.
8
8
  *
9
- * Pure and dependency-free.
9
+ * Pure; the only dependency is the shared escape-sequence strip.
10
10
  */
11
11
 
12
- // CSI escape sequences (colour codes, cursor moves) that adapters interleave
13
- // with their log lines: ESC `[`, parameter/intermediate bytes, then final byte.
14
- const ANSI_ESCAPE = /\u001B\[[0-?]*[ -/]*[@-~]/g;
12
+ import { stripAnsiSequences } from "../util/ansi.js";
15
13
 
16
14
  export function deriveFailureError(ackMessage: string, stderr: string): string {
17
- const clean = stderr.replace(ANSI_ESCAPE, "").trim();
15
+ const clean = stripAnsiSequences(stderr).trim();
18
16
 
19
17
  // Most precise: a structured adapter error — prefer it over the ack.
20
18
  const jsonMessage = lastJsonErrorMessage(clean);
@@ -76,35 +76,37 @@ export function attachmentsToReferenceBlocks(
76
76
 
77
77
  export function attachmentsToContentBlocks(
78
78
  attachments: MessageAttachmentInput[],
79
- ): ContentBlock[] {
80
- return attachments.map((attachment) => {
81
- if (attachment.mimeType.toLowerCase().startsWith("image/")) {
82
- const { data, mediaType } = optimizeImageForTransport(
83
- attachment.data,
84
- attachment.mimeType,
85
- );
79
+ ): Promise<ContentBlock[]> {
80
+ return Promise.all(
81
+ attachments.map(async (attachment) => {
82
+ if (attachment.mimeType.toLowerCase().startsWith("image/")) {
83
+ const { data, mediaType } = await optimizeImageForTransport(
84
+ attachment.data,
85
+ attachment.mimeType,
86
+ );
87
+ return {
88
+ type: "image",
89
+ source: {
90
+ type: "base64",
91
+ media_type: mediaType,
92
+ data,
93
+ },
94
+ } as ContentBlock;
95
+ }
96
+
86
97
  return {
87
- type: "image",
98
+ type: "file",
88
99
  source: {
89
100
  type: "base64",
90
- media_type: mediaType,
91
- data,
101
+ media_type: attachment.mimeType,
102
+ data: attachment.data,
103
+ filename: attachment.filename,
92
104
  },
105
+ extracted_text: attachment.extractedText,
106
+ ...(attachment.id ? { _attachmentId: attachment.id } : {}),
93
107
  } as ContentBlock;
94
- }
95
-
96
- return {
97
- type: "file",
98
- source: {
99
- type: "base64",
100
- media_type: attachment.mimeType,
101
- data: attachment.data,
102
- filename: attachment.filename,
103
- },
104
- extracted_text: attachment.extractedText,
105
- ...(attachment.id ? { _attachmentId: attachment.id } : {}),
106
- } as ContentBlock;
107
- });
108
+ }),
109
+ );
108
110
  }
109
111
 
110
112
  /**
@@ -15,6 +15,7 @@
15
15
  * recover — so detection and repair of ordering drift live together as one unit.
16
16
  */
17
17
 
18
+ import { analyzeServerToolPairing } from "../../providers/server-tool-pairing.js";
18
19
  import type {
19
20
  ContentBlock,
20
21
  Message,
@@ -69,6 +70,10 @@ export function repairHistory(messages: Message[]): RepairResult {
69
70
  let pendingToolUseIds = new Set<string>();
70
71
  // tool_result blocks stripped from assistant messages, keyed by tool_use_id
71
72
  let recoveredResults = new Map<string, ToolResultContent>();
73
+ // Server-tool pairs can legitimately span messages (deferred execution) or
74
+ // sit unanswered at the tail (the provider runs the search on the next
75
+ // request), so orphanhood is judged against the whole list, not per message.
76
+ const serverToolPairing = analyzeServerToolPairing(messages);
72
77
 
73
78
  for (const [msgIndex, msg] of messages.entries()) {
74
79
  if (msg.role === "assistant") {
@@ -100,36 +105,32 @@ export function repairHistory(messages: Message[]): RepairResult {
100
105
  }
101
106
  }
102
107
 
103
- // Pair server-side tool blocks within the same assistant message.
104
- // Server tools (e.g. web_search) emit server_tool_use + matching
105
- // web_search_tool_result. Either side can go missing — the synthetic
106
- // result is inserted IMMEDIATELY AFTER the orphan server_tool_use (not
108
+ // Repair orphaned server-side tool blocks. Server tools (e.g.
109
+ // web_search) emit server_tool_use + matching web_search_tool_result;
110
+ // orphanhood comes from `serverToolPairing`, which resolves pairs
111
+ // across messages and exempts the deferred tail. The synthetic result
112
+ // is inserted IMMEDIATELY AFTER the orphan server_tool_use (not
107
113
  // appended to the end) so ensureToolPairing's split at tool_use
108
114
  // boundaries cannot separate the pair. An orphan
109
- // web_search_tool_result (no preceding server_tool_use) is downgraded
110
- // to text — Anthropic rejects the request otherwise.
111
- const serverToolIds = new Set(
112
- cleanedContent
113
- .filter(
114
- (b): b is ServerToolUseContent => b.type === "server_tool_use",
115
- )
116
- .map((b) => b.id),
117
- );
118
- const matchedServerIds = new Set(
119
- cleanedContent
120
- .filter((b) => b.type === "web_search_tool_result")
121
- .map((b) => (b as { tool_use_id: string }).tool_use_id),
122
- );
115
+ // web_search_tool_result with no use anywhere is downgraded to text.
116
+ // Anthropic rejects the request otherwise.
123
117
  const orphanedServerIds = new Set<string>();
124
- for (const id of serverToolIds) {
125
- if (!matchedServerIds.has(id)) {
126
- orphanedServerIds.add(id);
127
- }
128
- }
129
118
  const orphanedWebSearchResultIds = new Set<string>();
130
- for (const id of matchedServerIds) {
131
- if (!serverToolIds.has(id)) {
132
- orphanedWebSearchResultIds.add(id);
119
+ for (const b of cleanedContent) {
120
+ if (b.type === "server_tool_use") {
121
+ const id = (b as ServerToolUseContent).id;
122
+ if (
123
+ !serverToolPairing.resolvedPairIds.has(id) &&
124
+ !serverToolPairing.deferredUseIds.has(id)
125
+ ) {
126
+ orphanedServerIds.add(id);
127
+ }
128
+ }
129
+ if (b.type === "web_search_tool_result") {
130
+ const id = (b as { tool_use_id: string }).tool_use_id;
131
+ if (!serverToolPairing.resolvedPairIds.has(id)) {
132
+ orphanedWebSearchResultIds.add(id);
133
+ }
133
134
  }
134
135
  }
135
136
 
@@ -110,10 +110,10 @@ export function upscaleTargetDimensions(dims: {
110
110
  * Reactive only: called by the image-recovery plugin after an actual
111
111
  * "Could not process image" rejection, never on the pre-send path.
112
112
  */
113
- export function upscaleImageToMinimum(
113
+ export async function upscaleImageToMinimum(
114
114
  base64Data: string,
115
115
  mediaType: string,
116
- ): { data: string; mediaType: string } | null {
116
+ ): Promise<{ data: string; mediaType: string } | null> {
117
117
  const dims = parseImageDimensions(base64Data, mediaType);
118
118
  if (!dims) {
119
119
  return null;
@@ -122,7 +122,7 @@ export function upscaleImageToMinimum(
122
122
  if (!target) {
123
123
  return null;
124
124
  }
125
- const upscaled = convertImageToJpeg(Buffer.from(base64Data, "base64"), {
125
+ const upscaled = await convertImageToJpeg(Buffer.from(base64Data, "base64"), {
126
126
  resizeToPx: target,
127
127
  quality: JPEG_QUALITY,
128
128
  });
@@ -144,10 +144,10 @@ export function upscaleImageToMinimum(
144
144
  * Conversion (and its content-addressed disk cache) is shared with attachment
145
145
  * storage normalization — see `util/image-conversion.ts`.
146
146
  */
147
- export function optimizeImageForTransport(
147
+ export async function optimizeImageForTransport(
148
148
  base64Data: string,
149
149
  mediaType: string,
150
- ): { data: string; mediaType: string } {
150
+ ): Promise<{ data: string; mediaType: string }> {
151
151
  const rawBytes = Buffer.from(base64Data, "base64");
152
152
  const dims = parseImageDimensions(base64Data, mediaType);
153
153
 
@@ -155,7 +155,7 @@ export function optimizeImageForTransport(
155
155
  return { data: base64Data, mediaType };
156
156
  }
157
157
 
158
- const optimized = convertImageToJpeg(rawBytes, {
158
+ const optimized = await convertImageToJpeg(rawBytes, {
159
159
  maxDimensionPx: MAX_DIMENSION,
160
160
  quality: JPEG_QUALITY,
161
161
  });
package/src/agent/loop.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { getConfig } from "../config/loader.js";
2
- import { isMemoryV3Live } from "../config/memory-v3-gate.js";
1
+ import type { AnsweredQuestion } from "../api/events/question-answered.js";
3
2
  import type { LLMCallSite } from "../config/schemas/llm.js";
4
3
  import { recordEstimate } from "../context/estimator-calibration.js";
5
4
  import { preModelCallSanitize } from "../context/outbound-sanitize.js";
5
+ import { turnStartUserMessageHasSpotlight } from "../context/strip-injections.js";
6
6
  import {
7
7
  estimatePromptTokensRaw,
8
8
  estimatePromptTokensWithTools,
@@ -116,9 +116,9 @@ export interface AgentLoopConfig {
116
116
  * This is a SERVER tool the provider runs itself, distinct from the client
117
117
  * tool list (`tools` / `resolveTools`): it is never executed by
118
118
  * {@link AgentLoopConstructorOptions.toolExecutor} and does not require any
119
- * client-tool allowlist entry. Used by the tool-less advisor consult to
120
- * ground its guidance with live web access while staying one-shot for client
121
- * tools. Defaults to false — existing behavior.
119
+ * client-tool allowlist entry. Used by the advisor consult to ground its
120
+ * guidance with live web access on top of its read-only client tools.
121
+ * Defaults to false.
122
122
  */
123
123
  enableNativeWebSearch?: boolean;
124
124
  }
@@ -289,6 +289,8 @@ export type AgentEvent =
289
289
  approvalReason?: string;
290
290
  riskThreshold?: string;
291
291
  activityMetadata?: ToolActivityMetadata;
292
+ /** Answered `ask_question` record (see `ToolExecutionResult.answeredQuestion`). */
293
+ answeredQuestion?: AnsweredQuestion;
292
294
  /** Stable machine-readable error classification (see `ToolExecutionResult.errorCode`). */
293
295
  errorCode?: string;
294
296
  /**
@@ -698,6 +700,7 @@ export type LoopToolExecutor = (
698
700
  approvalReason?: string;
699
701
  riskThreshold?: string;
700
702
  activityMetadata?: ToolActivityMetadata;
703
+ answeredQuestion?: AnsweredQuestion;
701
704
  errorCode?: string;
702
705
  }>;
703
706
 
@@ -1355,9 +1358,9 @@ export class AgentLoop {
1355
1358
  // `this.provider.supportsNativeWebSearch` snapshot; providers without
1356
1359
  // the routing-aware probe fall back to the static flag. This is a SERVER
1357
1360
  // tool — it bypasses the client allowlist and the tool executor — so the
1358
- // tool-less advisor consult can ground its guidance with live web access
1359
- // while staying one-shot for client tools. Skip when a `web_search` tool
1360
- // is already present so we never duplicate the name.
1361
+ // advisor consult can ground its guidance with live web access on top of
1362
+ // its read-only client tools. Skip when a `web_search` tool is already
1363
+ // present so we never duplicate the name.
1361
1364
  const supportsRoutedNativeWebSearch = this.provider
1362
1365
  .supportsNativeWebSearchFor
1363
1366
  ? this.provider.supportsNativeWebSearchFor(
@@ -1420,9 +1423,7 @@ export class AgentLoop {
1420
1423
  if (this.config.toolChoice) {
1421
1424
  providerConfig.tool_choice = this.config.toolChoice;
1422
1425
  } else if (attachNativeWebSearch) {
1423
- // The native web-search tool is the only tool on this turn (the
1424
- // advisor consult is otherwise tool-less). Let the model decide
1425
- // whether to search rather than forcing it.
1426
+ // Let the model decide whether to search rather than forcing it.
1426
1427
  providerConfig.tool_choice = { type: "auto" };
1427
1428
  }
1428
1429
 
@@ -1430,14 +1431,18 @@ export class AgentLoop {
1430
1431
  providerConfig.cacheTtl = this.config.cacheTtl;
1431
1432
  }
1432
1433
 
1433
- // Cache-anchor signal for volatile latest-user-message turns: when
1434
- // memory-v3 is live it injects a per-turn `<memory>` block into the
1435
- // latest user message, so the provider must anchor its long-TTL cache
1436
- // breakpoint on the most recent STABLE user message instead of the
1437
- // volatile latest one. Read here alongside the rest of the provider
1438
- // config; only set when true so the wire/config stays byte-identical
1439
- // when off.
1440
- if (isMemoryV3Live(getConfig())) {
1434
+ // Cache-anchor signal for turns whose opening message is volatile. The
1435
+ // memory-v3 `<memory_spotlight>` block is the only injected block that
1436
+ // is strip-and-replaced from every user message each turn, so when it
1437
+ // is present that message's bytes do not recur next turn and a
1438
+ // long-TTL breakpoint on it could never be read back. The provider
1439
+ // marks it at the short TTL instead. Derived from the history actually
1440
+ // being sent rather than from configuration, so turns where memory
1441
+ // contributed no spotlight keep a normal anchor. Read off the
1442
+ // turn-starting message, so the signal holds for every request in the
1443
+ // turn rather than flipping once tool results arrive. Only set when
1444
+ // true so the wire/config stays byte-identical when absent.
1445
+ if (turnStartUserMessageHasSpotlight(history)) {
1441
1446
  providerConfig.mutableLatestUserMessage = true;
1442
1447
  }
1443
1448
 
@@ -1459,8 +1464,17 @@ export class AgentLoop {
1459
1464
  // conversation id). Absent for standalone `AgentLoop` instances
1460
1465
  // (unit tests constructed without a conversation id) — those fall
1461
1466
  // back to per-call random mix selection.
1467
+ //
1468
+ // The same id also travels as `conversationId`, which
1469
+ // `RetryProvider.normalizeSendMessageOptions` uses to resolve the
1470
+ // conversation's subagent role and spawn mode for the runtime
1471
+ // proxy's billing-attribution headers. Both are stripped before any
1472
+ // provider wire request; they are carried separately because
1473
+ // `selectionSeed` is an opaque hashing input that callers may set to
1474
+ // something other than a conversation id.
1462
1475
  if (this.conversationId) {
1463
1476
  providerConfig.selectionSeed = this.conversationId;
1477
+ providerConfig.conversationId = this.conversationId;
1464
1478
  }
1465
1479
  }
1466
1480
 
@@ -2201,13 +2215,16 @@ export class AgentLoop {
2201
2215
  // message between calls would invalidate the prompt-cache prefix on
2202
2216
  // every iteration).
2203
2217
  if (conversationDir) {
2204
- const toolNameByUseId = new Map(
2205
- toolUseBlocks.map((tu) => [tu.id, tu.name]),
2218
+ const toolCallByUseId = new Map(
2219
+ toolUseBlocks.map((tu) => [
2220
+ tu.id,
2221
+ { name: tu.name, input: tu.input },
2222
+ ]),
2206
2223
  );
2207
2224
  try {
2208
2225
  spoolAndStubOversizedToolResults(rawResultBlocks, {
2209
2226
  conversationDir,
2210
- toolNameById: (id) => toolNameByUseId.get(id),
2227
+ toolCallById: (id) => toolCallByUseId.get(id),
2211
2228
  });
2212
2229
  } catch (err) {
2213
2230
  rlog.warn(
@@ -2286,6 +2303,7 @@ export class AgentLoop {
2286
2303
  approvalReason: result.approvalReason,
2287
2304
  riskThreshold: result.riskThreshold,
2288
2305
  activityMetadata: result.activityMetadata,
2306
+ answeredQuestion: result.answeredQuestion,
2289
2307
  errorCode: result.errorCode,
2290
2308
  });
2291
2309
  }