@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,23 +1,28 @@
1
1
  import { beforeEach, describe, expect, test } from "bun:test";
2
2
 
3
+ import {
4
+ clearConversations,
5
+ setConversation,
6
+ } from "../daemon/conversation-registry.js";
7
+ import type { ChannelCapabilities } from "../daemon/conversation-runtime-assembly.js";
3
8
  import {
4
9
  applyRuntimeInjections,
5
10
  stripInjectionsForCompaction,
6
11
  } from "../daemon/conversation-runtime-assembly.js";
7
12
  import {
8
13
  DEFAULT_INJECTOR_ORDER,
9
- defaultInjectorsPlugin,
14
+ defaultInjectors,
10
15
  DISK_PRESSURE_WARNING_PROMPT,
11
- } from "../plugins/defaults/injectors/register.js";
12
- import {
13
- registerPlugin,
14
- resetPluginRegistryForTests,
15
- } from "../plugins/registry.js";
16
+ } from "../plugins/defaults/memory-retrieval/injectors.js";
16
17
  import type { Injector, TurnContext } from "../plugins/types.js";
17
18
  import type { Message } from "../providers/types.js";
18
19
 
20
+ // `makeContext` and the workspace registry seed share this id so the
21
+ // `workspace-context` injector resolves the seeded block for the turn.
22
+ const TEST_CONVERSATION_ID = "conv-test";
23
+
19
24
  function findInjector(name: string): Injector {
20
- const injector = defaultInjectorsPlugin.injectors?.find(
25
+ const injector = defaultInjectors.find(
21
26
  (candidate) => candidate.name === name,
22
27
  );
23
28
  if (!injector) {
@@ -29,7 +34,7 @@ function findInjector(name: string): Injector {
29
34
  function makeContext(overrides: Partial<TurnContext> = {}): TurnContext {
30
35
  return {
31
36
  requestId: "req-test",
32
- conversationId: "conv-test",
37
+ conversationId: TEST_CONVERSATION_ID,
33
38
  turnIndex: 0,
34
39
  trust: { sourceChannel: "vellum", trustClass: "guardian" },
35
40
  ...overrides,
@@ -47,20 +52,58 @@ function tailTexts(messages: Message[]): string[] {
47
52
  }
48
53
 
49
54
  const diskPressureInjector = findInjector("disk-pressure-warning");
50
- const cleanupContext = { cleanupModeActive: true };
55
+
56
+ // The disk-pressure-warning and workspace-context injectors both read their
57
+ // per-conversation state off the live `Conversation` looked up by
58
+ // `conversationId`. Seed a single fake instance under the id `makeContext()`
59
+ // uses, carrying the disk-pressure flag and the workspace top-level cache, so a
60
+ // turn can exercise both; the seed helpers mutate and re-register the same
61
+ // instance. An empty (non-dirty) workspace cache resolves to no block, so
62
+ // disk-pressure-only tests don't trigger a directory scan.
63
+ let liveConversation: {
64
+ conversationId: string;
65
+ workingDir: string;
66
+ workspaceTopLevelContext: string | null;
67
+ workspaceTopLevelDirty: boolean;
68
+ diskPressureCleanupModeActive: boolean;
69
+ channelCapabilities?: ChannelCapabilities;
70
+ };
71
+
72
+ function resetLiveConversation(): void {
73
+ liveConversation = {
74
+ conversationId: TEST_CONVERSATION_ID,
75
+ workingDir: "/workspace",
76
+ workspaceTopLevelContext: "",
77
+ workspaceTopLevelDirty: false,
78
+ diskPressureCleanupModeActive: false,
79
+ };
80
+ }
81
+
82
+ function seedChannelCapabilities(caps: ChannelCapabilities): void {
83
+ liveConversation.channelCapabilities = caps;
84
+ setConversation(TEST_CONVERSATION_ID, liveConversation as never);
85
+ }
86
+
87
+ function seedDiskPressure(cleanupModeActive: boolean): void {
88
+ liveConversation.diskPressureCleanupModeActive = cleanupModeActive;
89
+ setConversation(TEST_CONVERSATION_ID, liveConversation as never);
90
+ }
91
+
92
+ function seedWorkspaceContext(text: string): void {
93
+ liveConversation.workspaceTopLevelContext = text;
94
+ liveConversation.workspaceTopLevelDirty = false;
95
+ setConversation(TEST_CONVERSATION_ID, liveConversation as never);
96
+ }
51
97
 
52
98
  describe("disk-pressure-warning injector", () => {
53
99
  beforeEach(() => {
54
- resetPluginRegistryForTests();
55
- registerPlugin(defaultInjectorsPlugin);
100
+ clearConversations();
101
+ resetLiveConversation();
56
102
  });
57
103
 
58
104
  test("emits the exact cleanup prompt during disk pressure cleanup mode", async () => {
59
- const block = await diskPressureInjector.produce(
60
- makeContext({
61
- injectionInputs: { diskPressureContext: cleanupContext },
62
- }),
63
- );
105
+ seedDiskPressure(true);
106
+ const block = await diskPressureInjector.produce(makeContext());
64
107
 
65
108
  expect(block).toEqual({
66
109
  id: "disk-pressure-warning",
@@ -81,21 +124,14 @@ Do not work on unrelated tasks until enough space is freed to clear the lock or
81
124
  </disk_pressure_warning>`);
82
125
  });
83
126
 
84
- test("omits the prompt when cleanup context is null or inactive", async () => {
127
+ test("omits the prompt when no cleanup context is registered or it is inactive", async () => {
85
128
  await expect(
86
- diskPressureInjector.produce(
87
- makeContext({ injectionInputs: { diskPressureContext: null } }),
88
- ),
129
+ diskPressureInjector.produce(makeContext()),
89
130
  ).resolves.toBeNull();
90
131
 
132
+ seedDiskPressure(false);
91
133
  await expect(
92
- diskPressureInjector.produce(
93
- makeContext({
94
- injectionInputs: {
95
- diskPressureContext: { cleanupModeActive: false },
96
- },
97
- }),
98
- ),
134
+ diskPressureInjector.produce(makeContext()),
99
135
  ).resolves.toBeNull();
100
136
  });
101
137
 
@@ -106,10 +142,10 @@ Do not work on unrelated tasks until enough space is freed to clear the lock or
106
142
  const workspace = "<workspace>\nRoot: /workspace\n</workspace>";
107
143
  const turnContext = "<turn_context>\ninterface: macos\n</turn_context>";
108
144
 
145
+ seedWorkspaceContext(workspace);
146
+ seedDiskPressure(true);
109
147
  const result = await applyRuntimeInjections(runMessages, {
110
148
  turnContext: makeContext(),
111
- diskPressureContext: cleanupContext,
112
- workspaceTopLevelContext: workspace,
113
149
  unifiedTurnContext: turnContext,
114
150
  });
115
151
 
@@ -127,13 +163,12 @@ Do not work on unrelated tasks until enough space is freed to clear the lock or
127
163
  });
128
164
 
129
165
  test("survives minimal mode as safety-critical context", async () => {
166
+ seedDiskPressure(true);
130
167
  const result = await applyRuntimeInjections(
131
168
  [{ role: "user", content: [{ type: "text", text: "status" }] }],
132
169
  {
133
170
  turnContext: makeContext(),
134
171
  mode: "minimal",
135
- diskPressureContext: cleanupContext,
136
- workspaceTopLevelContext: "<workspace>...</workspace>",
137
172
  unifiedTurnContext: "<turn_context>...</turn_context>",
138
173
  },
139
174
  );
@@ -163,16 +198,16 @@ Do not work on unrelated tasks until enough space is freed to clear the lock or
163
198
  },
164
199
  ];
165
200
 
201
+ seedDiskPressure(true);
202
+ seedChannelCapabilities({
203
+ channel: "slack",
204
+ dashboardCapable: false,
205
+ supportsDynamicUi: false,
206
+ supportsVoiceInput: false,
207
+ chatType: "channel",
208
+ });
166
209
  const result = await applyRuntimeInjections(originalRun, {
167
210
  turnContext: makeContext(),
168
- diskPressureContext: cleanupContext,
169
- channelCapabilities: {
170
- channel: "slack",
171
- dashboardCapable: false,
172
- supportsDynamicUi: false,
173
- supportsVoiceInput: false,
174
- chatType: "channel",
175
- },
176
211
  slackChronologicalMessages: slackTranscript,
177
212
  });
178
213
 
@@ -190,16 +225,15 @@ Do not work on unrelated tasks until enough space is freed to clear the lock or
190
225
  { role: "user", content: [{ type: "text", text: "find large files" }] },
191
226
  ];
192
227
 
228
+ seedDiskPressure(true);
193
229
  const first = await applyRuntimeInjections(runMessages, {
194
230
  turnContext: makeContext(),
195
- diskPressureContext: cleanupContext,
196
231
  });
197
232
  const stripped = stripInjectionsForCompaction(first.messages);
198
233
  expect(tailTexts(stripped)).toEqual(["find large files"]);
199
234
 
200
235
  const second = await applyRuntimeInjections(stripped, {
201
236
  turnContext: makeContext(),
202
- diskPressureContext: cleanupContext,
203
237
  });
204
238
  expect(
205
239
  tailTexts(second.messages).filter(
@@ -8,12 +8,12 @@ mock.module("../documents/document-comments-store.js", () => ({
8
8
  listComments: (...args: unknown[]) => listCommentsMock(...args),
9
9
  }));
10
10
 
11
- const { DEFAULT_INJECTOR_ORDER, defaultInjectorsPlugin } =
12
- await import("../plugins/defaults/injectors/register.js");
11
+ const { DEFAULT_INJECTOR_ORDER, defaultInjectors } =
12
+ await import("../plugins/defaults/memory-retrieval/injectors.js");
13
13
  import type { Injector, TurnContext } from "../plugins/types.js";
14
14
 
15
15
  function findInjector(name: string): Injector {
16
- const injector = defaultInjectorsPlugin.injectors?.find(
16
+ const injector = defaultInjectors.find(
17
17
  (candidate) => candidate.name === name,
18
18
  );
19
19
  if (!injector) {
@@ -12,7 +12,9 @@
12
12
  * search so the reminder-with-hints branch can resolve deterministically
13
13
  * when called.
14
14
  */
15
- import { beforeEach, describe, expect, mock, test } from "bun:test";
15
+ import { mkdirSync, rmSync, writeFileSync } from "node:fs";
16
+ import { dirname, join } from "node:path";
17
+ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
16
18
 
17
19
  let v2Active = false;
18
20
 
@@ -20,7 +22,12 @@ const realLoader = await import("../config/loader.js");
20
22
 
21
23
  mock.module("../config/loader.js", () => ({
22
24
  ...realLoader,
23
- getConfig: () => ({ memory: { v2: { enabled: v2Active } } }),
25
+ getConfig: () => ({
26
+ memory: {
27
+ v2: { enabled: v2Active },
28
+ retrieval: { scratchpadInjection: { enabled: true } },
29
+ },
30
+ }),
24
31
  }));
25
32
 
26
33
  mock.module("../memory/pkb/pkb-search.js", () => ({
@@ -29,12 +36,10 @@ mock.module("../memory/pkb/pkb-search.js", () => ({
29
36
 
30
37
  const { applyRuntimeInjections } =
31
38
  await import("../daemon/conversation-runtime-assembly.js");
32
- const { defaultInjectorsPlugin } =
33
- await import("../plugins/defaults/injectors/register.js");
34
- const { registerPlugin, resetPluginRegistryForTests } =
35
- await import("../plugins/registry.js");
39
+ import { getPkbRoot } from "../memory/pkb/types.js";
36
40
  import type { TurnContext } from "../plugins/types.js";
37
41
  import type { Message } from "../providers/types.js";
42
+ import { getWorkspacePromptPath } from "../util/platform.js";
38
43
 
39
44
  function makeTurnContext(): TurnContext {
40
45
  return {
@@ -55,28 +60,37 @@ function tailTexts(messages: Message[]): string[] {
55
60
  .map((b) => b.text);
56
61
  }
57
62
 
58
- const PKB_CONTEXT = "essentials of the project";
59
- const NOW_CONTENT = "Current focus: shipping G2.1";
60
63
  const RUN_MESSAGES: Message[] = [
61
64
  { role: "user", content: [{ type: "text", text: "What next?" }] },
62
65
  ];
63
66
 
64
67
  describe("PKB injector v2 cutover behavior", () => {
68
+ // The pkb-reminder gate derives PKB-active state from the workspace
69
+ // (`readPkbContext()` returning content) behind the guardian trust on
70
+ // `makeTurnContext()`, so seed a default auto-injected PKB file rather than
71
+ // passing a flag.
65
72
  beforeEach(() => {
66
- resetPluginRegistryForTests();
67
- registerPlugin(defaultInjectorsPlugin);
68
73
  v2Active = false;
74
+ mkdirSync(getPkbRoot(), { recursive: true });
75
+ writeFileSync(
76
+ join(getPkbRoot(), "INDEX.md"),
77
+ "workspace knowledge index",
78
+ "utf-8",
79
+ );
80
+ // now-md sources NOW.md from the workspace behind the same guardian trust,
81
+ // so seed the file rather than passing a flag.
82
+ const nowPath = getWorkspacePromptPath("NOW.md");
83
+ mkdirSync(dirname(nowPath), { recursive: true });
84
+ writeFileSync(nowPath, "Current focus: shipping G2.1", "utf-8");
85
+ });
86
+ afterEach(() => {
87
+ rmSync(getPkbRoot(), { recursive: true, force: true });
88
+ rmSync(getWorkspacePromptPath("NOW.md"), { force: true });
69
89
  });
70
90
 
71
91
  test("v2 inactive → pkb-context, pkb-reminder, and now-md all produce blocks", async () => {
72
92
  const result = await applyRuntimeInjections(RUN_MESSAGES, {
73
93
  turnContext: makeTurnContext(),
74
- pkbContext: PKB_CONTEXT,
75
- pkbActive: true,
76
- pkbScopeId: "scope-default",
77
- pkbRoot: "/tmp/pkb",
78
- pkbConversation: { messages: [] },
79
- nowScratchpad: NOW_CONTENT,
80
94
  });
81
95
 
82
96
  const texts = tailTexts(result.messages);
@@ -89,12 +103,6 @@ describe("PKB injector v2 cutover behavior", () => {
89
103
  v2Active = true;
90
104
  const result = await applyRuntimeInjections(RUN_MESSAGES, {
91
105
  turnContext: makeTurnContext(),
92
- pkbContext: PKB_CONTEXT,
93
- pkbActive: true,
94
- pkbScopeId: "scope-default",
95
- pkbRoot: "/tmp/pkb",
96
- pkbConversation: { messages: [] },
97
- nowScratchpad: NOW_CONTENT,
98
106
  });
99
107
 
100
108
  const texts = tailTexts(result.messages);
@@ -1,34 +1,38 @@
1
1
  /**
2
2
  * Tests for the memory-v3-live v2-suppression branch in
3
- * `applyRuntimeInjections` (PR L6 of the memory-v3-live plan).
3
+ * `applyRuntimeInjections`.
4
4
  *
5
- * When `suppressV2MemoryForV3` is on AND the v3 injector (id `memory-v3`,
5
+ * When the `memory-v3-live` flag is on AND the v3 injector (id `memory-v3`,
6
6
  * placement `after-memory-prefix`) actually produces a block, runtime
7
7
  * assembly strips the v2 `<memory>` prefix from EVERY user message before
8
8
  * splicing the v3 block — so v3 becomes the sole `<memory>` source and history
9
9
  * is byte-stable for prompt caching.
10
10
  *
11
- * Keyed off whether v3 produced a block, NOT off the option alone: a v3
11
+ * Keyed off whether v3 produced a block, NOT off the flag alone: a v3
12
12
  * failure (`produce()` → null) leaves v2's block intact (fallback-to-v2).
13
13
  *
14
14
  * The flag-off path must be byte-for-byte identical to today — that is the
15
- * load-bearing regression guard.
15
+ * load-bearing regression guard. `applyRuntimeInjections` reads the flag
16
+ * itself, so these tests drive it through the override cache.
16
17
  */
17
18
 
18
- import { beforeEach, describe, expect, test } from "bun:test";
19
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
19
20
 
20
- import {
21
- getInjectors,
22
- registerPlugin,
23
- resetPluginRegistryForTests,
24
- } from "../plugins/registry.js";
25
21
  import type {
26
22
  InjectionBlock,
27
23
  Injector,
28
- Plugin,
29
24
  TurnContext,
30
25
  } from "../plugins/types.js";
31
26
  import type { Message } from "../providers/types.js";
27
+ import { setOverridesForTesting } from "./feature-flag-test-helpers.js";
28
+
29
+ // Drive the suppression branch by controlling the static injector chain that
30
+ // `applyRuntimeInjections` walks. The slot is mutated per-test to stand in for
31
+ // the memory-v3 injector producing (or not producing) a block.
32
+ const injectorChainSlot: Injector[] = [];
33
+ mock.module("../plugins/defaults/memory-retrieval/injector-chain.js", () => ({
34
+ getInjectorChain: () => injectorChainSlot,
35
+ }));
32
36
 
33
37
  const { applyRuntimeInjections } =
34
38
  await import("../daemon/conversation-runtime-assembly.js");
@@ -42,10 +46,6 @@ function makeTurnContext(): TurnContext {
42
46
  };
43
47
  }
44
48
 
45
- function wrapInPlugin(name: string, injectors: Injector[]): Plugin {
46
- return { manifest: { name, version: "0.0.1" }, injectors };
47
- }
48
-
49
49
  /**
50
50
  * A fake v3 injector that mirrors the real one's id + placement. The real
51
51
  * injector's `renderMemoryBlock` already wraps its content in
@@ -88,11 +88,15 @@ function tailTexts(messages: Message[]): string[] {
88
88
 
89
89
  describe("memory-v3-live v2 suppression", () => {
90
90
  beforeEach(() => {
91
- resetPluginRegistryForTests();
91
+ injectorChainSlot.length = 0;
92
+ // Clean baseline: no overrides → `memory-v3-live` resolves to its registry
93
+ // default (off). Each test seeds the flag it needs.
94
+ setOverridesForTesting({});
92
95
  });
93
96
 
94
97
  test("flag ON + v3 produced a block → v2 stripped from all turns, exactly one <memory> (the v3 block)", async () => {
95
- registerPlugin(wrapInPlugin("v3", [v3Injector("v3 working set")]));
98
+ setOverridesForTesting({ "memory-v3-live": true });
99
+ injectorChainSlot.push(v3Injector("v3 working set"));
96
100
 
97
101
  // History: a prior user turn that still carries a v2 block (rehydrated),
98
102
  // plus the current tail user turn with its own v2 block.
@@ -107,7 +111,6 @@ describe("memory-v3-live v2 suppression", () => {
107
111
 
108
112
  const result = await applyRuntimeInjections(runMessages, {
109
113
  turnContext: makeTurnContext(),
110
- suppressV2MemoryForV3: true,
111
114
  });
112
115
 
113
116
  // Exactly one <memory> source across the WHOLE assembled context.
@@ -138,7 +141,8 @@ describe("memory-v3-live v2 suppression", () => {
138
141
  });
139
142
 
140
143
  test("flag ON but v3 produced NOTHING → v2 block left intact (fallback-to-v2)", async () => {
141
- registerPlugin(wrapInPlugin("v3", [v3Injector(null)]));
144
+ setOverridesForTesting({ "memory-v3-live": true });
145
+ injectorChainSlot.push(v3Injector(null));
142
146
 
143
147
  const runMessages: Message[] = [
144
148
  userMsgWithV2Memory("fresh recalled fact", "current question"),
@@ -146,7 +150,6 @@ describe("memory-v3-live v2 suppression", () => {
146
150
 
147
151
  const result = await applyRuntimeInjections(runMessages, {
148
152
  turnContext: makeTurnContext(),
149
- suppressV2MemoryForV3: true,
150
153
  });
151
154
 
152
155
  // v2's block survives — the turn still ships memory.
@@ -158,7 +161,7 @@ describe("memory-v3-live v2 suppression", () => {
158
161
  });
159
162
 
160
163
  test("flag OFF → byte-for-byte identical to today even when v3 would have produced a block", async () => {
161
- registerPlugin(wrapInPlugin("v3", [v3Injector("v3 working set")]));
164
+ injectorChainSlot.push(v3Injector("v3 working set"));
162
165
 
163
166
  const runMessages: Message[] = [
164
167
  userMsgWithV2Memory("old recalled fact", "earlier question"),
@@ -169,16 +172,16 @@ describe("memory-v3-live v2 suppression", () => {
169
172
  userMsgWithV2Memory("fresh recalled fact", "current question"),
170
173
  ];
171
174
 
172
- // With suppression off, the v3 injector still runs through the chain
173
- // (after-memory-prefix), but NO v2 stripping happens. This captures the
174
- // exact pre-flag assembly behavior: v2 prefix stays, v3 splices after it.
175
+ // With the flag off (registry default), the v3 injector still runs through
176
+ // the chain (after-memory-prefix), but NO v2 stripping happens. This
177
+ // captures the exact pre-flag assembly behavior: v2 prefix stays, v3
178
+ // splices after it.
175
179
  const offResult = await applyRuntimeInjections(runMessages, {
176
180
  turnContext: makeTurnContext(),
177
- suppressV2MemoryForV3: false,
178
181
  });
179
182
 
180
183
  // The tail keeps v2's block AND gains v3's (the historical double-injection
181
- // the suppression PR exists to prevent) — proving suppression is the ONLY
184
+ // the suppression exists to prevent) — proving suppression is the ONLY
182
185
  // behavior change and it is fully gated off here.
183
186
  const texts = tailTexts(offResult.messages);
184
187
  expect(texts[0]).toBe("<memory>\nfresh recalled fact\n</memory>");
@@ -190,21 +193,13 @@ describe("memory-v3-live v2 suppression", () => {
190
193
  .filter((b): b is { type: "text"; text: string } => b.type === "text")
191
194
  .map((b) => b.text);
192
195
  expect(firstUserTexts[0]).toBe("<memory>\nold recalled fact\n</memory>");
193
-
194
- // Strongest guard: omitting the option entirely yields the SAME result as
195
- // passing it false — the default path is untouched by this PR.
196
- resetPluginRegistryForTests();
197
- registerPlugin(wrapInPlugin("v3", [v3Injector("v3 working set")]));
198
- const defaultResult = await applyRuntimeInjections(runMessages, {
199
- turnContext: makeTurnContext(),
200
- });
201
- expect(defaultResult.messages).toEqual(offResult.messages);
202
196
  });
203
197
 
204
198
  test("no v3 injector registered + flag ON → no stripping, messages untouched", async () => {
205
199
  // No injector named memory-v3 at all (e.g. plugin not loaded): the
206
200
  // suppression branch keys off the produced block, so nothing is stripped.
207
- expect(getInjectors()).toHaveLength(0);
201
+ setOverridesForTesting({ "memory-v3-live": true });
202
+ expect(injectorChainSlot).toHaveLength(0);
208
203
 
209
204
  const runMessages: Message[] = [
210
205
  userMsgWithV2Memory("fresh recalled fact", "current question"),
@@ -212,7 +207,6 @@ describe("memory-v3-live v2 suppression", () => {
212
207
 
213
208
  const result = await applyRuntimeInjections(runMessages, {
214
209
  turnContext: makeTurnContext(),
215
- suppressV2MemoryForV3: true,
216
210
  });
217
211
 
218
212
  expect(result.messages).toEqual(runMessages);
@@ -0,0 +1,109 @@
1
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
2
+
3
+ mock.module("../util/logger.js", () => ({
4
+ getLogger: () =>
5
+ new Proxy({} as Record<string, unknown>, {
6
+ get: () => () => {},
7
+ }),
8
+ }));
9
+
10
+ // Toggle for the collectUsageData opt-out the real store consults. The store
11
+ // module is intentionally NOT mocked here — it has its own DB-backed tests, and
12
+ // Bun's `mock.module` is process-global, so mocking it would leak into those
13
+ // tests when files share an invocation. Exercising the real store keeps every
14
+ // auth-fallback test order-independent.
15
+ let collectUsageData = true;
16
+
17
+ mock.module("../config/loader.js", () => ({
18
+ getConfig: () => ({
19
+ ui: {},
20
+ model: "test",
21
+ provider: "test",
22
+ memory: { enabled: false },
23
+ rateLimit: { maxRequestsPerMinute: 0 },
24
+ secretDetection: { enabled: false },
25
+ collectUsageData,
26
+ }),
27
+ }));
28
+
29
+ import { queryUnreportedAuthFallbackEvents } from "../memory/auth-fallback-events-store.js";
30
+ import { getDb } from "../memory/db-connection.js";
31
+ import { initializeDb } from "../memory/db-init.js";
32
+ import { authFallbackEvents } from "../memory/schema.js";
33
+ import { GATEWAY_PRINCIPALS } from "../runtime/auth/route-policy.js";
34
+ import { RouteError } from "../runtime/routes/errors.js";
35
+ import { ROUTES } from "../runtime/routes/internal-telemetry-routes.js";
36
+ import type { RouteHandlerArgs } from "../runtime/routes/types.js";
37
+
38
+ initializeDb();
39
+
40
+ const route = ROUTES.find(
41
+ (r) => r.operationId === "internal_telemetry_auth_fallback",
42
+ );
43
+
44
+ function call(body: unknown) {
45
+ if (!route) throw new Error("route not found");
46
+ return route.handler({ body } as RouteHandlerArgs);
47
+ }
48
+
49
+ const VALID_BODY = {
50
+ window_start: 1000,
51
+ window_end: 2000,
52
+ counts: [
53
+ {
54
+ guard: "edge",
55
+ path: "/v1/messages",
56
+ failure_kind: "missing_authorization",
57
+ count: 5,
58
+ },
59
+ ],
60
+ };
61
+
62
+ describe("internal-telemetry-routes: auth-fallback", () => {
63
+ beforeEach(() => {
64
+ collectUsageData = true;
65
+ getDb().delete(authFallbackEvents).run();
66
+ });
67
+
68
+ test("route is locked to service-token callers (GATEWAY_PRINCIPALS + internal.write)", () => {
69
+ expect(route).toBeDefined();
70
+ expect(route?.endpoint).toBe("internal/telemetry/auth-fallback");
71
+ expect(route?.method).toBe("POST");
72
+ expect(route?.policy?.allowedPrincipalTypes).toEqual(GATEWAY_PRINCIPALS);
73
+ expect(route?.policy?.requiredScopes).toEqual(["internal.write"]);
74
+ });
75
+
76
+ test("valid batch is persisted with snake_case → camelCase mapping", () => {
77
+ const result = call(VALID_BODY);
78
+ expect(result).toEqual({ recorded: 1 });
79
+
80
+ const rows = queryUnreportedAuthFallbackEvents(0, undefined, 100);
81
+ expect(rows.length).toBe(1);
82
+ expect(rows[0]).toMatchObject({
83
+ guard: "edge",
84
+ path: "/v1/messages",
85
+ failureKind: "missing_authorization",
86
+ count: 5,
87
+ windowStart: 1000,
88
+ windowEnd: 2000,
89
+ });
90
+ });
91
+
92
+ test("returns skipped and persists nothing under the opt-out", () => {
93
+ collectUsageData = false;
94
+ expect(call(VALID_BODY)).toEqual({ skipped: true });
95
+ expect(queryUnreportedAuthFallbackEvents(0, undefined, 100).length).toBe(0);
96
+ });
97
+
98
+ test("rejects a malformed body without persisting", () => {
99
+ expect(() => call({ window_start: 1000 })).toThrow(RouteError);
100
+ expect(() => call({ ...VALID_BODY, counts: [] })).toThrow(RouteError);
101
+ expect(() =>
102
+ call({
103
+ ...VALID_BODY,
104
+ counts: [{ guard: "edge", path: "/x", failure_kind: "y", count: 0 }],
105
+ }),
106
+ ).toThrow(RouteError);
107
+ expect(queryUnreportedAuthFallbackEvents(0, undefined, 100).length).toBe(0);
108
+ });
109
+ });
@@ -96,6 +96,44 @@ describe("handleListMessages metadata.hidden filtering", () => {
96
96
  expect(llmRows[1].metadata).toContain('"hidden":true');
97
97
  });
98
98
 
99
+ test("UI serializer omits system rows but LLM-side getMessages includes them", async () => {
100
+ // GIVEN a conversation with a system row sandwiched between two
101
+ // renderable turns (e.g. a skill-authored context message)
102
+ const conv = createConversation();
103
+ await addMessage(
104
+ conv.id,
105
+ "user",
106
+ JSON.stringify([{ type: "text", text: "first visible" }]),
107
+ );
108
+ await addMessage(
109
+ conv.id,
110
+ "system",
111
+ JSON.stringify([{ type: "text", text: "system scaffolding" }]),
112
+ );
113
+ await addMessage(
114
+ conv.id,
115
+ "assistant",
116
+ JSON.stringify([{ type: "text", text: "second visible" }]),
117
+ );
118
+
119
+ // WHEN the UI history list is serialized
120
+ const response = handleListMessages({
121
+ queryParams: { conversationId: conv.id },
122
+ });
123
+ const body = response as { messages: MessagePayload[] };
124
+
125
+ // THEN only the user/assistant turns are returned, never the system row
126
+ expect(body.messages.map((m) => m.role)).toEqual(["user", "assistant"]);
127
+ expect(
128
+ body.messages.some((m) => plainText(m).includes("system scaffolding")),
129
+ ).toBe(false);
130
+
131
+ // AND the LLM-side loader still includes the system row for agent context
132
+ const llmRows = getMessages(conv.id);
133
+ expect(llmRows).toHaveLength(3);
134
+ expect(llmRows[1].role).toBe("system");
135
+ });
136
+
99
137
  test("messages without metadata or with hidden=false are returned", async () => {
100
138
  const conv = createConversation();
101
139
  await addMessage(