@vellumai/assistant 0.8.3 → 0.8.5

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 (665) hide show
  1. package/ARCHITECTURE.md +2 -2
  2. package/docker-entrypoint.sh +0 -1
  3. package/docs/browser-use-architecture-phase2.md +1 -1
  4. package/knip.json +2 -1
  5. package/node_modules/@vellumai/gateway-client/src/types.ts +2 -0
  6. package/openapi.yaml +1492 -100
  7. package/package.json +1 -1
  8. package/src/__tests__/agent-loop-exit-reason.test.ts +4 -5
  9. package/src/__tests__/agent-loop-override-profile.test.ts +1 -1
  10. package/src/__tests__/agent-loop.test.ts +88 -3
  11. package/src/__tests__/anthropic-provider.test.ts +302 -33
  12. package/src/__tests__/approval-cascade.test.ts +1 -1
  13. package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +293 -0
  14. package/src/__tests__/assistant-feature-flags-integration.test.ts +3 -3
  15. package/src/__tests__/audit-log-rotation.test.ts +70 -16
  16. package/src/__tests__/background-workers-disk-pressure.test.ts +4 -3
  17. package/src/__tests__/btw-routes.test.ts +2 -3
  18. package/src/__tests__/call-controller.test.ts +0 -1
  19. package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
  20. package/src/__tests__/channel-delivery-store.test.ts +193 -0
  21. package/src/__tests__/channel-guardian.test.ts +3 -3
  22. package/src/__tests__/channel-reply-delivery.test.ts +284 -5
  23. package/src/__tests__/channel-retry-sweep.test.ts +274 -1
  24. package/src/__tests__/checker.test.ts +6 -15
  25. package/src/__tests__/compaction-events.test.ts +2 -1
  26. package/src/__tests__/compactor-call-site-logging.test.ts +214 -0
  27. package/src/__tests__/compactor-preserved-tail-count.test.ts +110 -0
  28. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +5 -11
  29. package/src/__tests__/computer-use-tools.test.ts +2 -4
  30. package/src/__tests__/config-watcher.test.ts +1 -1
  31. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
  32. package/src/__tests__/context-token-estimator.test.ts +91 -1
  33. package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
  34. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -1
  35. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +55 -4
  36. package/src/__tests__/conversation-agent-loop-overflow.test.ts +228 -8
  37. package/src/__tests__/conversation-agent-loop.test.ts +188 -129
  38. package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -5
  39. package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
  40. package/src/__tests__/conversation-clean-command.test.ts +137 -0
  41. package/src/__tests__/conversation-clear-safety.test.ts +25 -25
  42. package/src/__tests__/conversation-confirmation-signals.test.ts +1 -1
  43. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +1 -1
  44. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
  45. package/src/__tests__/conversation-error.test.ts +31 -0
  46. package/src/__tests__/conversation-fork-crud.test.ts +324 -0
  47. package/src/__tests__/conversation-lifecycle.test.ts +53 -12
  48. package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
  49. package/src/__tests__/conversation-load-history-stripped.test.ts +279 -0
  50. package/src/__tests__/conversation-pairing.test.ts +2 -2
  51. package/src/__tests__/conversation-process-callsite.test.ts +1 -1
  52. package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -1
  53. package/src/__tests__/conversation-queue.test.ts +1 -1
  54. package/src/__tests__/conversation-routes-disk-view.test.ts +109 -0
  55. package/src/__tests__/conversation-routes-slash-commands.test.ts +35 -0
  56. package/src/__tests__/conversation-runtime-assembly.test.ts +264 -81
  57. package/src/__tests__/conversation-seed-composer.test.ts +66 -4
  58. package/src/__tests__/conversation-skill-tools.test.ts +2 -5
  59. package/src/__tests__/conversation-slash-commands.test.ts +36 -8
  60. package/src/__tests__/conversation-slash-queue.test.ts +1 -1
  61. package/src/__tests__/conversation-slash-unknown.test.ts +1 -1
  62. package/src/__tests__/conversation-speed-override.test.ts +1 -1
  63. package/src/__tests__/conversation-store.test.ts +1 -1
  64. package/src/__tests__/conversation-surfaces-task-progress.test.ts +220 -0
  65. package/src/__tests__/conversation-sync-tags.test.ts +99 -32
  66. package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -1
  67. package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
  68. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
  69. package/src/__tests__/credential-execution-feature-gates.test.ts +9 -7
  70. package/src/__tests__/credential-execution-tools.test.ts +6 -6
  71. package/src/__tests__/credential-security-invariants.test.ts +7 -0
  72. package/src/__tests__/credential-vault-unit.test.ts +2 -2
  73. package/src/__tests__/cu-unified-flow.test.ts +10 -1
  74. package/src/__tests__/dm-backfill.test.ts +64 -0
  75. package/src/__tests__/dm-persistence.test.ts +33 -0
  76. package/src/__tests__/document-find-replace.test.ts +501 -0
  77. package/src/__tests__/dynamic-page-surface.test.ts +2 -2
  78. package/src/__tests__/email-html-renderer.test.ts +12 -0
  79. package/src/__tests__/first-greeting.test.ts +23 -2
  80. package/src/__tests__/gateway-flag-listener.test.ts +237 -0
  81. package/src/__tests__/gemini-provider.test.ts +78 -0
  82. package/src/__tests__/guardian-dispatch.test.ts +0 -1
  83. package/src/__tests__/guardian-outbound-http.test.ts +7 -5
  84. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
  85. package/src/__tests__/headless-browser-navigate.test.ts +172 -0
  86. package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -0
  87. package/src/__tests__/heartbeat-service.test.ts +4 -0
  88. package/src/__tests__/host-bash-proxy.test.ts +6 -0
  89. package/src/__tests__/host-browser-proxy.test.ts +10 -0
  90. package/src/__tests__/host-cu-proxy.test.ts +8 -1
  91. package/src/__tests__/host-file-proxy.test.ts +8 -1
  92. package/src/__tests__/host-shell-tool.test.ts +1 -1
  93. package/src/__tests__/host-transfer-proxy.test.ts +8 -1
  94. package/src/__tests__/identity-routes.test.ts +57 -0
  95. package/src/__tests__/inbound-slack-persistence.test.ts +3 -0
  96. package/src/__tests__/init-feature-flag-overrides.test.ts +5 -6
  97. package/src/__tests__/injector-chain.test.ts +2 -0
  98. package/src/__tests__/injector-document-comments.test.ts +378 -0
  99. package/src/__tests__/injector-pkb-v2-silenced.test.ts +4 -25
  100. package/src/__tests__/list-messages-attachments.test.ts +21 -17
  101. package/src/__tests__/list-messages-hidden-metadata.test.ts +217 -0
  102. package/src/__tests__/list-messages-page-latest.test.ts +130 -14
  103. package/src/__tests__/list-messages-tool-merge.test.ts +77 -17
  104. package/src/__tests__/llm-context-normalization.test.ts +0 -2
  105. package/src/__tests__/llm-request-log-call-site.test.ts +136 -0
  106. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +26 -0
  107. package/src/__tests__/llm-resolver.test.ts +161 -9
  108. package/src/__tests__/llm-usage-store.test.ts +66 -0
  109. package/src/__tests__/log-export-routes.test.ts +99 -2
  110. package/src/__tests__/logger.test.ts +89 -0
  111. package/src/__tests__/mcp-abort-signal.test.ts +2 -2
  112. package/src/__tests__/media-generate-image.test.ts +31 -0
  113. package/src/__tests__/memory-v2-static-injector.test.ts +7 -7
  114. package/src/__tests__/message-queue-steer.test.ts +114 -0
  115. package/src/__tests__/model-intents.test.ts +2 -4
  116. package/src/__tests__/notification-guardian-path.test.ts +0 -1
  117. package/src/__tests__/onboarding-template-contract.test.ts +1 -1
  118. package/src/__tests__/openai-provider.test.ts +151 -0
  119. package/src/__tests__/openai-responses-provider.test.ts +118 -16
  120. package/src/__tests__/outbound-slack-persistence.test.ts +187 -20
  121. package/src/__tests__/pending-interactions-resolved-event.test.ts +189 -0
  122. package/src/__tests__/platform-bash-auto-approve.test.ts +2 -2
  123. package/src/__tests__/platform.test.ts +2 -5
  124. package/src/__tests__/plugin-api-tool-definition.test.ts +92 -0
  125. package/src/__tests__/plugin-bootstrap.test.ts +2 -2
  126. package/src/__tests__/plugin-source-watcher.test.ts +302 -0
  127. package/src/__tests__/plugin-tool-contribution.test.ts +13 -6
  128. package/src/__tests__/plugin-types.test.ts +3 -2
  129. package/src/__tests__/prechat-onboarding-contract.test.ts +131 -98
  130. package/src/__tests__/pricing.test.ts +12 -0
  131. package/src/__tests__/process-message-background-slack.test.ts +1 -51
  132. package/src/__tests__/process-message-display-content.test.ts +21 -16
  133. package/src/__tests__/prune-jobs-changes-parser.test.ts +61 -0
  134. package/src/__tests__/registry.test.ts +2 -8
  135. package/src/__tests__/require-fresh-approval.test.ts +2 -2
  136. package/src/__tests__/runtime-events-sse-bilingual.test.ts +154 -0
  137. package/src/__tests__/server-history-render.test.ts +83 -4
  138. package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
  139. package/src/__tests__/skill-feature-flags.test.ts +2 -2
  140. package/src/__tests__/skill-projection-feature-flag.test.ts +4 -7
  141. package/src/__tests__/skill-projection.benchmark.test.ts +2 -6
  142. package/src/__tests__/skill-tool-factory.test.ts +1 -1
  143. package/src/__tests__/steer-tool-repair.test.ts +249 -0
  144. package/src/__tests__/subagent-notify-parent.test.ts +1 -1
  145. package/src/__tests__/suggestion-routes.test.ts +1 -0
  146. package/src/__tests__/sync-message-contract.test.ts +59 -0
  147. package/src/__tests__/system-prompt.test.ts +161 -124
  148. package/src/__tests__/terminal-tools.test.ts +12 -2
  149. package/src/__tests__/thinking-block-replay.test.ts +113 -0
  150. package/src/__tests__/thread-backfill.test.ts +370 -22
  151. package/src/__tests__/tool-approval-handler.test.ts +1 -5
  152. package/src/__tests__/tool-execute-pipeline.test.ts +2 -2
  153. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -5
  154. package/src/__tests__/tool-executor-lifecycle-events.test.ts +15 -5
  155. package/src/__tests__/tool-executor.test.ts +89 -53
  156. package/src/__tests__/tool-grant-request-escalation.test.ts +1 -6
  157. package/src/__tests__/tool-result-metadata-plumbing.test.ts +167 -0
  158. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  159. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -6
  160. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
  161. package/src/__tests__/twilio-routes.test.ts +1 -1
  162. package/src/__tests__/ui-file-upload-surface.test.ts +2 -2
  163. package/src/__tests__/usage-routes.test.ts +3 -0
  164. package/src/__tests__/verification-control-plane-policy.test.ts +2 -2
  165. package/src/__tests__/web-fetch.test.ts +2 -2
  166. package/src/__tests__/workspace-git-service.test.ts +94 -10
  167. package/src/__tests__/workspace-migration-088-deprecate-background-conversation-override.test.ts +158 -0
  168. package/src/__tests__/workspace-migration-089-move-memory-tree-out-of-v3.test.ts +86 -0
  169. package/src/acp/__tests__/prepare-agent-env.test.ts +146 -0
  170. package/src/acp/prepare-agent-env.ts +78 -0
  171. package/src/acp/session-manager.ts +1 -1
  172. package/src/agent/attachments.ts +1 -0
  173. package/src/agent/loop.ts +65 -20
  174. package/src/api/README.md +5 -0
  175. package/src/api/index.ts +4 -0
  176. package/src/api/package.json +10 -0
  177. package/src/background-wake/background-wake-routes.test.ts +233 -0
  178. package/src/background-wake/next-wake.test.ts +289 -0
  179. package/src/background-wake/next-wake.ts +172 -0
  180. package/src/background-wake/runtime-registry.ts +24 -0
  181. package/src/browser/operations.ts +15 -0
  182. package/src/cli/commands/__tests__/browser.test.ts +23 -5
  183. package/src/cli/commands/__tests__/conversations-slack.test.ts +572 -0
  184. package/src/cli/commands/__tests__/domain-register.test.ts +110 -0
  185. package/src/cli/commands/__tests__/domain-status.test.ts +33 -33
  186. package/src/cli/commands/__tests__/inference-send.test.ts +108 -5
  187. package/src/cli/commands/__tests__/memory-v2-compare-render.test.ts +98 -0
  188. package/src/cli/commands/__tests__/memory-v2.test.ts +10 -12
  189. package/src/cli/commands/__tests__/memory-v3-render.test.ts +340 -0
  190. package/src/cli/commands/browser.ts +247 -0
  191. package/src/cli/commands/conversations.ts +128 -1
  192. package/src/cli/commands/domain.ts +91 -41
  193. package/src/cli/commands/inference-providers.ts +147 -1
  194. package/src/cli/commands/inference.ts +93 -40
  195. package/src/cli/commands/memory-v2-compare-render.ts +115 -0
  196. package/src/cli/commands/memory-v2.ts +483 -0
  197. package/src/cli/commands/memory-v3-render.ts +344 -0
  198. package/src/cli/commands/memory-v3.ts +316 -0
  199. package/src/cli/commands/notifications.ts +24 -2
  200. package/src/cli/program.ts +2 -0
  201. package/src/cli/utils/conversation-id.ts +17 -5
  202. package/src/config/assistant-feature-flags.ts +21 -9
  203. package/src/config/bundled-skills/app-builder/SKILL.md +2 -2
  204. package/src/config/bundled-skills/document-editor/SKILL.md +124 -0
  205. package/src/config/bundled-skills/document-editor/TOOLS.json +258 -0
  206. package/src/config/bundled-skills/document-editor/tools/comment-list.ts +12 -0
  207. package/src/config/bundled-skills/document-editor/tools/comment-reply.ts +12 -0
  208. package/src/config/bundled-skills/document-editor/tools/comment-resolve.ts +12 -0
  209. package/src/config/bundled-skills/document-editor/tools/document-find.ts +12 -0
  210. package/src/config/bundled-skills/document-editor/tools/document-open.ts +12 -0
  211. package/src/config/bundled-skills/document-editor/tools/document-replace-text.ts +12 -0
  212. package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
  213. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -2
  214. package/src/config/bundled-skills/media-processing/SKILL.md +8 -0
  215. package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +13 -8
  216. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +10 -3
  217. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +16 -14
  218. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +7 -2
  219. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +7 -2
  220. package/src/config/bundled-skills/schedule/SKILL.md +8 -0
  221. package/src/config/bundled-tool-registry.ts +24 -12
  222. package/src/config/call-site-defaults.ts +20 -0
  223. package/src/config/feature-flag-registry.json +115 -3
  224. package/src/config/llm-resolver.ts +16 -2
  225. package/src/config/schemas/__tests__/memory-v2.test.ts +217 -1
  226. package/src/config/schemas/call-site-catalog.ts +35 -0
  227. package/src/config/schemas/llm.ts +14 -0
  228. package/src/config/schemas/memory-v2.ts +294 -1
  229. package/src/config/schemas/memory.ts +2 -1
  230. package/src/context/compactor.ts +60 -1
  231. package/src/context/token-estimator.ts +47 -4
  232. package/src/context/window-manager.ts +25 -0
  233. package/src/conversations/__tests__/message-consolidation.test.ts +350 -0
  234. package/src/conversations/message-consolidation.ts +404 -0
  235. package/src/credential-health/credential-health-service.ts +34 -19
  236. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -1
  237. package/src/daemon/__tests__/conversation-tool-setup.test.ts +66 -6
  238. package/src/daemon/__tests__/meet-manifest-loader.test.ts +1 -1
  239. package/src/daemon/__tests__/native-web-search-metadata.test.ts +357 -0
  240. package/src/daemon/__tests__/web-search-status-text.test.ts +287 -0
  241. package/src/daemon/conversation-agent-loop-handlers.ts +155 -36
  242. package/src/daemon/conversation-agent-loop.ts +307 -88
  243. package/src/daemon/conversation-error.ts +31 -1
  244. package/src/daemon/conversation-lifecycle.ts +149 -118
  245. package/src/daemon/conversation-messaging.ts +3 -0
  246. package/src/daemon/conversation-process.ts +273 -0
  247. package/src/daemon/conversation-queue-manager.ts +14 -0
  248. package/src/daemon/conversation-runtime-assembly.ts +145 -84
  249. package/src/daemon/conversation-slash.ts +37 -5
  250. package/src/daemon/conversation-surfaces.ts +45 -2
  251. package/src/daemon/conversation-tool-setup.ts +70 -3
  252. package/src/daemon/conversation-usage.ts +2 -0
  253. package/src/daemon/conversation.ts +54 -32
  254. package/src/daemon/disk-pressure-guard.ts +14 -2
  255. package/src/daemon/first-greeting.ts +10 -0
  256. package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +498 -0
  257. package/src/daemon/handlers/config-a2a.ts +160 -0
  258. package/src/daemon/handlers/config-model.test.ts +2 -0
  259. package/src/daemon/handlers/conversations.ts +90 -3
  260. package/src/daemon/handlers/shared.ts +92 -29
  261. package/src/daemon/host-bash-proxy.ts +1 -1
  262. package/src/daemon/host-browser-proxy.ts +5 -5
  263. package/src/daemon/host-cu-proxy.ts +5 -5
  264. package/src/daemon/host-file-proxy.ts +5 -5
  265. package/src/daemon/host-proxy-base.ts +4 -4
  266. package/src/daemon/host-transfer-proxy.ts +11 -11
  267. package/src/daemon/lifecycle.ts +40 -23
  268. package/src/daemon/meet-manifest-loader.ts +1 -7
  269. package/src/daemon/message-protocol.ts +4 -0
  270. package/src/daemon/message-types/conversations.ts +14 -9
  271. package/src/daemon/message-types/document-comments.ts +50 -0
  272. package/src/daemon/message-types/home.ts +1 -13
  273. package/src/daemon/message-types/messages.ts +66 -7
  274. package/src/daemon/message-types/surfaces.ts +3 -1
  275. package/src/daemon/message-types/sync.ts +14 -0
  276. package/src/daemon/message-types/web-activity.ts +57 -0
  277. package/src/daemon/plugin-source-watcher.ts +135 -3
  278. package/src/daemon/process-message.ts +69 -12
  279. package/src/daemon/shutdown-handlers.ts +24 -5
  280. package/src/daemon/switch-inference-profile-tool.ts +52 -0
  281. package/src/daemon/tool-setup-types.ts +13 -0
  282. package/src/daemon/trust-context.ts +6 -0
  283. package/src/documents/document-comments-store.test.ts +338 -0
  284. package/src/documents/document-comments-store.ts +237 -0
  285. package/src/documents/document-store.ts +202 -0
  286. package/src/events/relationship-state-updated.ts +25 -0
  287. package/src/heartbeat/__tests__/heartbeat-service.test.ts +1 -2
  288. package/src/heartbeat/heartbeat-service.ts +1 -0
  289. package/src/home/__tests__/suggested-prompts.test.ts +33 -2
  290. package/src/home/feed-types.ts +6 -1
  291. package/src/home/home-content-refresh.ts +52 -0
  292. package/src/home/home-greeting-cache.ts +69 -0
  293. package/src/home/home-greeting.ts +85 -0
  294. package/src/home/suggested-prompts.ts +168 -9
  295. package/src/ipc/gateway-flag-listener.ts +123 -0
  296. package/src/ipc/skill-routes/registries.ts +8 -12
  297. package/src/memory/__tests__/db-async-query.test.ts +165 -0
  298. package/src/memory/__tests__/db-maintenance.test.ts +115 -0
  299. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +241 -0
  300. package/src/memory/__tests__/jobs-store-job-classes.test.ts +28 -1
  301. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +135 -2
  302. package/src/memory/__tests__/memory-retrospective-job.test.ts +327 -6
  303. package/src/memory/auto-analysis-enqueue.ts +5 -1
  304. package/src/memory/conversation-crud.ts +191 -100
  305. package/src/memory/conversation-starters-cadence.ts +3 -1
  306. package/src/memory/conversation-title-service.ts +19 -3
  307. package/src/memory/db-async-query.ts +214 -0
  308. package/src/memory/db-init.ts +26 -0
  309. package/src/memory/db-maintenance.ts +30 -21
  310. package/src/memory/delivery-crud.ts +41 -0
  311. package/src/memory/delivery-status.ts +141 -15
  312. package/src/memory/external-conversation-store.ts +32 -1
  313. package/src/memory/graph/bootstrap.ts +8 -1
  314. package/src/memory/graph/capability-seed.ts +7 -3
  315. package/src/memory/graph/conversation-graph-memory.ts +100 -17
  316. package/src/memory/graph/extraction.ts +1 -5
  317. package/src/memory/graph/graph-search.ts +7 -1
  318. package/src/memory/indexer.ts +28 -18
  319. package/src/memory/job-handlers/cleanup.ts +76 -18
  320. package/src/memory/job-handlers/conversation-starters.ts +1 -4
  321. package/src/memory/jobs/embed-pkb-file.ts +6 -1
  322. package/src/memory/jobs-store.ts +14 -0
  323. package/src/memory/jobs-worker.ts +68 -15
  324. package/src/memory/llm-request-log-source-clickhouse.ts +42 -2
  325. package/src/memory/llm-request-log-source-local.ts +7 -0
  326. package/src/memory/llm-request-log-source.ts +9 -2
  327. package/src/memory/llm-request-log-store.ts +43 -1
  328. package/src/memory/llm-usage-store.ts +24 -0
  329. package/src/memory/memory-retrospective-constants.ts +28 -0
  330. package/src/memory/memory-retrospective-enqueue.ts +11 -3
  331. package/src/memory/memory-retrospective-job.ts +413 -18
  332. package/src/memory/memory-retrospective-startup-cleanup.ts +3 -3
  333. package/src/memory/memory-v2-activation-log-store.ts +41 -14
  334. package/src/memory/migrations/100-core-tables.ts +1 -0
  335. package/src/memory/migrations/109-external-conversation-bindings.ts +1 -0
  336. package/src/memory/migrations/253-conversation-last-notified-profile.ts +15 -0
  337. package/src/memory/migrations/253-document-comments.ts +47 -0
  338. package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +43 -0
  339. package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +24 -0
  340. package/src/memory/migrations/256-memory-v2-injection-events.ts +113 -0
  341. package/src/memory/migrations/257-strip-base-url-non-openai-compatible.ts +22 -0
  342. package/src/memory/migrations/258-onboarding-events-prior-assistants.ts +13 -0
  343. package/src/memory/migrations/259-conversation-cleaned-at.ts +33 -0
  344. package/src/memory/migrations/260-rename-cleaned-at.ts +44 -0
  345. package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +36 -0
  346. package/src/memory/migrations/262-memory-v3-coactivation.ts +57 -0
  347. package/src/memory/migrations/263-memory-v3-auto-edges.ts +50 -0
  348. package/src/memory/migrations/264-llm-request-log-call-site.ts +29 -0
  349. package/src/memory/migrations/index.ts +34 -0
  350. package/src/memory/migrations/registry.ts +58 -0
  351. package/src/memory/onboarding-events-store.ts +7 -0
  352. package/src/memory/schema/calls.ts +1 -0
  353. package/src/memory/schema/conversations.ts +3 -0
  354. package/src/memory/schema/infrastructure.ts +22 -0
  355. package/src/memory/tool-usage-store.ts +36 -8
  356. package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -0
  357. package/src/memory/v2/__tests__/harness-compare.test.ts +186 -0
  358. package/src/memory/v2/__tests__/harness-metrics.test.ts +74 -0
  359. package/src/memory/v2/__tests__/harness-oracle.test.ts +257 -0
  360. package/src/memory/v2/__tests__/harness-replay-input.test.ts +225 -0
  361. package/src/memory/v2/__tests__/harness-runner.test.ts +109 -0
  362. package/src/memory/v2/__tests__/injection-events.test.ts +318 -0
  363. package/src/memory/v2/__tests__/injection.test.ts +158 -112
  364. package/src/memory/v2/__tests__/page-index.test.ts +365 -1
  365. package/src/memory/v2/__tests__/qdrant.test.ts +36 -0
  366. package/src/memory/v2/__tests__/router.test.ts +660 -4
  367. package/src/memory/v2/consolidation-job.ts +14 -0
  368. package/src/memory/v2/harness/compare.ts +57 -0
  369. package/src/memory/v2/harness/metrics.ts +124 -0
  370. package/src/memory/v2/harness/oracle.ts +145 -0
  371. package/src/memory/v2/harness/replay-input.ts +224 -0
  372. package/src/memory/v2/harness/retriever.ts +74 -0
  373. package/src/memory/v2/harness/router-retriever.ts +43 -0
  374. package/src/memory/v2/harness/runner.ts +106 -0
  375. package/src/memory/v2/harness/trace.ts +58 -0
  376. package/src/memory/v2/injection-events.ts +101 -0
  377. package/src/memory/v2/injection.ts +42 -25
  378. package/src/memory/v2/page-index.ts +209 -7
  379. package/src/memory/v2/page-store.ts +18 -0
  380. package/src/memory/v2/prompts/router.ts +26 -1
  381. package/src/memory/v2/qdrant.ts +14 -2
  382. package/src/memory/v2/router.ts +369 -62
  383. package/src/memory/v3/__tests__/coactivation-store.test.ts +422 -0
  384. package/src/memory/v3/__tests__/consolidation-job.test.ts +468 -0
  385. package/src/memory/v3/__tests__/edge-learning-job.test.ts +324 -0
  386. package/src/memory/v3/__tests__/edges.test.ts +563 -0
  387. package/src/memory/v3/__tests__/filter.test.ts +512 -0
  388. package/src/memory/v3/__tests__/gate.test.ts +574 -0
  389. package/src/memory/v3/__tests__/index-composition.test.ts +233 -0
  390. package/src/memory/v3/__tests__/loop.test.ts +530 -0
  391. package/src/memory/v3/__tests__/retriever.test.ts +226 -0
  392. package/src/memory/v3/__tests__/scouts.test.ts +440 -0
  393. package/src/memory/v3/__tests__/shadow-middleware.test.ts +312 -0
  394. package/src/memory/v3/__tests__/system-prompts.test.ts +154 -0
  395. package/src/memory/v3/__tests__/traversal.test.ts +469 -0
  396. package/src/memory/v3/__tests__/tree-index.test.ts +280 -0
  397. package/src/memory/v3/__tests__/tree-store.test.ts +529 -0
  398. package/src/memory/v3/__tests__/tree-walk.test.ts +707 -0
  399. package/src/memory/v3/__tests__/validate.test.ts +245 -0
  400. package/src/memory/v3/auto-edges.ts +223 -0
  401. package/src/memory/v3/coactivation-store.ts +124 -0
  402. package/src/memory/v3/consolidation-job.ts +323 -0
  403. package/src/memory/v3/edge-learning-job.ts +160 -0
  404. package/src/memory/v3/edges.ts +249 -0
  405. package/src/memory/v3/filter.ts +281 -0
  406. package/src/memory/v3/gate.ts +334 -0
  407. package/src/memory/v3/index-composition.ts +113 -0
  408. package/src/memory/v3/llm-capture.ts +46 -0
  409. package/src/memory/v3/loop.ts +382 -0
  410. package/src/memory/v3/maintenance.ts +144 -0
  411. package/src/memory/v3/prompt-context.ts +33 -0
  412. package/src/memory/v3/prompts/consolidation.ts +458 -0
  413. package/src/memory/v3/prompts/system-prompts.ts +196 -0
  414. package/src/memory/v3/retriever.ts +33 -0
  415. package/src/memory/v3/scouts.ts +420 -0
  416. package/src/memory/v3/shadow-middleware.ts +305 -0
  417. package/src/memory/v3/traversal.ts +206 -0
  418. package/src/memory/v3/tree-index.ts +237 -0
  419. package/src/memory/v3/tree-store.ts +394 -0
  420. package/src/memory/v3/tree-walk.ts +351 -0
  421. package/src/memory/v3/types.ts +65 -0
  422. package/src/memory/v3/validate.ts +300 -0
  423. package/src/messaging/providers/index.ts +7 -1
  424. package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +329 -3
  425. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +34 -1
  426. package/src/messaging/providers/slack/adapter.ts +178 -25
  427. package/src/messaging/providers/slack/api.test.ts +54 -0
  428. package/src/messaging/providers/slack/api.ts +119 -3
  429. package/src/messaging/providers/slack/client.ts +12 -0
  430. package/src/messaging/providers/slack/deep-link.ts +20 -1
  431. package/src/messaging/providers/slack/message-metadata.test.ts +48 -0
  432. package/src/messaging/providers/slack/message-metadata.ts +156 -0
  433. package/src/messaging/providers/slack/render-transcript.test.ts +107 -75
  434. package/src/messaging/providers/slack/render-transcript.ts +176 -49
  435. package/src/messaging/providers/slack/send.test.ts +77 -0
  436. package/src/messaging/providers/slack/send.ts +8 -2
  437. package/src/messaging/providers/slack/types.ts +14 -0
  438. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +4 -1
  439. package/src/notifications/__tests__/home-feed-side-effect.test.ts +116 -54
  440. package/src/notifications/adapters/macos.ts +18 -1
  441. package/src/notifications/adapters/platform.ts +1 -1
  442. package/src/notifications/conversation-seed-composer.ts +14 -2
  443. package/src/notifications/decision-engine.ts +1 -4
  444. package/src/notifications/deferred-emit.ts +135 -0
  445. package/src/notifications/emit-signal.ts +38 -50
  446. package/src/notifications/home-feed-side-effect.ts +60 -30
  447. package/src/oauth/connect-orchestrator.ts +3 -0
  448. package/src/oauth/credential-token-resolver.ts +2 -0
  449. package/src/oauth/manual-token-connection.ts +19 -0
  450. package/src/oauth/oauth-store.ts +12 -0
  451. package/src/oauth/seed-providers.ts +22 -0
  452. package/src/permissions/prompter.ts +8 -5
  453. package/src/permissions/question-prompter.ts +5 -2
  454. package/src/permissions/secret-prompter.ts +6 -3
  455. package/src/plugin-api/index.ts +4 -0
  456. package/src/plugin-api/types.ts +7 -33
  457. package/src/plugins/defaults/index.ts +6 -0
  458. package/src/plugins/defaults/injectors.ts +100 -20
  459. package/src/plugins/external-plugin-loader.ts +5 -68
  460. package/src/plugins/types.ts +11 -16
  461. package/src/proactive-artifact/aux-message-injector.ts +17 -4
  462. package/src/prompts/__tests__/system-prompt.test.ts +46 -2
  463. package/src/prompts/__tests__/task-progress-hint-section.test.ts +3 -9
  464. package/src/prompts/normalize-onboarding.ts +40 -0
  465. package/src/prompts/persona-resolver.ts +36 -21
  466. package/src/prompts/sections.ts +69 -19
  467. package/src/prompts/system-prompt.ts +118 -216
  468. package/src/prompts/template-detection.ts +37 -0
  469. package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +141 -0
  470. package/src/prompts/templates/BOOTSTRAP.md +10 -2
  471. package/src/prompts/templates/VOICE.md +3 -0
  472. package/src/prompts/templates/system-sections.ts +281 -9
  473. package/src/providers/__tests__/connection-model-compat.test.ts +234 -0
  474. package/src/providers/__tests__/retry-callsite.test.ts +85 -5
  475. package/src/providers/anthropic/client.ts +159 -66
  476. package/src/providers/call-site-routing.ts +14 -2
  477. package/src/providers/connection-model-compat.ts +38 -0
  478. package/src/providers/connection-resolution.ts +16 -2
  479. package/src/providers/fireworks/client.ts +20 -2
  480. package/src/providers/gemini/client.ts +49 -6
  481. package/src/providers/inference/__tests__/base-url-route-validation.test.ts +342 -0
  482. package/src/providers/inference/__tests__/base-url-security.test.ts +189 -0
  483. package/src/providers/inference/__tests__/codex-token-refresh.test.ts +254 -0
  484. package/src/providers/inference/adapter-factory.ts +18 -1
  485. package/src/providers/inference/auth.ts +3 -3
  486. package/src/providers/inference/codex-token-refresh.ts +128 -0
  487. package/src/providers/inference/resolve-auth.ts +49 -6
  488. package/src/providers/minimax/client.ts +106 -0
  489. package/src/providers/model-catalog.ts +91 -1
  490. package/src/providers/model-intents.ts +1 -1
  491. package/src/providers/openai/chat-completions-provider.ts +63 -23
  492. package/src/providers/openai/codex-models.ts +18 -0
  493. package/src/providers/openai/responses-provider.ts +86 -23
  494. package/src/providers/openrouter/client.ts +5 -1
  495. package/src/providers/provider-send-message.ts +7 -1
  496. package/src/providers/retry.ts +34 -3
  497. package/src/providers/thinking-config.ts +26 -1
  498. package/src/providers/types.ts +25 -0
  499. package/src/providers/usage-tracking.ts +2 -0
  500. package/src/runtime/AGENTS.md +2 -2
  501. package/src/runtime/__tests__/agent-wake.test.ts +214 -0
  502. package/src/runtime/__tests__/background-job-runner.test.ts +128 -0
  503. package/src/runtime/agent-wake.ts +152 -56
  504. package/src/runtime/assistant-event-hub.ts +76 -6
  505. package/src/runtime/auth/route-policy.ts +43 -3
  506. package/src/runtime/background-job-runner.ts +26 -0
  507. package/src/runtime/btw-sidechain.ts +0 -6
  508. package/src/runtime/channel-reply-delivery.ts +182 -47
  509. package/src/runtime/channel-retry-sweep.ts +141 -16
  510. package/src/runtime/http-types.ts +7 -6
  511. package/src/runtime/migrations/vbundle-builder.ts +10 -3
  512. package/src/runtime/pending-interactions.ts +50 -8
  513. package/src/runtime/routes/__tests__/content-source-routes.test.ts +162 -0
  514. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +161 -1
  515. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +14 -0
  516. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +290 -0
  517. package/src/runtime/routes/__tests__/plugins-routes.test.ts +512 -0
  518. package/src/runtime/routes/__tests__/sanity-routes.test.ts +280 -0
  519. package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +266 -0
  520. package/src/runtime/routes/acp-routes.test.ts +255 -6
  521. package/src/runtime/routes/acp-routes.ts +8 -1
  522. package/src/runtime/routes/approval-routes.ts +4 -1
  523. package/src/runtime/routes/avatar-routes.ts +10 -10
  524. package/src/runtime/routes/background-wake-routes.ts +188 -0
  525. package/src/runtime/routes/browser-tabs-routes.ts +200 -0
  526. package/src/runtime/routes/btw-routes.ts +0 -6
  527. package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +246 -0
  528. package/src/runtime/routes/content-source-routes.ts +78 -0
  529. package/src/runtime/routes/conversation-cli-routes.ts +147 -2
  530. package/src/runtime/routes/conversation-list-routes.ts +12 -4
  531. package/src/runtime/routes/conversation-management-routes.ts +77 -20
  532. package/src/runtime/routes/conversation-query-routes.ts +196 -31
  533. package/src/runtime/routes/conversation-routes.ts +472 -425
  534. package/src/runtime/routes/conversation-starter-routes.ts +6 -3
  535. package/src/runtime/routes/disk-pressure-routes.ts +1 -1
  536. package/src/runtime/routes/document-comments-routes.ts +287 -0
  537. package/src/runtime/routes/documents-routes.ts +33 -0
  538. package/src/runtime/routes/domain-routes.ts +60 -10
  539. package/src/runtime/routes/email-routes.ts +5 -2
  540. package/src/runtime/routes/events-routes.ts +54 -10
  541. package/src/runtime/routes/group-routes.ts +24 -8
  542. package/src/runtime/routes/home-feed-routes.ts +6 -3
  543. package/src/runtime/routes/host-app-control-routes.ts +1 -1
  544. package/src/runtime/routes/host-browser-routes.ts +17 -2
  545. package/src/runtime/routes/host-cu-routes.ts +2 -2
  546. package/src/runtime/routes/identity-routes.ts +21 -0
  547. package/src/runtime/routes/inbound-message-handler.ts +288 -58
  548. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +96 -3
  549. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +365 -6
  550. package/src/runtime/routes/inbound-stages/background-dispatch.ts +283 -82
  551. package/src/runtime/routes/index.ts +20 -4
  552. package/src/runtime/routes/inference-profile-session-handler.ts +22 -12
  553. package/src/runtime/routes/inference-profile-session-routes.ts +7 -1
  554. package/src/runtime/routes/inference-provider-connection-routes.ts +63 -7
  555. package/src/runtime/routes/integrations/a2a.ts +60 -1
  556. package/src/runtime/routes/llm-call-sites-routes.ts +32 -5
  557. package/src/runtime/routes/log-export-routes.ts +39 -0
  558. package/src/runtime/routes/memory-item-routes.ts +8 -3
  559. package/src/runtime/routes/memory-v2-routes.ts +427 -0
  560. package/src/runtime/routes/memory-v3-routes.ts +316 -0
  561. package/src/runtime/routes/migration-routes.ts +21 -24
  562. package/src/runtime/routes/notification-routes.ts +19 -2
  563. package/src/runtime/routes/plugins-routes.ts +337 -0
  564. package/src/runtime/routes/question-routes.ts +4 -1
  565. package/src/runtime/routes/rename-conversation-routes.ts +6 -2
  566. package/src/runtime/routes/sanity-routes.ts +159 -0
  567. package/src/runtime/routes/secret-routes.ts +25 -5
  568. package/src/runtime/routes/settings-routes.ts +12 -11
  569. package/src/runtime/routes/slack-channel-routes.ts +188 -0
  570. package/src/runtime/routes/workspace-routes.ts +25 -10
  571. package/src/runtime/services/conversation-serializer.ts +30 -4
  572. package/src/runtime/sync/resource-sync-events.ts +106 -38
  573. package/src/runtime/sync/sync-publisher.test.ts +49 -0
  574. package/src/runtime/sync/sync-publisher.ts +2 -1
  575. package/src/runtime/verification-outbound-actions.ts +73 -1
  576. package/src/schedule/integration-status.ts +3 -1
  577. package/src/security/__tests__/oauth2-device-code.test.ts +479 -0
  578. package/src/security/oauth2-device-code.ts +307 -0
  579. package/src/security/oauth2.ts +26 -9
  580. package/src/security/secure-keys.ts +5 -0
  581. package/src/skills/catalog-install.ts +6 -2
  582. package/src/telemetry/types.ts +12 -0
  583. package/src/telemetry/usage-telemetry-reporter.test.ts +48 -0
  584. package/src/telemetry/usage-telemetry-reporter.ts +1 -0
  585. package/src/tools/acp/spawn.test.ts +119 -0
  586. package/src/tools/acp/spawn.ts +15 -2
  587. package/src/tools/apps/definitions.ts +2 -8
  588. package/src/tools/ask-question/ask-question-tool.test.ts +3 -3
  589. package/src/tools/ask-question/ask-question-tool.ts +38 -45
  590. package/src/tools/browser/__tests__/pinned-tabs.test.ts +150 -0
  591. package/src/tools/browser/browser-execution.ts +106 -0
  592. package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +402 -0
  593. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +28 -0
  594. package/src/tools/browser/cdp-client/__tests__/types.test.ts +4 -0
  595. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +22 -0
  596. package/src/tools/browser/cdp-client/extension-cdp-client.ts +42 -2
  597. package/src/tools/browser/cdp-client/factory.ts +171 -4
  598. package/src/tools/browser/cdp-client/local-cdp-client.ts +21 -0
  599. package/src/tools/browser/cdp-client/types.ts +101 -0
  600. package/src/tools/browser/pinned-tabs.ts +146 -0
  601. package/src/tools/computer-use/definitions.ts +22 -78
  602. package/src/tools/credential-execution/make-authenticated-request.ts +3 -9
  603. package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -9
  604. package/src/tools/credential-execution/run-authenticated-command.ts +3 -9
  605. package/src/tools/credentials/vault.ts +3 -9
  606. package/src/tools/document/document-comment-tool.test.ts +379 -0
  607. package/src/tools/document/document-comment-tool.ts +156 -0
  608. package/src/tools/document/document-tool.ts +187 -2
  609. package/src/tools/execution-target.ts +21 -23
  610. package/src/tools/executor.ts +6 -1
  611. package/src/tools/filesystem/edit.ts +3 -9
  612. package/src/tools/filesystem/list.ts +3 -9
  613. package/src/tools/filesystem/read.ts +3 -9
  614. package/src/tools/filesystem/write.ts +3 -9
  615. package/src/tools/host-filesystem/edit.ts +3 -9
  616. package/src/tools/host-filesystem/read.ts +3 -9
  617. package/src/tools/host-filesystem/transfer.ts +3 -9
  618. package/src/tools/host-filesystem/write.ts +3 -9
  619. package/src/tools/host-terminal/host-shell.ts +3 -9
  620. package/src/tools/mcp/mcp-tool-factory.ts +1 -8
  621. package/src/tools/memory/register.test.ts +1 -1
  622. package/src/tools/memory/register.ts +4 -9
  623. package/src/tools/network/__tests__/web-fetch-metadata.test.ts +229 -0
  624. package/src/tools/network/__tests__/web-search-metadata.test.ts +346 -0
  625. package/src/tools/network/domain-normalize.ts +17 -0
  626. package/src/tools/network/web-fetch.ts +216 -73
  627. package/src/tools/network/web-search.ts +216 -98
  628. package/src/tools/registry.ts +7 -23
  629. package/src/tools/schema-transforms.ts +1 -1
  630. package/src/tools/skills/execute.ts +3 -9
  631. package/src/tools/skills/load.ts +3 -9
  632. package/src/tools/skills/skill-tool-factory.ts +1 -8
  633. package/src/tools/subagent/notify-parent.ts +3 -9
  634. package/src/tools/system/request-permission.ts +3 -9
  635. package/src/tools/terminal/safe-env.ts +3 -2
  636. package/src/tools/terminal/shell.ts +3 -9
  637. package/src/tools/tool-approval-handler.ts +19 -12
  638. package/src/tools/tool-defaults.ts +94 -0
  639. package/src/tools/types.ts +31 -98
  640. package/src/tools/ui-surface/definitions.ts +9 -23
  641. package/src/types/onboarding-context.ts +4 -0
  642. package/src/usage/pricing.ts +23 -0
  643. package/src/usage/types.ts +12 -0
  644. package/src/util/__tests__/favicon.test.ts +84 -0
  645. package/src/util/favicon.ts +40 -0
  646. package/src/util/logger.ts +16 -7
  647. package/src/util/platform.ts +7 -7
  648. package/src/util/sqlite3-runtime.ts +65 -0
  649. package/src/workspace/git-service.ts +75 -4
  650. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +1 -0
  651. package/src/workspace/migrations/088-deprecate-background-conversation-override.ts +103 -0
  652. package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +86 -0
  653. package/src/workspace/migrations/registry.ts +4 -0
  654. package/src/__tests__/compaction-strip-metadata-clear.test.ts +0 -206
  655. package/src/__tests__/message-complete-display-id.test.ts +0 -175
  656. package/src/config/bundled-skills/document/SKILL.md +0 -54
  657. package/src/config/bundled-skills/document/TOOLS.json +0 -106
  658. package/src/daemon/seed-files.ts +0 -18
  659. package/src/prompts/cache-boundary.ts +0 -8
  660. package/src/runtime/routes/interface-routes.ts +0 -43
  661. /package/src/config/bundled-skills/{document → document-editor}/tools/document-create.ts +0 -0
  662. /package/src/config/bundled-skills/{document → document-editor}/tools/document-delete.ts +0 -0
  663. /package/src/config/bundled-skills/{document → document-editor}/tools/document-list.ts +0 -0
  664. /package/src/config/bundled-skills/{document → document-editor}/tools/document-read.ts +0 -0
  665. /package/src/config/bundled-skills/{document → document-editor}/tools/document-update.ts +0 -0
@@ -1,3 +1,4 @@
1
+ import type { RenderedHistoryContent } from "../daemon/handlers/shared.js";
1
2
  import { renderHistoryContent } from "../daemon/handlers/shared.js";
2
3
  import { getAttachmentMetadataForMessage } from "../memory/attachments-store.js";
3
4
  import {
@@ -76,6 +77,18 @@ function toDeliverableTextSegments(
76
77
  return [];
77
78
  }
78
79
 
80
+ function hasDeliverableReply(
81
+ rendered: RenderedHistoryContent,
82
+ attachments: RuntimeAttachmentMetadata[],
83
+ ): boolean {
84
+ return (
85
+ toDeliverableTextSegments(rendered.textSegments, rendered.text).length >
86
+ 0 ||
87
+ attachments.length > 0 ||
88
+ hasNoResponseMarker(rendered.textSegments)
89
+ );
90
+ }
91
+
79
92
  export async function deliverRenderedReplyViaCallback(
80
93
  params: DeliverRenderedReplyParams,
81
94
  ): Promise<void> {
@@ -169,6 +182,13 @@ export async function deliverRenderedReplyViaCallback(
169
182
  }
170
183
 
171
184
  export type DeliverReplyOptions = {
185
+ /** Persisted assistant message row to deliver; defaults to latest assistant. */
186
+ messageId?: string;
187
+ /**
188
+ * Internal conversation message id for the user row that started this
189
+ * delivery. When set, fallback scans never cross into older turns.
190
+ */
191
+ sinceMessageId?: string;
172
192
  startFromSegment?: number;
173
193
  onSegmentDelivered?: (deliveredCount: number) => void;
174
194
  /** Deliver as ephemeral (visible only to `user`). Fire-and-forget. */
@@ -181,6 +201,125 @@ export type DeliverReplyOptions = {
181
201
  onMessageTs?: (ts: string) => void;
182
202
  };
183
203
 
204
+ type PersistedMessage = ReturnType<typeof getMessages>[number];
205
+
206
+ function readPersistedAssistantReply(msg: PersistedMessage): {
207
+ rendered: RenderedHistoryContent;
208
+ replyAttachments: RuntimeAttachmentMetadata[];
209
+ } {
210
+ let parsed: unknown;
211
+ try {
212
+ parsed = JSON.parse(msg.content);
213
+ } catch {
214
+ parsed = msg.content;
215
+ }
216
+ const rendered = renderHistoryContent(parsed);
217
+
218
+ const linked = getAttachmentMetadataForMessage(msg.id);
219
+ const replyAttachments: RuntimeAttachmentMetadata[] = linked.map((a) => ({
220
+ id: a.id,
221
+ filename: a.originalFilename,
222
+ mimeType: a.mimeType,
223
+ sizeBytes: a.sizeBytes,
224
+ kind: a.kind,
225
+ }));
226
+
227
+ return { rendered, replyAttachments };
228
+ }
229
+
230
+ function isToolResultUserMessage(msg: PersistedMessage): boolean {
231
+ if (msg.role !== "user") return false;
232
+ try {
233
+ const parsed = JSON.parse(msg.content) as unknown;
234
+ return (
235
+ Array.isArray(parsed) &&
236
+ parsed.length > 0 &&
237
+ parsed.every(
238
+ (block) =>
239
+ block !== null &&
240
+ typeof block === "object" &&
241
+ (block as Record<string, unknown>).type === "tool_result",
242
+ )
243
+ );
244
+ } catch {
245
+ return false;
246
+ }
247
+ }
248
+
249
+ export function findAssistantReplyMessageIdForTurn(
250
+ conversationId: string,
251
+ userMessageId: string,
252
+ ): string | undefined {
253
+ const msgs = getMessages(conversationId);
254
+ const userIndex = msgs.findIndex((msg) => msg.id === userMessageId);
255
+ if (userIndex === -1) return undefined;
256
+
257
+ let turnEndIndex = msgs.length;
258
+ for (let i = userIndex + 1; i < msgs.length; i++) {
259
+ const msg = msgs[i];
260
+ if (msg.role === "user" && !isToolResultUserMessage(msg)) {
261
+ turnEndIndex = i;
262
+ break;
263
+ }
264
+ }
265
+
266
+ for (let i = turnEndIndex - 1; i > userIndex; i--) {
267
+ const msg = msgs[i];
268
+ if (msg.role === "assistant") {
269
+ const { rendered, replyAttachments } = readPersistedAssistantReply(msg);
270
+ if (hasDeliverableReply(rendered, replyAttachments)) {
271
+ return msg.id;
272
+ }
273
+ }
274
+ }
275
+ return undefined;
276
+ }
277
+
278
+ async function deliverPersistedAssistantMessageViaCallback(
279
+ msg: PersistedMessage,
280
+ externalChatId: string,
281
+ callbackUrl: string,
282
+ assistantId: string | undefined,
283
+ options: DeliverReplyOptions | undefined,
284
+ ): Promise<boolean> {
285
+ const { rendered, replyAttachments } = readPersistedAssistantReply(msg);
286
+ if (!hasDeliverableReply(rendered, replyAttachments)) {
287
+ return false;
288
+ }
289
+
290
+ // Compose an `onMessageTs` that reconciles `slackMeta.channelTs` on the
291
+ // persisted assistant row once Slack returns the authoritative ts. The
292
+ // assistant row was written BEFORE the gateway POST in
293
+ // `handleMessageComplete`, so the partial `slackMeta` it carries is
294
+ // missing `channelTs` and would otherwise be rejected by
295
+ // `readSlackMetadata`, dropping the row out of chronological/thread-tag
296
+ // rendering. We only act on the FIRST ts (top-level segment); any
297
+ // subsequent split segments become independent Slack messages with
298
+ // their own ts and are not represented as separate DB rows.
299
+ const reconcileOnMessageTs = makeChannelTsReconciler(msg.id);
300
+ const callerOnMessageTs = options?.onMessageTs;
301
+ const composedOnMessageTs = (ts: string): void => {
302
+ reconcileOnMessageTs(ts);
303
+ callerOnMessageTs?.(ts);
304
+ };
305
+
306
+ await deliverRenderedReplyViaCallback({
307
+ callbackUrl,
308
+ chatId: externalChatId,
309
+ textSegments: rendered.textSegments,
310
+ fallbackText: rendered.text,
311
+ attachments: replyAttachments,
312
+ assistantId,
313
+ startFromSegment: options?.startFromSegment,
314
+ onSegmentDelivered: options?.onSegmentDelivered,
315
+ ephemeral: options?.ephemeral,
316
+ user: options?.user,
317
+ messageTs: options?.messageTs,
318
+ onMessageTs: composedOnMessageTs,
319
+ });
320
+ return true;
321
+ }
322
+
184
323
  export async function deliverReplyViaCallback(
185
324
  conversationId: string,
186
325
  externalChatId: string,
@@ -188,58 +327,54 @@ export async function deliverReplyViaCallback(
188
327
  assistantId?: string,
189
328
  options?: DeliverReplyOptions,
190
329
  ): Promise<void> {
330
+ if (options?.messageId) {
331
+ const msg = getMessageById(options.messageId, conversationId);
332
+ if (!msg || msg.role !== "assistant") {
333
+ throw new Error(
334
+ `Target assistant reply message not found: ${options.messageId}`,
335
+ );
336
+ }
337
+ await deliverPersistedAssistantMessageViaCallback(
338
+ msg,
339
+ externalChatId,
340
+ callbackUrl,
341
+ assistantId,
342
+ options,
343
+ );
344
+ return;
345
+ }
346
+
347
+ if (options?.sinceMessageId) {
348
+ const replyMessageId = findAssistantReplyMessageIdForTurn(
349
+ conversationId,
350
+ options.sinceMessageId,
351
+ );
352
+ if (replyMessageId) {
353
+ const msg = getMessageById(replyMessageId, conversationId);
354
+ if (msg && msg.role === "assistant") {
355
+ await deliverPersistedAssistantMessageViaCallback(
356
+ msg,
357
+ externalChatId,
358
+ callbackUrl,
359
+ assistantId,
360
+ options,
361
+ );
362
+ }
363
+ }
364
+ return;
365
+ }
366
+
191
367
  const msgs = getMessages(conversationId);
192
368
  for (let i = msgs.length - 1; i >= 0; i--) {
193
369
  if (msgs[i].role !== "assistant") continue;
194
-
195
- let parsed: unknown;
196
- try {
197
- parsed = JSON.parse(msgs[i].content);
198
- } catch {
199
- parsed = msgs[i].content;
200
- }
201
- const rendered = renderHistoryContent(parsed);
202
-
203
- const linked = getAttachmentMetadataForMessage(msgs[i].id);
204
- const replyAttachments: RuntimeAttachmentMetadata[] = linked.map((a) => ({
205
- id: a.id,
206
- filename: a.originalFilename,
207
- mimeType: a.mimeType,
208
- sizeBytes: a.sizeBytes,
209
- kind: a.kind,
210
- }));
211
-
212
- // Compose an `onMessageTs` that reconciles `slackMeta.channelTs` on the
213
- // persisted assistant row once Slack returns the authoritative ts. The
214
- // assistant row was written BEFORE the gateway POST in
215
- // `handleMessageComplete`, so the partial `slackMeta` it carries is
216
- // missing `channelTs` and would otherwise be rejected by
217
- // `readSlackMetadata`, dropping the row out of chronological/thread-tag
218
- // rendering. We only act on the FIRST ts (top-level segment); any
219
- // subsequent split segments become independent Slack messages with
220
- // their own ts and are not represented as separate DB rows.
221
- const reconcileOnMessageTs = makeChannelTsReconciler(msgs[i].id);
222
- const callerOnMessageTs = options?.onMessageTs;
223
- const composedOnMessageTs = (ts: string): void => {
224
- reconcileOnMessageTs(ts);
225
- callerOnMessageTs?.(ts);
226
- };
227
-
228
- await deliverRenderedReplyViaCallback({
370
+ const delivered = await deliverPersistedAssistantMessageViaCallback(
371
+ msgs[i],
372
+ externalChatId,
229
373
  callbackUrl,
230
- chatId: externalChatId,
231
- textSegments: rendered.textSegments,
232
- fallbackText: rendered.text,
233
- attachments: replyAttachments,
234
374
  assistantId,
235
- startFromSegment: options?.startFromSegment,
236
- onSegmentDelivered: options?.onSegmentDelivered,
237
- ephemeral: options?.ephemeral,
238
- user: options?.user,
239
- messageTs: options?.messageTs,
240
- onMessageTs: composedOnMessageTs,
241
- });
242
- break;
375
+ options,
376
+ );
377
+ if (delivered) break;
243
378
  }
244
379
  }
245
380
 
@@ -9,17 +9,28 @@ import {
9
9
  } from "../channels/types.js";
10
10
  import { getDiskPressureStatus } from "../daemon/disk-pressure-guard.js";
11
11
  import { classifyDiskPressureTurnPolicy } from "../daemon/disk-pressure-policy.js";
12
+ import type { ServerMessage } from "../daemon/message-protocol.js";
12
13
  import type { TrustContext } from "../daemon/trust-context.js";
13
14
  import { updateDeliveredSegmentCount } from "../memory/delivery-channels.js";
14
- import { clearPayload, linkMessage } from "../memory/delivery-crud.js";
15
15
  import {
16
+ clearPayload,
17
+ linkMessage,
18
+ storeReplyMessageId,
19
+ } from "../memory/delivery-crud.js";
20
+ import {
21
+ getRetryableDeliveryEvents,
16
22
  getRetryableEvents,
23
+ markDeliveryDelivered,
17
24
  markProcessed,
18
25
  markRetryableFailure,
26
+ recordDeliveryFailure,
19
27
  recordProcessingFailure,
20
28
  } from "../memory/delivery-status.js";
21
29
  import { getLogger } from "../util/logger.js";
22
- import { deliverReplyViaCallback } from "./channel-reply-delivery.js";
30
+ import {
31
+ deliverReplyViaCallback,
32
+ findAssistantReplyMessageIdForTurn,
33
+ } from "./channel-reply-delivery.js";
23
34
  import { deliverChannelReply } from "./gateway-client.js";
24
35
  import type { MessageProcessor } from "./http-types.js";
25
36
  import { resolveRoutingStateFromRuntime } from "./trust-context-resolver.js";
@@ -91,9 +102,13 @@ export async function sweepFailedEvents(
91
102
  processMessage: MessageProcessor,
92
103
  ): Promise<void> {
93
104
  const events = getRetryableEvents();
94
- if (events.length === 0) return;
105
+ const deliveryEvents = getRetryableDeliveryEvents();
106
+ if (events.length === 0 && deliveryEvents.length === 0) return;
95
107
 
96
- log.info({ count: events.length }, "Retrying failed channel inbound events");
108
+ log.info(
109
+ { processingCount: events.length, deliveryCount: deliveryEvents.length },
110
+ "Retrying failed channel inbound events",
111
+ );
97
112
 
98
113
  for (const event of events) {
99
114
  if (!event.rawPayload) {
@@ -243,9 +258,20 @@ export async function sweepFailedEvents(
243
258
  sourceMetadata.chatType.trim().length > 0
244
259
  ? sourceMetadata.chatType.trim()
245
260
  : undefined;
261
+ let replyMessageId: string | undefined;
262
+ const observeAgentEvent = (msg: ServerMessage): void => {
263
+ if (
264
+ msg.type === "message_complete" &&
265
+ (msg.source === undefined || msg.source === "main") &&
266
+ typeof msg.messageId === "string"
267
+ ) {
268
+ replyMessageId = msg.messageId;
269
+ }
270
+ };
246
271
 
272
+ let userMessageId: string | undefined;
247
273
  try {
248
- const { messageId: userMessageId } = await processMessage(
274
+ const result = await processMessage(
249
275
  event.conversationId,
250
276
  content,
251
277
  attachmentIds,
@@ -260,27 +286,39 @@ export async function sweepFailedEvents(
260
286
  trustContext,
261
287
  isInteractive:
262
288
  resolveRoutingStateFromRuntime(trustContext).promptWaitingAllowed,
289
+ onEvent: observeAgentEvent,
263
290
  },
264
291
  sourceChannel,
265
292
  sourceInterface,
266
293
  );
294
+ userMessageId = result.messageId;
267
295
  linkMessage(event.id, userMessageId);
268
296
  markProcessed(event.id);
297
+ replyMessageId ??= result.assistantMessageId;
298
+ if (replyMessageId) {
299
+ storeReplyMessageId(event.id, replyMessageId);
300
+ }
269
301
  log.info(
270
302
  { eventId: event.id },
271
303
  "Successfully replayed failed channel event",
272
304
  );
305
+ } catch (err) {
306
+ log.error({ err, eventId: event.id }, "Retry failed for channel event");
307
+ recordProcessingFailure(event.id, err);
308
+ continue;
309
+ }
273
310
 
274
- const replyCallbackUrl =
275
- typeof payload.replyCallbackUrl === "string"
276
- ? payload.replyCallbackUrl
311
+ const replyCallbackUrl =
312
+ typeof payload.replyCallbackUrl === "string"
313
+ ? payload.replyCallbackUrl
314
+ : undefined;
315
+ if (replyCallbackUrl) {
316
+ const externalChatId =
317
+ typeof payload.externalChatId === "string"
318
+ ? payload.externalChatId
277
319
  : undefined;
278
- if (replyCallbackUrl) {
279
- const externalChatId =
280
- typeof payload.externalChatId === "string"
281
- ? payload.externalChatId
282
- : undefined;
283
- if (externalChatId) {
320
+ if (externalChatId) {
321
+ try {
284
322
  // processMessage above generated a fresh assistant response, so any
285
323
  // previously tracked segment progress belongs to the old response and
286
324
  // must not carry over. Reset to 0 so we deliver all segments of the
@@ -292,16 +330,103 @@ export async function sweepFailedEvents(
292
330
  replyCallbackUrl,
293
331
  assistantId,
294
332
  {
333
+ messageId: replyMessageId,
334
+ sinceMessageId: userMessageId,
295
335
  startFromSegment: 0,
296
336
  onSegmentDelivered: (count) =>
297
337
  updateDeliveredSegmentCount(event.id, count),
298
338
  },
299
339
  );
340
+ markDeliveryDelivered(event.id);
341
+ } catch (err) {
342
+ log.error(
343
+ { err, eventId: event.id },
344
+ "Retry delivery failed for channel event",
345
+ );
346
+ recordDeliveryFailure(event.id, err);
300
347
  }
301
348
  }
349
+ }
350
+ }
351
+
352
+ for (const event of deliveryEvents) {
353
+ if (!event.rawPayload) {
354
+ recordDeliveryFailure(
355
+ event.id,
356
+ new Error("No raw payload stored for delivery retry"),
357
+ );
358
+ continue;
359
+ }
360
+
361
+ let payload: Record<string, unknown>;
362
+ try {
363
+ payload = JSON.parse(event.rawPayload) as Record<string, unknown>;
364
+ } catch {
365
+ recordDeliveryFailure(
366
+ event.id,
367
+ new Error("Failed to parse stored raw payload for delivery retry"),
368
+ );
369
+ continue;
370
+ }
371
+
372
+ const replyCallbackUrl =
373
+ typeof payload.replyCallbackUrl === "string"
374
+ ? payload.replyCallbackUrl
375
+ : undefined;
376
+ const externalChatId =
377
+ typeof payload.externalChatId === "string"
378
+ ? payload.externalChatId
379
+ : undefined;
380
+ let replyMessageId =
381
+ typeof payload.replyMessageId === "string"
382
+ ? payload.replyMessageId
383
+ : undefined;
384
+ const assistantId =
385
+ typeof payload.assistantId === "string" ? payload.assistantId : undefined;
386
+ if (!replyCallbackUrl || !externalChatId) {
387
+ recordDeliveryFailure(
388
+ event.id,
389
+ new Error("Stored payload is missing delivery callback details"),
390
+ );
391
+ continue;
392
+ }
393
+ if (!replyMessageId && event.messageId) {
394
+ replyMessageId = findAssistantReplyMessageIdForTurn(
395
+ event.conversationId,
396
+ event.messageId,
397
+ );
398
+ if (replyMessageId) {
399
+ storeReplyMessageId(event.id, replyMessageId);
400
+ }
401
+ }
402
+ if (!replyMessageId) {
403
+ recordDeliveryFailure(
404
+ event.id,
405
+ new Error("Stored payload is missing assistant reply message id"),
406
+ );
407
+ continue;
408
+ }
409
+
410
+ try {
411
+ await deliverReplyViaCallback(
412
+ event.conversationId,
413
+ externalChatId,
414
+ replyCallbackUrl,
415
+ assistantId,
416
+ {
417
+ messageId: replyMessageId,
418
+ startFromSegment: event.deliveredSegmentCount,
419
+ onSegmentDelivered: (count) =>
420
+ updateDeliveredSegmentCount(event.id, count),
421
+ },
422
+ );
423
+ markDeliveryDelivered(event.id);
302
424
  } catch (err) {
303
- log.error({ err, eventId: event.id }, "Retry failed for channel event");
304
- recordProcessingFailure(event.id, err);
425
+ log.error(
426
+ { err, eventId: event.id },
427
+ "Retry delivery failed for processed channel event",
428
+ );
429
+ recordDeliveryFailure(event.id, err);
305
430
  }
306
431
  }
307
432
  }
@@ -63,6 +63,7 @@ export interface RuntimeMessageConversationOptions {
63
63
  hints?: string[];
64
64
  uxBrief?: string;
65
65
  chatType?: string;
66
+ clientTimezone?: string;
66
67
  };
67
68
  assistantId?: string;
68
69
  trustContext?: TrustContext;
@@ -74,8 +75,6 @@ export interface RuntimeMessageConversationOptions {
74
75
  isInteractive?: boolean;
75
76
  /** Channel command intent metadata (e.g. Telegram /start). */
76
77
  commandIntent?: { type: string; payload?: string; languageCode?: string };
77
- /** Slack-only non-persisted notice injected into the active model turn. */
78
- slackRuntimeContextNotice?: string;
79
78
  /**
80
79
  * Persisted user-facing content. When present, storage/UI use this value
81
80
  * while the model-facing turn continues to use `content`.
@@ -106,7 +105,7 @@ export type MessageProcessor = (
106
105
  options?: RuntimeMessageConversationOptions,
107
106
  sourceChannel?: ChannelId,
108
107
  sourceInterface?: InterfaceId,
109
- ) => Promise<{ messageId: string }>;
108
+ ) => Promise<{ messageId: string; assistantMessageId?: string }>;
110
109
 
111
110
  /**
112
111
  * Dependencies for the POST /v1/messages handler.
@@ -149,8 +148,6 @@ export interface RuntimeAttachmentMetadata {
149
148
 
150
149
  export interface RuntimeMessagePayload {
151
150
  id: string;
152
- /** Concrete persisted assistant row id for row-scoped actions. */
153
- daemonMessageId?: string;
154
151
  role: string;
155
152
  content: string;
156
153
  timestamp: string;
@@ -167,7 +164,6 @@ export interface RuntimeMessagePayload {
167
164
  approvalReason?: string;
168
165
  riskThreshold?: string;
169
166
  }>;
170
- interfaces?: string[];
171
167
  surfaces?: Array<{
172
168
  surfaceId: string;
173
169
  surfaceType: string;
@@ -189,8 +185,13 @@ export interface RuntimeMessagePayload {
189
185
  };
190
186
  slackMessage?: {
191
187
  channelId: string;
188
+ channelName?: string;
192
189
  channelTs: string;
193
190
  threadTs?: string;
191
+ sender?: {
192
+ displayName?: string;
193
+ externalUserId?: string;
194
+ };
194
195
  messageLink?: {
195
196
  appUrl?: string;
196
197
  webUrl?: string;
@@ -681,8 +681,13 @@ export interface BuildExportVBundleOptions {
681
681
  * flushed to the main .db file. Callers should pass a function that runs
682
682
  * PRAGMA wal_checkpoint(TRUNCATE) on the live database connection.
683
683
  * Called before the workspace walk so the DB file is up to date.
684
+ *
685
+ * May return a Promise — `streamExportVBundle` awaits the result so an
686
+ * async-dispatched checkpoint (e.g. via `runAsyncSqlite`) does not race
687
+ * with the file walk. The synchronous `buildExportVBundle` path does
688
+ * not await; pass a sync callback there.
684
689
  */
685
- checkpoint?: () => void;
690
+ checkpoint?: () => void | Promise<void>;
686
691
  /** Optional credential entries to include in the archive under credentials/ prefix. */
687
692
  credentials?: Array<{ account: string; value: string }>;
688
693
  }
@@ -1120,9 +1125,11 @@ export async function streamExportVBundle(
1120
1125
  credentials,
1121
1126
  } = options;
1122
1127
 
1123
- // Flush WAL to the main database file before reading
1128
+ // Flush WAL to the main database file before reading. Awaiting allows
1129
+ // the callback to dispatch the checkpoint via `runAsyncSqlite` so the
1130
+ // daemon event loop stays responsive while SQLite truncates the WAL.
1124
1131
  if (checkpoint) {
1125
- checkpoint();
1132
+ await checkpoint();
1126
1133
  }
1127
1134
 
1128
1135
  const allFileMetadata: FileMetadata[] = [];
@@ -18,7 +18,14 @@
18
18
  * resolve the interaction.
19
19
  */
20
20
 
21
+ import type { InteractionResolutionState } from "../daemon/message-types/messages.js";
21
22
  import type { UserDecision } from "../permissions/types.js";
23
+ import { getLogger } from "../util/logger.js";
24
+ import { broadcastMessage } from "./assistant-event-hub.js";
25
+
26
+ const log = getLogger("pending-interactions");
27
+
28
+ export type { InteractionResolutionState } from "../daemon/message-types/messages.js";
22
29
 
23
30
  export interface ConfirmationDetails {
24
31
  toolName: string;
@@ -98,17 +105,49 @@ export function register(
98
105
  * Remove and return the pending interaction for the given requestId.
99
106
  * Auto-clears the proxy timer and detaches the abort listener if present.
100
107
  * Returns undefined if no interaction is registered.
108
+ *
109
+ * Emits `interaction_resolved` on the event hub when an interaction is
110
+ * actually removed (no-op when the entry was already consumed by another
111
+ * path). Callers pass `state` to communicate the lifecycle outcome
112
+ * — defaults to `"cancelled"`, the safest value when the call site has
113
+ * no extra context.
101
114
  */
102
- export function resolve(requestId: string): PendingInteraction | undefined {
115
+ export function resolve(
116
+ requestId: string,
117
+ state: InteractionResolutionState = "cancelled",
118
+ ): PendingInteraction | undefined {
103
119
  const interaction = pending.get(requestId);
104
- if (interaction) {
105
- pending.delete(requestId);
106
- if (interaction.timer != null) clearTimeout(interaction.timer);
107
- interaction.detachAbort?.();
108
- }
120
+ if (!interaction) return undefined;
121
+ pending.delete(requestId);
122
+ if (interaction.timer != null) clearTimeout(interaction.timer);
123
+ interaction.detachAbort?.();
124
+ emitResolved(requestId, interaction, state);
109
125
  return interaction;
110
126
  }
111
127
 
128
+ function emitResolved(
129
+ requestId: string,
130
+ interaction: PendingInteraction,
131
+ state: InteractionResolutionState,
132
+ ): void {
133
+ log.info(
134
+ {
135
+ requestId,
136
+ conversationId: interaction.conversationId,
137
+ kind: interaction.kind,
138
+ state,
139
+ },
140
+ "Pending interaction resolved",
141
+ );
142
+ broadcastMessage({
143
+ type: "interaction_resolved",
144
+ requestId,
145
+ conversationId: interaction.conversationId,
146
+ kind: interaction.kind,
147
+ state,
148
+ });
149
+ }
150
+
112
151
  /**
113
152
  * Return the pending interaction without removing it.
114
153
  * Used by trust-rule endpoint which doesn't resolve the confirmation itself.
@@ -146,7 +185,10 @@ export function getByConversation(
146
185
  * /v1/host-transfer-result after completing the operation, get a 404, and the
147
186
  * proxy timer would fire with a spurious timeout error.
148
187
  */
149
- export function removeByConversation(conversationId: string): void {
188
+ export function removeByConversation(
189
+ conversationId: string,
190
+ state: InteractionResolutionState = "superseded",
191
+ ): void {
150
192
  // Snapshot keys to avoid mutation-during-iteration.
151
193
  for (const [requestId, interaction] of [...pending]) {
152
194
  if (
@@ -160,7 +202,7 @@ export function removeByConversation(conversationId: string): void {
160
202
  interaction.kind !== "acp_confirmation"
161
203
  ) {
162
204
  // resolve() clears the stored timer and detaches abort listeners.
163
- resolve(requestId);
205
+ resolve(requestId, state);
164
206
  }
165
207
  }
166
208
  }