@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
@@ -22,8 +22,8 @@ import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
22
22
 
23
23
  import { drizzle } from "drizzle-orm/bun-sqlite";
24
24
 
25
- import { migrateAddMemoryV3Selections } from "../../migrations/268-add-memory-v3-selections.js";
26
- import * as schema from "../../schema.js";
25
+ import { migrateAddMemoryV3Selections } from "../../../../memory/migrations/268-add-memory-v3-selections.js";
26
+ import * as schema from "../../../../memory/schema.js";
27
27
  import type { LeafTree, SelectionSource } from "../types.js";
28
28
 
29
29
  // `mock.module` is process-global and, in Bun, neither `mock.restore()` nor a
@@ -41,10 +41,10 @@ const realTree = { ...(await import("../tree.js")) };
41
41
  const realCore = { ...(await import("../core.js")) };
42
42
  const realNeedle = { ...(await import("../needle.js")) };
43
43
  const realOrchestrate = { ...(await import("../orchestrate.js")) };
44
- const realPlatform = { ...(await import("../../../util/platform.js")) };
45
- const realPageStore = { ...(await import("../../v2/page-store.js")) };
44
+ const realPlatform = { ...(await import("../../../../util/platform.js")) };
45
+ const realPageStore = { ...(await import("../../../../memory/v2/page-store.js")) };
46
46
  const realConversationCrud = {
47
- ...(await import("../../conversation-crud.js")),
47
+ ...(await import("../../../../memory/conversation-crud.js")),
48
48
  };
49
49
 
50
50
  let shadowMockActive = false;
@@ -68,6 +68,7 @@ const orchestrateSpy = mock(async () => ({
68
68
  let treeLoads = 0;
69
69
  let coreLoads = 0;
70
70
  let needleBuilds = 0;
71
+ let configL2Concurrency = 16;
71
72
 
72
73
  // Shared in-memory DB so writes are observable from the test. We hold the raw
73
74
  // sqlite handle alongside the drizzle wrapper so the test can both read rows
@@ -94,7 +95,7 @@ const FAKE_TREE = {
94
95
 
95
96
  // ─── module mocks (installed before the plugin import) ──────────────────────
96
97
 
97
- mock.module("../../../config/assistant-feature-flags.js", () => ({
98
+ mock.module("../../../../config/assistant-feature-flags.js", () => ({
98
99
  isAssistantFeatureFlagEnabled: (key: string) =>
99
100
  key === "memory-v3-live"
100
101
  ? liveEnabled
@@ -103,9 +104,14 @@ mock.module("../../../config/assistant-feature-flags.js", () => ({
103
104
  : false,
104
105
  }));
105
106
 
106
- mock.module("../../../config/loader.js", () => ({
107
+ mock.module("../../../../config/loader.js", () => ({
107
108
  getConfig: () => ({
108
- memory: { v3: { workingSet: { maxPages: 150, evictWindow: 5 } } },
109
+ memory: {
110
+ v3: {
111
+ workingSet: { maxPages: 150, evictWindow: 5 },
112
+ l2Concurrency: configL2Concurrency,
113
+ },
114
+ },
109
115
  }),
110
116
  }));
111
117
 
@@ -113,12 +119,12 @@ mock.module("../../../config/loader.js", () => ({
113
119
  // (e.g. `getMessageById` via page-content.ts) stays present — replacing the
114
120
  // whole module with a bare `{ getMessages }` made those consumers fail to load.
115
121
  // Only `getMessages` is overridden, since that's the one the plugin reads.
116
- mock.module("../../conversation-crud.js", () => ({
122
+ mock.module("../../../../memory/conversation-crud.js", () => ({
117
123
  ...realConversationCrud,
118
124
  getMessages: () => messages.map((m, i) => ({ ...m, id: `m${i}` })),
119
125
  }));
120
126
 
121
- mock.module("../../db-connection.js", () => ({
127
+ mock.module("../../../../memory/db-connection.js", () => ({
122
128
  getDb: () => testDb,
123
129
  getSqliteFrom: () => testSqlite,
124
130
  }));
@@ -130,7 +136,7 @@ mock.module("../v2/page-index.js", () => ({
130
136
  // `pageContent` (live mode) reads the full page via `readPage`/`renderPageContent`.
131
137
  // Stub them to return a deterministic body per slug so the rendered `<memory>`
132
138
  // block is assertable without touching the filesystem.
133
- mock.module("../../v2/page-store.js", () => ({
139
+ mock.module("../../../../memory/v2/page-store.js", () => ({
134
140
  ...realPageStore,
135
141
  readPage: async (workspaceDir: string, slug: string) =>
136
142
  shadowMockActive
@@ -144,7 +150,7 @@ mock.module("../../v2/page-store.js", () => ({
144
150
  ),
145
151
  }));
146
152
 
147
- mock.module("../../../util/platform.js", () => ({
153
+ mock.module("../../../../util/platform.js", () => ({
148
154
  ...realPlatform,
149
155
  getWorkspaceDir: () =>
150
156
  shadowMockActive
@@ -203,8 +209,8 @@ const {
203
209
  runShadowObservation,
204
210
  resetShadowLanesForTests,
205
211
  invalidateLanes,
206
- memoryV3ShadowPlugin,
207
212
  } = await import("../shadow-plugin.js");
213
+ const { memoryV3Injector } = await import("../injector.js");
208
214
 
209
215
  // The module stubs above stay installed for the rest of the process (Bun can't
210
216
  // reliably uninstall them), but `shadowMockActive` gates their fake behavior to
@@ -235,14 +241,14 @@ beforeEach(() => {
235
241
  treeLoads = 0;
236
242
  coreLoads = 0;
237
243
  needleBuilds = 0;
244
+ configL2Concurrency = 16;
238
245
  testDb = makeDb();
239
246
  resetShadowLanesForTests();
240
247
  });
241
248
 
242
- /** Invoke the plugin's single injector's `produce()` for a turn. */
249
+ /** Invoke the memory-v3 injector's `produce()` for a turn. */
243
250
  function produce(conversationId: string, turnIndex: number) {
244
- const injector = memoryV3ShadowPlugin.injectors![0]!;
245
- return injector.produce({
251
+ return memoryV3Injector.produce({
246
252
  requestId: "r1",
247
253
  conversationId,
248
254
  turnIndex,
@@ -289,6 +295,18 @@ describe("memory-v3 shadow plugin", () => {
289
295
  expect(turn.currentMessage).toBe("hello world");
290
296
  });
291
297
 
298
+ test("orchestrate receives the configured L2 concurrency", async () => {
299
+ shadowEnabled = true;
300
+ configL2Concurrency = 9;
301
+ await runShadowObservation("conv-1", 0);
302
+ const deps = (
303
+ orchestrateSpy.mock.calls as unknown as unknown[][]
304
+ )[0]![1] as {
305
+ l2Concurrency?: number;
306
+ };
307
+ expect(deps.l2Concurrency).toBe(9);
308
+ });
309
+
292
310
  test("both flags OFF → produce returns null, no orchestrate, no writes", async () => {
293
311
  liveEnabled = false;
294
312
  shadowEnabled = false;
@@ -18,15 +18,15 @@
18
18
  * omitted, resolves the `memoryV3RouteL1` callsite provider.
19
19
  */
20
20
 
21
+ import { listPages, readPage, writePage } from "../../../memory/v2/page-store.js";
22
+ import type { ConceptPage } from "../../../memory/v2/types.js";
21
23
  import {
22
24
  extractToolUse,
23
25
  getConfiguredProvider,
24
26
  userMessage,
25
- } from "../../providers/provider-send-message.js";
26
- import type { Provider, ToolDefinition } from "../../providers/types.js";
27
- import { getLogger } from "../../util/logger.js";
28
- import { listPages, readPage, writePage } from "../v2/page-store.js";
29
- import type { ConceptPage } from "../v2/types.js";
27
+ } from "../../../providers/provider-send-message.js";
28
+ import type { Provider, ToolDefinition } from "../../../providers/types.js";
29
+ import { getLogger } from "../../../util/logger.js";
30
30
  import type { LeafPath, LeafTree, Slug } from "./types.js";
31
31
 
32
32
  const log = getLogger("memory-v3-assign");
@@ -28,8 +28,8 @@
28
28
  import {
29
29
  getCliCommandCapability,
30
30
  isCliCommandSlug,
31
- } from "../v2/cli-command-store.js";
32
- import { getSkillCapability, isSkillSlug } from "../v2/skill-store.js";
31
+ } from "../../../memory/v2/cli-command-store.js";
32
+ import { getSkillCapability, isSkillSlug } from "../../../memory/v2/skill-store.js";
33
33
  import type { LeafNode, LeafPath, LeafTree, Slug } from "./types.js";
34
34
 
35
35
  /** Path of the always-on synthetic leaf that owns skill + CLI capability rows. */
@@ -0,0 +1,14 @@
1
+ /**
2
+ * No-op `post-compact` scaffolding for the memory-v3-shadow plugin.
3
+ *
4
+ * v3 re-injection after mid-turn compaction is not yet owned by this plugin —
5
+ * the active injector still runs through the static chain. Once the
6
+ * post-compaction hook API stabilizes we will import `memoryV3Injector` from
7
+ * `../injector.js` and re-apply it here. Until then this hook does nothing.
8
+ */
9
+
10
+ import type { PluginHookFn } from "@vellumai/plugin-api";
11
+
12
+ const postCompact: PluginHookFn = async () => {};
13
+
14
+ export default postCompact;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * No-op `user-prompt-submit` scaffolding for the memory-v3-shadow plugin.
3
+ *
4
+ * The v3 injector currently runs through the static injector chain
5
+ * (`memory-retrieval/injector-chain.ts`), not through this hook. Once the
6
+ * prompt-submit hook API stabilizes we will import `memoryV3Injector` from
7
+ * `../injector.js` and run it here, so v3 injection is owned by the plugin's
8
+ * own lifecycle rather than the loop-driven chain. Until then this hook
9
+ * intentionally does nothing.
10
+ */
11
+
12
+ import type {
13
+ PluginHookFn,
14
+ UserPromptSubmitContext,
15
+ } from "@vellumai/plugin-api";
16
+
17
+ const userPromptSubmit: PluginHookFn<UserPromptSubmitContext> = async () => {};
18
+
19
+ export default userPromptSubmit;
@@ -0,0 +1,75 @@
1
+ /**
2
+ * The memory-v3 {@link Injector}. Reads both v3 flags:
3
+ * - `memory-v3-live` on → orchestrate, log, render the working-set selection
4
+ * into a `<memory>` block, and return it at v2's dynamic-memory placement.
5
+ * - `memory-v3-shadow` on (live off) → orchestrate + log only, return `null`.
6
+ * - both off → return `null` (no orchestration).
7
+ *
8
+ * Empty selection and any failure return `null` (no v3 injection). v2
9
+ * suppression keys off BOTH the flag AND this return value, so a `null` here
10
+ * (failure or empty selection) falls back to v2 memory rather than dropping all
11
+ * memory.
12
+ *
13
+ * Orchestration and telemetry live in {@link observeTurn}; this module is the
14
+ * thin injector wrapper that renders the result for live injection.
15
+ */
16
+
17
+ import { isAssistantFeatureFlagEnabled } from "../../../config/assistant-feature-flags.js";
18
+ import { getConfig } from "../../../config/loader.js";
19
+ import { getLogger } from "../../../util/logger.js";
20
+ import {
21
+ type InjectionBlock,
22
+ type Injector,
23
+ type TurnContext as PluginTurnContext,
24
+ } from "../../types.js";
25
+ import { renderV3PageContent } from "./page-content.js";
26
+ import { renderMemoryBlock } from "./render-injection.js";
27
+ import {
28
+ MEMORY_V3_LIVE,
29
+ MEMORY_V3_SHADOW,
30
+ observeTurn,
31
+ } from "./shadow-plugin.js";
32
+ import { MEMORY_V3_BLOCK_ID } from "./types.js";
33
+
34
+ const log = getLogger("memory-v3-shadow");
35
+
36
+ export const memoryV3Injector: Injector = {
37
+ name: "memory-v3-shadow",
38
+ // High order so it sorts last; the live `<memory>` block uses the
39
+ // after-memory-prefix placement so it lands at the memory boundary regardless
40
+ // of this sort key, which only orders content-producing injectors.
41
+ order: 1000,
42
+ async produce(ctx: PluginTurnContext): Promise<InjectionBlock | null> {
43
+ const config = getConfig();
44
+ const live = isAssistantFeatureFlagEnabled(MEMORY_V3_LIVE, config);
45
+ const shadow = isAssistantFeatureFlagEnabled(MEMORY_V3_SHADOW, config);
46
+ if (!live && !shadow) return null;
47
+
48
+ const result = await observeTurn(ctx.conversationId, ctx.turnIndex);
49
+ if (!live || !result) return null;
50
+
51
+ try {
52
+ // `renderMemoryBlock` returns "" for an empty selection; inject nothing.
53
+ const text = await renderMemoryBlock(
54
+ result.finalInjection,
55
+ renderV3PageContent,
56
+ );
57
+ if (text.length === 0) return null;
58
+ return {
59
+ id: MEMORY_V3_BLOCK_ID,
60
+ text,
61
+ // Mirror v2's dynamic `<memory>` block placement.
62
+ placement: "after-memory-prefix",
63
+ };
64
+ } catch (err) {
65
+ log.warn(
66
+ {
67
+ err: err instanceof Error ? err.message : String(err),
68
+ conversationId: ctx.conversationId,
69
+ },
70
+ "memory-v3 live render failed (non-fatal) — falling back to v2",
71
+ );
72
+ return null;
73
+ }
74
+ },
75
+ };
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Memory v3 — shared retry helper for the L1 router and L2 selector model calls.
3
+ *
4
+ * The configured provider is already wrapped in `RetryProvider`
5
+ * (`../../providers/retry.ts`), which retries transient transport failures
6
+ * (network errors, 429s, 5xx, stream aborts) with exponential backoff before it
7
+ * ever throws. This helper therefore adds NO backoff of its own; it exists to:
8
+ * (a) re-prompt on a malformed-but-successful response — a 200 whose body has
9
+ * no usable forced `tool_use`, or whose tool input fails schema validation
10
+ * (the provider's retry never re-runs these, since nothing threw); and
11
+ * (b) cheaply re-attempt a call that threw after the provider exhausted its
12
+ * own retries, before the lane degrades to its deterministic fallback.
13
+ *
14
+ * `attempt` signals "unusable, retry me" by returning `null` (or throwing). The
15
+ * first non-null result wins; `null` after `maxAttempts` tells the caller to
16
+ * degrade to the deterministic recall lanes.
17
+ */
18
+ export async function retryForResult<T>(
19
+ attempt: () => Promise<T | null>,
20
+ maxAttempts = 3,
21
+ ): Promise<T | null> {
22
+ for (let i = 0; i < maxAttempts; i++) {
23
+ try {
24
+ const result = await attempt();
25
+ if (result !== null) return result;
26
+ } catch {
27
+ // Treat a throw like an unusable result and retry. The provider layer has
28
+ // already backed off transient errors, so there is nothing to wait for.
29
+ }
30
+ }
31
+ return null;
32
+ }
@@ -25,14 +25,14 @@
25
25
  * `assignPages`, and `invalidateLanes` without process-global module mocks.
26
26
  */
27
27
 
28
- import { isAssistantFeatureFlagEnabled } from "../../config/assistant-feature-flags.js";
29
- import type { AssistantConfig } from "../../config/types.js";
30
- import { getLogger } from "../../util/logger.js";
31
- import { getWorkspaceDir } from "../../util/platform.js";
32
- import { getMemoryCheckpoint, setMemoryCheckpoint } from "../checkpoints.js";
33
- import type { MemoryJob } from "../jobs-store.js";
34
- import { getPageIndex } from "../v2/page-index.js";
35
- import { listPages, readPage, writePage } from "../v2/page-store.js";
28
+ import { isAssistantFeatureFlagEnabled } from "../../../config/assistant-feature-flags.js";
29
+ import type { AssistantConfig } from "../../../config/types.js";
30
+ import { getMemoryCheckpoint, setMemoryCheckpoint } from "../../../memory/checkpoints.js";
31
+ import type { MemoryJob } from "../../../memory/jobs-store.js";
32
+ import { getPageIndex } from "../../../memory/v2/page-index.js";
33
+ import { listPages, readPage, writePage } from "../../../memory/v2/page-store.js";
34
+ import { getLogger } from "../../../util/logger.js";
35
+ import { getWorkspaceDir } from "../../../util/platform.js";
36
36
  import { assignPages as realAssignPages } from "./assign.js";
37
37
  import { invalidateLanes as realInvalidateLanes } from "./shadow-plugin.js";
38
38
  import { loadLeafTree as realLoadLeafTree, resolveDataDir } from "./tree.js";
@@ -13,11 +13,16 @@
13
13
  * then dedup by slug (a page assigned to multiple opened leaves comes back
14
14
  * once per leaf) ORing the pinned flag so a page pinned anywhere stays
15
15
  * pinned.
16
- * 4. Record each deduped selection into the carry-forward working set and
17
- * evict (core slugs, stale non-pinned entries, then the cap).
18
- * 5. Final injection = unique union of this turn's selected slugs and the
19
- * working-set union, so pages selected on earlier turns carry forward even
20
- * when this turn does not re-select them.
16
+ * 4. Age the carry-forward working set to this turn (evict core slugs, stale
17
+ * non-pinned entries, then the cap) and snapshot it — the pages carried in
18
+ * from EARLIER turns.
19
+ * 5. Final injection = unique union of this turn's selected slugs and that
20
+ * carried-forward set, so pages selected on earlier turns carry forward
21
+ * even when this turn does not re-select them.
22
+ * 6. Record this turn's selections into the working set for LATER turns. This
23
+ * runs AFTER the snapshot so the cap is spent on genuinely carried pages,
24
+ * not on this turn's selections (which are injected directly) — otherwise a
25
+ * turn selecting more pages than the cap would evict the entire carry.
21
26
  */
22
27
 
23
28
  import type { NeedleIndex } from "./needle.js";
@@ -48,7 +53,8 @@ export interface OrchestrateResult {
48
53
  openedLeaves: LeafPath[];
49
54
  /** This turn's L2 selections, deduped by slug (pinned flags ORed). */
50
55
  currentSelections: SelectedPage[];
51
- /** Snapshot of the working-set union after record + evict. */
56
+ /** The carried-forward set: selections from EARLIER turns, aged to this turn
57
+ * (snapshotted before this turn's selections are recorded). */
52
58
  workingSetUnion: Set<Slug>;
53
59
  /** Slugs to inject: this turn's selections ∪ the carried-forward working set. */
54
60
  finalInjection: Slug[];
@@ -95,20 +101,26 @@ export async function orchestrate(
95
101
  }
96
102
  const currentSelections = [...bySlug.values()];
97
103
 
98
- // Step 4: record this turn's selections into the carry-forward working set.
99
- for (const sel of currentSelections) {
100
- deps.workingSet.recordSelection(sel.slug, turn.turnNumber, sel.pinned);
101
- }
102
-
103
- // Step 5: evict. Core slugs are owned by core, not the working set.
104
+ // Step 4: age the carry-forward set to this turn (drop core slugs, stale
105
+ // non-pinned entries, then the cap) and snapshot it. This is the set carried
106
+ // in from EARLIER turns; recording this turn happens afterward (step 6) so the
107
+ // cap is spent on genuinely carried pages, not on this turn's selections
108
+ // (which are injected directly anyway).
104
109
  deps.workingSet.evict(turn.turnNumber, coreSlugs(deps.tree, deps.core));
105
-
106
- // Step 6: final injection = this turn's selections ∪ carried-forward set.
107
110
  const workingSetUnion = deps.workingSet.union();
111
+
112
+ // Step 5: final injection = this turn's selections ∪ the carried-forward set,
113
+ // so pages selected on earlier turns carry forward even when this turn does
114
+ // not re-select them.
108
115
  const finalInjection = unique<Slug>([
109
116
  ...currentSelections.map((s) => s.slug),
110
117
  ...workingSetUnion,
111
118
  ]);
112
119
 
120
+ // Step 6: record this turn's selections so they carry forward to LATER turns.
121
+ for (const sel of currentSelections) {
122
+ deps.workingSet.recordSelection(sel.slug, turn.turnNumber, sel.pinned);
123
+ }
124
+
113
125
  return { openedLeaves, currentSelections, workingSetUnion, finalInjection };
114
126
  }
@@ -1,7 +1,7 @@
1
1
  {
2
- "name": "default-llm-call",
2
+ "name": "default-memory-v3-shadow",
3
3
  "version": "1.0.0",
4
- "description": "First-party default plugin wrapping the assistant's built-in llm-call pipeline with a passthrough implementation.",
4
+ "description": "First-party default plugin housing the memory-v3 shadow/live orchestration engine and its injector.",
5
5
  "private": true,
6
6
  "license": "MIT",
7
7
  "type": "module",
@@ -1,5 +1,5 @@
1
- import { getWorkspaceDir } from "../../util/platform.js";
2
- import { readPage, renderPageContent } from "../v2/page-store.js";
1
+ import { readPage, renderPageContent } from "../../../memory/v2/page-store.js";
2
+ import { getWorkspaceDir } from "../../../util/platform.js";
3
3
  import { renderCapabilityContent } from "./capabilities.js";
4
4
  import type { Slug } from "./types.js";
5
5
 
@@ -0,0 +1,26 @@
1
+ import type { ContentBlock } from "../../../providers/types.js";
2
+
3
+ /**
4
+ * Text content block carrying a `cache_control` breakpoint with a 1-hour TTL.
5
+ * Shared by the v3 router (the static leaf-tree block) and selector (each
6
+ * leaf's static `<pages>` block): these prefixes are stable across turns — the
7
+ * leaf tree is byte-identical every turn, and a leaf's pages block changes only
8
+ * when its pages/summaries do — while v3 turns are frequently more than the
9
+ * default 5-minute cache window apart. A 1h TTL keeps the prefix warm across
10
+ * those gaps so it is read from cache rather than re-created every turn; the
11
+ * volatile current-message block is rendered after this one and left un-cached.
12
+ * Haiku does not support the extended-cache-ttl beta, so the Anthropic provider
13
+ * strips this `ttl` for Haiku models.
14
+ *
15
+ * Our internal `TextContent` type omits `cache_control` (only the Anthropic
16
+ * provider transforms it onto the wire), so we reach through a `Record` cast to
17
+ * keep the core types provider-agnostic.
18
+ */
19
+ export function cachedTextBlock(text: string): ContentBlock {
20
+ const block: ContentBlock = { type: "text", text };
21
+ (block as unknown as Record<string, unknown>).cache_control = {
22
+ type: "ephemeral",
23
+ ttl: "1h",
24
+ };
25
+ return block;
26
+ }
@@ -38,9 +38,9 @@ import { join, relative, sep } from "node:path";
38
38
 
39
39
  import { parse as parseYaml } from "yaml";
40
40
 
41
- import type { Provider } from "../../providers/types.js";
42
- import { getLogger } from "../../util/logger.js";
43
- import { listPages, readPage, writePage } from "../v2/page-store.js";
41
+ import { listPages, readPage, writePage } from "../../../memory/v2/page-store.js";
42
+ import type { Provider } from "../../../providers/types.js";
43
+ import { getLogger } from "../../../util/logger.js";
44
44
  import { assignPages } from "./assign.js";
45
45
  import { loadCore } from "./core.js";
46
46
  import { invalidateLanes } from "./shadow-plugin.js";
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Default `memory-v3-shadow` plugin.
3
+ *
4
+ * Houses the memory-v3 shadow/live orchestration engine (this directory) and
5
+ * its injector (`./injector.ts`). The injector is still consumed by the static
6
+ * chain in `memory-retrieval/injector-chain.ts`; the `user-prompt-submit` /
7
+ * `post-compact` hooks below are no-op scaffolding for the eventual
8
+ * convergence, when v3 injection moves off the loop-driven chain and into these
9
+ * lifecycle hooks. See each hook file for the convergence note.
10
+ */
11
+
12
+ import { type Plugin } from "../../types.js";
13
+ import postCompact from "./hooks/post-compact.js";
14
+ import userPromptSubmit from "./hooks/user-prompt-submit.js";
15
+ import pkg from "./package.json" with { type: "json" };
16
+
17
+ export const memoryV3ShadowPlugin: Plugin = {
18
+ manifest: {
19
+ name: pkg.name,
20
+ version: pkg.version,
21
+ },
22
+ hooks: {
23
+ "user-prompt-submit": userPromptSubmit,
24
+ "post-compact": postCompact,
25
+ },
26
+ };
@@ -1,4 +1,4 @@
1
- import { wrapMemoryBlock } from "../memory-marker.js";
1
+ import { wrapMemoryBlock } from "../../../memory/memory-marker.js";
2
2
  import { Slug } from "./types.js";
3
3
 
4
4
  /**