@vellumai/assistant 0.8.7 → 0.8.8-dev.202606052332.17fc8ea

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 (570) hide show
  1. package/Dockerfile +20 -4
  2. package/bun.lock +2 -2
  3. package/docker-entrypoint.sh +4 -2
  4. package/docker-init-apt-root.sh +3 -1
  5. package/docker-kata-apt-env.sh +3 -1
  6. package/docker-kata-runtime-family.sh +12 -0
  7. package/docs/architecture/memory.md +1 -1
  8. package/examples/plugins/echo/README.md +61 -66
  9. package/examples/plugins/echo/hooks/post-tool-use.ts +18 -0
  10. package/examples/plugins/echo/hooks/stop.ts +16 -0
  11. package/examples/plugins/echo/hooks/user-prompt-submit.ts +18 -0
  12. package/examples/plugins/echo/package.json +1 -2
  13. package/examples/plugins/echo/src/emit.ts +19 -0
  14. package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +3 -3
  15. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +7 -6
  16. package/openapi.yaml +3378 -335
  17. package/package.json +2 -2
  18. package/scripts/generate-openapi.ts +68 -41
  19. package/src/__tests__/agent-loop-exit-reason.test.ts +35 -93
  20. package/src/__tests__/agent-loop-provider-error-recording.test.ts +1 -1
  21. package/src/__tests__/agent-loop.test.ts +37 -87
  22. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +2 -0
  23. package/src/__tests__/annotate-activity-metadata.test.ts +262 -0
  24. package/src/__tests__/annotate-risk-options.test.ts +2 -3
  25. package/src/__tests__/anthropic-provider.test.ts +95 -2
  26. package/src/__tests__/app-control-flow.test.ts +1 -1
  27. package/src/__tests__/app-dir-path-guard.test.ts +1 -0
  28. package/src/__tests__/approval-routes-http.test.ts +4 -1
  29. package/src/__tests__/assistant-event-hub.test.ts +25 -0
  30. package/src/__tests__/assistant-events-sse-shed.test.ts +8 -0
  31. package/src/__tests__/{conversation-stream-state.test.ts → assistant-stream-state.test.ts} +252 -91
  32. package/src/__tests__/auth-fallback-events-store.test.ts +116 -0
  33. package/src/__tests__/background-workers-disk-pressure.test.ts +6 -0
  34. package/src/__tests__/btw-routes.test.ts +62 -3
  35. package/src/__tests__/build-persisted-content.test.ts +184 -0
  36. package/src/__tests__/catalog-files.test.ts +1 -1
  37. package/src/__tests__/channel-approval-routes.test.ts +1 -1
  38. package/src/__tests__/channel-approvals.test.ts +1 -1
  39. package/src/__tests__/clawhub-files.test.ts +1 -1
  40. package/src/__tests__/compaction-circuit.test.ts +258 -0
  41. package/src/__tests__/compaction-direct.test.ts +132 -0
  42. package/src/__tests__/compaction.benchmark.test.ts +0 -30
  43. package/src/__tests__/config-watcher.test.ts +1 -1
  44. package/src/__tests__/conversation-abort-tool-results.test.ts +57 -19
  45. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +6 -5
  46. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +10 -7
  47. package/src/__tests__/conversation-agent-loop-overflow.test.ts +316 -1143
  48. package/src/__tests__/conversation-agent-loop.test.ts +638 -1655
  49. package/src/__tests__/conversation-analysis-routes.test.ts +6 -0
  50. package/src/__tests__/conversation-clean-command.test.ts +5 -2
  51. package/src/__tests__/conversation-history-web-search.test.ts +11 -1
  52. package/src/__tests__/conversation-pairing.test.ts +4 -31
  53. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +6 -0
  54. package/src/__tests__/conversation-provider-retry-repair.test.ts +30 -10
  55. package/src/__tests__/conversation-queue.test.ts +2 -0
  56. package/src/__tests__/conversation-routes-disk-view.test.ts +3 -0
  57. package/src/__tests__/conversation-routes-slash-commands.test.ts +6 -5
  58. package/src/__tests__/conversation-runtime-assembly.test.ts +310 -300
  59. package/src/__tests__/conversation-runtime-workspace.test.ts +105 -45
  60. package/src/__tests__/conversation-slash-commands.test.ts +8 -42
  61. package/src/__tests__/conversation-slash-queue.test.ts +6 -1
  62. package/src/__tests__/conversation-starter-routes.test.ts +14 -6
  63. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +84 -0
  64. package/src/__tests__/conversation-sync-tags.test.ts +27 -15
  65. package/src/__tests__/conversation-title-service.test.ts +135 -2
  66. package/src/__tests__/conversation-workspace-cache-state.test.ts +17 -16
  67. package/src/__tests__/conversation-workspace-injection.test.ts +67 -2
  68. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +7 -6
  69. package/src/__tests__/conversations-import-system-filter.test.ts +101 -0
  70. package/src/__tests__/cross-provider-web-search.test.ts +214 -1
  71. package/src/__tests__/db-acp-history.test.ts +101 -0
  72. package/src/__tests__/db-schedule-syntax-migration.test.ts +5 -0
  73. package/src/__tests__/dm-persistence.test.ts +5 -1
  74. package/src/__tests__/dynamic-page-surface.test.ts +31 -0
  75. package/src/__tests__/empty-response-hook.test.ts +304 -0
  76. package/src/__tests__/feature-flag-test-helpers.ts +2 -2
  77. package/src/__tests__/file-write-tool.test.ts +63 -0
  78. package/src/__tests__/gateway-only-guard.test.ts +12 -2
  79. package/src/__tests__/gemini-image-service.test.ts +13 -0
  80. package/src/__tests__/guardian-grant-minting.test.ts +1 -1
  81. package/src/__tests__/guardian-routing-invariants.test.ts +2 -4
  82. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
  83. package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
  84. package/src/__tests__/heartbeat-service.test.ts +1 -0
  85. package/src/__tests__/helpers/mock-provider.ts +110 -0
  86. package/src/__tests__/helpers/native-web-search-harness.ts +129 -0
  87. package/src/__tests__/history-repair-hook.test.ts +1 -0
  88. package/src/__tests__/host-app-control-routes.test.ts +1 -1
  89. package/src/__tests__/host-cu-routes-targeted.test.ts +3 -3
  90. package/src/__tests__/identity-intro-cache.test.ts +12 -100
  91. package/src/__tests__/identity-routes.test.ts +248 -7
  92. package/src/__tests__/inbound-slack-persistence.test.ts +5 -1
  93. package/src/__tests__/injector-background-turn.test.ts +3 -9
  94. package/src/__tests__/injector-chain.test.ts +139 -275
  95. package/src/__tests__/injector-disk-pressure.test.ts +75 -41
  96. package/src/__tests__/injector-document-comments.test.ts +3 -3
  97. package/src/__tests__/injector-pkb-v2-silenced.test.ts +30 -22
  98. package/src/__tests__/injector-v3-suppression.test.ts +31 -37
  99. package/src/__tests__/internal-telemetry-routes.test.ts +109 -0
  100. package/src/__tests__/list-messages-hidden-metadata.test.ts +38 -0
  101. package/src/__tests__/list-messages-page-latest.test.ts +60 -0
  102. package/src/__tests__/list-messages-tool-merge.test.ts +20 -0
  103. package/src/__tests__/llm-usage-store.test.ts +223 -1
  104. package/src/__tests__/memory-retrieval-hook.test.ts +297 -0
  105. package/src/__tests__/memory-v2-static-injector.test.ts +103 -35
  106. package/src/__tests__/native-web-search.test.ts +191 -0
  107. package/src/__tests__/onboarding-template-contract.test.ts +2 -0
  108. package/src/__tests__/openai-image-service.test.ts +17 -0
  109. package/src/__tests__/openai-provider.test.ts +31 -1
  110. package/src/__tests__/{overflow-reduce-pipeline.test.ts → overflow-reduction-loop.test.ts} +64 -284
  111. package/src/__tests__/persist-unsendable-image.test.ts +215 -0
  112. package/src/__tests__/persistence-secret-redaction.test.ts +1 -0
  113. package/src/__tests__/pkb-autoinject.test.ts +2 -5
  114. package/src/__tests__/plugin-api-shim.test.ts +3 -6
  115. package/src/__tests__/plugin-bootstrap.test.ts +14 -40
  116. package/src/__tests__/plugin-registry.test.ts +3 -76
  117. package/src/__tests__/plugin-types.test.ts +0 -193
  118. package/src/__tests__/process-message-display-content.test.ts +6 -2
  119. package/src/__tests__/reaction-persistence.test.ts +1 -1
  120. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +5 -1
  121. package/src/__tests__/resolve-trust-class.test.ts +4 -4
  122. package/src/__tests__/runtime-events-sse-reconnect.test.ts +60 -23
  123. package/src/__tests__/schedule-routes.test.ts +603 -2
  124. package/src/__tests__/schedule-store.test.ts +41 -0
  125. package/src/__tests__/schedule-tools.test.ts +35 -0
  126. package/src/__tests__/send-endpoint-busy.test.ts +4 -1
  127. package/src/__tests__/server-history-render.test.ts +314 -1
  128. package/src/__tests__/skill-feature-flags-integration.test.ts +33 -0
  129. package/src/__tests__/skillssh-files.test.ts +1 -1
  130. package/src/__tests__/subagent-call-site-routing.test.ts +1 -1
  131. package/src/__tests__/subagent-fork-notifications.test.ts +1 -3
  132. package/src/__tests__/subagent-fork-spawn.test.ts +1 -1
  133. package/src/__tests__/subagent-manager-notify.test.ts +1 -3
  134. package/src/__tests__/subagent-notify-parent.test.ts +1 -3
  135. package/src/__tests__/subagent-spawn-tool-fork.test.ts +1 -1
  136. package/src/__tests__/system-prompt.test.ts +20 -0
  137. package/src/__tests__/task-scheduler.test.ts +162 -1
  138. package/src/__tests__/terminal-tools.test.ts +6 -1
  139. package/src/__tests__/title-generate-hook.test.ts +319 -0
  140. package/src/__tests__/tool-error-hook.test.ts +278 -0
  141. package/src/__tests__/tool-preview-lifecycle.test.ts +468 -5
  142. package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
  143. package/src/__tests__/tool-result-truncate-hook.test.ts +127 -0
  144. package/src/__tests__/tool-result-truncation.test.ts +0 -2
  145. package/src/__tests__/ui-choice-copy-surfaces.test.ts +254 -0
  146. package/src/__tests__/ui-work-result-surface.test.ts +159 -0
  147. package/src/__tests__/usage-routes.test.ts +285 -1
  148. package/src/__tests__/user-plugin-loader.test.ts +54 -286
  149. package/src/__tests__/voice-session-bridge.test.ts +6 -3
  150. package/src/__tests__/web-search-backend-failure.test.ts +166 -0
  151. package/src/acp/__tests__/agent-process.test.ts +161 -0
  152. package/src/acp/__tests__/client-handler.test.ts +40 -0
  153. package/src/acp/__tests__/helpers/acp-history-db.ts +82 -0
  154. package/src/acp/__tests__/helpers/exec-file-stub.ts +101 -0
  155. package/src/acp/__tests__/prepare-agent-env.test.ts +137 -0
  156. package/src/acp/__tests__/session-manager-persistence.test.ts +95 -28
  157. package/src/acp/__tests__/session-manager-resume.test.ts +736 -0
  158. package/src/acp/agent-process.ts +61 -1
  159. package/src/acp/auto-install.test.ts +196 -0
  160. package/src/acp/auto-install.ts +177 -0
  161. package/src/acp/client-handler.ts +31 -0
  162. package/src/acp/feature-gate.test.ts +48 -0
  163. package/src/acp/feature-gate.ts +34 -0
  164. package/src/acp/prepare-agent-env.ts +83 -29
  165. package/src/acp/resolve-agent.test.ts +320 -7
  166. package/src/acp/resolve-agent.ts +182 -18
  167. package/src/acp/resume-hint.ts +25 -0
  168. package/src/acp/session-manager.ts +495 -73
  169. package/src/acp/types.ts +8 -0
  170. package/src/agent/compaction-circuit.ts +60 -102
  171. package/src/agent/loop.ts +362 -485
  172. package/src/api/events/assistant-thinking-delta.ts +33 -0
  173. package/src/api/events/tool-output-chunk.ts +45 -0
  174. package/src/api/events/tool-use-preview-start.ts +32 -0
  175. package/src/api/events/trace-event.ts +69 -0
  176. package/src/api/index.ts +48 -13
  177. package/src/api/responses/conversation-message.ts +374 -0
  178. package/src/approvals/guardian-request-resolvers.ts +1 -1
  179. package/src/avatar/__tests__/avatar-store.test.ts +34 -29
  180. package/src/background-wake/next-wake.ts +1 -0
  181. package/src/cli/commands/__tests__/notifications.test.ts +58 -14
  182. package/src/cli/commands/notifications.ts +112 -60
  183. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  184. package/src/config/acp-defaults.test.ts +10 -0
  185. package/src/config/acp-defaults.ts +6 -0
  186. package/src/config/assistant-feature-flags.ts +22 -11
  187. package/src/config/bundled-skills/acp/SKILL.md +83 -31
  188. package/src/config/bundled-skills/acp/TOOLS.json +4 -4
  189. package/src/config/bundled-skills/app-builder/SKILL.md +224 -398
  190. package/src/config/bundled-skills/app-builder/TOOLS.json +29 -0
  191. package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +48 -0
  192. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +57 -0
  193. package/src/config/bundled-skills/app-builder/references/SLIDES.md +38 -0
  194. package/src/config/bundled-skills/app-builder/references/examples/README.md +17 -0
  195. package/src/config/bundled-skills/app-builder/references/examples/expense-tracker.md +515 -0
  196. package/src/config/bundled-skills/app-builder/references/examples/focus-timer.md +342 -0
  197. package/src/config/bundled-skills/app-builder/references/examples/habit-tracker.md +490 -0
  198. package/src/config/bundled-skills/app-builder/tools/app-list.ts +62 -0
  199. package/src/config/bundled-skills/document-editor/SKILL.md +28 -23
  200. package/src/config/bundled-skills/document-editor/TOOLS.json +1 -1
  201. package/src/config/bundled-skills/messaging/SKILL.md +0 -7
  202. package/src/config/bundled-tool-registry.ts +2 -0
  203. package/src/config/feature-flag-cache.ts +3 -3
  204. package/src/config/feature-flag-registry.json +48 -7
  205. package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
  206. package/src/config/schemas/__tests__/memory-v3.test.ts +25 -0
  207. package/src/config/schemas/heartbeat.ts +9 -0
  208. package/src/config/schemas/llm.ts +1 -0
  209. package/src/config/schemas/memory-v2.ts +8 -0
  210. package/src/config/schemas/memory-v3.ts +8 -0
  211. package/src/config/schemas/platform.ts +8 -0
  212. package/src/config/seed-inference-profiles.ts +2 -2
  213. package/src/config/skills.ts +13 -0
  214. package/src/context/compactor.ts +1 -1
  215. package/src/context/strip-injections.ts +128 -0
  216. package/src/context/token-estimator.ts +23 -0
  217. package/src/context/tool-result-truncation.ts +0 -23
  218. package/src/context/window-manager.ts +5 -7
  219. package/src/credential-execution/executable-discovery.ts +16 -0
  220. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +6 -0
  221. package/src/daemon/__tests__/inference-profile-notification.test.ts +153 -0
  222. package/src/daemon/__tests__/native-web-search-metadata.test.ts +10 -8
  223. package/src/daemon/assistant-attachments.ts +1 -1
  224. package/src/daemon/config-watcher.ts +2 -2
  225. package/src/daemon/context-overflow-reducer.ts +0 -1
  226. package/src/daemon/conversation-agent-loop-handlers.ts +594 -153
  227. package/src/daemon/conversation-agent-loop.ts +301 -997
  228. package/src/daemon/conversation-history.ts +5 -4
  229. package/src/daemon/conversation-lifecycle.ts +3 -4
  230. package/src/daemon/conversation-messaging.ts +7 -6
  231. package/src/daemon/conversation-process.ts +11 -16
  232. package/src/daemon/conversation-registry.ts +159 -0
  233. package/src/daemon/conversation-runtime-assembly.ts +218 -398
  234. package/src/daemon/conversation-slash.ts +6 -25
  235. package/src/daemon/conversation-store.ts +9 -90
  236. package/src/daemon/conversation-surfaces.ts +222 -4
  237. package/src/daemon/conversation-tool-setup.ts +2 -29
  238. package/src/daemon/conversation-workspace.ts +17 -0
  239. package/src/daemon/conversation.ts +32 -20
  240. package/src/daemon/external-plugins-bootstrap.ts +17 -18
  241. package/src/daemon/handlers/config-a2a.ts +51 -36
  242. package/src/daemon/handlers/config-slack-channel.ts +20 -14
  243. package/src/daemon/handlers/config-telegram.ts +16 -2
  244. package/src/daemon/handlers/conversations.ts +3 -1
  245. package/src/daemon/handlers/shared.ts +156 -84
  246. package/src/daemon/handlers/skills.ts +42 -10
  247. package/src/daemon/lifecycle.ts +25 -0
  248. package/src/daemon/message-types/apps.ts +1 -29
  249. package/src/daemon/message-types/messages.ts +9 -57
  250. package/src/daemon/message-types/skills.ts +2 -0
  251. package/src/daemon/message-types/surfaces.ts +136 -3
  252. package/src/daemon/now-scratchpad.ts +21 -0
  253. package/src/daemon/orphan-reaper.test.ts +210 -0
  254. package/src/daemon/orphan-reaper.ts +240 -0
  255. package/src/daemon/overflow-reduction-loop.ts +230 -0
  256. package/src/daemon/persist-unsendable-image.ts +117 -0
  257. package/src/daemon/process-message.ts +1 -3
  258. package/src/daemon/server.ts +2 -0
  259. package/src/daemon/trace-emitter.ts +6 -4
  260. package/src/daemon/trust-context.ts +19 -0
  261. package/src/daemon/wake-target-adapter.ts +3 -1
  262. package/src/heartbeat/__tests__/heartbeat-service.test.ts +3 -0
  263. package/src/heartbeat/heartbeat-run-store.ts +23 -1
  264. package/src/heartbeat/heartbeat-service.ts +26 -0
  265. package/src/home/home-greeting-cache.ts +24 -1
  266. package/src/ipc/__tests__/browser-ipc.test.ts +1 -1
  267. package/src/ipc/__tests__/ui-request-route.test.ts +3 -3
  268. package/src/ipc/gateway-client.test.ts +2 -2
  269. package/src/ipc/gateway-client.ts +3 -3
  270. package/src/ipc/skill-routes/__tests__/memory.test.ts +15 -0
  271. package/src/ipc/skill-routes/memory.ts +4 -2
  272. package/src/media/gemini-image-service.ts +15 -0
  273. package/src/media/openai-image-service.ts +14 -0
  274. package/src/media/types.ts +34 -0
  275. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +56 -0
  276. package/src/memory/auth-fallback-events-store.ts +94 -0
  277. package/src/memory/conversation-starter-checkpoints.ts +1 -0
  278. package/src/memory/conversation-title-service.ts +65 -41
  279. package/src/memory/db-init.ts +6 -0
  280. package/src/memory/graph/__tests__/conversation-graph-memory-registry.test.ts +119 -0
  281. package/src/memory/graph/conversation-graph-memory.ts +65 -0
  282. package/src/memory/job-handlers/conversation-starters.ts +13 -2
  283. package/src/memory/jobs-store.ts +33 -0
  284. package/src/memory/jobs-worker.ts +32 -5
  285. package/src/memory/llm-usage-store.ts +224 -50
  286. package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +6 -5
  287. package/src/memory/migrations/270-schedule-source-conversation.ts +13 -0
  288. package/src/memory/migrations/271-create-auth-fallback-events.ts +21 -0
  289. package/src/memory/migrations/272-acp-session-history-cwd.ts +36 -0
  290. package/src/memory/migrations/index.ts +3 -0
  291. package/src/memory/pkb/autoinject.ts +61 -0
  292. package/src/memory/pkb/context.ts +50 -0
  293. package/src/memory/pkb/types.ts +14 -0
  294. package/src/memory/schedule-attribution-sql.ts +104 -0
  295. package/src/memory/schema/acp.ts +4 -0
  296. package/src/memory/schema/infrastructure.ts +16 -0
  297. package/src/memory/usage-grouped-buckets.ts +6 -1
  298. package/src/memory/v2/__tests__/consolidation-job.test.ts +4 -4
  299. package/src/memory/v2/consolidation-job.ts +14 -5
  300. package/src/notifications/conversation-pairing.ts +8 -15
  301. package/src/notifications/decision-engine.ts +6 -3
  302. package/src/notifications/home-feed-side-effect.ts +12 -1
  303. package/src/permissions/prompter.ts +4 -0
  304. package/src/plugin-api/constants.ts +4 -0
  305. package/src/plugin-api/index.ts +7 -5
  306. package/src/plugin-api/types.ts +151 -1
  307. package/src/plugins/defaults/compaction/compact.ts +59 -0
  308. package/src/plugins/defaults/compaction/package.json +1 -1
  309. package/src/plugins/defaults/compaction/register.ts +8 -19
  310. package/src/plugins/defaults/empty-response/hooks/stop.ts +126 -0
  311. package/src/plugins/defaults/empty-response/register.ts +8 -13
  312. package/src/plugins/defaults/index.ts +2 -18
  313. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +95 -0
  314. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +216 -0
  315. package/src/plugins/defaults/memory-retrieval/injector-chain.ts +35 -0
  316. package/src/plugins/defaults/{injectors/register.ts → memory-retrieval/injectors.ts} +288 -81
  317. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/assign.test.ts +4 -4
  318. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/health.test.ts +16 -0
  319. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/live-integration.test.ts +4 -4
  320. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/maintain-job.test.ts +5 -5
  321. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/orchestrate.test.ts +48 -12
  322. package/src/plugins/defaults/memory-v3-shadow/__tests__/provider-blocks.test.ts +13 -0
  323. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/reconcile.test.ts +2 -2
  324. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/render-injection.test.ts +1 -1
  325. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/router.test.ts +104 -32
  326. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selection-log-store.test.ts +8 -8
  327. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selector.test.ts +96 -30
  328. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/shadow-plugin.test.ts +34 -16
  329. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/assign.ts +5 -5
  330. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/capabilities.ts +2 -2
  331. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/health.ts +0 -0
  332. package/src/plugins/defaults/memory-v3-shadow/hooks/post-compact.ts +14 -0
  333. package/src/plugins/defaults/memory-v3-shadow/hooks/user-prompt-submit.ts +19 -0
  334. package/src/plugins/defaults/memory-v3-shadow/injector.ts +75 -0
  335. package/src/plugins/defaults/memory-v3-shadow/llm-retry.ts +32 -0
  336. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/maintain-job.ts +8 -8
  337. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/orchestrate.ts +26 -14
  338. package/src/plugins/defaults/{llm-call → memory-v3-shadow}/package.json +2 -2
  339. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/page-content.ts +2 -2
  340. package/src/plugins/defaults/memory-v3-shadow/provider-blocks.ts +26 -0
  341. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/reconcile.ts +3 -3
  342. package/src/plugins/defaults/memory-v3-shadow/register.ts +26 -0
  343. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/render-injection.ts +1 -1
  344. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/router.ts +51 -45
  345. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/selection-log-store.ts +4 -4
  346. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/selector.ts +61 -46
  347. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/shadow-plugin.ts +69 -99
  348. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/tree.ts +1 -1
  349. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/types.ts +8 -0
  350. package/src/plugins/defaults/title-generate/hooks/stop.ts +75 -0
  351. package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +35 -0
  352. package/src/plugins/defaults/title-generate/package.json +1 -1
  353. package/src/plugins/defaults/title-generate/register.ts +18 -18
  354. package/src/plugins/defaults/tool-error/hooks/post-tool-use.ts +118 -0
  355. package/src/plugins/defaults/tool-error/package.json +1 -1
  356. package/src/plugins/defaults/tool-error/register.ts +9 -21
  357. package/src/plugins/defaults/tool-result-truncate/hooks/post-tool-use.ts +32 -0
  358. package/src/plugins/defaults/tool-result-truncate/register.ts +10 -21
  359. package/src/plugins/defaults/tool-result-truncate/terminal.ts +37 -18
  360. package/src/plugins/external-api.ts +2 -2
  361. package/src/plugins/pipeline.ts +6 -305
  362. package/src/plugins/registry.ts +10 -55
  363. package/src/plugins/types.ts +62 -797
  364. package/src/plugins/user-loader.ts +30 -127
  365. package/src/proactive-artifact/aux-message-injector.ts +4 -4
  366. package/src/proactive-artifact/job.test.ts +8 -13
  367. package/src/prompts/__tests__/system-prompt.test.ts +42 -0
  368. package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +64 -0
  369. package/src/prompts/templates/BOOTSTRAP.md +2 -2
  370. package/src/prompts/templates/system-sections.ts +15 -0
  371. package/src/providers/anthropic/client.ts +37 -29
  372. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +112 -0
  373. package/src/providers/openai/chat-completions-provider.ts +44 -0
  374. package/src/providers/openrouter/client.ts +1 -0
  375. package/src/providers/placeholder-sentinels.ts +35 -0
  376. package/src/runtime/__tests__/agent-wake.test.ts +10 -6
  377. package/src/runtime/__tests__/interactive-ui.test.ts +1 -1
  378. package/src/runtime/agent-wake.ts +2 -5
  379. package/src/runtime/assistant-event-hub.ts +37 -7
  380. package/src/runtime/{conversation-stream-state.ts → assistant-stream-state.ts} +132 -58
  381. package/src/runtime/channel-approvals.ts +1 -1
  382. package/src/runtime/http-router.ts +16 -21
  383. package/src/runtime/http-types.ts +16 -70
  384. package/src/runtime/interactive-ui.ts +1 -1
  385. package/src/runtime/pending-interactions.ts +1 -0
  386. package/src/runtime/routes/__tests__/acp-routes.test.ts +283 -55
  387. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +265 -2
  388. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
  389. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +31 -1
  390. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +6 -2
  391. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +5 -4
  392. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +4 -1
  393. package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
  394. package/src/runtime/routes/acp-routes.test.ts +89 -25
  395. package/src/runtime/routes/acp-routes.ts +81 -29
  396. package/src/runtime/routes/app-management-routes.ts +6 -117
  397. package/src/runtime/routes/app-routes.ts +13 -15
  398. package/src/runtime/routes/approval-routes.ts +1 -1
  399. package/src/runtime/routes/attachment-routes.ts +26 -15
  400. package/src/runtime/routes/avatar-routes.ts +26 -0
  401. package/src/runtime/routes/browser-routes.ts +1 -1
  402. package/src/runtime/routes/browser-tabs-routes.ts +6 -10
  403. package/src/runtime/routes/btw-routes.ts +29 -23
  404. package/src/runtime/routes/consolidation-routes.ts +120 -20
  405. package/src/runtime/routes/conversation-cli-routes.ts +1 -1
  406. package/src/runtime/routes/conversation-list-routes.ts +1 -1
  407. package/src/runtime/routes/conversation-query-routes.ts +3 -1
  408. package/src/runtime/routes/conversation-routes.ts +372 -185
  409. package/src/runtime/routes/conversation-starter-routes.ts +13 -7
  410. package/src/runtime/routes/conversations-import-routes.ts +24 -7
  411. package/src/runtime/routes/documents-routes.ts +4 -0
  412. package/src/runtime/routes/domain-routes.ts +51 -37
  413. package/src/runtime/routes/epoch-millis-range.ts +34 -0
  414. package/src/runtime/routes/events-routes.ts +28 -34
  415. package/src/runtime/routes/gateway-log-routes.ts +26 -4
  416. package/src/runtime/routes/heartbeat-routes.ts +32 -12
  417. package/src/runtime/routes/host-app-control-routes.ts +1 -1
  418. package/src/runtime/routes/host-cu-routes.ts +1 -1
  419. package/src/runtime/routes/identity-intro-cache.ts +11 -34
  420. package/src/runtime/routes/identity-routes.ts +224 -18
  421. package/src/runtime/routes/image-generation-routes.ts +40 -2
  422. package/src/runtime/routes/inbound-message-handler.ts +1 -1
  423. package/src/runtime/routes/index.ts +2 -0
  424. package/src/runtime/routes/integrations/a2a.ts +12 -10
  425. package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +16 -0
  426. package/src/runtime/routes/integrations/slack/channel.ts +4 -0
  427. package/src/runtime/routes/integrations/slack/share.ts +27 -6
  428. package/src/runtime/routes/integrations/telegram.ts +6 -0
  429. package/src/runtime/routes/integrations/twilio.ts +42 -0
  430. package/src/runtime/routes/internal-telemetry-routes.ts +88 -0
  431. package/src/runtime/routes/log-export-routes.ts +8 -0
  432. package/src/runtime/routes/memory-v2-routes.ts +15 -8
  433. package/src/runtime/routes/memory-v3-routes.ts +66 -34
  434. package/src/runtime/routes/oauth-apps.ts +66 -12
  435. package/src/runtime/routes/oauth-providers.ts +44 -5
  436. package/src/runtime/routes/platform-routes.ts +81 -5
  437. package/src/runtime/routes/playground/__tests__/force-compact.test.ts +6 -4
  438. package/src/runtime/routes/playground/force-compact.ts +1 -1
  439. package/src/runtime/routes/playground/helpers.ts +1 -1
  440. package/src/runtime/routes/rename-conversation-routes.ts +5 -0
  441. package/src/runtime/routes/schedule-routes.ts +152 -42
  442. package/src/runtime/routes/secret-routes.ts +14 -2
  443. package/src/runtime/routes/skills-routes.ts +43 -14
  444. package/src/runtime/routes/surface-conversation-resolver.ts +4 -3
  445. package/src/runtime/routes/tool-call-confirmation-enrichment.test.ts +161 -0
  446. package/src/runtime/routes/tool-call-confirmation-enrichment.ts +107 -0
  447. package/src/runtime/routes/trust-rules-routes.ts +26 -2
  448. package/src/runtime/routes/tts-routes.ts +35 -0
  449. package/src/runtime/routes/types.ts +66 -8
  450. package/src/runtime/routes/usage-routes.ts +47 -39
  451. package/src/runtime/routes/webhook-routes.ts +41 -2
  452. package/src/runtime/routes/work-items-routes.ts +2 -4
  453. package/src/runtime/routes/workspace-routes.ts +4 -0
  454. package/src/runtime/services/__tests__/analyze-conversation.test.ts +6 -0
  455. package/src/runtime/services/analyze-conversation.ts +2 -2
  456. package/src/runtime/services/conversation-serializer.ts +1 -1
  457. package/src/schedule/schedule-store.ts +20 -1
  458. package/src/schedule/schedule-usage-store.ts +83 -0
  459. package/src/schedule/scheduler.ts +12 -5
  460. package/src/signals/cancel.ts +2 -4
  461. package/src/skills/catalog-files.ts +2 -2
  462. package/src/skills/catalog-install.ts +3 -0
  463. package/src/skills/categories-cache.ts +118 -0
  464. package/src/skills/clawhub-files.ts +1 -2
  465. package/src/skills/skillssh-files.ts +1 -2
  466. package/src/subagent/manager.ts +17 -5
  467. package/src/telemetry/types.ts +29 -1
  468. package/src/telemetry/usage-telemetry-reporter.test.ts +112 -3
  469. package/src/telemetry/usage-telemetry-reporter.ts +57 -2
  470. package/src/tools/acp/context.ts +20 -0
  471. package/src/tools/acp/list-agents.test.ts +7 -1
  472. package/src/tools/acp/spawn.test.ts +158 -55
  473. package/src/tools/acp/spawn.ts +47 -72
  474. package/src/tools/acp/steer.test.ts +105 -8
  475. package/src/tools/acp/steer.ts +48 -17
  476. package/src/tools/apps/executors.ts +13 -8
  477. package/src/tools/executor.ts +1 -53
  478. package/src/tools/filesystem/write.ts +34 -0
  479. package/src/tools/network/__tests__/web-search-metadata.test.ts +7 -1
  480. package/src/tools/network/__tests__/web-search.test.ts +11 -3
  481. package/src/tools/network/web-search-error.test.ts +248 -0
  482. package/src/tools/network/web-search-error.ts +267 -0
  483. package/src/tools/network/web-search.ts +207 -48
  484. package/src/tools/schedule/create.ts +2 -0
  485. package/src/tools/subagent/spawn.ts +2 -4
  486. package/src/tools/terminal/safe-env.ts +10 -1
  487. package/src/tools/ui-surface/definitions.ts +34 -5
  488. package/src/tts/__tests__/provider-catalog-consistency.test.ts +85 -1
  489. package/src/tts/provider-catalog.ts +76 -1
  490. package/src/util/mutex.ts +47 -0
  491. package/src/workspace/git-service.ts +1 -42
  492. package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +4 -5
  493. package/src/workspace/migrations/095-bump-heartbeat-interval-30m-to-60m.ts +51 -0
  494. package/src/workspace/migrations/096-reduce-quality-profile-effort.ts +72 -0
  495. package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +117 -0
  496. package/src/workspace/migrations/registry.ts +6 -0
  497. package/docs/plugins.md +0 -836
  498. package/examples/plugins/echo/register.ts +0 -184
  499. package/src/__tests__/bootstrap-turn-cleanup.test.ts +0 -44
  500. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -405
  501. package/src/__tests__/compaction-pipeline.test.ts +0 -210
  502. package/src/__tests__/compaction-timeout-recovery.test.ts +0 -251
  503. package/src/__tests__/empty-response-pipeline.test.ts +0 -423
  504. package/src/__tests__/llm-call-pipeline.test.ts +0 -287
  505. package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -418
  506. package/src/__tests__/persistence-pipeline.test.ts +0 -503
  507. package/src/__tests__/pipeline-runner.test.ts +0 -564
  508. package/src/__tests__/title-generate-pipeline.test.ts +0 -211
  509. package/src/__tests__/token-estimate-pipeline.test.ts +0 -479
  510. package/src/__tests__/tool-error-pipeline.test.ts +0 -241
  511. package/src/__tests__/tool-execute-pipeline.test.ts +0 -417
  512. package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -341
  513. package/src/daemon/bootstrap-turn-cleanup.ts +0 -45
  514. package/src/gallery/default-gallery.ts +0 -1359
  515. package/src/gallery/gallery-manifest.ts +0 -28
  516. package/src/home/feature-gate.ts +0 -22
  517. package/src/memory/v3/provider-blocks.ts +0 -16
  518. package/src/plugins/defaults/circuit-breaker/middlewares/circuitBreaker.ts +0 -93
  519. package/src/plugins/defaults/circuit-breaker/package.json +0 -15
  520. package/src/plugins/defaults/circuit-breaker/register.ts +0 -39
  521. package/src/plugins/defaults/compaction/middlewares/compaction.ts +0 -25
  522. package/src/plugins/defaults/compaction/terminal.ts +0 -73
  523. package/src/plugins/defaults/empty-response/middlewares/emptyResponse.ts +0 -22
  524. package/src/plugins/defaults/empty-response/terminal.ts +0 -106
  525. package/src/plugins/defaults/injectors/package.json +0 -15
  526. package/src/plugins/defaults/llm-call/middlewares/llmCall.ts +0 -17
  527. package/src/plugins/defaults/llm-call/register.ts +0 -45
  528. package/src/plugins/defaults/memory-retrieval/middlewares/memoryRetrieval.ts +0 -17
  529. package/src/plugins/defaults/memory-retrieval/package.json +0 -15
  530. package/src/plugins/defaults/memory-retrieval/register.ts +0 -181
  531. package/src/plugins/defaults/overflow-reduce/middlewares/overflowReduce.ts +0 -126
  532. package/src/plugins/defaults/overflow-reduce/package.json +0 -15
  533. package/src/plugins/defaults/overflow-reduce/register.ts +0 -42
  534. package/src/plugins/defaults/persistence/middlewares/persistence.ts +0 -19
  535. package/src/plugins/defaults/persistence/package.json +0 -15
  536. package/src/plugins/defaults/persistence/register.ts +0 -38
  537. package/src/plugins/defaults/persistence/terminal.ts +0 -83
  538. package/src/plugins/defaults/title-generate/terminal.ts +0 -31
  539. package/src/plugins/defaults/token-estimate/middlewares/tokenEstimate.ts +0 -23
  540. package/src/plugins/defaults/token-estimate/package.json +0 -15
  541. package/src/plugins/defaults/token-estimate/register.ts +0 -34
  542. package/src/plugins/defaults/token-estimate/terminal.ts +0 -40
  543. package/src/plugins/defaults/tool-error/middlewares/toolError.ts +0 -21
  544. package/src/plugins/defaults/tool-error/terminal.ts +0 -47
  545. package/src/plugins/defaults/tool-execute/middlewares/toolExecute.ts +0 -23
  546. package/src/plugins/defaults/tool-execute/package.json +0 -15
  547. package/src/plugins/defaults/tool-execute/register.ts +0 -49
  548. package/src/plugins/defaults/tool-result-truncate/middlewares/toolResultTruncate.ts +0 -23
  549. package/src/plugins/defaults/tool-result-truncate/types.ts +0 -22
  550. package/src/skills/category-inference.ts +0 -111
  551. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/capabilities.test.ts +0 -0
  552. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/core.test.ts +0 -0
  553. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/eval-turns.json +0 -0
  554. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/live-turns.json +0 -0
  555. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/needle.test.ts +0 -0
  556. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/snapshot.test.ts +0 -0
  557. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/tree.test.ts +0 -0
  558. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/types.test.ts +0 -0
  559. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-eviction.test.ts +0 -0
  560. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-skeleton.test.ts +0 -0
  561. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/core.ts +0 -0
  562. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/README.md +0 -0
  563. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/assignments.json +0 -0
  564. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/core.json +0 -0
  565. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-x.md +0 -0
  566. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-y.md +0 -0
  567. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-b/topic-z.md +0 -0
  568. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/needle.ts +0 -0
  569. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/snapshot.ts +0 -0
  570. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/working-set.ts +0 -0
@@ -1,11 +1,19 @@
1
1
  /**
2
- * Conversation Stream State -- per-conversation SSE sequence counter and
3
- * ring buffer for `Last-Event-ID` replay (B7 Unit 1).
2
+ * Assistant Stream State -- a single per-assistant (per-daemon-process)
3
+ * SSE sequence counter and ring buffer for `Last-Event-ID` replay.
4
4
  *
5
5
  * Every conversation-scoped outbound event picks up a monotonic `seq`
6
- * number from this module. The same event is also pushed onto a bounded
7
- * ring buffer so a reconnecting client can request replay of events the
8
- * daemon emitted while it was disconnected.
6
+ * from one global counter shared across all conversations, and is pushed
7
+ * onto one shared ring buffer. A reconnecting client presents the highest
8
+ * `seq` it has applied; the daemon replays everything newer from the ring
9
+ * -- re-applying the subscriber's targeting/scope filter -- then goes
10
+ * live.
11
+ *
12
+ * A single global seq space means the reconnect cursor is one number, not
13
+ * a per-conversation map: on one ordered SSE connection the client has
14
+ * received a contiguous prefix of the global stream, so "highest seq
15
+ * applied" is a valid resume point no matter how many conversations are
16
+ * multiplexed on the connection.
9
17
  *
10
18
  * Bounds (oldest evicted first; first bound hit wins):
11
19
  * - Count: 200 events
@@ -13,9 +21,23 @@
13
21
  * - Age: 30 seconds
14
22
  *
15
23
  * The ring is in-memory and per-daemon-process. After a daemon restart
16
- * all seqs reset and reconnecting clients fall through to the snapshot
17
- * path (delivered by B7 Unit 2). The ring is sized generously enough
18
- * that a typical refresh round-trip (~1-3s) is well within window.
24
+ * the seq resets and reconnecting clients fall through to the snapshot
25
+ * path. The ring is sized generously enough that a typical refresh
26
+ * round-trip (~1-3s) is well within window.
27
+ *
28
+ * Persisted-seq map: alongside the live counter and ring, this module
29
+ * tracks, per conversation, the `seq` of the last event whose content is
30
+ * durably committed to the message rows (`persistedSeqByConversation`).
31
+ * The `/messages` snapshot returns this value so a client can align the
32
+ * snapshot with the stream: "these rows reflect all of this
33
+ * conversation's events through `seq = S`." It is recorded at each
34
+ * persistence flush (assistant rows persist incrementally, debounced, so
35
+ * the snapshot can lag the live counter) -- never the live counter
36
+ * itself, which would over-claim events that have streamed but not yet
37
+ * been written. It shares the live counter's lifetime by design: both
38
+ * are in-memory and reset together on restart, so a stored value can
39
+ * never dangle against a fresh counter. The map is LRU-bounded; an
40
+ * evicted conversation reports no seq and the client cold-starts.
19
41
  */
20
42
 
21
43
  import type { AssistantEvent } from "./assistant-event.js";
@@ -26,6 +48,16 @@ const RING_COUNT_LIMIT = 200;
26
48
  const RING_SIZE_LIMIT_BYTES = 256 * 1024;
27
49
  const RING_AGE_LIMIT_MS = 30_000;
28
50
 
51
+ /**
52
+ * Cap on how many conversations retain a persisted-seq entry. Unlike the
53
+ * ring (which the live stream needs only briefly), the persisted-seq map
54
+ * grows with the number of conversations that have ever streamed in this
55
+ * process. Bound it LRU so it can't grow without limit; an evicted
56
+ * conversation simply reports no seq on its next `/messages` and the
57
+ * client cold-starts, which is harmless.
58
+ */
59
+ const PERSISTED_SEQ_CONVERSATION_LIMIT = 1024;
60
+
29
61
  // ── Types ────────────────────────────────────────────────────────────
30
62
 
31
63
  /**
@@ -63,30 +95,33 @@ interface RingEntry {
63
95
  targeting?: EventTargeting;
64
96
  }
65
97
 
66
- interface ConversationStreamState {
98
+ interface AssistantStreamState {
67
99
  nextSeq: number;
68
100
  ring: RingEntry[];
69
101
  totalSizeBytes: number;
102
+ /**
103
+ * Per-conversation `seq` of the last event durably committed to the
104
+ * message rows. Insertion order is maintained as an LRU recency list:
105
+ * the oldest key is evicted first once the map exceeds
106
+ * {@link PERSISTED_SEQ_CONVERSATION_LIMIT}.
107
+ */
108
+ persistedSeqByConversation: Map<string, number>;
70
109
  }
71
110
 
72
111
  // ── State ────────────────────────────────────────────────────────────
73
112
 
74
- const streams = new Map<string, ConversationStreamState>();
75
-
76
- function getOrCreate(conversationId: string): ConversationStreamState {
77
- let state = streams.get(conversationId);
78
- if (!state) {
79
- state = { nextSeq: 1, ring: [], totalSizeBytes: 0 };
80
- streams.set(conversationId, state);
81
- }
82
- return state;
83
- }
113
+ const state: AssistantStreamState = {
114
+ nextSeq: 1,
115
+ ring: [],
116
+ totalSizeBytes: 0,
117
+ persistedSeqByConversation: new Map(),
118
+ };
84
119
 
85
120
  // ── Public API ───────────────────────────────────────────────────────
86
121
 
87
122
  /**
88
- * Assign a monotonic `seq` to a conversation-scoped event and push it
89
- * onto the ring buffer. No-op when `event.conversationId` is absent
123
+ * Assign a monotonic global `seq` to a conversation-scoped event and push
124
+ * it onto the ring buffer. No-op when `event.conversationId` is absent
90
125
  * (unscoped broadcasts are never replayable).
91
126
  *
92
127
  * When `options.targeting` is provided, the metadata is stored on the
@@ -101,10 +136,8 @@ export function stampAndBuffer(
101
136
  event: AssistantEvent,
102
137
  options?: { targeting?: EventTargeting },
103
138
  ): void {
104
- const cid = event.conversationId;
105
- if (cid == null) return;
139
+ if (event.conversationId == null) return;
106
140
 
107
- const state = getOrCreate(cid);
108
141
  event.seq = state.nextSeq++;
109
142
 
110
143
  // Approximate size by serialized JSON length. This is the same
@@ -123,43 +156,36 @@ export function stampAndBuffer(
123
156
  state.ring.push(entry);
124
157
  state.totalSizeBytes += sizeBytes;
125
158
 
126
- evict(state);
159
+ evict();
127
160
  }
128
161
 
129
162
  /**
130
- * Replay events with `seq > lastSeenSeq` for a given conversation.
163
+ * Replay events with `seq > lastSeenSeq` from the single global ring.
131
164
  * Returns `null` when the requested cursor is older than the oldest
132
165
  * buffered entry -- callers should fall back to a snapshot resync.
133
166
  *
134
167
  * When `subscriber` is provided, entries carrying targeting metadata
135
168
  * are filtered using the same rules as the live `publish()` path in
136
- * `AssistantEventHub`. This prevents targeted events from leaking to
137
- * subscribers outside their intended delivery set on reconnect.
138
- * When `subscriber` is omitted, all entries are returned unfiltered
139
- * (backwards-compatible behaviour).
169
+ * `AssistantEventHub`, so targeted events do not leak to subscribers
170
+ * outside their intended delivery set on reconnect.
171
+ *
172
+ * When `conversationId` is provided, only that conversation's events are
173
+ * returned -- a conversation-scoped subscription only delivers its own
174
+ * conversation live, so replaying any other conversation's gap would
175
+ * push events the client will never receive again live.
140
176
  *
141
- * Sweeps age-expired entries at read time so an idle conversation
142
- * cannot serve stale deltas past the 30-second window (eviction
143
- * only runs on `stampAndBuffer`, so without this an idle stream
144
- * would retain its tail until the next write). When the sweep
145
- * drains the ring entirely, the conversation's state entry is
146
- * dropped to keep the global map from growing unboundedly with
147
- * inactive conversations.
177
+ * Sweeps age-expired entries at read time so an idle stream cannot serve
178
+ * stale deltas past the 30-second window (eviction otherwise only runs on
179
+ * `stampAndBuffer`).
148
180
  */
149
181
  export function getReplayWindow(
150
- conversationId: string,
151
182
  lastSeenSeq: number,
152
183
  subscriber?: ReplaySubscriber,
184
+ conversationId?: string,
153
185
  ): readonly AssistantEvent[] | null {
154
- const state = streams.get(conversationId);
155
- if (!state) return [];
186
+ evict();
156
187
 
157
- evict(state);
158
-
159
- if (state.ring.length === 0) {
160
- streams.delete(conversationId);
161
- return [];
162
- }
188
+ if (state.ring.length === 0) return [];
163
189
 
164
190
  const oldest = state.ring[0]?.seq ?? Infinity;
165
191
  if (lastSeenSeq < oldest - 1) return null;
@@ -168,39 +194,87 @@ export function getReplayWindow(
168
194
  .filter(
169
195
  (entry) =>
170
196
  entry.seq > lastSeenSeq &&
197
+ (conversationId == null ||
198
+ entry.event.conversationId === conversationId) &&
171
199
  (subscriber == null || matchesSubscriber(entry, subscriber)),
172
200
  )
173
201
  .map((entry) => entry.event);
174
202
  }
175
203
 
176
204
  /**
177
- * Drop all state for a conversation. Currently unused -- the ring
178
- * self-evicts by age -- but exposed for explicit dispose flows
179
- * (e.g. when a conversation is deleted).
205
+ * Current high-water `seq` -- the value last assigned by
206
+ * {@link stampAndBuffer}, or `0` when nothing has been stamped yet in
207
+ * this process.
208
+ *
209
+ * Read synchronously right after emitting an event to learn that event's
210
+ * `seq`: `stampAndBuffer` runs inline on the publish path (before the
211
+ * async fanout), so no other event can interleave between the emit
212
+ * returning and this read on the single-threaded event loop.
213
+ */
214
+ export function getCurrentSeq(): number {
215
+ return state.nextSeq - 1;
216
+ }
217
+
218
+ /**
219
+ * Record that conversation `conversationId` has durably persisted all of
220
+ * its events through `seq`. Called at each persistence flush with the
221
+ * `seq` of the last event whose content the write committed.
222
+ *
223
+ * Monotonic: a lower `seq` never regresses a higher one (out-of-order
224
+ * async commits are clamped). LRU-bounded by
225
+ * {@link PERSISTED_SEQ_CONVERSATION_LIMIT}: re-recording refreshes
226
+ * recency, and the oldest conversation is evicted once the cap is
227
+ * exceeded. Non-positive or non-finite `seq` values are ignored.
228
+ */
229
+ export function recordPersistedSeq(conversationId: string, seq: number): void {
230
+ if (!Number.isFinite(seq) || seq <= 0) return;
231
+
232
+ const map = state.persistedSeqByConversation;
233
+ const prev = map.get(conversationId);
234
+ if (prev !== undefined) {
235
+ // Re-insert to move this key to the most-recently-used end.
236
+ map.delete(conversationId);
237
+ map.set(conversationId, Math.max(prev, seq));
238
+ return;
239
+ }
240
+
241
+ map.set(conversationId, seq);
242
+ if (map.size > PERSISTED_SEQ_CONVERSATION_LIMIT) {
243
+ const oldestKey = map.keys().next().value;
244
+ if (oldestKey !== undefined) map.delete(oldestKey);
245
+ }
246
+ }
247
+
248
+ /**
249
+ * Highest `seq` durably persisted for `conversationId`, or `null` when
250
+ * none has been recorded in this process (cold conversation, or evicted
251
+ * from the LRU map). Returned by `/messages` so a client can align the
252
+ * snapshot with the live stream.
180
253
  */
181
- export function clearConversationStream(conversationId: string): void {
182
- streams.delete(conversationId);
254
+ export function getPersistedSeq(conversationId: string): number | null {
255
+ return state.persistedSeqByConversation.get(conversationId) ?? null;
183
256
  }
184
257
 
185
258
  /**
186
259
  * Reset all stream state. Test-only.
187
260
  */
188
- export function _resetConversationStreamsForTesting(): void {
189
- streams.clear();
261
+ export function _resetStreamStateForTesting(): void {
262
+ state.nextSeq = 1;
263
+ state.ring = [];
264
+ state.totalSizeBytes = 0;
265
+ state.persistedSeqByConversation.clear();
190
266
  }
191
267
 
192
268
  /**
193
269
  * Read-only inspector for tests.
194
270
  */
195
- export function _peekStreamForTesting(conversationId: string): {
271
+ export function _peekStreamForTesting(): {
196
272
  nextSeq: number;
197
273
  ringLength: number;
198
274
  totalSizeBytes: number;
199
275
  oldestSeq: number | null;
200
276
  newestSeq: number | null;
201
- } | null {
202
- const state = streams.get(conversationId);
203
- if (!state) return null;
277
+ } {
204
278
  return {
205
279
  nextSeq: state.nextSeq,
206
280
  ringLength: state.ring.length,
@@ -276,7 +350,7 @@ function matchesSubscriber(
276
350
  return true;
277
351
  }
278
352
 
279
- function evict(state: ConversationStreamState): void {
353
+ function evict(): void {
280
354
  const now = Date.now();
281
355
  while (state.ring.length > 0) {
282
356
  const head = state.ring[0];
@@ -9,7 +9,7 @@
9
9
  * 3. Consume user decisions and apply them to the underlying session
10
10
  */
11
11
 
12
- import { findConversation } from "../daemon/conversation-store.js";
12
+ import { findConversation } from "../daemon/conversation-registry.js";
13
13
  import type { UserDecision } from "../permissions/types.js";
14
14
  import { composeApprovalMessage } from "./approval-message-composer.js";
15
15
  import type {
@@ -19,7 +19,12 @@ import { httpError } from "./http-errors.js";
19
19
  import { withErrorHandling } from "./middleware/error-handler.js";
20
20
  import { routeDefinitionsToHTTPRoutes } from "./routes/http-adapter.js";
21
21
  import { ROUTES } from "./routes/index.js";
22
- import type { RouteLoggingConfig, RoutePathParam } from "./routes/types.js";
22
+ import type {
23
+ RouteLoggingConfig,
24
+ RoutePathParam,
25
+ RouteRequestBody,
26
+ RouteResponseBody,
27
+ } from "./routes/types.js";
23
28
 
24
29
  // ---------------------------------------------------------------------------
25
30
  // Route definition types
@@ -64,17 +69,6 @@ export interface RouteAdditionalResponse {
64
69
  schema?: RouteBodySchema | Record<string, unknown>;
65
70
  }
66
71
 
67
- /**
68
- * Request-body variant keyed by Content-Type. Use this when an endpoint
69
- * accepts multiple body shapes (e.g. `application/octet-stream` OR
70
- * `application/json`). For the common single-JSON case, use `requestBody`.
71
- */
72
- export interface RouteRequestBodyVariant {
73
- contentType: string;
74
- /** Zod schema or plain JSON Schema fragment. Plain objects are embedded verbatim. */
75
- schema: RouteBodySchema | Record<string, unknown>;
76
- }
77
-
78
72
  /**
79
73
  * A single route entry in the declarative table.
80
74
  *
@@ -110,17 +104,18 @@ export interface HTTPRouteDefinition {
110
104
  tags?: string[];
111
105
  /** Query parameter definitions for the operation. */
112
106
  queryParams?: RouteQueryParam[];
113
- /** Zod schema for the request body (POST/PUT/PATCH/DELETE). */
114
- requestBody?: RouteBodySchema;
115
107
  /**
116
- * Alternate request-body variants keyed by Content-Type. When set,
117
- * overrides `requestBody` in the generated OpenAPI spec use this for
118
- * endpoints that accept multiple body shapes on the same URL (e.g.
119
- * raw bytes OR JSON URL).
108
+ * Request body for POST/PUT/PATCH/DELETE. A bare Zod schema is advertised
109
+ * as `application/json`; use the `{ contentType, schema }` form for non-JSON
110
+ * bodies (e.g. a raw `application/octet-stream` upload).
111
+ */
112
+ requestBody?: RouteRequestBody;
113
+ /**
114
+ * Success response body. A bare Zod schema is advertised as
115
+ * `application/json`; use the `{ contentType, schema }` form for non-JSON
116
+ * responses (e.g. a binary `application/octet-stream` download).
120
117
  */
121
- requestBodies?: RouteRequestBodyVariant[];
122
- /** Zod schema for the success response body. */
123
- responseBody?: RouteBodySchema;
118
+ responseBody?: RouteResponseBody;
124
119
  /**
125
120
  * HTTP status code for the documented success response. Defaults to 200.
126
121
  * Set to "202" for async endpoints that enqueue a job and return
@@ -1,6 +1,10 @@
1
1
  /**
2
2
  * Shared types for the runtime HTTP server and its route handlers.
3
3
  */
4
+ import type {
5
+ ConversationMessage,
6
+ ConversationMessageAttachment,
7
+ } from "../api/responses/conversation-message.js";
4
8
  import type { ChannelId, InterfaceId } from "../channels/types.js";
5
9
  import type { LLMCallSite } from "../config/schemas/llm.js";
6
10
  import type { Conversation } from "../daemon/conversation.js";
@@ -137,74 +141,16 @@ export interface RuntimeHttpServerOptions {
137
141
  hostname?: string;
138
142
  }
139
143
 
140
- export interface RuntimeAttachmentMetadata {
141
- id: string;
142
- filename: string;
143
- mimeType: string;
144
- sizeBytes: number;
145
- kind: string;
146
- data?: string;
147
- thumbnailData?: string;
148
- fileBacked?: boolean;
149
- }
144
+ /**
145
+ * Structured attachment metadata returned on a history row. Canonical wire
146
+ * shape lives in `@vellumai/assistant-api`; aliased here so route modules can
147
+ * keep importing the runtime-local name.
148
+ */
149
+ export type RuntimeAttachmentMetadata = ConversationMessageAttachment;
150
150
 
151
- export interface RuntimeMessagePayload {
152
- id: string;
153
- /**
154
- * Server message ids that were folded into this display row when consecutive
155
- * assistant messages were consolidated for history rendering.
156
- */
157
- mergedMessageIds?: string[];
158
- role: string;
159
- timestamp: string;
160
- attachments: RuntimeAttachmentMetadata[];
161
- toolCalls?: Array<{
162
- name: string;
163
- input: Record<string, unknown>;
164
- result?: string;
165
- isError?: boolean;
166
- riskLevel?: string;
167
- riskReason?: string;
168
- autoApproved?: boolean;
169
- approvalMode?: string;
170
- approvalReason?: string;
171
- riskThreshold?: string;
172
- }>;
173
- surfaces?: Array<{
174
- surfaceId: string;
175
- surfaceType: string;
176
- title?: string;
177
- data: Record<string, unknown>;
178
- actions?: unknown[];
179
- display?: string;
180
- }>;
181
- textSegments?: string[];
182
- thinkingSegments?: string[];
183
- contentOrder?: string[];
184
- subagentNotification?: {
185
- subagentId: string;
186
- label: string;
187
- status: string;
188
- error?: string;
189
- conversationId?: string;
190
- objective?: string;
191
- };
192
- slackMessage?: {
193
- channelId: string;
194
- channelName?: string;
195
- channelTs: string;
196
- threadTs?: string;
197
- sender?: {
198
- displayName?: string;
199
- externalUserId?: string;
200
- };
201
- messageLink?: {
202
- appUrl?: string;
203
- webUrl?: string;
204
- };
205
- threadLink?: {
206
- appUrl?: string;
207
- webUrl?: string;
208
- };
209
- };
210
- }
151
+ /**
152
+ * The daemon's history-row payload. Canonical wire contract lives in
153
+ * `@vellumai/assistant-api` (`responses/conversation-message.ts`) so the
154
+ * producer and every consumer (web, CLI, evals) derive from one source.
155
+ */
156
+ export type RuntimeMessagePayload = ConversationMessage;
@@ -30,7 +30,7 @@
30
30
  * `"timed_out"`.
31
31
  */
32
32
 
33
- import { findConversation } from "../daemon/conversation-store.js";
33
+ import { findConversation } from "../daemon/conversation-registry.js";
34
34
  import { showStandaloneSurface } from "../daemon/conversation-surfaces.js";
35
35
  import { getLogger } from "../util/logger.js";
36
36
  import { mintDecisionToken } from "./decision-token.js";
@@ -38,6 +38,7 @@ export interface ConfirmationDetails {
38
38
  pattern: string;
39
39
  }>;
40
40
  scopeOptions: Array<{ label: string; scope: string }>;
41
+ directoryScopeOptions?: Array<{ label: string; scope: string }>;
41
42
  persistentDecisionsAllowed?: boolean;
42
43
  /** ACP tool kind from the agent (e.g. "read", "edit", "execute"). */
43
44
  acpToolKind?: string;