@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
@@ -0,0 +1,404 @@
1
+ /**
2
+ * Message consolidation — shared logic that maps the raw DB row sequence
3
+ * onto the displayed transcript.
4
+ *
5
+ * A single "display turn" in the UI can span multiple DB rows. During
6
+ * streaming the agent loop persists each API call as a separate
7
+ * assistant row (deferred consolidation, for prefix-cache stability),
8
+ * and intervening user rows often carry only tool_result blocks that
9
+ * are suppressed at display time. The two-pass collapse here is what
10
+ * turns the raw sequence into the rows the user actually sees.
11
+ *
12
+ * Pass 1 — `mergeToolResultsIntoAssistantMessages`
13
+ * For each user row, lift its `tool_result` (and `web_search_tool_result`)
14
+ * blocks onto the preceding assistant row. If the user row had
15
+ * nothing else (only tool_result + system_notice blocks), drop the
16
+ * row entirely. Otherwise keep its non-tool-result content as a
17
+ * real user message.
18
+ *
19
+ * Pass 2 — `mergeConsecutiveAssistantMessages`
20
+ * After pass 1 removes tool-result-only user separators, fold runs
21
+ * of adjacent assistant rows onto the first row of the run
22
+ * ("anchor"). Anchors keep their id, createdAt, and metadata;
23
+ * subagent-notification metadata is promoted from later rows when
24
+ * the anchor lacks it.
25
+ *
26
+ * `findDisplayTurnEndIndex` is the primitive any write-path needs when
27
+ * it has a single DB-row id and wants to know "which DB rows make up
28
+ * the display turn that this row anchors". It uses the same
29
+ * `isToolResultOnlyUserMessage` predicate that pass 1 uses to decide
30
+ * which user rows are suppressed, so the read-path and write-path
31
+ * agree on cluster boundaries without duplicating the merge code.
32
+ */
33
+
34
+ import type { MessageRow } from "../memory/conversation-crud.js";
35
+ import { getLogger } from "../util/logger.js";
36
+
37
+ const log = getLogger("message-consolidation");
38
+
39
+ // ── Block predicates ────────────────────────────────────────────────
40
+
41
+ function isToolResultType(type: string): boolean {
42
+ return type === "tool_result" || type === "web_search_tool_result";
43
+ }
44
+
45
+ function isSystemNoticeText(block: Record<string, unknown>): boolean {
46
+ if (block.type !== "text") return false;
47
+ const text = typeof block.text === "string" ? block.text : "";
48
+ return (
49
+ text.startsWith("<system_notice>") && text.endsWith("</system_notice>")
50
+ );
51
+ }
52
+
53
+ /**
54
+ * True when a user row's content is exclusively tool_result blocks
55
+ * (and optional system_notice text). Such rows are suppressed by the
56
+ * read-path collapse — they exist in the DB to satisfy the LLM's
57
+ * tool_use ↔ tool_result pairing requirement but are never displayed
58
+ * to the user. Any write-path that walks DB rows in display order
59
+ * must treat them as part of the surrounding assistant turn.
60
+ */
61
+ export function isToolResultOnlyUserMessage(msg: MessageRow): boolean {
62
+ if (msg.role !== "user") return false;
63
+ let blocks: unknown[];
64
+ try {
65
+ const parsed = JSON.parse(msg.content);
66
+ if (!Array.isArray(parsed)) return false;
67
+ blocks = parsed;
68
+ } catch {
69
+ return false;
70
+ }
71
+
72
+ let sawToolResult = false;
73
+ for (const block of blocks) {
74
+ if (
75
+ typeof block !== "object" ||
76
+ block === null ||
77
+ typeof (block as Record<string, unknown>).type !== "string"
78
+ ) {
79
+ return false;
80
+ }
81
+ const rec = block as Record<string, unknown>;
82
+ if (isToolResultType(rec.type as string)) {
83
+ sawToolResult = true;
84
+ continue;
85
+ }
86
+ if (isSystemNoticeText(rec)) {
87
+ continue;
88
+ }
89
+ return false;
90
+ }
91
+ return sawToolResult;
92
+ }
93
+
94
+ // ── Display-turn boundary lookup ────────────────────────────────────
95
+
96
+ /**
97
+ * Returns the inclusive DB-row index where the display turn that
98
+ * contains `messages[startIdx]` ends.
99
+ *
100
+ * For non-assistant rows, returns `startIdx` unchanged — only assistant
101
+ * turns can span multiple rows.
102
+ *
103
+ * For assistant rows, advances past any consecutive rows that the
104
+ * read-path collapse would fold into the same display turn:
105
+ * - another assistant row → part of the consecutive-assistant run, OR
106
+ * - a tool-result-only user row → suppressed at display time, sits
107
+ * between two halves of the same assistant turn.
108
+ *
109
+ * Stops at the first real user message (or any non-collapsible row),
110
+ * end-of-array, or invalid index.
111
+ *
112
+ * Mirror of the cluster boundary that `mergeConsecutiveAssistantMessages`
113
+ * (post pass-1) would produce — without paying the cost of parsing
114
+ * every content block.
115
+ */
116
+ export function findDisplayTurnEndIndex(
117
+ messages: MessageRow[],
118
+ startIdx: number,
119
+ ): number {
120
+ if (startIdx < 0 || startIdx >= messages.length) return startIdx;
121
+ if (messages[startIdx]?.role !== "assistant") return startIdx;
122
+
123
+ let endIdx = startIdx;
124
+ while (endIdx + 1 < messages.length) {
125
+ const next = messages[endIdx + 1];
126
+ if (!next) break;
127
+ if (next.role === "assistant") {
128
+ endIdx += 1;
129
+ continue;
130
+ }
131
+ if (next.role === "user" && isToolResultOnlyUserMessage(next)) {
132
+ endIdx += 1;
133
+ continue;
134
+ }
135
+ break;
136
+ }
137
+ return endIdx;
138
+ }
139
+
140
+ // ── Pass 1: tool-result merging ─────────────────────────────────────
141
+
142
+ /**
143
+ * Merge tool_result blocks from user messages into the preceding assistant
144
+ * message's content array. This lets renderHistoryContent's pendingToolUses
145
+ * map pair tool_use and tool_result blocks, preventing "unknown" tool names.
146
+ *
147
+ * User messages that consist entirely of tool_result blocks (and optional
148
+ * system_notice text) are removed from the output. Mixed messages (tool_result
149
+ * + real user text) keep only the non-tool-result blocks.
150
+ */
151
+ export function mergeToolResultsIntoAssistantMessages(
152
+ messages: MessageRow[],
153
+ ): MessageRow[] {
154
+ // Index of the most recent assistant message in the output array.
155
+ let lastAssistantIdx = -1;
156
+ // Parsed content caches — lazily populated per assistant message.
157
+ const parsedAssistantContent = new Map<number, unknown[]>();
158
+
159
+ const result: MessageRow[] = [];
160
+
161
+ for (const msg of messages) {
162
+ if (msg.role === "assistant") {
163
+ lastAssistantIdx = result.length;
164
+ result.push(msg);
165
+ continue;
166
+ }
167
+
168
+ // Only process user messages — other roles pass through.
169
+ if (msg.role !== "user") {
170
+ result.push(msg);
171
+ continue;
172
+ }
173
+
174
+ let blocks: unknown[];
175
+ try {
176
+ const parsed = JSON.parse(msg.content);
177
+ if (!Array.isArray(parsed)) {
178
+ result.push(msg);
179
+ continue;
180
+ }
181
+ blocks = parsed;
182
+ } catch {
183
+ result.push(msg);
184
+ continue;
185
+ }
186
+
187
+ // Separate tool-result blocks from real user content.
188
+ const toolResultBlocks: unknown[] = [];
189
+ const otherBlocks: unknown[] = [];
190
+ for (const block of blocks) {
191
+ if (
192
+ typeof block === "object" &&
193
+ block !== null &&
194
+ typeof (block as Record<string, unknown>).type === "string"
195
+ ) {
196
+ const rec = block as Record<string, unknown>;
197
+ if (isToolResultType(rec.type as string)) {
198
+ toolResultBlocks.push(block);
199
+ } else if (isSystemNoticeText(rec)) {
200
+ // System notices don't count as user content — drop them when
201
+ // the message is otherwise tool-result-only.
202
+ otherBlocks.push(block);
203
+ } else {
204
+ otherBlocks.push(block);
205
+ }
206
+ } else {
207
+ otherBlocks.push(block);
208
+ }
209
+ }
210
+
211
+ // No tool results → pass through unchanged. System notices are only
212
+ // injected alongside tool results in the agent loop, so a pure user
213
+ // message (no tool_result blocks) should never be filtered — even if
214
+ // the user's text happens to look like a system_notice tag.
215
+ if (toolResultBlocks.length === 0) {
216
+ result.push(msg);
217
+ continue;
218
+ }
219
+
220
+ // Append tool_result blocks to the preceding assistant message's content.
221
+ // No-op at pagination boundaries (lastAssistantIdx < 0); orphan tool_results
222
+ // are silently dropped by renderHistoryContent downstream either way.
223
+ if (lastAssistantIdx >= 0) {
224
+ const assistant = result[lastAssistantIdx];
225
+ let assistantContent = parsedAssistantContent.get(lastAssistantIdx);
226
+ if (!assistantContent) {
227
+ try {
228
+ const parsed = JSON.parse(assistant.content);
229
+ assistantContent = Array.isArray(parsed) ? parsed : [parsed];
230
+ } catch {
231
+ assistantContent = [];
232
+ }
233
+ parsedAssistantContent.set(lastAssistantIdx, assistantContent);
234
+ }
235
+ assistantContent.push(...toolResultBlocks);
236
+ }
237
+
238
+ // If the user message had only tool_result (+ system_notice) blocks,
239
+ // suppress it entirely. Otherwise keep the non-tool-result content.
240
+ const realUserContent = otherBlocks.filter(
241
+ (b) =>
242
+ !(
243
+ typeof b === "object" &&
244
+ b !== null &&
245
+ isSystemNoticeText(b as Record<string, unknown>)
246
+ ),
247
+ );
248
+ if (realUserContent.length > 0) {
249
+ result.push({ ...msg, content: JSON.stringify(otherBlocks) });
250
+ }
251
+ // else: tool-result-only → suppressed
252
+ }
253
+
254
+ // Write back any modified assistant message content.
255
+ for (const [idx, content] of parsedAssistantContent) {
256
+ result[idx] = { ...result[idx], content: JSON.stringify(content) };
257
+ }
258
+
259
+ return result;
260
+ }
261
+
262
+ // ── Pass 2: consecutive-assistant merging ───────────────────────────
263
+
264
+ /** Parse a message's JSON content into an array of content blocks. */
265
+ function parseContentBlocks(content: string): unknown[] {
266
+ try {
267
+ const parsed = JSON.parse(content);
268
+ return Array.isArray(parsed) ? parsed : [parsed];
269
+ } catch (err) {
270
+ log.warn(
271
+ { err },
272
+ "Failed to parse content blocks during assistant message merge",
273
+ );
274
+ return [];
275
+ }
276
+ }
277
+
278
+ /**
279
+ * Append content blocks from a donor message onto a target block array.
280
+ * Parses the donor's JSON content and pushes each block into `target`.
281
+ */
282
+ function appendContentBlocks(target: unknown[], donorContent: string): void {
283
+ try {
284
+ const parsed = JSON.parse(donorContent);
285
+ if (Array.isArray(parsed)) {
286
+ target.push(...parsed);
287
+ } else {
288
+ target.push(parsed);
289
+ }
290
+ } catch (err) {
291
+ log.warn(
292
+ { err },
293
+ "Failed to parse donor content blocks during assistant message merge",
294
+ );
295
+ }
296
+ }
297
+
298
+ /**
299
+ * Promote metadata fields from a donor message to the surviving message
300
+ * when the survivor lacks them. Currently promotes `subagentNotification`.
301
+ * Returns a new MessageRow if promotion occurred, otherwise the original.
302
+ */
303
+ function promoteMetadata(survivor: MessageRow, donor: MessageRow): MessageRow {
304
+ if (donor.metadata && survivor.metadata) {
305
+ try {
306
+ const survivorMeta = JSON.parse(survivor.metadata);
307
+ const donorMeta = JSON.parse(donor.metadata);
308
+ if (
309
+ !survivorMeta.subagentNotification &&
310
+ donorMeta.subagentNotification
311
+ ) {
312
+ survivorMeta.subagentNotification = donorMeta.subagentNotification;
313
+ return { ...survivor, metadata: JSON.stringify(survivorMeta) };
314
+ }
315
+ } catch (err) {
316
+ log.warn(
317
+ { err },
318
+ "Failed to parse metadata during assistant message merge",
319
+ );
320
+ }
321
+ } else if (donor.metadata && !survivor.metadata) {
322
+ return { ...survivor, metadata: donor.metadata };
323
+ }
324
+ return survivor;
325
+ }
326
+
327
+ /**
328
+ * Merge consecutive assistant messages into a single message at query time.
329
+ *
330
+ * During streaming, all assistant turns within one agent loop accumulate on
331
+ * a single client-side message. In the DB, each API turn is stored as a
332
+ * separate assistant row (consolidation is deferred to compaction for
333
+ * prefix-cache stability). This produces N separate assistant messages that
334
+ * the client would otherwise render as N individual rows — each showing
335
+ * "Completed 1 step" instead of one grouped "Completed N steps" accordion.
336
+ *
337
+ * This function concatenates the content block arrays of consecutive
338
+ * assistant messages (no intervening user messages after tool-result
339
+ * merging) into the first message of each run. The merged messages are
340
+ * removed from the output. This is query-time only — the DB is not
341
+ * modified.
342
+ *
343
+ * The first message in each run keeps its id, createdAt, and metadata so
344
+ * that attachment lookups, display timestamps, and subagent notifications
345
+ * continue to work. Metadata from later messages in the run (e.g.
346
+ * subagentNotification) is preserved by promoting it to the surviving
347
+ * message when the surviving message has no metadata of its own for that
348
+ * field.
349
+ */
350
+ export function mergeConsecutiveAssistantMessages(messages: MessageRow[]): {
351
+ messages: MessageRow[];
352
+ /** Maps each surviving message ID → all original message IDs merged into it. */
353
+ mergedIdMap: Map<string, string[]>;
354
+ } {
355
+ const result: MessageRow[] = [];
356
+ // Key = index in `result`, value = accumulated content blocks.
357
+ const pendingMerges = new Map<number, unknown[]>();
358
+ // Key = index in `result`, value = IDs of messages merged into the target.
359
+ const mergedIds = new Map<number, string[]>();
360
+
361
+ for (const msg of messages) {
362
+ const lastIdx = result.length - 1;
363
+ const isConsecutiveAssistant =
364
+ msg.role === "assistant" &&
365
+ lastIdx >= 0 &&
366
+ result[lastIdx].role === "assistant";
367
+
368
+ if (!isConsecutiveAssistant) {
369
+ result.push(msg);
370
+ continue;
371
+ }
372
+
373
+ // Track the donor message ID.
374
+ let ids = mergedIds.get(lastIdx);
375
+ if (!ids) {
376
+ ids = [];
377
+ mergedIds.set(lastIdx, ids);
378
+ }
379
+ ids.push(msg.id);
380
+
381
+ // Lazily parse the target's content on first merge.
382
+ let targetContent = pendingMerges.get(lastIdx);
383
+ if (!targetContent) {
384
+ targetContent = parseContentBlocks(result[lastIdx].content);
385
+ pendingMerges.set(lastIdx, targetContent);
386
+ }
387
+
388
+ appendContentBlocks(targetContent, msg.content);
389
+ result[lastIdx] = promoteMetadata(result[lastIdx], msg);
390
+ }
391
+
392
+ // Write back merged content for any messages that were targets.
393
+ for (const [idx, content] of pendingMerges) {
394
+ result[idx] = { ...result[idx], content: JSON.stringify(content) };
395
+ }
396
+
397
+ // Build the merged ID map keyed by surviving message ID.
398
+ const mergedIdMap = new Map<string, string[]>();
399
+ for (const [idx, ids] of mergedIds) {
400
+ mergedIdMap.set(result[idx].id, ids);
401
+ }
402
+
403
+ return { messages: result, mergedIdMap };
404
+ }
@@ -315,9 +315,11 @@ async function checkManagedProvider(
315
315
  const client = await VellumPlatformClient.create();
316
316
  if (!client?.platformAssistantId) return results;
317
317
 
318
+ // Query without a status filter so we can distinguish "never
319
+ // connected" (empty result) from "previously connected but now
320
+ // inactive" (non-empty result with no ACTIVE entries).
318
321
  const params = new URLSearchParams();
319
322
  params.set("provider", providerRow.provider);
320
- params.set("status", "ACTIVE");
321
323
 
322
324
  const path = `/v1/assistants/${encodeURIComponent(client.platformAssistantId)}/oauth/connections/?${params.toString()}`;
323
325
  const response = await client.fetch(path);
@@ -331,19 +333,30 @@ async function checkManagedProvider(
331
333
  }
332
334
 
333
335
  const body = (await response.json()) as unknown;
334
- const connections = (
336
+ const allConnections = (
335
337
  Array.isArray(body)
336
338
  ? body
337
339
  : ((body as Record<string, unknown>).results ?? [])
338
- ) as Array<{ id: string; account_label?: string }>;
340
+ ) as Array<{ id: string; account_label?: string; status?: string }>;
341
+
342
+ if (allConnections.length === 0) {
343
+ // No connections of any status — the user has never connected this
344
+ // provider. The suggested-prompts system handles prompting them to
345
+ // connect; this is not a health issue.
346
+ return results;
347
+ }
348
+
349
+ const connections = allConnections.filter(
350
+ (c) => (c.status ?? "ACTIVE").toUpperCase() === "ACTIVE",
351
+ );
339
352
 
340
353
  if (connections.length === 0) {
341
- // No active managed connections report as missing so the
342
- // heartbeat can notify the user.
354
+ // Connections exist but none are active the user previously
355
+ // connected and the connection was revoked/deactivated.
343
356
  results.push({
344
357
  connectionId: `managed:${providerRow.provider}`,
345
358
  provider: providerRow.provider,
346
- accountInfo: null,
359
+ accountInfo: allConnections[0]?.account_label ?? null,
347
360
  status: "missing_token",
348
361
  details: `No active managed connection for ${providerRow.provider}. Reconnect on the Vellum platform.`,
349
362
  missingScopes: [],
@@ -550,9 +563,20 @@ export async function checkAllCredentials(): Promise<CredentialHealthReport> {
550
563
  for (const providerRow of providers) {
551
564
  if (!(await isManagedProvider(providerRow))) continue;
552
565
 
553
- // If the provider is in managed mode and also has BYO connections,
554
- // remove the stale BYO results — managed mode takes priority.
555
- if (byoProviders.has(providerRow.provider)) {
566
+ let managedResults: CredentialHealthResult[] = [];
567
+ try {
568
+ managedResults = await checkManagedProvider(providerRow);
569
+ } catch (err) {
570
+ log.warn(
571
+ { err, provider: providerRow.provider },
572
+ "Failed to check managed provider health",
573
+ );
574
+ }
575
+
576
+ // Only replace BYO results with managed results when the managed
577
+ // check returned something. If managed returned empty (user never
578
+ // connected via managed mode), keep any existing BYO results.
579
+ if (managedResults.length > 0 && byoProviders.has(providerRow.provider)) {
556
580
  const beforeLen = results.length;
557
581
  const filtered = results.filter(
558
582
  (r) => r.provider !== providerRow.provider,
@@ -562,16 +586,7 @@ export async function checkAllCredentials(): Promise<CredentialHealthReport> {
562
586
  results.push(...filtered);
563
587
  }
564
588
  }
565
-
566
- try {
567
- const managedResults = await checkManagedProvider(providerRow);
568
- results.push(...managedResults);
569
- } catch (err) {
570
- log.warn(
571
- { err, provider: providerRow.provider },
572
- "Failed to check managed provider health",
573
- );
574
- }
589
+ results.push(...managedResults);
575
590
  }
576
591
 
577
592
  const unhealthy = results.filter((r) => r.status !== "healthy");
@@ -30,7 +30,7 @@ function mcpTool(name: string): Tool {
30
30
  name,
31
31
  description: name,
32
32
  origin: "mcp",
33
- getDefinition: () => def(name),
33
+ input_schema: def(name).input_schema,
34
34
  } as unknown as Tool;
35
35
  }
36
36
 
@@ -49,11 +49,8 @@ mock.module("../../runtime/assistant-event-hub.js", () => ({
49
49
 
50
50
  // Dynamic imports after mock.module calls so the stubs take effect
51
51
  // before the modules under test are loaded.
52
- const {
53
- HOST_TOOL_NAMES,
54
- HOST_TOOL_TO_CAPABILITY,
55
- isToolActiveForContext,
56
- } = await import("../conversation-tool-setup.js");
52
+ const { HOST_TOOL_NAMES, HOST_TOOL_TO_CAPABILITY, isToolActiveForContext } =
53
+ await import("../conversation-tool-setup.js");
57
54
  type SkillProjectionContext =
58
55
  import("../conversation-tool-setup.js").SkillProjectionContext;
59
56
  type SkillProjectionCache =
@@ -75,6 +72,66 @@ beforeEach(() => {
75
72
  mockClientCountByCapability.clear();
76
73
  });
77
74
 
75
+ describe("isToolActiveForContext — Slack task_progress UI exception", () => {
76
+ test("ui_show and ui_update are active for Slack task_progress turns", () => {
77
+ const ctx = makeCtx({
78
+ hasNoClient: false,
79
+ channelCapabilities: {
80
+ channel: "slack",
81
+ supportsDynamicUi: false,
82
+ },
83
+ });
84
+
85
+ expect(isToolActiveForContext("ui_show", ctx)).toBe(true);
86
+ expect(isToolActiveForContext("ui_update", ctx)).toBe(true);
87
+ });
88
+
89
+ test("ui_dismiss remains hidden for Slack without dynamic UI support", () => {
90
+ expect(
91
+ isToolActiveForContext(
92
+ "ui_dismiss",
93
+ makeCtx({
94
+ hasNoClient: false,
95
+ channelCapabilities: {
96
+ channel: "slack",
97
+ supportsDynamicUi: false,
98
+ },
99
+ }),
100
+ ),
101
+ ).toBe(false);
102
+ });
103
+
104
+ test("Slack task_progress UI tools still require a connected client path", () => {
105
+ expect(
106
+ isToolActiveForContext(
107
+ "ui_show",
108
+ makeCtx({
109
+ hasNoClient: true,
110
+ channelCapabilities: {
111
+ channel: "slack",
112
+ supportsDynamicUi: false,
113
+ },
114
+ }),
115
+ ),
116
+ ).toBe(false);
117
+ });
118
+
119
+ test("other non-dynamic channels still hide UI surface tools", () => {
120
+ expect(
121
+ isToolActiveForContext(
122
+ "ui_show",
123
+ makeCtx({
124
+ hasNoClient: false,
125
+ channelCapabilities: {
126
+ channel: "telegram",
127
+ supportsDynamicUi: false,
128
+ },
129
+ }),
130
+ ),
131
+ ).toBe(false);
132
+ });
133
+ });
134
+
78
135
  describe("isToolActiveForContext — host tool capability gating", () => {
79
136
  // macOS transport: SSE-based interactive approval required.
80
137
  test("host_bash is active for macOS with a connected client", () => {
@@ -331,7 +388,10 @@ describe("isToolActiveForContext — cross-client exposure for host_file_*", ()
331
388
  expect(
332
389
  isToolActiveForContext(
333
390
  tool,
334
- makeCtx({ hasNoClient: true, transportInterface: "chrome-extension" }),
391
+ makeCtx({
392
+ hasNoClient: true,
393
+ transportInterface: "chrome-extension",
394
+ }),
335
395
  ),
336
396
  ).toBe(false);
337
397
  });
@@ -183,7 +183,7 @@ describe("loadMeetManifestProxies", () => {
183
183
  expect(t.ownerSkillId).toBe("meet-join");
184
184
  expect(t.ownerSkillBundled).toBe(true);
185
185
  expect(t.ownerSkillVersionHash).toBe(FIXTURE_MANIFEST.sourceHash);
186
- expect(t.getDefinition().input_schema).toEqual(
186
+ expect(t.input_schema).toEqual(
187
187
  FIXTURE_MANIFEST.tools[0]!.input_schema,
188
188
  );
189
189
  });