@vellumai/assistant 0.8.4 → 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 (438) hide show
  1. package/ARCHITECTURE.md +2 -2
  2. package/docs/browser-use-architecture-phase2.md +1 -1
  3. package/knip.json +2 -1
  4. package/openapi.yaml +809 -11
  5. package/package.json +1 -1
  6. package/src/__tests__/anthropic-provider.test.ts +34 -37
  7. package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +293 -0
  8. package/src/__tests__/assistant-feature-flags-integration.test.ts +3 -3
  9. package/src/__tests__/audit-log-rotation.test.ts +70 -16
  10. package/src/__tests__/background-workers-disk-pressure.test.ts +3 -3
  11. package/src/__tests__/btw-routes.test.ts +2 -3
  12. package/src/__tests__/call-controller.test.ts +0 -1
  13. package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
  14. package/src/__tests__/channel-guardian.test.ts +3 -3
  15. package/src/__tests__/checker.test.ts +6 -15
  16. package/src/__tests__/compaction-events.test.ts +1 -0
  17. package/src/__tests__/compactor-call-site-logging.test.ts +214 -0
  18. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +5 -11
  19. package/src/__tests__/computer-use-tools.test.ts +2 -4
  20. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
  21. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -1
  22. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -1
  23. package/src/__tests__/conversation-agent-loop-overflow.test.ts +197 -2
  24. package/src/__tests__/conversation-agent-loop.test.ts +163 -122
  25. package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -5
  26. package/src/__tests__/conversation-clear-safety.test.ts +25 -25
  27. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +1 -1
  28. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
  29. package/src/__tests__/conversation-error.test.ts +31 -0
  30. package/src/__tests__/conversation-fork-crud.test.ts +178 -15
  31. package/src/__tests__/conversation-lifecycle.test.ts +52 -11
  32. package/src/__tests__/{conversation-load-cleaned-at.test.ts → conversation-load-history-stripped.test.ts} +13 -13
  33. package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -0
  34. package/src/__tests__/conversation-routes-disk-view.test.ts +109 -0
  35. package/src/__tests__/conversation-routes-slash-commands.test.ts +35 -0
  36. package/src/__tests__/conversation-skill-tools.test.ts +2 -5
  37. package/src/__tests__/conversation-store.test.ts +1 -1
  38. package/src/__tests__/conversation-sync-tags.test.ts +99 -32
  39. package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -0
  40. package/src/__tests__/conversation-workspace-injection.test.ts +1 -1
  41. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -1
  42. package/src/__tests__/credential-execution-feature-gates.test.ts +9 -7
  43. package/src/__tests__/credential-execution-tools.test.ts +6 -6
  44. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  45. package/src/__tests__/credential-vault-unit.test.ts +2 -2
  46. package/src/__tests__/dynamic-page-surface.test.ts +2 -2
  47. package/src/__tests__/email-html-renderer.test.ts +12 -0
  48. package/src/__tests__/gateway-flag-listener.test.ts +237 -0
  49. package/src/__tests__/gemini-provider.test.ts +78 -0
  50. package/src/__tests__/guardian-dispatch.test.ts +0 -1
  51. package/src/__tests__/guardian-outbound-http.test.ts +7 -5
  52. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
  53. package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -0
  54. package/src/__tests__/heartbeat-service.test.ts +4 -0
  55. package/src/__tests__/host-shell-tool.test.ts +1 -1
  56. package/src/__tests__/init-feature-flag-overrides.test.ts +5 -6
  57. package/src/__tests__/list-messages-tool-merge.test.ts +70 -11
  58. package/src/__tests__/llm-request-log-call-site.test.ts +136 -0
  59. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +26 -0
  60. package/src/__tests__/llm-resolver.test.ts +77 -9
  61. package/src/__tests__/llm-usage-store.test.ts +66 -0
  62. package/src/__tests__/logger.test.ts +89 -0
  63. package/src/__tests__/mcp-abort-signal.test.ts +2 -2
  64. package/src/__tests__/media-generate-image.test.ts +31 -0
  65. package/src/__tests__/memory-v2-static-injector.test.ts +7 -7
  66. package/src/__tests__/model-intents.test.ts +2 -4
  67. package/src/__tests__/notification-guardian-path.test.ts +0 -1
  68. package/src/__tests__/onboarding-template-contract.test.ts +1 -1
  69. package/src/__tests__/openai-provider.test.ts +46 -0
  70. package/src/__tests__/openai-responses-provider.test.ts +114 -12
  71. package/src/__tests__/pending-interactions-resolved-event.test.ts +0 -1
  72. package/src/__tests__/platform-bash-auto-approve.test.ts +2 -2
  73. package/src/__tests__/platform.test.ts +2 -2
  74. package/src/__tests__/plugin-api-tool-definition.test.ts +92 -0
  75. package/src/__tests__/plugin-bootstrap.test.ts +2 -2
  76. package/src/__tests__/plugin-tool-contribution.test.ts +13 -6
  77. package/src/__tests__/plugin-types.test.ts +3 -2
  78. package/src/__tests__/prechat-onboarding-contract.test.ts +131 -98
  79. package/src/__tests__/pricing.test.ts +12 -0
  80. package/src/__tests__/prune-jobs-changes-parser.test.ts +61 -0
  81. package/src/__tests__/registry.test.ts +2 -8
  82. package/src/__tests__/require-fresh-approval.test.ts +2 -2
  83. package/src/__tests__/runtime-events-sse-bilingual.test.ts +154 -0
  84. package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
  85. package/src/__tests__/skill-feature-flags.test.ts +2 -2
  86. package/src/__tests__/skill-projection-feature-flag.test.ts +4 -7
  87. package/src/__tests__/skill-projection.benchmark.test.ts +2 -6
  88. package/src/__tests__/skill-tool-factory.test.ts +1 -1
  89. package/src/__tests__/subagent-notify-parent.test.ts +1 -1
  90. package/src/__tests__/suggestion-routes.test.ts +1 -0
  91. package/src/__tests__/sync-message-contract.test.ts +59 -0
  92. package/src/__tests__/system-prompt.test.ts +145 -131
  93. package/src/__tests__/terminal-tools.test.ts +1 -1
  94. package/src/__tests__/tool-approval-handler.test.ts +1 -5
  95. package/src/__tests__/tool-execute-pipeline.test.ts +2 -2
  96. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -5
  97. package/src/__tests__/tool-executor-lifecycle-events.test.ts +15 -5
  98. package/src/__tests__/tool-executor.test.ts +9 -62
  99. package/src/__tests__/tool-grant-request-escalation.test.ts +1 -6
  100. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  101. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -6
  102. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
  103. package/src/__tests__/ui-file-upload-surface.test.ts +2 -2
  104. package/src/__tests__/usage-routes.test.ts +3 -0
  105. package/src/__tests__/verification-control-plane-policy.test.ts +2 -2
  106. package/src/__tests__/workspace-git-service.test.ts +6 -5
  107. package/src/__tests__/workspace-migration-089-move-memory-tree-out-of-v3.test.ts +86 -0
  108. package/src/acp/__tests__/prepare-agent-env.test.ts +146 -0
  109. package/src/acp/prepare-agent-env.ts +78 -0
  110. package/src/acp/session-manager.ts +1 -1
  111. package/src/agent/loop.ts +8 -0
  112. package/src/api/README.md +5 -0
  113. package/src/api/index.ts +4 -0
  114. package/src/api/package.json +10 -0
  115. package/src/background-wake/background-wake-routes.test.ts +233 -0
  116. package/src/background-wake/runtime-registry.ts +24 -0
  117. package/src/cli/commands/__tests__/browser.test.ts +23 -5
  118. package/src/cli/commands/__tests__/domain-register.test.ts +110 -0
  119. package/src/cli/commands/__tests__/domain-status.test.ts +33 -33
  120. package/src/cli/commands/__tests__/inference-send.test.ts +108 -5
  121. package/src/cli/commands/__tests__/memory-v2-compare-render.test.ts +98 -0
  122. package/src/cli/commands/__tests__/memory-v2.test.ts +1 -0
  123. package/src/cli/commands/__tests__/memory-v3-render.test.ts +340 -0
  124. package/src/cli/commands/browser.ts +247 -0
  125. package/src/cli/commands/domain.ts +91 -41
  126. package/src/cli/commands/inference.ts +93 -40
  127. package/src/cli/commands/memory-v2-compare-render.ts +115 -0
  128. package/src/cli/commands/memory-v2.ts +176 -1
  129. package/src/cli/commands/memory-v3-render.ts +344 -0
  130. package/src/cli/commands/memory-v3.ts +316 -0
  131. package/src/cli/program.ts +2 -0
  132. package/src/config/assistant-feature-flags.ts +21 -9
  133. package/src/config/bundled-skills/document-editor/SKILL.md +11 -2
  134. package/src/config/bundled-skills/document-editor/TOOLS.json +18 -0
  135. package/src/config/bundled-skills/document-editor/tools/document-open.ts +12 -0
  136. package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
  137. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -2
  138. package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +13 -8
  139. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +10 -3
  140. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +16 -14
  141. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +7 -2
  142. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +7 -2
  143. package/src/config/bundled-tool-registry.ts +2 -0
  144. package/src/config/call-site-defaults.ts +7 -6
  145. package/src/config/feature-flag-registry.json +16 -0
  146. package/src/config/schemas/__tests__/memory-v2.test.ts +213 -1
  147. package/src/config/schemas/call-site-catalog.ts +21 -7
  148. package/src/config/schemas/llm.ts +12 -1
  149. package/src/config/schemas/memory-v2.ts +246 -0
  150. package/src/config/schemas/memory.ts +2 -1
  151. package/src/context/compactor.ts +52 -0
  152. package/src/conversations/__tests__/message-consolidation.test.ts +350 -0
  153. package/src/conversations/message-consolidation.ts +404 -0
  154. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -1
  155. package/src/daemon/__tests__/meet-manifest-loader.test.ts +1 -1
  156. package/src/daemon/conversation-agent-loop-handlers.ts +2 -13
  157. package/src/daemon/conversation-agent-loop.ts +126 -76
  158. package/src/daemon/conversation-error.ts +31 -1
  159. package/src/daemon/conversation-lifecycle.ts +27 -22
  160. package/src/daemon/conversation-runtime-assembly.ts +10 -9
  161. package/src/daemon/conversation-tool-setup.ts +63 -3
  162. package/src/daemon/conversation-usage.ts +2 -0
  163. package/src/daemon/conversation.ts +14 -29
  164. package/src/daemon/disk-pressure-guard.ts +14 -2
  165. package/src/daemon/handlers/config-model.test.ts +1 -0
  166. package/src/daemon/handlers/conversations.ts +11 -3
  167. package/src/daemon/host-browser-proxy.ts +5 -5
  168. package/src/daemon/host-cu-proxy.ts +4 -4
  169. package/src/daemon/host-file-proxy.ts +4 -4
  170. package/src/daemon/host-proxy-base.ts +4 -4
  171. package/src/daemon/host-transfer-proxy.ts +10 -10
  172. package/src/daemon/lifecycle.ts +23 -20
  173. package/src/daemon/meet-manifest-loader.ts +1 -7
  174. package/src/daemon/message-types/conversations.ts +6 -9
  175. package/src/daemon/message-types/home.ts +1 -13
  176. package/src/daemon/message-types/messages.ts +6 -14
  177. package/src/daemon/message-types/sync.ts +14 -0
  178. package/src/daemon/shutdown-handlers.ts +24 -5
  179. package/src/daemon/switch-inference-profile-tool.ts +52 -0
  180. package/src/daemon/tool-setup-types.ts +13 -0
  181. package/src/events/relationship-state-updated.ts +25 -0
  182. package/src/heartbeat/__tests__/heartbeat-service.test.ts +1 -1
  183. package/src/home/home-greeting.ts +0 -9
  184. package/src/home/suggested-prompts.ts +0 -9
  185. package/src/ipc/gateway-flag-listener.ts +123 -0
  186. package/src/ipc/skill-routes/registries.ts +8 -12
  187. package/src/memory/__tests__/db-async-query.test.ts +165 -0
  188. package/src/memory/__tests__/db-maintenance.test.ts +115 -0
  189. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +241 -0
  190. package/src/memory/__tests__/jobs-store-job-classes.test.ts +28 -1
  191. package/src/memory/__tests__/memory-retrospective-job.test.ts +7 -0
  192. package/src/memory/auto-analysis-enqueue.ts +5 -1
  193. package/src/memory/conversation-crud.ts +71 -70
  194. package/src/memory/conversation-starters-cadence.ts +3 -1
  195. package/src/memory/conversation-title-service.ts +19 -3
  196. package/src/memory/db-async-query.ts +214 -0
  197. package/src/memory/db-init.ts +10 -0
  198. package/src/memory/db-maintenance.ts +30 -21
  199. package/src/memory/graph/bootstrap.ts +8 -1
  200. package/src/memory/graph/capability-seed.ts +7 -3
  201. package/src/memory/graph/conversation-graph-memory.ts +100 -17
  202. package/src/memory/graph/extraction.ts +1 -5
  203. package/src/memory/graph/graph-search.ts +7 -1
  204. package/src/memory/indexer.ts +28 -18
  205. package/src/memory/job-handlers/cleanup.ts +76 -18
  206. package/src/memory/job-handlers/conversation-starters.ts +1 -4
  207. package/src/memory/jobs/embed-pkb-file.ts +6 -1
  208. package/src/memory/jobs-store.ts +14 -0
  209. package/src/memory/jobs-worker.ts +55 -22
  210. package/src/memory/llm-request-log-source-clickhouse.ts +42 -2
  211. package/src/memory/llm-request-log-source-local.ts +7 -0
  212. package/src/memory/llm-request-log-source.ts +9 -2
  213. package/src/memory/llm-request-log-store.ts +43 -1
  214. package/src/memory/llm-usage-store.ts +24 -0
  215. package/src/memory/memory-retrospective-enqueue.ts +8 -1
  216. package/src/memory/memory-retrospective-job.ts +5 -0
  217. package/src/memory/memory-v2-activation-log-store.ts +15 -6
  218. package/src/memory/migrations/260-rename-cleaned-at.ts +44 -0
  219. package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +36 -0
  220. package/src/memory/migrations/262-memory-v3-coactivation.ts +57 -0
  221. package/src/memory/migrations/263-memory-v3-auto-edges.ts +50 -0
  222. package/src/memory/migrations/264-llm-request-log-call-site.ts +29 -0
  223. package/src/memory/migrations/index.ts +17 -0
  224. package/src/memory/migrations/registry.ts +33 -0
  225. package/src/memory/schema/conversations.ts +1 -1
  226. package/src/memory/schema/infrastructure.ts +21 -0
  227. package/src/memory/tool-usage-store.ts +36 -8
  228. package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -0
  229. package/src/memory/v2/__tests__/harness-compare.test.ts +186 -0
  230. package/src/memory/v2/__tests__/harness-metrics.test.ts +74 -0
  231. package/src/memory/v2/__tests__/harness-oracle.test.ts +257 -0
  232. package/src/memory/v2/__tests__/harness-replay-input.test.ts +225 -0
  233. package/src/memory/v2/__tests__/harness-runner.test.ts +109 -0
  234. package/src/memory/v2/__tests__/injection.test.ts +127 -98
  235. package/src/memory/v2/__tests__/qdrant.test.ts +36 -0
  236. package/src/memory/v2/__tests__/router.test.ts +171 -3
  237. package/src/memory/v2/harness/compare.ts +57 -0
  238. package/src/memory/v2/harness/metrics.ts +124 -0
  239. package/src/memory/v2/harness/oracle.ts +145 -0
  240. package/src/memory/v2/harness/replay-input.ts +224 -0
  241. package/src/memory/v2/harness/retriever.ts +74 -0
  242. package/src/memory/v2/harness/router-retriever.ts +43 -0
  243. package/src/memory/v2/harness/runner.ts +106 -0
  244. package/src/memory/v2/harness/trace.ts +58 -0
  245. package/src/memory/v2/injection.ts +21 -15
  246. package/src/memory/v2/prompts/router.ts +26 -1
  247. package/src/memory/v2/qdrant.ts +14 -2
  248. package/src/memory/v2/router.ts +171 -18
  249. package/src/memory/v3/__tests__/coactivation-store.test.ts +422 -0
  250. package/src/memory/v3/__tests__/consolidation-job.test.ts +468 -0
  251. package/src/memory/v3/__tests__/edge-learning-job.test.ts +324 -0
  252. package/src/memory/v3/__tests__/edges.test.ts +563 -0
  253. package/src/memory/v3/__tests__/filter.test.ts +512 -0
  254. package/src/memory/v3/__tests__/gate.test.ts +574 -0
  255. package/src/memory/v3/__tests__/index-composition.test.ts +233 -0
  256. package/src/memory/v3/__tests__/loop.test.ts +530 -0
  257. package/src/memory/v3/__tests__/retriever.test.ts +226 -0
  258. package/src/memory/v3/__tests__/scouts.test.ts +440 -0
  259. package/src/memory/v3/__tests__/shadow-middleware.test.ts +312 -0
  260. package/src/memory/v3/__tests__/system-prompts.test.ts +154 -0
  261. package/src/memory/v3/__tests__/traversal.test.ts +469 -0
  262. package/src/memory/v3/__tests__/tree-index.test.ts +280 -0
  263. package/src/memory/v3/__tests__/tree-store.test.ts +529 -0
  264. package/src/memory/v3/__tests__/tree-walk.test.ts +707 -0
  265. package/src/memory/v3/__tests__/validate.test.ts +245 -0
  266. package/src/memory/v3/auto-edges.ts +223 -0
  267. package/src/memory/v3/coactivation-store.ts +124 -0
  268. package/src/memory/v3/consolidation-job.ts +323 -0
  269. package/src/memory/v3/edge-learning-job.ts +160 -0
  270. package/src/memory/v3/edges.ts +249 -0
  271. package/src/memory/v3/filter.ts +281 -0
  272. package/src/memory/v3/gate.ts +334 -0
  273. package/src/memory/v3/index-composition.ts +113 -0
  274. package/src/memory/v3/llm-capture.ts +46 -0
  275. package/src/memory/v3/loop.ts +382 -0
  276. package/src/memory/v3/maintenance.ts +144 -0
  277. package/src/memory/v3/prompt-context.ts +33 -0
  278. package/src/memory/v3/prompts/consolidation.ts +458 -0
  279. package/src/memory/v3/prompts/system-prompts.ts +196 -0
  280. package/src/memory/v3/retriever.ts +33 -0
  281. package/src/memory/v3/scouts.ts +420 -0
  282. package/src/memory/v3/shadow-middleware.ts +305 -0
  283. package/src/memory/v3/traversal.ts +206 -0
  284. package/src/memory/v3/tree-index.ts +237 -0
  285. package/src/memory/v3/tree-store.ts +394 -0
  286. package/src/memory/v3/tree-walk.ts +351 -0
  287. package/src/memory/v3/types.ts +65 -0
  288. package/src/memory/v3/validate.ts +300 -0
  289. package/src/notifications/adapters/macos.ts +18 -1
  290. package/src/notifications/adapters/platform.ts +1 -1
  291. package/src/notifications/decision-engine.ts +1 -4
  292. package/src/notifications/emit-signal.ts +29 -49
  293. package/src/permissions/prompter.ts +3 -3
  294. package/src/permissions/question-prompter.ts +5 -2
  295. package/src/permissions/secret-prompter.ts +2 -2
  296. package/src/plugin-api/index.ts +4 -0
  297. package/src/plugin-api/types.ts +7 -33
  298. package/src/plugins/defaults/index.ts +6 -0
  299. package/src/plugins/defaults/injectors.ts +18 -11
  300. package/src/plugins/external-plugin-loader.ts +5 -68
  301. package/src/plugins/types.ts +11 -16
  302. package/src/proactive-artifact/aux-message-injector.ts +17 -4
  303. package/src/prompts/__tests__/task-progress-hint-section.test.ts +3 -9
  304. package/src/prompts/persona-resolver.ts +36 -21
  305. package/src/prompts/sections.ts +39 -7
  306. package/src/prompts/system-prompt.ts +50 -185
  307. package/src/prompts/templates/BOOTSTRAP.md +2 -2
  308. package/src/prompts/templates/system-sections.ts +230 -8
  309. package/src/providers/__tests__/connection-model-compat.test.ts +234 -0
  310. package/src/providers/__tests__/retry-callsite.test.ts +85 -5
  311. package/src/providers/anthropic/client.ts +32 -66
  312. package/src/providers/call-site-routing.ts +14 -2
  313. package/src/providers/connection-model-compat.ts +38 -0
  314. package/src/providers/connection-resolution.ts +16 -2
  315. package/src/providers/gemini/client.ts +49 -6
  316. package/src/providers/inference/adapter-factory.ts +3 -0
  317. package/src/providers/minimax/client.ts +106 -0
  318. package/src/providers/model-catalog.ts +43 -0
  319. package/src/providers/model-intents.ts +1 -1
  320. package/src/providers/openai/chat-completions-provider.ts +6 -3
  321. package/src/providers/openai/codex-models.ts +18 -0
  322. package/src/providers/openai/responses-provider.ts +78 -21
  323. package/src/providers/provider-send-message.ts +7 -1
  324. package/src/providers/retry.ts +34 -3
  325. package/src/providers/thinking-config.ts +26 -1
  326. package/src/providers/usage-tracking.ts +2 -0
  327. package/src/runtime/AGENTS.md +2 -2
  328. package/src/runtime/agent-wake.ts +1 -0
  329. package/src/runtime/assistant-event-hub.ts +76 -6
  330. package/src/runtime/auth/route-policy.ts +36 -0
  331. package/src/runtime/btw-sidechain.ts +0 -6
  332. package/src/runtime/http-types.ts +0 -2
  333. package/src/runtime/migrations/vbundle-builder.ts +10 -3
  334. package/src/runtime/pending-interactions.ts +0 -1
  335. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +106 -0
  336. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +25 -6
  337. package/src/runtime/routes/__tests__/plugins-routes.test.ts +512 -0
  338. package/src/runtime/routes/acp-routes.test.ts +255 -6
  339. package/src/runtime/routes/acp-routes.ts +8 -1
  340. package/src/runtime/routes/avatar-routes.ts +10 -10
  341. package/src/runtime/routes/background-wake-routes.ts +188 -0
  342. package/src/runtime/routes/browser-tabs-routes.ts +200 -0
  343. package/src/runtime/routes/btw-routes.ts +0 -6
  344. package/src/runtime/routes/conversation-cli-routes.ts +1 -1
  345. package/src/runtime/routes/conversation-list-routes.ts +12 -4
  346. package/src/runtime/routes/conversation-management-routes.ts +77 -20
  347. package/src/runtime/routes/conversation-query-routes.ts +142 -36
  348. package/src/runtime/routes/conversation-routes.ts +252 -410
  349. package/src/runtime/routes/conversation-starter-routes.ts +6 -3
  350. package/src/runtime/routes/disk-pressure-routes.ts +1 -1
  351. package/src/runtime/routes/domain-routes.ts +60 -10
  352. package/src/runtime/routes/email-routes.ts +5 -2
  353. package/src/runtime/routes/events-routes.ts +54 -10
  354. package/src/runtime/routes/group-routes.ts +24 -8
  355. package/src/runtime/routes/host-browser-routes.ts +10 -2
  356. package/src/runtime/routes/host-cu-routes.ts +2 -2
  357. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +96 -3
  358. package/src/runtime/routes/index.ts +8 -0
  359. package/src/runtime/routes/inference-profile-session-handler.ts +22 -12
  360. package/src/runtime/routes/inference-profile-session-routes.ts +7 -1
  361. package/src/runtime/routes/llm-call-sites-routes.ts +32 -5
  362. package/src/runtime/routes/memory-item-routes.ts +8 -3
  363. package/src/runtime/routes/memory-v2-routes.ts +215 -5
  364. package/src/runtime/routes/memory-v3-routes.ts +316 -0
  365. package/src/runtime/routes/migration-routes.ts +21 -24
  366. package/src/runtime/routes/plugins-routes.ts +337 -0
  367. package/src/runtime/routes/rename-conversation-routes.ts +6 -2
  368. package/src/runtime/routes/secret-routes.ts +25 -5
  369. package/src/runtime/routes/settings-routes.ts +12 -11
  370. package/src/runtime/routes/slack-channel-routes.ts +5 -4
  371. package/src/runtime/routes/workspace-routes.ts +25 -10
  372. package/src/runtime/sync/resource-sync-events.ts +106 -38
  373. package/src/runtime/sync/sync-publisher.test.ts +49 -0
  374. package/src/runtime/sync/sync-publisher.ts +2 -1
  375. package/src/runtime/verification-outbound-actions.ts +73 -1
  376. package/src/telemetry/types.ts +12 -0
  377. package/src/telemetry/usage-telemetry-reporter.test.ts +48 -0
  378. package/src/telemetry/usage-telemetry-reporter.ts +1 -0
  379. package/src/tools/acp/spawn.test.ts +119 -0
  380. package/src/tools/acp/spawn.ts +15 -2
  381. package/src/tools/apps/definitions.ts +2 -8
  382. package/src/tools/ask-question/ask-question-tool.test.ts +3 -3
  383. package/src/tools/ask-question/ask-question-tool.ts +38 -45
  384. package/src/tools/browser/__tests__/pinned-tabs.test.ts +70 -0
  385. package/src/tools/browser/browser-execution.ts +16 -3
  386. package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +402 -0
  387. package/src/tools/browser/cdp-client/__tests__/types.test.ts +3 -0
  388. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +12 -0
  389. package/src/tools/browser/cdp-client/extension-cdp-client.ts +27 -1
  390. package/src/tools/browser/cdp-client/factory.ts +100 -17
  391. package/src/tools/browser/cdp-client/local-cdp-client.ts +12 -0
  392. package/src/tools/browser/cdp-client/types.ts +65 -0
  393. package/src/tools/browser/pinned-tabs.ts +96 -40
  394. package/src/tools/computer-use/definitions.ts +22 -78
  395. package/src/tools/credential-execution/make-authenticated-request.ts +3 -9
  396. package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -9
  397. package/src/tools/credential-execution/run-authenticated-command.ts +3 -9
  398. package/src/tools/credentials/vault.ts +3 -9
  399. package/src/tools/document/document-tool.ts +59 -0
  400. package/src/tools/execution-target.ts +21 -23
  401. package/src/tools/executor.ts +6 -1
  402. package/src/tools/filesystem/edit.ts +3 -9
  403. package/src/tools/filesystem/list.ts +3 -9
  404. package/src/tools/filesystem/read.ts +3 -9
  405. package/src/tools/filesystem/write.ts +3 -9
  406. package/src/tools/host-filesystem/edit.ts +3 -9
  407. package/src/tools/host-filesystem/read.ts +3 -9
  408. package/src/tools/host-filesystem/transfer.ts +3 -9
  409. package/src/tools/host-filesystem/write.ts +3 -9
  410. package/src/tools/host-terminal/host-shell.ts +3 -9
  411. package/src/tools/mcp/mcp-tool-factory.ts +1 -8
  412. package/src/tools/memory/register.test.ts +1 -1
  413. package/src/tools/memory/register.ts +4 -9
  414. package/src/tools/network/web-fetch.ts +3 -9
  415. package/src/tools/network/web-search.ts +25 -32
  416. package/src/tools/registry.ts +7 -23
  417. package/src/tools/schema-transforms.ts +1 -1
  418. package/src/tools/skills/execute.ts +3 -9
  419. package/src/tools/skills/load.ts +3 -9
  420. package/src/tools/skills/skill-tool-factory.ts +1 -8
  421. package/src/tools/subagent/notify-parent.ts +3 -9
  422. package/src/tools/system/request-permission.ts +3 -9
  423. package/src/tools/terminal/shell.ts +3 -9
  424. package/src/tools/tool-defaults.ts +94 -0
  425. package/src/tools/types.ts +27 -98
  426. package/src/tools/ui-surface/definitions.ts +6 -22
  427. package/src/usage/pricing.ts +23 -0
  428. package/src/usage/types.ts +12 -0
  429. package/src/util/logger.ts +16 -7
  430. package/src/util/platform.ts +7 -2
  431. package/src/util/sqlite3-runtime.ts +65 -0
  432. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +1 -0
  433. package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +86 -0
  434. package/src/workspace/migrations/registry.ts +2 -0
  435. package/src/__tests__/compaction-strip-metadata-clear.test.ts +0 -206
  436. package/src/__tests__/message-complete-display-id.test.ts +0 -175
  437. package/src/daemon/query-complexity-router.ts +0 -75
  438. package/src/prompts/cache-boundary.ts +0 -8
@@ -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
+ }
@@ -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
 
@@ -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
  });
@@ -144,11 +144,6 @@ export interface EventHandlerState {
144
144
  */
145
145
  contextTooLargeError: unknown;
146
146
  providerErrorUserMessage: string | null;
147
- /**
148
- * First persisted assistant row in this run; history keeps this id when it
149
- * merges tool-turn rows into one display bubble.
150
- */
151
- firstAssistantMessageId: string | undefined;
152
147
  lastAssistantMessageId: string | undefined;
153
148
  readonly pendingToolResults: Map<string, PendingToolResult>;
154
149
  readonly persistedToolUseIds: Set<string>;
@@ -249,7 +244,6 @@ export function createEventHandlerState(): EventHandlerState {
249
244
  imageTooLargeDetected: false,
250
245
  contextTooLargeError: null,
251
246
  providerErrorUserMessage: null,
252
- firstAssistantMessageId: undefined,
253
247
  lastAssistantMessageId: undefined,
254
248
  pendingToolResults: new Map(),
255
249
  persistedToolUseIds: new Set(),
@@ -275,12 +269,6 @@ export function createEventHandlerState(): EventHandlerState {
275
269
  };
276
270
  }
277
271
 
278
- export function getClientDisplayMessageId(
279
- state: EventHandlerState,
280
- ): string | undefined {
281
- return state.firstAssistantMessageId ?? state.lastAssistantMessageId;
282
- }
283
-
284
272
  // ── Shared Helper ────────────────────────────────────────────────────
285
273
 
286
274
  // providerNameOverride should be supplied when the caller already knows the
@@ -1111,7 +1099,6 @@ export async function handleMessageComplete(
1111
1099
  DEFAULT_TIMEOUTS.persistence,
1112
1100
  )) as PersistAddResult;
1113
1101
  const assistantMsg = assistantPersistResult.message;
1114
- state.firstAssistantMessageId ??= assistantMsg.id;
1115
1102
  state.lastAssistantMessageId = assistantMsg.id;
1116
1103
 
1117
1104
  // Backfill message_id on all LLM request logs from this turn.
@@ -1222,6 +1209,7 @@ function handleUsage(
1222
1209
  JSON.stringify(event.rawResponse),
1223
1210
  undefined,
1224
1211
  providerName,
1212
+ "mainAgent",
1225
1213
  );
1226
1214
  } catch (err) {
1227
1215
  deps.rlog.warn({ err }, "Failed to persist LLM request log (non-fatal)");
@@ -1287,6 +1275,7 @@ function handleProviderError(
1287
1275
  JSON.stringify(buildProviderErrorResponsePayload(event.error)),
1288
1276
  undefined,
1289
1277
  event.actualProvider,
1278
+ "mainAgent",
1290
1279
  );
1291
1280
  } catch (err) {
1292
1281
  deps.rlog.warn(