@vellumai/assistant 0.7.0 → 0.7.1

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 (666) hide show
  1. package/ARCHITECTURE.md +6 -7
  2. package/Dockerfile +1 -0
  3. package/README.md +2 -2
  4. package/__tests__/permissions/gateway-threshold-reader.test.ts +79 -139
  5. package/bun.lock +3 -0
  6. package/docs/architecture/security.md +18 -16
  7. package/knip.json +1 -0
  8. package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +1 -5
  9. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -5
  10. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -16
  11. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +1 -9
  12. package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +12 -12
  13. package/node_modules/@vellumai/slack-text/bun.lock +24 -0
  14. package/node_modules/@vellumai/slack-text/package.json +18 -0
  15. package/node_modules/@vellumai/slack-text/src/index.test.ts +153 -0
  16. package/node_modules/@vellumai/slack-text/src/index.ts +235 -0
  17. package/node_modules/@vellumai/slack-text/tsconfig.json +20 -0
  18. package/openapi.yaml +294 -107
  19. package/package.json +4 -2
  20. package/scripts/generate-openapi.ts +16 -111
  21. package/src/__tests__/agent-wake-override-profile.test.ts +23 -1
  22. package/src/__tests__/anthropic-provider.test.ts +56 -13
  23. package/src/__tests__/app-conversation-ids-backfill.test.ts +278 -0
  24. package/src/__tests__/app-conversation-ids.test.ts +151 -0
  25. package/src/__tests__/approval-cascade.test.ts +0 -15
  26. package/src/__tests__/approval-routes-http.test.ts +6 -17
  27. package/src/__tests__/assistant-event-hub.test.ts +126 -77
  28. package/src/__tests__/assistant-event.test.ts +0 -5
  29. package/src/__tests__/assistant-events-sse-hardening.test.ts +37 -15
  30. package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -29
  31. package/src/__tests__/background-shell-host-bash.test.ts +34 -43
  32. package/src/__tests__/call-controller.test.ts +1 -1
  33. package/src/__tests__/call-site-routing-provider.test.ts +193 -0
  34. package/src/__tests__/channel-approval-routes.test.ts +10 -296
  35. package/src/__tests__/channel-approvals.test.ts +25 -17
  36. package/src/__tests__/channel-guardian.test.ts +100 -146
  37. package/src/__tests__/checker.test.ts +20 -34
  38. package/src/__tests__/compact-event-conversation-id-guard.test.ts +50 -0
  39. package/src/__tests__/compaction-events.test.ts +2 -0
  40. package/src/__tests__/config-schema.test.ts +6 -48
  41. package/src/__tests__/config-watcher.test.ts +12 -0
  42. package/src/__tests__/connection-policy.test.ts +1 -52
  43. package/src/__tests__/contacts-write.test.ts +2 -64
  44. package/src/__tests__/context-image-dimensions.test.ts +1 -1
  45. package/src/__tests__/context-search-memory-source.test.ts +120 -1
  46. package/src/__tests__/context-search-memory-v2-source.test.ts +383 -0
  47. package/src/__tests__/context-search-pkb-source.test.ts +49 -0
  48. package/src/__tests__/context-search-workspace-source.test.ts +9 -22
  49. package/src/__tests__/context-window-manager.test.ts +46 -0
  50. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
  51. package/src/__tests__/conversation-agent-loop-overflow.test.ts +102 -29
  52. package/src/__tests__/conversation-agent-loop.test.ts +980 -13
  53. package/src/__tests__/conversation-analysis-routes.test.ts +12 -10
  54. package/src/__tests__/conversation-attention-telegram.test.ts +11 -3
  55. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -291
  56. package/src/__tests__/conversation-history-web-search.test.ts +4 -3
  57. package/src/__tests__/conversation-inference-profile-route.test.ts +12 -23
  58. package/src/__tests__/conversation-lifecycle.test.ts +4 -4
  59. package/src/__tests__/conversation-process-callsite.test.ts +79 -2
  60. package/src/__tests__/conversation-queue.test.ts +3 -8
  61. package/src/__tests__/conversation-routes-disk-view.test.ts +1 -161
  62. package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -32
  63. package/src/__tests__/conversation-routes-slash-commands.test.ts +75 -66
  64. package/src/__tests__/conversation-runtime-assembly.test.ts +257 -3
  65. package/src/__tests__/conversation-slash-commands.test.ts +24 -4
  66. package/src/__tests__/conversation-slash-queue.test.ts +2 -0
  67. package/src/__tests__/conversation-speed-override.test.ts +0 -3
  68. package/src/__tests__/conversation-starter-routes.test.ts +79 -2
  69. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -5
  70. package/src/__tests__/conversation-surfaces-standalone.test.ts +18 -14
  71. package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -2
  72. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +8 -46
  73. package/src/__tests__/conversation-usage.test.ts +253 -3
  74. package/src/__tests__/credential-execution-shell-lockdown.test.ts +0 -39
  75. package/src/__tests__/credential-health-service.test.ts +68 -0
  76. package/src/__tests__/credential-security-e2e.test.ts +4 -3
  77. package/src/__tests__/credential-security-invariants.test.ts +1 -5
  78. package/src/__tests__/credential-token-resolver.test.ts +180 -0
  79. package/src/__tests__/cu-unified-flow.test.ts +33 -16
  80. package/src/__tests__/daemon-assistant-events.test.ts +34 -21
  81. package/src/__tests__/daemon-credential-client.test.ts +4 -1
  82. package/src/__tests__/db-connection-isolation.test.ts +125 -0
  83. package/src/__tests__/db-migration-rollback.test.ts +101 -0
  84. package/src/__tests__/db-slack-compaction-watermark-migration.test.ts +169 -0
  85. package/src/__tests__/deterministic-verification-control-plane.test.ts +7 -80
  86. package/src/__tests__/document-conversations.test.ts +332 -0
  87. package/src/__tests__/embedding-managed-proxy-selection.test.ts +2 -2
  88. package/src/__tests__/emit-event-signal.test.ts +4 -6
  89. package/src/__tests__/events-client-registration.test.ts +193 -49
  90. package/src/__tests__/filing-service.test.ts +58 -7
  91. package/src/__tests__/first-greeting.test.ts +156 -150
  92. package/src/__tests__/fixtures/mock-chrome-extension.ts +108 -66
  93. package/src/__tests__/get-skill-detail-audit.test.ts +3 -8
  94. package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
  95. package/src/__tests__/guardian-dispatch.test.ts +1 -1
  96. package/src/__tests__/guardian-grant-minting.test.ts +7 -2
  97. package/src/__tests__/guardian-routing-invariants.test.ts +7 -2
  98. package/src/__tests__/guardian-routing-state.test.ts +1 -1
  99. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +32 -11
  100. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -83
  101. package/src/__tests__/headless-browser-mode.test.ts +4 -9
  102. package/src/__tests__/headless-browser-navigate.test.ts +21 -20
  103. package/src/__tests__/heartbeat-service.test.ts +289 -7
  104. package/src/__tests__/helpers/channel-test-adapter.ts +2 -2
  105. package/src/__tests__/helpers/create-guardian-binding.ts +91 -0
  106. package/src/__tests__/host-bash-proxy.test.ts +46 -122
  107. package/src/__tests__/host-browser-e2e-cloud.test.ts +36 -497
  108. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +26 -96
  109. package/src/__tests__/host-browser-proxy.test.ts +111 -185
  110. package/src/__tests__/host-browser-routes.test.ts +45 -75
  111. package/src/__tests__/host-browser-ws-events-e2e.test.ts +26 -30
  112. package/src/__tests__/host-cu-proxy.test.ts +56 -111
  113. package/src/__tests__/host-file-proxy.test.ts +44 -98
  114. package/src/__tests__/host-file-read-tool.test.ts +42 -21
  115. package/src/__tests__/host-shell-tool.test.ts +33 -68
  116. package/src/__tests__/host-transfer-pending-interactions.test.ts +2 -18
  117. package/src/__tests__/host-transfer-proxy.test.ts +43 -53
  118. package/src/__tests__/http-user-message-parity.test.ts +0 -6
  119. package/src/__tests__/inbound-slack-persistence.test.ts +31 -0
  120. package/src/__tests__/injector-chain.test.ts +10 -5
  121. package/src/__tests__/injector-pkb-v2-silenced.test.ts +124 -0
  122. package/src/__tests__/inline-command-runner.test.ts +0 -66
  123. package/src/__tests__/inline-skill-load-permissions.test.ts +0 -2
  124. package/src/__tests__/install-skill-routing.test.ts +1 -13
  125. package/src/__tests__/llm-callsite-catalog.test.ts +34 -0
  126. package/src/__tests__/llm-catalog-parity.test.ts +90 -0
  127. package/src/__tests__/llm-context-resolution.test.ts +180 -0
  128. package/src/__tests__/llm-resolver.test.ts +80 -12
  129. package/src/__tests__/llm-usage-store.test.ts +269 -4
  130. package/src/__tests__/log-export-routes.test.ts +89 -0
  131. package/src/__tests__/managed-profile-guard.test.ts +225 -0
  132. package/src/__tests__/managed-skill-lifecycle.test.ts +0 -10
  133. package/src/__tests__/manual-token-reconciliation.test.ts +334 -0
  134. package/src/__tests__/memory-v2-static-injector.test.ts +95 -0
  135. package/src/__tests__/migration-cross-version-compatibility.test.ts +197 -291
  136. package/src/__tests__/migration-export-http.test.ts +33 -26
  137. package/src/__tests__/migration-export-streaming.test.ts +18 -10
  138. package/src/__tests__/migration-export-to-gcs.test.ts +49 -9
  139. package/src/__tests__/migration-import-commit-http.test.ts +66 -21
  140. package/src/__tests__/migration-import-from-gcs.test.ts +50 -9
  141. package/src/__tests__/migration-import-from-url.test.ts +20 -6
  142. package/src/__tests__/migration-import-preflight-http.test.ts +95 -95
  143. package/src/__tests__/migration-parity-persistence.test.ts +62 -25
  144. package/src/__tests__/migration-transport.test.ts +115 -23
  145. package/src/__tests__/migration-validate-http.test.ts +105 -80
  146. package/src/__tests__/migration-wizard.test.ts +133 -27
  147. package/src/__tests__/non-member-access-request.test.ts +1 -1
  148. package/src/__tests__/notification-guardian-path.test.ts +1 -1
  149. package/src/__tests__/oauth-store.test.ts +19 -0
  150. package/src/__tests__/platform-bash-auto-approve.test.ts +21 -12
  151. package/src/__tests__/prechat-onboarding-contract.test.ts +31 -7
  152. package/src/__tests__/pricing.test.ts +68 -4
  153. package/src/__tests__/process-message-background-slack.test.ts +331 -0
  154. package/src/__tests__/provider-managed-proxy-integration.test.ts +153 -17
  155. package/src/__tests__/provider-send-message-override-profile.test.ts +50 -0
  156. package/src/__tests__/provider-usage-tracking.test.ts +208 -0
  157. package/src/__tests__/reaction-persistence.test.ts +9 -6
  158. package/src/__tests__/rebind-secrets-screen.test.ts +53 -16
  159. package/src/__tests__/recording-handler.test.ts +64 -81
  160. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +4 -3
  161. package/src/__tests__/relay-server.test.ts +18 -13
  162. package/src/__tests__/require-fresh-approval.test.ts +13 -22
  163. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
  164. package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
  165. package/src/__tests__/runtime-events-sse.test.ts +3 -12
  166. package/src/__tests__/search-skills-unified.test.ts +9 -15
  167. package/src/__tests__/secret-ingress-cli.test.ts +2 -5
  168. package/src/__tests__/secret-ingress-http.test.ts +0 -4
  169. package/src/__tests__/secret-onetime-send.test.ts +4 -2
  170. package/src/__tests__/secret-prompt-log-hygiene.test.ts +24 -7
  171. package/src/__tests__/secret-prompter-channel-fallback.test.ts +42 -47
  172. package/src/__tests__/secret-response-routing.test.ts +29 -15
  173. package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -1
  174. package/src/__tests__/secret-scanner.test.ts +2 -545
  175. package/src/__tests__/send-endpoint-busy.test.ts +9 -24
  176. package/src/__tests__/settings-routes.test.ts +1 -1
  177. package/src/__tests__/shell-credential-ref.test.ts +0 -8
  178. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -56
  179. package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -11
  180. package/src/__tests__/skill-tool-factory.test.ts +97 -0
  181. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -30
  182. package/src/__tests__/skills-files-catalog-fallback.test.ts +11 -17
  183. package/src/__tests__/slack-inbound-verification.test.ts +1 -62
  184. package/src/__tests__/subagent-fork-notifications.test.ts +57 -47
  185. package/src/__tests__/subagent-manager-notify.test.ts +70 -70
  186. package/src/__tests__/subagent-notify-parent.test.ts +80 -83
  187. package/src/__tests__/system-prompt.test.ts +115 -13
  188. package/src/__tests__/terminal-tools.test.ts +0 -89
  189. package/src/__tests__/thread-backfill.test.ts +945 -31
  190. package/src/__tests__/tool-domain-event-publisher.test.ts +0 -36
  191. package/src/__tests__/tool-execute-pipeline.test.ts +0 -6
  192. package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -16
  193. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +9 -19
  194. package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -7
  195. package/src/__tests__/tool-executor.test.ts +12 -19
  196. package/src/__tests__/tool-metrics-listener.test.ts +0 -35
  197. package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
  198. package/src/__tests__/tool-trace-listener.test.ts +0 -17
  199. package/src/__tests__/transfer-progress-screen.test.ts +63 -26
  200. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -149
  201. package/src/__tests__/trusted-contact-multichannel.test.ts +2 -4
  202. package/src/__tests__/trusted-contact-verification.test.ts +1 -1
  203. package/src/__tests__/tts-catalog-parity.test.ts +16 -5
  204. package/src/__tests__/usage-attribution.test.ts +247 -0
  205. package/src/__tests__/usage-cli.test.ts +143 -0
  206. package/src/__tests__/usage-grouped-buckets.test.ts +155 -0
  207. package/src/__tests__/usage-routes.test.ts +150 -0
  208. package/src/__tests__/validation-results-screen.test.ts +39 -16
  209. package/src/__tests__/vbundle-pax-and-symlink.test.ts +12 -3
  210. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +49 -137
  211. package/src/__tests__/verification-control-plane-policy.test.ts +4 -7
  212. package/src/__tests__/voice-session-bridge.test.ts +5 -5
  213. package/src/__tests__/workspace-migration-062-drop-memory-v2-edges-json.test.ts +103 -0
  214. package/src/__tests__/workspace-migration-063-release-notes-dynamic-model-context.test.ts +77 -0
  215. package/src/__tests__/workspace-migration-064-unwind-main-agent-opus-seed.test.ts +225 -0
  216. package/src/__tests__/workspace-migration-memory-v2-init.test.ts +8 -30
  217. package/src/acp/index.ts +0 -15
  218. package/src/acp/session-manager.ts +37 -34
  219. package/src/agent/loop.ts +16 -1
  220. package/src/approvals/AGENTS.md +4 -0
  221. package/src/approvals/__tests__/guardian-feed-event.test.ts +10 -3
  222. package/src/approvals/guardian-request-resolvers.ts +10 -2
  223. package/src/backup/__tests__/backup-worker.test.ts +36 -8
  224. package/src/backup/__tests__/paths.test.ts +2 -2
  225. package/src/backup/__tests__/restore.test.ts +45 -28
  226. package/src/backup/backup-worker.ts +36 -2
  227. package/src/backup/paths.ts +9 -6
  228. package/src/browser-session/events.ts +0 -9
  229. package/src/calls/call-store.ts +1 -34
  230. package/src/calls/guardian-question-copy.ts +0 -108
  231. package/src/calls/relay-server.ts +0 -24
  232. package/src/calls/twilio-rest.ts +0 -38
  233. package/src/calls/twilio-routes.ts +1 -1
  234. package/src/calls/voice-session-bridge.ts +7 -38
  235. package/src/channels/types.ts +1 -36
  236. package/src/cli/commands/__tests__/cache.test.ts +152 -5
  237. package/src/cli/commands/__tests__/memory-v2.test.ts +14 -28
  238. package/src/cli/commands/__tests__/trust.test.ts +21 -387
  239. package/src/cli/commands/backup.ts +4 -4
  240. package/src/cli/commands/cache-fs.ts +8 -0
  241. package/src/cli/commands/cache.ts +153 -82
  242. package/src/cli/commands/clients.ts +63 -5
  243. package/src/cli/commands/completions.ts +3 -3
  244. package/src/cli/commands/contacts.ts +231 -76
  245. package/src/cli/commands/keys.ts +4 -1
  246. package/src/cli/commands/memory-v2.ts +24 -52
  247. package/src/cli/commands/oauth/shared.ts +2 -29
  248. package/src/cli/commands/pending.ts +102 -0
  249. package/src/cli/commands/skills.ts +77 -35
  250. package/src/cli/commands/trust.ts +70 -430
  251. package/src/cli/commands/usage.ts +25 -16
  252. package/src/cli/lib/daemon-credential-client.ts +14 -0
  253. package/src/cli/program.ts +2 -0
  254. package/src/cli.ts +0 -21
  255. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  256. package/src/config/bundled-skills/messaging/TOOLS.json +14 -4
  257. package/src/config/env-registry.ts +12 -2
  258. package/src/config/env.ts +3 -14
  259. package/src/config/feature-flag-registry.json +30 -30
  260. package/src/config/llm-callsite-catalog.ts +12 -0
  261. package/src/config/llm-context-resolution.ts +80 -0
  262. package/src/config/llm-resolver.ts +58 -22
  263. package/src/config/loader.ts +3 -3
  264. package/src/config/schema.ts +2 -158
  265. package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
  266. package/src/config/schemas/call-site-catalog.ts +271 -0
  267. package/src/config/schemas/calls.ts +5 -5
  268. package/src/config/schemas/inference.ts +1 -1
  269. package/src/config/schemas/ingress.ts +1 -1
  270. package/src/config/schemas/llm.ts +31 -3
  271. package/src/config/schemas/memory-retrieval.ts +2 -2
  272. package/src/config/schemas/memory-v2.ts +9 -0
  273. package/src/config/schemas/security.ts +1 -42
  274. package/src/config/schemas/services.ts +6 -6
  275. package/src/config/schemas/skills.ts +5 -5
  276. package/src/config/schemas/tts.ts +1 -1
  277. package/src/config/seed-inference-profiles.ts +117 -0
  278. package/src/config/skills.ts +0 -90
  279. package/src/config/types.ts +3 -6
  280. package/src/contacts/contact-store.ts +0 -17
  281. package/src/contacts/contacts-write.ts +1 -105
  282. package/src/context/window-manager.ts +44 -5
  283. package/src/credential-execution/process-manager.ts +34 -10
  284. package/src/credential-health/credential-health-service.ts +21 -16
  285. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +75 -82
  286. package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -9
  287. package/src/daemon/connection-policy.ts +1 -26
  288. package/src/daemon/conversation-agent-loop-handlers.ts +53 -4
  289. package/src/daemon/conversation-agent-loop.ts +277 -36
  290. package/src/daemon/conversation-history.ts +8 -8
  291. package/src/daemon/conversation-launch.ts +20 -135
  292. package/src/daemon/conversation-lifecycle.ts +1 -1
  293. package/src/daemon/conversation-messaging.ts +1 -0
  294. package/src/daemon/conversation-process.ts +83 -163
  295. package/src/daemon/conversation-runtime-assembly.ts +219 -76
  296. package/src/daemon/conversation-slash.ts +47 -5
  297. package/src/daemon/conversation-store.ts +7 -31
  298. package/src/daemon/conversation-surfaces.ts +22 -28
  299. package/src/daemon/conversation-tool-setup.ts +3 -33
  300. package/src/daemon/conversation-usage.ts +36 -0
  301. package/src/daemon/conversation.ts +117 -233
  302. package/src/daemon/daemon-control.ts +3 -71
  303. package/src/daemon/daemon-skill-host.ts +8 -11
  304. package/src/daemon/dictation-profile-store.ts +2 -26
  305. package/src/daemon/first-greeting.ts +44 -156
  306. package/src/daemon/handlers/config-channels.ts +12 -12
  307. package/src/daemon/handlers/config-ingress.ts +4 -165
  308. package/src/daemon/handlers/config-model.ts +1 -1
  309. package/src/daemon/handlers/config-voice.ts +0 -42
  310. package/src/daemon/handlers/conversations.ts +11 -190
  311. package/src/daemon/handlers/recording.ts +26 -158
  312. package/src/daemon/handlers/shared.ts +23 -71
  313. package/src/daemon/handlers/skills.ts +42 -93
  314. package/src/daemon/host-bash-proxy.ts +67 -45
  315. package/src/daemon/host-browser-proxy.ts +65 -27
  316. package/src/daemon/host-cu-proxy.ts +40 -39
  317. package/src/daemon/host-file-proxy.ts +58 -37
  318. package/src/daemon/host-transfer-proxy.ts +84 -46
  319. package/src/daemon/lifecycle.ts +49 -15
  320. package/src/daemon/message-types/conversations.ts +7 -0
  321. package/src/daemon/message-types/host-bash.ts +1 -0
  322. package/src/daemon/message-types/host-cu.ts +1 -0
  323. package/src/daemon/message-types/host-file.ts +1 -0
  324. package/src/daemon/message-types/host-transfer.ts +1 -0
  325. package/src/daemon/message-types/messages.ts +10 -9
  326. package/src/daemon/message-types/workspace.ts +1 -1
  327. package/src/daemon/process-message.ts +102 -239
  328. package/src/daemon/server.ts +13 -462
  329. package/src/daemon/shutdown-handlers.ts +2 -2
  330. package/src/daemon/tool-side-effects.ts +125 -107
  331. package/src/daemon/trust-context.ts +13 -0
  332. package/src/daemon/wake-target-adapter.ts +4 -9
  333. package/src/events/domain-events.ts +0 -8
  334. package/src/events/tool-audit-listener.ts +3 -1
  335. package/src/events/tool-domain-event-publisher.ts +0 -10
  336. package/src/events/tool-metrics-listener.ts +0 -17
  337. package/src/events/tool-trace-listener.ts +0 -14
  338. package/src/filing/filing-service.ts +13 -1
  339. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +6 -2
  340. package/src/heartbeat/heartbeat-service.ts +23 -5
  341. package/src/home/__tests__/feed-writer.test.ts +0 -4
  342. package/src/home/__tests__/relationship-state-writer.test.ts +30 -0
  343. package/src/home/feed-writer.ts +1 -2
  344. package/src/home/relationship-state-writer.ts +16 -3
  345. package/src/ipc/__tests__/browser-ipc.test.ts +2 -12
  346. package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -1
  347. package/src/ipc/assistant-server.ts +3 -10
  348. package/src/ipc/routes/__tests__/memory-v2-backfill.test.ts +39 -20
  349. package/src/ipc/routes/route-adapter.ts +1 -1
  350. package/src/ipc/routes/trust-rules.test.ts +0 -95
  351. package/src/ipc/skill-ipc-types.ts +41 -0
  352. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +13 -27
  353. package/src/ipc/skill-routes/__tests__/identity.test.ts +4 -23
  354. package/src/ipc/skill-routes/events.ts +12 -23
  355. package/src/ipc/skill-routes/identity.ts +4 -17
  356. package/src/ipc/skill-routes/index.ts +1 -1
  357. package/src/ipc/skill-server.ts +6 -39
  358. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -8
  359. package/src/live-voice/protocol.ts +4 -13
  360. package/src/mcp/manager.ts +0 -5
  361. package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +55 -0
  362. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +127 -0
  363. package/src/memory/app-git-service.ts +0 -32
  364. package/src/memory/app-store.ts +154 -0
  365. package/src/memory/attachments-store.ts +6 -0
  366. package/src/memory/context-search/sources/memory-v2.ts +578 -0
  367. package/src/memory/context-search/sources/memory.ts +5 -0
  368. package/src/memory/context-search/sources/pkb.ts +10 -1
  369. package/src/memory/context-search/sources/workspace.ts +3 -2
  370. package/src/memory/conversation-crud.ts +29 -4
  371. package/src/memory/conversation-disk-view.ts +1 -5
  372. package/src/memory/conversation-starter-checkpoints.ts +63 -0
  373. package/src/memory/db-connection.ts +62 -0
  374. package/src/memory/db-init.ts +14 -0
  375. package/src/memory/embedding-backend.ts +3 -21
  376. package/src/memory/embedding-gemini.ts +0 -2
  377. package/src/memory/embedding-local.ts +6 -6
  378. package/src/memory/embedding-ollama.ts +6 -6
  379. package/src/memory/embedding-openai.ts +6 -6
  380. package/src/memory/embedding-types.ts +21 -0
  381. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +3 -7
  382. package/src/memory/graph/conversation-graph-memory.ts +35 -13
  383. package/src/memory/graph/injection.test.ts +2 -2
  384. package/src/memory/graph/injection.ts +1 -1
  385. package/src/memory/guardian-action-store.ts +0 -83
  386. package/src/memory/guardian-approvals.ts +0 -48
  387. package/src/memory/indexer.ts +1 -15
  388. package/src/memory/job-handlers/conversation-starters.ts +36 -53
  389. package/src/memory/job-utils.ts +0 -6
  390. package/src/memory/jobs-store.ts +0 -1
  391. package/src/memory/jobs-worker.ts +2 -16
  392. package/src/memory/llm-request-log-store.ts +0 -41
  393. package/src/memory/llm-usage-store.ts +129 -43
  394. package/src/memory/memory-v2-activation-log-store.ts +115 -0
  395. package/src/memory/migrations/233-document-conversations.ts +54 -0
  396. package/src/memory/migrations/234-memory-v2-activation-logs.ts +55 -0
  397. package/src/memory/migrations/235-llm-usage-attribution.ts +31 -0
  398. package/src/memory/migrations/235-slack-compaction-watermark.ts +44 -0
  399. package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +26 -0
  400. package/src/memory/migrations/__tests__/234-memory-v2-activation-logs.test.ts +182 -0
  401. package/src/memory/migrations/index.ts +14 -0
  402. package/src/memory/migrations/registry.ts +24 -0
  403. package/src/memory/raw-query.ts +2 -68
  404. package/src/memory/schema/conversations.ts +7 -0
  405. package/src/memory/schema/infrastructure.ts +25 -0
  406. package/src/memory/search/semantic.ts +5 -16
  407. package/src/memory/tool-usage-store.ts +2 -0
  408. package/src/memory/usage-buckets.ts +40 -1
  409. package/src/memory/usage-grouped-buckets.ts +127 -0
  410. package/src/memory/v2/__tests__/activation.test.ts +289 -90
  411. package/src/memory/v2/__tests__/backfill-jobs.test.ts +2 -129
  412. package/src/memory/v2/__tests__/consolidation-job.test.ts +28 -11
  413. package/src/memory/v2/__tests__/edge-index.test.ts +278 -0
  414. package/src/memory/v2/__tests__/injection.test.ts +384 -15
  415. package/src/memory/v2/__tests__/migration.test.ts +64 -36
  416. package/src/memory/v2/__tests__/page-store.test.ts +191 -8
  417. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +181 -0
  418. package/src/memory/v2/__tests__/skill-store.test.ts +115 -3
  419. package/src/memory/v2/__tests__/static-context.test.ts +153 -0
  420. package/src/memory/v2/activation.ts +168 -97
  421. package/src/memory/v2/backfill-jobs.ts +15 -100
  422. package/src/memory/v2/consolidation-job.ts +14 -12
  423. package/src/memory/v2/edge-index.ts +191 -0
  424. package/src/memory/v2/injection.ts +182 -58
  425. package/src/memory/v2/migration.ts +57 -64
  426. package/src/memory/v2/now-text.ts +2 -3
  427. package/src/memory/v2/page-store.ts +168 -31
  428. package/src/memory/v2/prompts/consolidation.ts +118 -42
  429. package/src/memory/v2/prompts/sweep.ts +3 -3
  430. package/src/memory/v2/skill-store.ts +55 -7
  431. package/src/memory/v2/static-context.ts +62 -0
  432. package/src/memory/v2/types.ts +10 -20
  433. package/src/memory/validation.ts +0 -11
  434. package/src/messaging/draft-store.ts +0 -6
  435. package/src/messaging/provider-types.ts +8 -0
  436. package/src/messaging/provider.ts +7 -0
  437. package/src/messaging/providers/gmail/client.ts +1 -121
  438. package/src/messaging/providers/outlook/client.ts +0 -73
  439. package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +226 -0
  440. package/src/messaging/providers/slack/adapter.ts +122 -21
  441. package/src/messaging/providers/slack/backfill.test.ts +95 -6
  442. package/src/messaging/providers/slack/backfill.ts +89 -11
  443. package/src/messaging/providers/slack/client.ts +10 -124
  444. package/src/messaging/providers/slack/message-metadata.ts +12 -2
  445. package/src/messaging/providers/slack/render-transcript.test.ts +56 -0
  446. package/src/messaging/providers/slack/render-transcript.ts +126 -25
  447. package/src/messaging/providers/slack/types.ts +1 -0
  448. package/src/oauth/connection-resolver.test.ts +8 -0
  449. package/src/oauth/connection-resolver.ts +8 -16
  450. package/src/oauth/credential-token-resolver.ts +97 -0
  451. package/src/oauth/manual-token-connection.ts +30 -34
  452. package/src/oauth/oauth-store.ts +6 -4
  453. package/src/outbound-proxy/certs.ts +0 -7
  454. package/src/outbound-proxy/config.ts +0 -74
  455. package/src/outbound-proxy/health.ts +0 -44
  456. package/src/outbound-proxy/index.ts +0 -22
  457. package/src/permissions/approval-provenance.test.ts +184 -0
  458. package/src/permissions/approval-provenance.ts +70 -0
  459. package/src/permissions/checker.ts +4 -1
  460. package/src/permissions/gateway-threshold-reader.ts +4 -1
  461. package/src/permissions/prompter.ts +9 -2
  462. package/src/permissions/secret-prompter.ts +21 -48
  463. package/src/permissions/types.ts +33 -0
  464. package/src/permissions/workspace-policy.ts +0 -5
  465. package/src/platform/sync-identity.ts +0 -8
  466. package/src/plugins/defaults/injectors.ts +69 -2
  467. package/src/plugins/defaults/overflow-reduce.ts +3 -2
  468. package/src/plugins/types.ts +8 -0
  469. package/src/prompts/system-prompt.ts +34 -70
  470. package/src/prompts/templates/BOOTSTRAP.md +52 -6
  471. package/src/prompts/update-bulletin-job.ts +2 -0
  472. package/src/providers/__tests__/retry-callsite.test.ts +138 -1
  473. package/src/providers/anthropic/client.ts +72 -33
  474. package/src/providers/call-site-routing.ts +42 -3
  475. package/src/providers/gemini/client.ts +18 -2
  476. package/src/providers/managed-proxy/context.ts +0 -5
  477. package/src/providers/model-catalog.ts +105 -19
  478. package/src/providers/openai/chat-completions-provider.ts +6 -0
  479. package/src/providers/openai/responses-provider.ts +7 -1
  480. package/src/providers/provider-send-message.ts +45 -2
  481. package/src/providers/ratelimit.ts +7 -2
  482. package/src/providers/registry.ts +14 -9
  483. package/src/providers/retry.ts +96 -8
  484. package/src/providers/types.ts +13 -0
  485. package/src/providers/usage-tracking.ts +96 -0
  486. package/src/runtime/AGENTS.md +10 -6
  487. package/src/runtime/__tests__/agent-wake.test.ts +89 -0
  488. package/src/runtime/agent-wake.ts +39 -2
  489. package/src/runtime/assistant-event-hub.ts +541 -45
  490. package/src/runtime/assistant-event.ts +1 -6
  491. package/src/runtime/auth/context.ts +0 -9
  492. package/src/runtime/auth/middleware.ts +1 -1
  493. package/src/runtime/auth/route-policy.ts +11 -9
  494. package/src/runtime/auth/token-service.ts +0 -11
  495. package/src/runtime/channel-approvals.ts +6 -2
  496. package/src/runtime/channel-verification-service.ts +3 -5
  497. package/src/runtime/http-errors.ts +0 -34
  498. package/src/runtime/http-router.ts +6 -3
  499. package/src/runtime/http-server.ts +22 -82
  500. package/src/runtime/http-types.ts +5 -0
  501. package/src/runtime/interactive-ui.ts +0 -1
  502. package/src/runtime/middleware/auth.ts +0 -20
  503. package/src/runtime/migrations/__tests__/v1-test-helpers.ts +112 -0
  504. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +11 -4
  505. package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +253 -0
  506. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +19 -6
  507. package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +71 -27
  508. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +41 -2
  509. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +143 -79
  510. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +143 -23
  511. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +2 -2
  512. package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +371 -0
  513. package/src/runtime/migrations/migration-transport.ts +46 -13
  514. package/src/runtime/migrations/migration-wizard.ts +2 -2
  515. package/src/runtime/migrations/origin-mode.ts +40 -0
  516. package/src/runtime/migrations/vbundle-builder.ts +133 -79
  517. package/src/runtime/migrations/vbundle-import-analyzer.ts +9 -7
  518. package/src/runtime/migrations/vbundle-importer.ts +7 -7
  519. package/src/runtime/migrations/vbundle-metadata-merge.ts +1 -1
  520. package/src/runtime/migrations/vbundle-streaming-importer.ts +3 -3
  521. package/src/runtime/migrations/vbundle-streaming-validator.ts +48 -26
  522. package/src/runtime/migrations/vbundle-validator.ts +214 -41
  523. package/src/runtime/pending-interactions.ts +13 -4
  524. package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -1
  525. package/src/runtime/routes/__tests__/backup-routes.test.ts +28 -19
  526. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +235 -0
  527. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +58 -0
  528. package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +54 -0
  529. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +19 -6
  530. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +7 -7
  531. package/src/runtime/routes/acp-routes.test.ts +0 -3
  532. package/src/runtime/routes/acp-routes.ts +3 -7
  533. package/src/runtime/routes/app-management-routes.ts +18 -9
  534. package/src/runtime/routes/approval-routes.ts +55 -14
  535. package/src/runtime/routes/avatar-routes.ts +3 -5
  536. package/src/runtime/routes/browser-routes.ts +1 -15
  537. package/src/runtime/routes/channel-guardian-routes.ts +1 -5
  538. package/src/runtime/routes/channel-readiness-routes.ts +3 -7
  539. package/src/runtime/routes/channel-route-shared.ts +2 -28
  540. package/src/runtime/routes/client-routes.ts +45 -12
  541. package/src/runtime/routes/consolidation-routes.ts +115 -0
  542. package/src/runtime/routes/conversation-list-routes.ts +12 -29
  543. package/src/runtime/routes/conversation-management-routes.ts +14 -51
  544. package/src/runtime/routes/conversation-query-routes.ts +120 -8
  545. package/src/runtime/routes/conversation-routes.ts +44 -528
  546. package/src/runtime/routes/conversation-starter-routes.ts +19 -40
  547. package/src/runtime/routes/documents-routes.ts +53 -18
  548. package/src/runtime/routes/events-routes.ts +59 -91
  549. package/src/runtime/routes/filing-routes.ts +18 -1
  550. package/src/runtime/routes/guardian-action-routes.ts +4 -9
  551. package/src/runtime/routes/host-bash-routes.ts +3 -2
  552. package/src/runtime/routes/host-browser-routes.ts +9 -33
  553. package/src/runtime/routes/host-cu-routes.ts +6 -1
  554. package/src/runtime/routes/host-file-routes.ts +3 -2
  555. package/src/runtime/routes/host-transfer-routes.ts +11 -15
  556. package/src/runtime/routes/identity-routes.ts +78 -6
  557. package/src/runtime/routes/inbound-message-handler.ts +580 -137
  558. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -88
  559. package/src/runtime/routes/inbound-stages/background-dispatch.ts +3 -0
  560. package/src/runtime/routes/index.ts +4 -0
  561. package/src/runtime/routes/integrations/slack/channel.ts +0 -24
  562. package/src/runtime/routes/llm-call-sites-routes.ts +22 -0
  563. package/src/runtime/routes/memory-v2-routes.ts +10 -15
  564. package/src/runtime/routes/migration-routes.ts +188 -31
  565. package/src/runtime/routes/playground/guard.ts +1 -1
  566. package/src/runtime/routes/playground/index.ts +0 -2
  567. package/src/runtime/routes/recording-routes.ts +4 -24
  568. package/src/runtime/routes/rename-conversation-routes.ts +2 -6
  569. package/src/runtime/routes/schedule-routes.ts +3 -6
  570. package/src/runtime/routes/secret-routes.ts +87 -18
  571. package/src/runtime/routes/settings-routes.ts +29 -28
  572. package/src/runtime/routes/skills-routes.ts +12 -31
  573. package/src/runtime/routes/suggest-trust-rule-routes.ts +32 -1
  574. package/src/runtime/routes/task-routes.ts +6 -6
  575. package/src/runtime/routes/trust-rules-routes.ts +3 -94
  576. package/src/runtime/routes/types.ts +4 -4
  577. package/src/runtime/routes/upgrade-broadcast-routes.ts +3 -10
  578. package/src/runtime/routes/usage-routes.ts +87 -10
  579. package/src/runtime/routes/user-routes.ts +17 -31
  580. package/src/runtime/routes/work-items-routes.ts +1 -4
  581. package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -2
  582. package/src/runtime/services/analyze-conversation.ts +7 -17
  583. package/src/runtime/services/conversation-serializer.ts +2 -4
  584. package/src/runtime/verification-outbound-actions.ts +1 -1
  585. package/src/runtime/verification-rate-limiter.ts +1 -1
  586. package/src/schedule/schedule-store.ts +0 -16
  587. package/src/security/secret-scanner.ts +14 -547
  588. package/src/security/secure-keys.ts +31 -11
  589. package/src/security/token-manager.ts +7 -3
  590. package/src/signals/cancel.ts +16 -25
  591. package/src/signals/conversation-undo.ts +2 -27
  592. package/src/signals/emit-event.ts +1 -2
  593. package/src/signals/user-message.ts +108 -22
  594. package/src/skills/catalog-install.ts +1 -0
  595. package/src/skills/clawhub.ts +2 -2
  596. package/src/skills/inline-command-runner.ts +1 -7
  597. package/src/subagent/manager.ts +67 -84
  598. package/src/tasks/task-store.ts +1 -28
  599. package/src/telemetry/types.ts +6 -0
  600. package/src/telemetry/usage-telemetry-reporter.test.ts +38 -15
  601. package/src/telemetry/usage-telemetry-reporter.ts +3 -5
  602. package/src/tools/acp/spawn.test.ts +1 -2
  603. package/src/tools/acp/steer.test.ts +1 -2
  604. package/src/tools/browser/__tests__/browser-status.test.ts +44 -127
  605. package/src/tools/browser/browser-execution.ts +31 -147
  606. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +92 -68
  607. package/src/tools/browser/cdp-client/factory.ts +48 -76
  608. package/src/tools/browser/cdp-client/index.ts +1 -14
  609. package/src/tools/executor.ts +44 -31
  610. package/src/tools/host-filesystem/edit.ts +3 -2
  611. package/src/tools/host-filesystem/read.ts +3 -2
  612. package/src/tools/host-filesystem/transfer.test.ts +45 -42
  613. package/src/tools/host-filesystem/transfer.ts +4 -3
  614. package/src/tools/host-filesystem/write.ts +3 -2
  615. package/src/tools/host-terminal/host-shell.ts +4 -3
  616. package/src/tools/network/script-proxy/index.ts +1 -10
  617. package/src/tools/permission-checker.ts +66 -1
  618. package/src/tools/skills/sandbox-runner.ts +1 -6
  619. package/src/tools/skills/skill-tool-factory.ts +32 -0
  620. package/src/tools/terminal/safe-env.ts +1 -0
  621. package/src/tools/terminal/shell.ts +2 -78
  622. package/src/tools/types.ts +12 -39
  623. package/src/tts/__tests__/provider-catalog.test.ts +2 -2
  624. package/src/tts/provider-catalog.ts +1 -1
  625. package/src/usage/actors.ts +2 -1
  626. package/src/usage/attribution.ts +185 -0
  627. package/src/usage/pricing.ts +166 -0
  628. package/src/usage/types.ts +14 -0
  629. package/src/util/json.ts +13 -0
  630. package/src/util/logger.ts +3 -3
  631. package/src/util/pricing.ts +50 -3
  632. package/src/work-items/work-item-runner.ts +15 -42
  633. package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +4 -3
  634. package/src/workspace/migrations/052-seed-default-inference-profiles.ts +3 -3
  635. package/src/workspace/migrations/060-memory-v2-init.ts +2 -18
  636. package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +59 -0
  637. package/src/workspace/migrations/062-drop-memory-v2-edges-json.ts +27 -0
  638. package/src/workspace/migrations/063-release-notes-dynamic-model-context.ts +70 -0
  639. package/src/workspace/migrations/064-unwind-main-agent-opus-seed.ts +64 -0
  640. package/src/workspace/migrations/registry.ts +8 -0
  641. package/src/workspace/provider-commit-message-generator.ts +3 -3
  642. package/src/__tests__/sandbox-diagnostics.test.ts +0 -138
  643. package/src/__tests__/sandbox-host-parity.test.ts +0 -1024
  644. package/src/__tests__/secret-detection-handler.test.ts +0 -67
  645. package/src/__tests__/secret-scanner-executor.test.ts +0 -450
  646. package/src/__tests__/tcc-sandbox-deny.test.ts +0 -198
  647. package/src/__tests__/terminal-sandbox.test.ts +0 -374
  648. package/src/__tests__/tool-notification-listener.test.ts +0 -65
  649. package/src/context/__tests__/microcompact.test.ts +0 -805
  650. package/src/context/microcompact.ts +0 -443
  651. package/src/daemon/handlers/slack-channel-oauth-install.ts +0 -197
  652. package/src/events/tool-notification-listener.ts +0 -17
  653. package/src/ipc/routes/__tests__/memory-v2-validate.test.ts +0 -219
  654. package/src/memory/v2/__tests__/edges.test.ts +0 -435
  655. package/src/memory/v2/edges.ts +0 -217
  656. package/src/prompts/__tests__/system-prompt-memory-v2.test.ts +0 -197
  657. package/src/runtime/__tests__/chrome-extension-registry.test.ts +0 -518
  658. package/src/runtime/__tests__/client-registry.test.ts +0 -271
  659. package/src/runtime/chrome-extension-registry.ts +0 -368
  660. package/src/runtime/client-registry.ts +0 -254
  661. package/src/runtime/routes/inbound-stages/verification-intercept.ts +0 -329
  662. package/src/tools/secret-detection-handler.ts +0 -269
  663. package/src/tools/terminal/backends/native.ts +0 -327
  664. package/src/tools/terminal/backends/types.ts +0 -37
  665. package/src/tools/terminal/sandbox-diagnostics.ts +0 -87
  666. package/src/tools/terminal/sandbox.ts +0 -40
@@ -5,11 +5,6 @@
5
5
  * Called from `handleSurfaceAction` when a persistent `ui_show` card fires a
6
6
  * `launch_conversation` action — the origin conversation's `TrustContext` is
7
7
  * forwarded so spawned conversations inherit guardian / trust class.
8
- *
9
- * The helper depends on DaemonServer state (conversation map,
10
- * `persistAndProcessMessage`, assistant ID, hub publisher) and is wired via
11
- * {@link registerLaunchConversationDeps} at daemon startup. Tests can stub
12
- * deps directly via the same registration.
13
8
  */
14
9
 
15
10
  import { randomUUID } from "node:crypto";
@@ -18,71 +13,13 @@ import { updateConversationTitle } from "../memory/conversation-crud.js";
18
13
  import { getOrCreateConversation as getOrCreateConversationKey } from "../memory/conversation-key-store.js";
19
14
  import { buildAssistantEvent } from "../runtime/assistant-event.js";
20
15
  import { assistantEventHub } from "../runtime/assistant-event-hub.js";
21
- import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
22
16
  import { getLogger } from "../util/logger.js";
23
- import type { Conversation } from "./conversation.js";
24
- import type { ConversationCreateOptions } from "./handlers/shared.js";
25
- import type { ServerMessage } from "./message-protocol.js";
17
+ import { getOrCreateConversation } from "./conversation-store.js";
18
+ import { processMessageInBackground } from "./process-message.js";
26
19
  import type { TrustContext } from "./trust-context.js";
27
20
 
28
21
  const log = getLogger("conversation-launch");
29
22
 
30
- // ── Dependency registry ─────────────────────────────────────────────
31
-
32
- export interface LaunchConversationDeps {
33
- /**
34
- * Return the live {@link Conversation} instance for the given id,
35
- * creating + hydrating it if necessary. Wraps `DaemonServer.getOrCreateConversation`.
36
- */
37
- getOrCreateConversation: (
38
- conversationId: string,
39
- options?: ConversationCreateOptions,
40
- ) => Promise<Conversation>;
41
- /**
42
- * Persist the seed message and run the agent loop. Wraps
43
- * `DaemonServer.persistAndProcessMessage`.
44
- */
45
- persistAndProcessMessage: (
46
- conversationId: string,
47
- content: string,
48
- attachmentIds?: string[],
49
- options?: ConversationCreateOptions,
50
- sourceChannel?: string,
51
- sourceInterface?: string,
52
- ) => Promise<{ messageId: string }>;
53
- /**
54
- * Forward a `ServerMessage` to the process-level assistant event hub.
55
- * Wraps `DaemonServer.publishAssistantEvent`.
56
- */
57
- publishAssistantEvent: (msg: ServerMessage, conversationId?: string) => void;
58
- /** Assistant id to stamp onto the `open_conversation` event. */
59
- getAssistantId: () => string | undefined;
60
- }
61
-
62
- let _deps: LaunchConversationDeps | null = null;
63
-
64
- /**
65
- * Register the daemon-side dependencies the helper needs. Called once by
66
- * `DaemonServer.start()` and (in tests) by unit tests that exercise
67
- * {@link launchConversation} directly.
68
- */
69
- export function registerLaunchConversationDeps(
70
- deps: LaunchConversationDeps,
71
- ): void {
72
- _deps = deps;
73
- }
74
-
75
- /**
76
- * Test-only helper: reset the module-level `_deps` between test cases so
77
- * accidental coupling between tests can't hide bugs (e.g. a test that does
78
- * not register deps but happens to pass because an earlier test in the same
79
- * file left deps registered and the validation short-circuit hides the
80
- * "deps not registered" throw).
81
- */
82
- export function resetLaunchConversationDeps(): void {
83
- _deps = null;
84
- }
85
-
86
23
  // ── Helper ──────────────────────────────────────────────────────────
87
24
 
88
25
  export interface LaunchConversationParams {
@@ -109,74 +46,37 @@ export interface LaunchConversationParams {
109
46
  * spawning context. When absent, the conversation runs without an inherited
110
47
  * trust context.
111
48
  *
112
- * The seed turn (`persistAndProcessMessage`) runs **fire-and-forget** so this
113
- * helper returns as soon as the conversation is created, titled, and the
114
- * `open_conversation` event has been published. Callers driving a fan-out
115
- * UX (multiple launches from a single click) rely on this: blocking on the
116
- * full LLM turn would hold the HTTP request open for tens of seconds.
117
- * Errors from the seed turn are logged but not surfaced — the new
118
- * conversation still exists in the sidebar so the user can retry from there.
49
+ * The seed turn runs **fire-and-forget** so this helper returns as soon as
50
+ * the conversation is created, titled, and the `open_conversation` event has
51
+ * been published. Errors from the seed turn are logged but not surfaced.
119
52
  *
120
- * Throws if the helper's daemon-side dependencies have not been registered
121
- * or if conversation creation / titling itself fails.
53
+ * Throws if conversation creation / titling itself fails.
122
54
  */
123
55
  export async function launchConversation(
124
56
  params: LaunchConversationParams,
125
57
  ): Promise<{ conversationId: string }> {
126
- // Belt-and-suspenders validation: callers (handleSurfaceAction) also check
127
- // for these, but enforcing here keeps the helper self-contained so future
128
- // direct callers can't accidentally emit `open_conversation` events with a
129
- // blank title (which would create a blank-titled sidebar entry on macOS).
130
58
  if (!params.title || !params.seedPrompt) {
131
59
  throw new Error("launchConversation: title and seedPrompt are required");
132
60
  }
133
- if (!_deps) {
134
- throw new Error(
135
- "launchConversation dependencies not registered — daemon may not be ready",
136
- );
137
- }
138
- const deps = _deps;
139
61
 
140
- // Each launch gets a globally unique conversation key so the skill always
141
- // creates a fresh conversation rather than reusing any prior mapping.
142
- // `getOrCreateConversation` will insert a new row.
143
62
  const conversationKey = `launcher-${randomUUID()}`;
144
63
  const { conversationId } = getOrCreateConversationKey(conversationKey);
145
64
 
146
- // Hydrate the live Conversation instance so we can apply trust context
147
- // before the seed turn begins. persistAndProcessMessage will reuse this
148
- // instance from the conversations map.
149
- const conversation = await deps.getOrCreateConversation(conversationId);
65
+ const conversation = await getOrCreateConversation(conversationId);
150
66
 
151
- // Inherit guardian / trust-class state from the caller when available.
152
- // `handleSurfaceAction` passes the origin conversation's trustContext.
153
67
  if (params.originTrustContext) {
154
68
  conversation.setTrustContext(params.originTrustContext);
155
69
  }
156
70
 
157
- // Set the user-facing title immediately so clients that stub a sidebar
158
- // entry from the open_conversation event see the right label even before
159
- // the turn completes.
160
71
  if (params.title) {
161
72
  updateConversationTitle(conversationId, params.title, 0);
162
73
  }
163
74
 
164
- // Tell connected clients about the new conversation BEFORE kicking off the
165
- // seed turn so the sidebar entry appears instantly. This helper is the sole
166
- // emitter of `open_conversation` for this launch path. Pass through the
167
- // caller-specified `focus` so fan-out launchers can avoid stealing focus
168
- // from the origin.
169
75
  await assistantEventHub.publish(
170
76
  buildAssistantEvent(
171
- deps.getAssistantId() ?? DAEMON_INTERNAL_ASSISTANT_ID,
172
77
  {
173
78
  type: "open_conversation",
174
79
  conversationId,
175
- // Conditional spread so an empty / falsy title is omitted entirely
176
- // instead of leaking into the Swift handler (`if let title = msg.title`
177
- // accepts empty strings and would create a blank-titled sidebar entry).
178
- // The validation guard above already rejects empty titles for our
179
- // current callers, but this is defense-in-depth for future ones.
180
80
  ...(params.title ? { title: params.title } : {}),
181
81
  ...(params.anchorMessageId
182
82
  ? { anchorMessageId: params.anchorMessageId }
@@ -187,34 +87,19 @@ export async function launchConversation(
187
87
  ),
188
88
  );
189
89
 
190
- // Seed the conversation by running the seed prompt through the same
191
- // pipeline POST /v1/messages uses. Publishing to the hub lets any
192
- // connected client stream the turn live. Fire-and-forget so callers
193
- // aren't blocked on the full LLM turn — errors are logged but swallowed.
194
- const hubSender = (msg: ServerMessage) => {
195
- const msgConversationId =
196
- "conversationId" in msg &&
197
- typeof (msg as { conversationId?: unknown }).conversationId === "string"
198
- ? (msg as { conversationId: string }).conversationId
199
- : undefined;
200
- deps.publishAssistantEvent(msg, msgConversationId ?? conversationId);
201
- };
202
-
203
- deps
204
- .persistAndProcessMessage(
205
- conversationId,
206
- params.seedPrompt,
207
- undefined,
208
- { onEvent: hubSender },
209
- "vellum",
210
- "cli",
211
- )
212
- .catch((err) => {
213
- log.error(
214
- { err, conversationId },
215
- "Seed turn failed for launched conversation (non-fatal)",
216
- );
217
- });
90
+ processMessageInBackground(
91
+ conversationId,
92
+ params.seedPrompt,
93
+ undefined,
94
+ undefined,
95
+ "vellum",
96
+ "cli",
97
+ ).catch((err) => {
98
+ log.error(
99
+ { err, conversationId },
100
+ "Seed turn failed for launched conversation (non-fatal)",
101
+ );
102
+ });
218
103
 
219
104
  return { conversationId };
220
105
  }
@@ -244,7 +244,7 @@ export async function loadFromDb(ctx: LoadFromDbContext): Promise<void> {
244
244
  content = [
245
245
  {
246
246
  type: "text" as const,
247
- text: `<memory __injected>\n${meta.memoryInjectedBlock}\n</memory>`,
247
+ text: `<memory>\n${meta.memoryInjectedBlock}\n</memory>`,
248
248
  },
249
249
  ...content,
250
250
  ];
@@ -309,6 +309,7 @@ export function enqueueMessage(
309
309
  if (!accepted) {
310
310
  onEvent({
311
311
  type: "error",
312
+ conversationId: ctx.conversationId,
312
313
  message:
313
314
  "The assistant is busy and cannot accept more messages right now. Please try again shortly.",
314
315
  category: "queue_full",
@@ -12,14 +12,12 @@ import {
12
12
  createUserMessage,
13
13
  } from "../agent/message-types.js";
14
14
  import {
15
- canServiceRegistryBrowser,
16
15
  parseChannelId,
17
16
  parseInterfaceId,
18
17
  supportsHostProxy,
19
18
  type TurnChannelContext,
20
19
  type TurnInterfaceContext,
21
20
  } from "../channels/types.js";
22
- import { getConfig } from "../config/loader.js";
23
21
  import type { LLMCallSite } from "../config/schemas/llm.js";
24
22
  import type { ContextWindowResult } from "../context/window-manager.js";
25
23
  import { listPendingRequestsByConversationScope } from "../memory/canonical-guardian-store.js";
@@ -42,12 +40,12 @@ import type {
42
40
  } from "./conversation-queue-manager.js";
43
41
  import type { ChannelCapabilities } from "./conversation-runtime-assembly.js";
44
42
  import {
43
+ buildSlashContextForContent,
45
44
  classifySlash,
46
45
  resolveSlash,
47
46
  type SlashContext,
48
47
  } from "./conversation-slash.js";
49
48
  import { getModelInfo } from "./handlers/config-model.js";
50
- import type { HostBrowserProxy } from "./host-browser-proxy.js";
51
49
  import type {
52
50
  ServerMessage,
53
51
  UsageStats,
@@ -63,22 +61,32 @@ const log = getLogger("conversation-process");
63
61
 
64
62
  /** Format the result of a forced compaction into a user-facing message. */
65
63
  export function formatCompactResult(result: ContextWindowResult): string {
66
- const fmt = (n: number) => n.toLocaleString("en-US");
64
+ const fmt = (n: number | undefined) => (n ?? 0).toLocaleString("en-US");
67
65
  if (!result.compacted) {
68
- return `Context compaction skipped — ${result.reason ?? "nothing to compact"}.`;
66
+ return [
67
+ `Context compaction skipped — ${result.reason ?? "nothing to compact"}.`,
68
+ `Context: ${fmt(result.estimatedInputTokens)} / ${fmt(
69
+ result.maxInputTokens,
70
+ )} tokens`,
71
+ ].join("\n");
69
72
  }
70
73
  const saved =
71
74
  result.previousEstimatedInputTokens - result.estimatedInputTokens;
72
75
  return [
73
76
  "Context Compacted\n",
74
77
  `Tokens: ${fmt(result.previousEstimatedInputTokens)} → ${fmt(result.estimatedInputTokens)} (${fmt(saved)} saved)`,
78
+ `Context: ${fmt(result.estimatedInputTokens)} / ${fmt(
79
+ result.maxInputTokens,
80
+ )} tokens`,
75
81
  `Messages: ${fmt(result.compactedMessages)} compacted`,
76
82
  ].join("\n");
77
83
  }
78
84
 
79
85
  /** Build a model_info event with fresh config data. */
80
- export async function buildModelInfoEvent(): Promise<ServerMessage> {
81
- return { type: "model_info", ...(await getModelInfo()) };
86
+ export async function buildModelInfoEvent(
87
+ conversationId?: string,
88
+ ): Promise<ServerMessage> {
89
+ return { type: "model_info", conversationId, ...(await getModelInfo()) };
82
90
  }
83
91
 
84
92
  /** True when the trimmed content is the /models slash command. */
@@ -134,7 +142,7 @@ export interface ProcessConversationContext {
134
142
  runAgentLoop(
135
143
  content: string,
136
144
  userMessageId: string,
137
- onEvent: (msg: ServerMessage) => void,
145
+ onEvent?: (msg: ServerMessage) => void,
138
146
  options?: {
139
147
  isInteractive?: boolean;
140
148
  isUserMessage?: boolean;
@@ -146,26 +154,6 @@ export interface ProcessConversationContext {
146
154
  setTurnChannelContext(ctx: TurnChannelContext): void;
147
155
  getTurnInterfaceContext(): TurnInterfaceContext | null;
148
156
  setTurnInterfaceContext(ctx: TurnInterfaceContext): void;
149
- /** Mark host proxies as unavailable so tool execution uses local fallback. */
150
- clearProxyAvailability(): void;
151
- /**
152
- * Restore host proxy availability based on whether a real client is connected.
153
- * When `skipBrowser` is true, the browser proxy is left untouched — use this
154
- * when `restoreBrowserProxyAvailability()` will handle the browser proxy
155
- * separately with the correct registry-routed sender.
156
- */
157
- restoreProxyAvailability(options?: { skipBrowser?: boolean }): void;
158
- /** Restore only the host browser proxy (used by chrome-extension and macOS drains). */
159
- restoreBrowserProxyAvailability(): void;
160
- /**
161
- * Registry-routed sender override for the host browser proxy. When set,
162
- * `restoreBrowserProxyAvailability()` uses this function instead of
163
- * `sendToClient`. Set by the POST /messages handler when the guardian
164
- * has an active extension connection (regardless of interface).
165
- */
166
- hostBrowserSenderOverride?: (msg: ServerMessage) => void;
167
- /** Replace or clear the conversation's host browser proxy. */
168
- setHostBrowserProxy(proxy: HostBrowserProxy | undefined): void;
169
157
  emitActivityState(
170
158
  phase:
171
159
  | "idle"
@@ -249,20 +237,18 @@ function resolveQueuedTurnInterfaceContext(
249
237
 
250
238
  /** Build a SlashContext from the current conversation state and config. */
251
239
  function buildSlashContext(
240
+ content: string,
252
241
  conversation: ProcessConversationContext,
253
- ): SlashContext {
254
- const config = getConfig();
242
+ ): SlashContext | undefined {
255
243
  const turnInterface = conversation.getTurnInterfaceContext();
256
- return {
244
+ return buildSlashContextForContent(content, {
245
+ conversationId: conversation.conversationId,
257
246
  messageCount: conversation.messages.length,
258
247
  inputTokens: conversation.usageStats.inputTokens,
259
248
  outputTokens: conversation.usageStats.outputTokens,
260
- maxInputTokens: config.llm.default.contextWindow.maxInputTokens,
261
- model: config.llm.default.model,
262
- provider: config.llm.default.provider,
263
249
  estimatedCost: conversation.usageStats.estimatedCost,
264
250
  userMessageInterface: turnInterface?.userMessageInterface,
265
- };
251
+ });
266
252
  }
267
253
 
268
254
  /**
@@ -439,87 +425,14 @@ async function drainSingleMessage(
439
425
  conversation.applyHostEnvFromTransport(next.transport);
440
426
  }
441
427
 
442
- // Non-interactive queued messages (channel requests) must not execute tools
443
- // via the desktop host proxy. Clear proxy availability so isAvailable()
444
- // returns false and tool execution falls back to local.
445
- if (next.isInteractive === false) {
446
- conversation.clearProxyAvailability();
447
- // chrome-extension is non-interactive (no SSE prompter UI) but DOES have
448
- // a connected client that can service host_browser_request events. The
449
- // unconditional clear above turned its hostBrowserProxy off; restore it
450
- // here so the queued turn can still drive the browser via CDP.
451
- const drainInterfaceCtx =
452
- queuedInterfaceCtx ?? conversation.getTurnInterfaceContext();
453
- const drainInterface = drainInterfaceCtx?.userMessageInterface;
454
- if (
455
- drainInterface &&
456
- !supportsHostProxy(drainInterface) &&
457
- supportsHostProxy(drainInterface, "host_browser")
458
- ) {
459
- conversation.restoreBrowserProxyAvailability();
460
- }
461
- } else {
462
- // Restore proxy availability only for desktop-originating turns (macos)
463
- // in case a prior non-interactive drain disabled it. Non-desktop interactive
464
- // interfaces (CLI, Vellum) should not re-enable desktop host proxies. The
465
- // chrome-extension interface only supports host_browser, not the desktop
466
- // proxies or computer-use, so it is excluded by the no-arg form of
467
- // supportsHostProxy (which returns false for chrome-extension).
428
+ // Preactivate computer-use skill for interactive desktop turns.
429
+ if (next.isInteractive !== false) {
468
430
  const interfaceCtx =
469
431
  queuedInterfaceCtx ?? conversation.getTurnInterfaceContext();
470
432
  const sourceInterface = interfaceCtx?.userMessageInterface;
471
433
  if (sourceInterface && supportsHostProxy(sourceInterface)) {
472
- // When hostBrowserSenderOverride is set, skip the browser proxy here
473
- // — restoreBrowserProxyAvailability() below will handle it with the
474
- // correct registry-routed sender instead of the SSE hub emitter.
475
- // When no override is set (macOS without extension), restoring the
476
- // browser proxy via restoreProxyAvailability is correct — it will
477
- // use the SSE sender so host_browser_request frames reach the
478
- // desktop client directly.
479
- conversation.restoreProxyAvailability(
480
- conversation.hostBrowserSenderOverride
481
- ? { skipBrowser: true }
482
- : undefined,
483
- );
484
434
  conversation.addPreactivatedSkillId("computer-use");
485
435
  }
486
- // Tear down a stale hostBrowserProxy inherited from a prior turn on a
487
- // different interface (e.g. chrome-extension or macOS installed one,
488
- // then a CLI turn drains). Without this, restoreProxyAvailability()
489
- // above would re-enable the proxy and getCdpClient() would route
490
- // browser tools through host_browser_request and hang waiting for a
491
- // client that this turn's interface can't service.
492
- //
493
- // Skip teardown only when BOTH conditions hold:
494
- // 1. `hostBrowserSenderOverride` is set (live registry-routed sender)
495
- // 2. The current turn's interface can service host_browser frames
496
- // (chrome-extension or macOS).
497
- // Without the interface check, queued turns from CLI/iOS/Vellum would
498
- // inherit a stale override left by a prior extension-connected turn
499
- // and keep the proxy alive, causing cross-interface misrouting.
500
- //
501
- // macOS and chrome-extension both support host_browser natively, so
502
- // this teardown only fires for interfaces that do not support
503
- // host_browser at all (CLI, iOS, Vellum, channels).
504
- const currentTurnCanServiceBrowser =
505
- !!sourceInterface && canServiceRegistryBrowser(sourceInterface);
506
- if (
507
- sourceInterface &&
508
- !supportsHostProxy(sourceInterface, "host_browser") &&
509
- !(conversation.hostBrowserSenderOverride && currentTurnCanServiceBrowser)
510
- ) {
511
- conversation.setHostBrowserProxy(undefined);
512
- }
513
- // When a macOS turn has a registry-routed sender override (active
514
- // extension connection), restore the browser proxy so host_browser
515
- // tools route through the extension rather than cdp-inspect/local.
516
- if (
517
- sourceInterface &&
518
- supportsHostProxy(sourceInterface) &&
519
- conversation.hostBrowserSenderOverride
520
- ) {
521
- conversation.restoreBrowserProxyAvailability();
522
- }
523
436
  }
524
437
 
525
438
  // Snapshot persona context at turn start so later tool turns can't pick up
@@ -531,7 +444,7 @@ async function drainSingleMessage(
531
444
  // Resolve slash commands for queued messages
532
445
  const slashResult = await resolveSlash(
533
446
  next.content,
534
- buildSlashContext(conversation),
447
+ buildSlashContext(next.content, conversation),
535
448
  );
536
449
 
537
450
  // Unknown slash — persist the exchange and continue draining.
@@ -616,9 +529,13 @@ async function drainSingleMessage(
616
529
  // Emit fresh model info before the text delta so the client has
617
530
  // up-to-date configuredProviders when rendering /model or /models UI.
618
531
  if (isModelSlashCommand(next.content)) {
619
- next.onEvent(await buildModelInfoEvent());
532
+ next.onEvent(await buildModelInfoEvent(conversation.conversationId));
620
533
  }
621
- next.onEvent({ type: "assistant_text_delta", text: slashResult.message });
534
+ next.onEvent({
535
+ type: "assistant_text_delta",
536
+ text: slashResult.message,
537
+ conversationId: conversation.conversationId,
538
+ });
622
539
  conversation.traceEmitter.emit(
623
540
  "message_complete",
624
541
  "Unknown slash command handled",
@@ -650,7 +567,11 @@ async function drainSingleMessage(
650
567
  attributes: { reason: "persist_failure" },
651
568
  },
652
569
  );
653
- next.onEvent({ type: "error", message });
570
+ next.onEvent({
571
+ type: "error",
572
+ conversationId: conversation.conversationId,
573
+ message,
574
+ });
654
575
  }
655
576
  // Continue draining regardless of success/failure
656
577
  await drainQueue(conversation);
@@ -707,7 +628,11 @@ async function drainSingleMessage(
707
628
  );
708
629
  conversation.messages.push(assistantMsg);
709
630
 
710
- next.onEvent({ type: "assistant_text_delta", text: responseText });
631
+ next.onEvent({
632
+ type: "assistant_text_delta",
633
+ text: responseText,
634
+ conversationId: conversation.conversationId,
635
+ });
711
636
  conversation.traceEmitter.emit(
712
637
  "message_complete",
713
638
  "Compact slash command handled",
@@ -727,7 +652,11 @@ async function drainSingleMessage(
727
652
  },
728
653
  "Failed to execute /compact",
729
654
  );
730
- next.onEvent({ type: "error", message });
655
+ next.onEvent({
656
+ type: "error",
657
+ conversationId: conversation.conversationId,
658
+ message,
659
+ });
731
660
  }
732
661
  await drainQueue(conversation);
733
662
  return;
@@ -787,7 +716,11 @@ async function drainSingleMessage(
787
716
  attributes: { reason: "persist_failure" },
788
717
  },
789
718
  );
790
- next.onEvent({ type: "error", message });
719
+ next.onEvent({
720
+ type: "error",
721
+ conversationId: conversation.conversationId,
722
+ message,
723
+ });
791
724
  // runAgentLoop never ran, so its finally block won't clear this
792
725
  conversation.preactivatedSkillIds = undefined;
793
726
  // Continue draining — don't strand remaining messages
@@ -872,6 +805,7 @@ async function drainSingleMessage(
872
805
  );
873
806
  next.onEvent({
874
807
  type: "error",
808
+ conversationId: conversation.conversationId,
875
809
  message: `Failed to process queued message: ${message}`,
876
810
  });
877
811
  });
@@ -928,50 +862,15 @@ async function drainBatch(
928
862
  conversation.applyHostEnvFromTransport(head.transport);
929
863
  }
930
864
 
931
- // Non-interactive queued messages (channel requests) must not execute tools
932
- // via the desktop host proxy. Clear proxy availability so isAvailable()
933
- // returns false and tool execution falls back to local. Mirrors the
934
- // single-message path exactly — sourced from `head`.
935
- if (head.isInteractive === false) {
936
- conversation.clearProxyAvailability();
937
- const drainInterfaceCtx =
938
- queuedInterfaceCtx ?? conversation.getTurnInterfaceContext();
939
- const drainInterface = drainInterfaceCtx?.userMessageInterface;
940
- if (
941
- drainInterface &&
942
- !supportsHostProxy(drainInterface) &&
943
- supportsHostProxy(drainInterface, "host_browser")
944
- ) {
945
- conversation.restoreBrowserProxyAvailability();
946
- }
947
- } else {
865
+ // Preactivate computer-use skill for interactive desktop turns.
866
+ // Mirrors the single-message path exactly sourced from `head`.
867
+ if (head.isInteractive !== false) {
948
868
  const interfaceCtx =
949
869
  queuedInterfaceCtx ?? conversation.getTurnInterfaceContext();
950
870
  const sourceInterface = interfaceCtx?.userMessageInterface;
951
871
  if (sourceInterface && supportsHostProxy(sourceInterface)) {
952
- conversation.restoreProxyAvailability(
953
- conversation.hostBrowserSenderOverride
954
- ? { skipBrowser: true }
955
- : undefined,
956
- );
957
872
  conversation.addPreactivatedSkillId("computer-use");
958
873
  }
959
- const currentTurnCanServiceBrowser =
960
- !!sourceInterface && canServiceRegistryBrowser(sourceInterface);
961
- if (
962
- sourceInterface &&
963
- !supportsHostProxy(sourceInterface, "host_browser") &&
964
- !(conversation.hostBrowserSenderOverride && currentTurnCanServiceBrowser)
965
- ) {
966
- conversation.setHostBrowserProxy(undefined);
967
- }
968
- if (
969
- sourceInterface &&
970
- supportsHostProxy(sourceInterface) &&
971
- conversation.hostBrowserSenderOverride
972
- ) {
973
- conversation.restoreBrowserProxyAvailability();
974
- }
975
874
  }
976
875
 
977
876
  // Snapshot persona context at turn start so later tool turns can't pick up
@@ -1025,7 +924,7 @@ async function drainBatch(
1025
924
 
1026
925
  const qmSlash = await resolveSlash(
1027
926
  qm.content,
1028
- buildSlashContext(conversation),
927
+ buildSlashContext(qm.content, conversation),
1029
928
  );
1030
929
  if (qmSlash.kind !== "passthrough") {
1031
930
  // Defensive recovery. `buildPassthroughBatch` should make this
@@ -1051,7 +950,11 @@ async function drainBatch(
1051
950
  status: "error",
1052
951
  attributes: { reason: "batch_invariant_violation" },
1053
952
  });
1054
- qm.onEvent({ type: "error", message: invariantMessage });
953
+ qm.onEvent({
954
+ type: "error",
955
+ conversationId: conversation.conversationId,
956
+ message: invariantMessage,
957
+ });
1055
958
  if (i === 0) {
1056
959
  // Head invariant fired — no in-flight turn yet (the check runs
1057
960
  // before persistUserMessage, so the head was never persisted).
@@ -1118,7 +1021,11 @@ async function drainBatch(
1118
1021
  attributes: { reason: "persist_failure" },
1119
1022
  },
1120
1023
  );
1121
- qm.onEvent({ type: "error", message });
1024
+ qm.onEvent({
1025
+ type: "error",
1026
+ conversationId: conversation.conversationId,
1027
+ message,
1028
+ });
1122
1029
 
1123
1030
  if (i === 0) {
1124
1031
  // Head persist failed — processing is not set yet, no in-flight turn
@@ -1279,6 +1186,7 @@ async function drainBatch(
1279
1186
  );
1280
1187
  fanOutOnEvent({
1281
1188
  type: "error",
1189
+ conversationId: conversation.conversationId,
1282
1190
  message: `Failed to process queued messages: ${message}`,
1283
1191
  });
1284
1192
  });
@@ -1415,7 +1323,7 @@ export async function processMessage(
1415
1323
  // Resolve slash commands before persistence
1416
1324
  const slashResult = await resolveSlash(
1417
1325
  content,
1418
- buildSlashContext(conversation),
1326
+ buildSlashContext(content, conversation),
1419
1327
  );
1420
1328
 
1421
1329
  // Unknown slash command — persist the exchange (user + assistant) so the
@@ -1491,9 +1399,13 @@ export async function processMessage(
1491
1399
  // Emit fresh model info before the text delta so the client has
1492
1400
  // up-to-date configuredProviders when rendering /model or /models UI.
1493
1401
  if (isModelSlashCommand(content)) {
1494
- onEvent(await buildModelInfoEvent());
1402
+ onEvent(await buildModelInfoEvent(conversation.conversationId));
1495
1403
  }
1496
- onEvent({ type: "assistant_text_delta", text: slashResult.message });
1404
+ onEvent({
1405
+ type: "assistant_text_delta",
1406
+ text: slashResult.message,
1407
+ conversationId: conversation.conversationId,
1408
+ });
1497
1409
  conversation.traceEmitter.emit(
1498
1410
  "message_complete",
1499
1411
  "Unknown slash command handled",
@@ -1561,7 +1473,11 @@ export async function processMessage(
1561
1473
  );
1562
1474
  conversation.messages.push(assistantMsg);
1563
1475
 
1564
- onEvent({ type: "assistant_text_delta", text: responseText });
1476
+ onEvent({
1477
+ type: "assistant_text_delta",
1478
+ text: responseText,
1479
+ conversationId: conversation.conversationId,
1480
+ });
1565
1481
  conversation.traceEmitter.emit(
1566
1482
  "message_complete",
1567
1483
  "Compact slash command handled",
@@ -1613,7 +1529,11 @@ export async function processMessage(
1613
1529
  );
1614
1530
  } catch (err) {
1615
1531
  const message = err instanceof Error ? err.message : String(err);
1616
- onEvent({ type: "error", message });
1532
+ onEvent({
1533
+ type: "error",
1534
+ conversationId: conversation.conversationId,
1535
+ message,
1536
+ });
1617
1537
  // runAgentLoop never ran, so its finally block won't clear this
1618
1538
  conversation.preactivatedSkillIds = undefined;
1619
1539
  return "";