@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
@@ -134,10 +134,10 @@ function advanceGlobalSeq(count: number): void {
134
134
  }
135
135
  }
136
136
 
137
- function callList(query: Record<string, string>): ListResponse {
138
- return handleListMessages({
137
+ async function callList(query: Record<string, string>): Promise<ListResponse> {
138
+ return (await handleListMessages({
139
139
  queryParams: query,
140
- }) as unknown as ListResponse;
140
+ })) as unknown as ListResponse;
141
141
  }
142
142
 
143
143
  describe("handleListMessages page=latest", () => {
@@ -148,7 +148,7 @@ describe("handleListMessages page=latest", () => {
148
148
  });
149
149
 
150
150
  describe("persisted seq", () => {
151
- test("getMaxPersistedConversationSeq reports the highest anchor across conversations", () => {
151
+ test("getMaxPersistedConversationSeq reports the highest anchor across conversations", async () => {
152
152
  /**
153
153
  * The startup seq floor resumes issuance above this value, so it
154
154
  * must reflect the highest anchor any conversation has served.
@@ -161,7 +161,7 @@ describe("handleListMessages page=latest", () => {
161
161
  expect(getMaxPersistedConversationSeq()).toBe(907779);
162
162
  });
163
163
 
164
- test("returns the recorded persisted seq for the conversation", () => {
164
+ test("returns the recorded persisted seq for the conversation", async () => {
165
165
  /**
166
166
  * The snapshot must advertise the `seq` of the last durably-persisted
167
167
  * event so a client can align it with the `/events` stream.
@@ -174,13 +174,13 @@ describe("handleListMessages page=latest", () => {
174
174
  recordConversationPersistedSeq(conv.id, 42);
175
175
 
176
176
  // WHEN the snapshot is fetched
177
- const body = callList({ conversationId: conv.id, page: "latest" });
177
+ const body = await callList({ conversationId: conv.id, page: "latest" });
178
178
 
179
179
  // THEN the response carries that seq
180
180
  expect(body.seq).toBe(42);
181
181
  });
182
182
 
183
- test("returns null seq when nothing has been persisted in-process", () => {
183
+ test("returns null seq when nothing has been persisted in-process", async () => {
184
184
  /**
185
185
  * A cold conversation (or one aged out / post-restart) reports no seq,
186
186
  * signalling the client to cold-start rather than align to a stale
@@ -192,13 +192,13 @@ describe("handleListMessages page=latest", () => {
192
192
  seedMessages(conv.id, 2);
193
193
 
194
194
  // WHEN the snapshot is fetched
195
- const body = callList({ conversationId: conv.id, page: "latest" });
195
+ const body = await callList({ conversationId: conv.id, page: "latest" });
196
196
 
197
197
  // THEN seq is null
198
198
  expect(body.seq).toBeNull();
199
199
  });
200
200
 
201
- test("the no-pagination path also returns the persisted seq", () => {
201
+ test("the no-pagination path also returns the persisted seq", async () => {
202
202
  /** `seq` is present on every resolved-conversation response shape. */
203
203
 
204
204
  // GIVEN a conversation with a recorded persisted seq
@@ -207,13 +207,13 @@ describe("handleListMessages page=latest", () => {
207
207
  recordConversationPersistedSeq(conv.id, 7);
208
208
 
209
209
  // WHEN fetched with no pagination params
210
- const body = callList({ conversationId: conv.id });
210
+ const body = await callList({ conversationId: conv.id });
211
211
 
212
212
  // THEN the seq still rides along
213
213
  expect(body.seq).toBe(7);
214
214
  });
215
215
 
216
- test("recording advances the seq monotonically and never regresses", () => {
216
+ test("recording advances the seq monotonically and never regresses", async () => {
217
217
  /**
218
218
  * Out-of-order async commits must not lower the high-water mark — the
219
219
  * `WHERE seq < ?` guard on the persist UPDATE keeps it monotonic.
@@ -227,14 +227,14 @@ describe("handleListMessages page=latest", () => {
227
227
  recordConversationPersistedSeq(conv.id, 8);
228
228
 
229
229
  // THEN the high-water seq is unchanged
230
- expect(callList({ conversationId: conv.id }).seq).toBe(12);
230
+ expect((await callList({ conversationId: conv.id })).seq).toBe(12);
231
231
 
232
232
  // AND a higher seq still advances it
233
233
  recordConversationPersistedSeq(conv.id, 20);
234
- expect(callList({ conversationId: conv.id }).seq).toBe(20);
234
+ expect((await callList({ conversationId: conv.id })).seq).toBe(20);
235
235
  });
236
236
 
237
- test("recording ignores non-positive and non-finite seq values", () => {
237
+ test("recording ignores non-positive and non-finite seq values", async () => {
238
238
  // GIVEN a freshly created conversation (no stream activity → null seed)
239
239
  const conv = createConversation();
240
240
 
@@ -245,10 +245,10 @@ describe("handleListMessages page=latest", () => {
245
245
  recordConversationPersistedSeq(conv.id, Number.POSITIVE_INFINITY);
246
246
 
247
247
  // THEN none take effect and seq stays null
248
- expect(callList({ conversationId: conv.id }).seq).toBeNull();
248
+ expect((await callList({ conversationId: conv.id })).seq).toBeNull();
249
249
  });
250
250
 
251
- test("a freshly created conversation is anchored to the current global seq", () => {
251
+ test("a freshly created conversation is anchored to the current global seq", async () => {
252
252
  /**
253
253
  * Conversations created after some stream activity must not report a
254
254
  * null `seq` — that would force the client to cold-start with no
@@ -262,13 +262,13 @@ describe("handleListMessages page=latest", () => {
262
262
 
263
263
  // WHEN a brand-new conversation is created and its snapshot fetched
264
264
  const conv = createConversation();
265
- const body = callList({ conversationId: conv.id, page: "latest" });
265
+ const body = await callList({ conversationId: conv.id, page: "latest" });
266
266
 
267
267
  // THEN the snapshot is anchored to the global seq at creation time
268
268
  expect(body.seq).toBe(5);
269
269
  });
270
270
 
271
- test("a conversation created before any stream activity stays null", () => {
271
+ test("a conversation created before any stream activity stays null", async () => {
272
272
  /**
273
273
  * With nothing stamped this process, `getCurrentSeq()` is 0 and the
274
274
  * creation seed stores NULL (non-positive seqs aren't recorded), so the
@@ -280,7 +280,7 @@ describe("handleListMessages page=latest", () => {
280
280
 
281
281
  // WHEN a conversation is created and its snapshot fetched
282
282
  const conv = createConversation();
283
- const body = callList({ conversationId: conv.id, page: "latest" });
283
+ const body = await callList({ conversationId: conv.id, page: "latest" });
284
284
 
285
285
  // THEN seq remains null
286
286
  expect(body.seq).toBeNull();
@@ -288,7 +288,7 @@ describe("handleListMessages page=latest", () => {
288
288
  });
289
289
 
290
290
  describe("processing state", () => {
291
- test("reports processing=true while the conversation is mid-turn", () => {
291
+ test("reports processing=true while the conversation is mid-turn", async () => {
292
292
  /**
293
293
  * The authoritative processing flag lets a client recover from a
294
294
  * dropped stream: it can ask the server whether a turn is still
@@ -301,25 +301,25 @@ describe("handleListMessages page=latest", () => {
301
301
  setConversationProcessingStartedAt(conv.id, Date.now());
302
302
 
303
303
  // WHEN the snapshot is fetched
304
- const body = callList({ conversationId: conv.id, page: "latest" });
304
+ const body = await callList({ conversationId: conv.id, page: "latest" });
305
305
 
306
306
  // THEN it reports the conversation is processing
307
307
  expect(body.processing).toBe(true);
308
308
  });
309
309
 
310
- test("reports processing=false when the conversation is idle", () => {
310
+ test("reports processing=false when the conversation is idle", async () => {
311
311
  // GIVEN an idle conversation (processing_started_at is null)
312
312
  const conv = createConversation();
313
313
  seedMessages(conv.id, 2);
314
314
 
315
315
  // WHEN the snapshot is fetched
316
- const body = callList({ conversationId: conv.id, page: "latest" });
316
+ const body = await callList({ conversationId: conv.id, page: "latest" });
317
317
 
318
318
  // THEN it reports the conversation is not processing
319
319
  expect(body.processing).toBe(false);
320
320
  });
321
321
 
322
- test("the no-pagination path also reports processing state", () => {
322
+ test("the no-pagination path also reports processing state", async () => {
323
323
  /** `processing` is present on every resolved-conversation shape. */
324
324
 
325
325
  // GIVEN a processing conversation
@@ -328,15 +328,15 @@ describe("handleListMessages page=latest", () => {
328
328
  setConversationProcessingStartedAt(conv.id, Date.now());
329
329
 
330
330
  // WHEN fetched with no pagination params
331
- const body = callList({ conversationId: conv.id });
331
+ const body = await callList({ conversationId: conv.id });
332
332
 
333
333
  // THEN processing rides along
334
334
  expect(body.processing).toBe(true);
335
335
  });
336
336
 
337
- test("an unresolved conversationKey reports processing=false (page=latest)", () => {
337
+ test("an unresolved conversationKey reports processing=false (page=latest)", async () => {
338
338
  // WHEN a never-created key is fetched with the stable contract
339
- const body = callList({
339
+ const body = await callList({
340
340
  conversationKey: "no-such-key",
341
341
  page: "latest",
342
342
  });
@@ -346,11 +346,11 @@ describe("handleListMessages page=latest", () => {
346
346
  });
347
347
  });
348
348
 
349
- test("page=latest with no limit returns all messages chronologically", () => {
349
+ test("page=latest with no limit returns all messages chronologically", async () => {
350
350
  const conv = createConversation();
351
351
  seedMessages(conv.id, 120);
352
352
 
353
- const body = callList({ conversationId: conv.id, page: "latest" });
353
+ const body = await callList({ conversationId: conv.id, page: "latest" });
354
354
 
355
355
  expect(body.messages).toHaveLength(120);
356
356
  expect(body.messages[0].id).toBe("msg-1");
@@ -360,11 +360,11 @@ describe("handleListMessages page=latest", () => {
360
360
  expect(body.oldestMessageId).toBe("msg-1");
361
361
  });
362
362
 
363
- test("page=latest&limit=50 with 120 seeded messages returns newest 50 chronologically", () => {
363
+ test("page=latest&limit=50 with 120 seeded messages returns newest 50 chronologically", async () => {
364
364
  const conv = createConversation();
365
365
  seedMessages(conv.id, 120);
366
366
 
367
- const body = callList({
367
+ const body = await callList({
368
368
  conversationId: conv.id,
369
369
  page: "latest",
370
370
  limit: "50",
@@ -379,11 +379,11 @@ describe("handleListMessages page=latest", () => {
379
379
  expect(body.oldestMessageId).toBe("msg-71");
380
380
  });
381
381
 
382
- test("page=latest&limit=50 with 10 seeded messages returns all 10 with hasMore=false", () => {
382
+ test("page=latest&limit=50 with 10 seeded messages returns all 10 with hasMore=false", async () => {
383
383
  const conv = createConversation();
384
384
  seedMessages(conv.id, 10);
385
385
 
386
- const body = callList({
386
+ const body = await callList({
387
387
  conversationId: conv.id,
388
388
  page: "latest",
389
389
  limit: "50",
@@ -397,20 +397,20 @@ describe("handleListMessages page=latest", () => {
397
397
  expect(body.oldestMessageId).toBe("msg-1");
398
398
  });
399
399
 
400
- test("beforeTimestamp wins when combined with page=latest", () => {
400
+ test("beforeTimestamp wins when combined with page=latest", async () => {
401
401
  const conv = createConversation();
402
402
  seedMessages(conv.id, 120);
403
403
 
404
404
  // beforeTimestamp=100 + limit=50 should return msgs 50..99 (the 50 messages
405
405
  // immediately older than ts=100), regardless of the page=latest signal.
406
- const combinedBody = callList({
406
+ const combinedBody = await callList({
407
407
  conversationId: conv.id,
408
408
  page: "latest",
409
409
  limit: "50",
410
410
  beforeTimestamp: "100",
411
411
  });
412
412
 
413
- const beforeOnlyBody = callList({
413
+ const beforeOnlyBody = await callList({
414
414
  conversationId: conv.id,
415
415
  limit: "50",
416
416
  beforeTimestamp: "100",
@@ -428,10 +428,10 @@ describe("handleListMessages page=latest", () => {
428
428
  expect(combinedBody.messages[49].id).toBe("msg-99");
429
429
  });
430
430
 
431
- test("page=latest on empty conversation returns null pagination metadata", () => {
431
+ test("page=latest on empty conversation returns null pagination metadata", async () => {
432
432
  const conv = createConversation();
433
433
 
434
- const body = callList({ conversationId: conv.id, page: "latest" });
434
+ const body = await callList({ conversationId: conv.id, page: "latest" });
435
435
 
436
436
  expect(body.messages).toEqual([]);
437
437
  expect(body.hasMore).toBe(false);
@@ -439,7 +439,7 @@ describe("handleListMessages page=latest", () => {
439
439
  expect(body.oldestMessageId).toBeNull();
440
440
  });
441
441
 
442
- test("messages expose Slack message and thread links from slackMeta", () => {
442
+ test("messages expose Slack message and thread links from slackMeta", async () => {
443
443
  const conv = createConversation();
444
444
  const db = getDb();
445
445
  db.insert(messages)
@@ -464,7 +464,7 @@ describe("handleListMessages page=latest", () => {
464
464
  })
465
465
  .run();
466
466
 
467
- const body = callList({ conversationId: conv.id, page: "latest" });
467
+ const body = await callList({ conversationId: conv.id, page: "latest" });
468
468
 
469
469
  expect(body.messages[0].slackMessage).toEqual({
470
470
  channelId: "C123ABCDEF",
@@ -491,7 +491,7 @@ describe("handleListMessages page=latest", () => {
491
491
  });
492
492
  });
493
493
 
494
- test("top-level Slack messages with matching threadTs use plain permalinks", () => {
494
+ test("top-level Slack messages with matching threadTs use plain permalinks", async () => {
495
495
  const conv = createConversation();
496
496
  const db = getDb();
497
497
  db.insert(messages)
@@ -516,7 +516,7 @@ describe("handleListMessages page=latest", () => {
516
516
  })
517
517
  .run();
518
518
 
519
- const body = callList({ conversationId: conv.id, page: "latest" });
519
+ const body = await callList({ conversationId: conv.id, page: "latest" });
520
520
 
521
521
  expect(body.messages[0].slackMessage).toEqual({
522
522
  channelId: "C123ABCDEF",
@@ -537,7 +537,7 @@ describe("handleListMessages page=latest", () => {
537
537
  });
538
538
  });
539
539
 
540
- test("assistant Slack messages without stored sender use the assistant name", () => {
540
+ test("assistant Slack messages without stored sender use the assistant name", async () => {
541
541
  mockAssistantName = "Nova";
542
542
  const conv = createConversation();
543
543
  const db = getDb();
@@ -559,14 +559,14 @@ describe("handleListMessages page=latest", () => {
559
559
  })
560
560
  .run();
561
561
 
562
- const body = callList({ conversationId: conv.id, page: "latest" });
562
+ const body = await callList({ conversationId: conv.id, page: "latest" });
563
563
 
564
564
  expect(body.messages[0].slackMessage?.sender).toEqual({
565
565
  displayName: "Nova",
566
566
  });
567
567
  });
568
568
 
569
- test("user Slack messages without stored sender do not use the assistant name", () => {
569
+ test("user Slack messages without stored sender do not use the assistant name", async () => {
570
570
  mockAssistantName = "Nova";
571
571
  const conv = createConversation();
572
572
  const db = getDb();
@@ -588,13 +588,13 @@ describe("handleListMessages page=latest", () => {
588
588
  })
589
589
  .run();
590
590
 
591
- const body = callList({ conversationId: conv.id, page: "latest" });
591
+ const body = await callList({ conversationId: conv.id, page: "latest" });
592
592
 
593
593
  expect(body.messages[0].slackMessage?.sender).toBeUndefined();
594
594
  });
595
595
 
596
- test("page=latest on unresolved conversationKey returns null metadata contract", () => {
597
- const body = callList({
596
+ test("page=latest on unresolved conversationKey returns null metadata contract", async () => {
597
+ const body = await callList({
598
598
  conversationKey: "no-such-key",
599
599
  page: "latest",
600
600
  });
@@ -605,8 +605,8 @@ describe("handleListMessages page=latest", () => {
605
605
  expect(body.oldestMessageId).toBeNull();
606
606
  });
607
607
 
608
- test("no-page GET on unresolved conversationKey keeps minimal shape", () => {
609
- const body = callList({ conversationKey: "no-such-key" });
608
+ test("no-page GET on unresolved conversationKey keeps minimal shape", async () => {
609
+ const body = await callList({ conversationKey: "no-such-key" });
610
610
 
611
611
  expect(body.messages).toEqual([]);
612
612
  expect("hasMore" in body).toBe(false);
@@ -614,26 +614,26 @@ describe("handleListMessages page=latest", () => {
614
614
  expect("oldestMessageId" in body).toBe(false);
615
615
  });
616
616
 
617
- test("page=invalid throws BadRequestError", () => {
617
+ test("page=invalid throws BadRequestError", async () => {
618
618
  const conv = createConversation();
619
619
 
620
- expect(() =>
620
+ await expect(
621
621
  handleListMessages({
622
622
  queryParams: { conversationId: conv.id, page: "invalid" },
623
623
  }),
624
- ).toThrow(BadRequestError);
625
- expect(() =>
624
+ ).rejects.toThrow(BadRequestError);
625
+ await expect(
626
626
  handleListMessages({
627
627
  queryParams: { conversationId: conv.id, page: "invalid" },
628
628
  }),
629
- ).toThrow("page must be 'latest' when provided");
629
+ ).rejects.toThrow("page must be 'latest' when provided");
630
630
  });
631
631
 
632
- test("no-param GET returns full history without pagination metadata", () => {
632
+ test("no-param GET returns full history without pagination metadata", async () => {
633
633
  const conv = createConversation();
634
634
  seedMessages(conv.id, 5);
635
635
 
636
- const body = callList({ conversationId: conv.id });
636
+ const body = await callList({ conversationId: conv.id });
637
637
 
638
638
  expect(body.messages).toHaveLength(5);
639
639
  expect(body.messages[0].id).toBe("msg-1");
@@ -644,12 +644,12 @@ describe("handleListMessages page=latest", () => {
644
644
  expect("oldestMessageId" in body).toBe(false);
645
645
  });
646
646
 
647
- test("beforeTimestamp-only GET keeps existing conditional-metadata shape (no results)", () => {
647
+ test("beforeTimestamp-only GET keeps existing conditional-metadata shape (no results)", async () => {
648
648
  const conv = createConversation();
649
649
  seedMessages(conv.id, 5);
650
650
 
651
651
  // beforeTimestamp before all seeded rows => no results, metadata omitted.
652
- const body = callList({
652
+ const body = await callList({
653
653
  conversationId: conv.id,
654
654
  limit: "10",
655
655
  beforeTimestamp: "0",
@@ -662,11 +662,11 @@ describe("handleListMessages page=latest", () => {
662
662
  expect("oldestMessageId" in body).toBe(false);
663
663
  });
664
664
 
665
- test("beforeTimestamp-only GET keeps existing conditional-metadata shape (with results)", () => {
665
+ test("beforeTimestamp-only GET keeps existing conditional-metadata shape (with results)", async () => {
666
666
  const conv = createConversation();
667
667
  seedMessages(conv.id, 5);
668
668
 
669
- const body = callList({
669
+ const body = await callList({
670
670
  conversationId: conv.id,
671
671
  limit: "10",
672
672
  beforeTimestamp: "100",
@@ -72,9 +72,9 @@ describe("handleListMessages provider-error projection", () => {
72
72
  },
73
73
  );
74
74
 
75
- const response = handleListMessages({
75
+ const response = (await handleListMessages({
76
76
  queryParams: { conversationId: conv.id },
77
- }) as { messages: ProjectedMessage[] };
77
+ })) as { messages: ProjectedMessage[] };
78
78
 
79
79
  // Every projected message validates against the wire schema.
80
80
  for (const message of response.messages) {
@@ -106,9 +106,9 @@ describe("handleListMessages provider-error projection", () => {
106
106
  },
107
107
  );
108
108
 
109
- const response = handleListMessages({
109
+ const response = (await handleListMessages({
110
110
  queryParams: { conversationId: conv.id },
111
- }) as { messages: ProjectedMessage[] };
111
+ })) as { messages: ProjectedMessage[] };
112
112
 
113
113
  expect(response.messages).toHaveLength(1);
114
114
  expect(response.messages[0]?.providerError).toEqual({});
@@ -130,9 +130,9 @@ describe("handleListMessages provider-error projection", () => {
130
130
  JSON.stringify([{ type: "text", text: "hi there" }]),
131
131
  );
132
132
 
133
- const response = handleListMessages({
133
+ const response = (await handleListMessages({
134
134
  queryParams: { conversationId: conv.id },
135
- }) as { messages: ProjectedMessage[] };
135
+ })) as { messages: ProjectedMessage[] };
136
136
 
137
137
  expect(response.messages).toHaveLength(2);
138
138
  for (const message of response.messages) {
@@ -91,7 +91,7 @@ describe("handleListMessages in-memory queue", () => {
91
91
  ]);
92
92
 
93
93
  // WHEN the messages snapshot is built for the newest page
94
- const response = handleListMessages({
94
+ const response = await handleListMessages({
95
95
  queryParams: { conversationId: conv.id },
96
96
  });
97
97
  const body = response as { messages: MessagePayload[] };
@@ -128,7 +128,7 @@ describe("handleListMessages in-memory queue", () => {
128
128
  }),
129
129
  ]);
130
130
 
131
- const response = handleListMessages({
131
+ const response = await handleListMessages({
132
132
  queryParams: { conversationId: conv.id },
133
133
  });
134
134
  const body = response as { messages: MessagePayload[] };
@@ -156,7 +156,7 @@ describe("handleListMessages in-memory queue", () => {
156
156
  }),
157
157
  ]);
158
158
 
159
- const response = handleListMessages({
159
+ const response = await handleListMessages({
160
160
  queryParams: { conversationId: conv.id },
161
161
  });
162
162
  const body = response as { messages: MessagePayload[] };
@@ -182,7 +182,50 @@ describe("handleListMessages in-memory queue", () => {
182
182
  makeQueued({ requestId: "req-visible", content: "a real message" }),
183
183
  ]);
184
184
 
185
- const response = handleListMessages({
185
+ const response = await handleListMessages({
186
+ queryParams: { conversationId: conv.id },
187
+ });
188
+ const body = response as { messages: MessagePayload[] };
189
+
190
+ expect(body.messages).toHaveLength(1);
191
+ expect(body.messages[0].id).toBe("req-visible");
192
+ expect(body.messages[0].queuePosition).toBe(1);
193
+ });
194
+
195
+ test("filters daemon-injected notifications from the snapshot, keeping positions contiguous", async () => {
196
+ // A subagent's completion summary injected into a busy parent queues like
197
+ // any other turn, but it is scaffolding the user follows through the
198
+ // subagent card — never a queued bubble they could steer or cancel. Same
199
+ // for ACP run outcomes and wake triggers.
200
+ const conv = createConversation();
201
+ registerLiveConversation(conv.id, [
202
+ makeQueued({
203
+ requestId: "req-subagent",
204
+ content: '[Subagent "hermes-local-review" — important] review finished',
205
+ metadata: {
206
+ subagentNotification: {
207
+ subagentId: "sub-1",
208
+ label: "hermes-local-review",
209
+ status: "completed",
210
+ conversationId: "conv-sub-1",
211
+ objective: "review the diff",
212
+ },
213
+ },
214
+ }),
215
+ makeQueued({
216
+ requestId: "req-acp",
217
+ content: "[ACP run finished]",
218
+ metadata: { acpNotification: { acpSessionId: "acp-1" } },
219
+ }),
220
+ makeQueued({
221
+ requestId: "req-wake",
222
+ content: '<background_event source="schedule">',
223
+ metadata: { backgroundEventSource: "schedule" },
224
+ }),
225
+ makeQueued({ requestId: "req-visible", content: "a real message" }),
226
+ ]);
227
+
228
+ const response = await handleListMessages({
186
229
  queryParams: { conversationId: conv.id },
187
230
  });
188
231
  const body = response as { messages: MessagePayload[] };
@@ -204,7 +247,7 @@ describe("handleListMessages in-memory queue", () => {
204
247
  registerLiveConversation(conv.id, [makeQueued({ requestId: "req-old" })]);
205
248
 
206
249
  // WHEN paging older history
207
- const response = handleListMessages({
250
+ const response = await handleListMessages({
208
251
  queryParams: {
209
252
  conversationId: conv.id,
210
253
  beforeTimestamp: String(Date.now() + 1_000),
@@ -226,7 +269,7 @@ describe("handleListMessages in-memory queue", () => {
226
269
  { skipIndexing: true },
227
270
  );
228
271
 
229
- const response = handleListMessages({
272
+ const response = await handleListMessages({
230
273
  queryParams: { conversationId: conv.id },
231
274
  });
232
275
  const body = response as { messages: MessagePayload[] };
@@ -60,9 +60,9 @@ describe("handleListMessages system-card projection", () => {
60
60
  { metadata: { messageKind: SYSTEM_CARD_MESSAGE_KIND } },
61
61
  );
62
62
 
63
- const response = handleListMessages({
63
+ const response = (await handleListMessages({
64
64
  queryParams: { conversationId: conv.id },
65
- }) as { messages: ProjectedMessage[] };
65
+ })) as { messages: ProjectedMessage[] };
66
66
 
67
67
  // Every projected message validates against the wire schema.
68
68
  for (const message of response.messages) {
@@ -87,9 +87,9 @@ describe("handleListMessages system-card projection", () => {
87
87
  JSON.stringify([{ type: "text", text: "hi there" }]),
88
88
  );
89
89
 
90
- const response = handleListMessages({
90
+ const response = (await handleListMessages({
91
91
  queryParams: { conversationId: conv.id },
92
- }) as { messages: ProjectedMessage[] };
92
+ })) as { messages: ProjectedMessage[] };
93
93
 
94
94
  expect(response.messages).toHaveLength(2);
95
95
  for (const message of response.messages) {
@@ -86,7 +86,7 @@ describe("handleListMessages tool_result merging", () => {
86
86
  ]),
87
87
  );
88
88
 
89
- const response = handleListMessages(createTestArgs(conv.id));
89
+ const response = await handleListMessages(createTestArgs(conv.id));
90
90
  const body = response as { messages: MessagePayload[] };
91
91
 
92
92
  // Should be 2 messages: user prompt + assistant (tool_result user msg suppressed)
@@ -150,7 +150,7 @@ describe("handleListMessages tool_result merging", () => {
150
150
  ]),
151
151
  );
152
152
 
153
- const response = handleListMessages(createTestArgs(conv.id));
153
+ const response = await handleListMessages(createTestArgs(conv.id));
154
154
  const body = response as { messages: MessagePayload[] };
155
155
 
156
156
  expect(body.messages).toHaveLength(2);
@@ -180,7 +180,7 @@ describe("handleListMessages tool_result merging", () => {
180
180
  JSON.stringify([{ type: "text", text: "how are you?" }]),
181
181
  );
182
182
 
183
- const response = handleListMessages(createTestArgs(conv.id));
183
+ const response = await handleListMessages(createTestArgs(conv.id));
184
184
  const body = response as { messages: MessagePayload[] };
185
185
 
186
186
  expect(body.messages).toHaveLength(3);
@@ -206,7 +206,7 @@ describe("handleListMessages tool_result merging", () => {
206
206
  JSON.stringify([{ type: "text", text: "Done." }]),
207
207
  );
208
208
 
209
- const response = handleListMessages(createTestArgs(conv.id));
209
+ const response = await handleListMessages(createTestArgs(conv.id));
210
210
  const body = response as { messages: MessagePayload[] };
211
211
 
212
212
  expect(body.messages).toHaveLength(2);
@@ -241,7 +241,7 @@ describe("handleListMessages tool_result merging", () => {
241
241
  JSON.stringify([{ type: "text", text: "response" }]),
242
242
  );
243
243
 
244
- const response = handleListMessages(createTestArgs(conv.id));
244
+ const response = await handleListMessages(createTestArgs(conv.id));
245
245
  const body = response as { messages: MessagePayload[] };
246
246
 
247
247
  // User row dropped entirely; only the assistant survives.
@@ -273,7 +273,7 @@ describe("handleListMessages tool_result merging", () => {
273
273
  JSON.stringify([{ type: "text", text: "answering" }]),
274
274
  );
275
275
 
276
- const response = handleListMessages(createTestArgs(conv.id));
276
+ const response = await handleListMessages(createTestArgs(conv.id));
277
277
  const body = response as { messages: MessagePayload[] };
278
278
 
279
279
  expect(body.messages).toHaveLength(2);
@@ -307,7 +307,7 @@ describe("handleListMessages tool_result merging", () => {
307
307
  JSON.stringify([{ type: "text", text: "ok" }]),
308
308
  );
309
309
 
310
- const response = handleListMessages(createTestArgs(conv.id));
310
+ const response = await handleListMessages(createTestArgs(conv.id));
311
311
  const body = response as { messages: MessagePayload[] };
312
312
 
313
313
  expect(body.messages).toHaveLength(1);
@@ -364,7 +364,7 @@ describe("handleListMessages tool_result merging", () => {
364
364
  JSON.stringify([{ type: "text", text: "thanks" }]),
365
365
  );
366
366
 
367
- const response = handleListMessages(createTestArgs(conv.id));
367
+ const response = await handleListMessages(createTestArgs(conv.id));
368
368
  const body = response as { messages: MessagePayload[] };
369
369
 
370
370
  // Consecutive assistant messages are merged at query time so the client
@@ -414,7 +414,7 @@ describe("handleListMessages tool_result merging", () => {
414
414
  ]),
415
415
  );
416
416
 
417
- const response = handleListMessages(createTestArgs(conv.id));
417
+ const response = await handleListMessages(createTestArgs(conv.id));
418
418
  const body = response as { messages: MessagePayload[] };
419
419
 
420
420
  expect(body.messages).toHaveLength(2);