@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
@@ -32,35 +32,49 @@
32
32
  * closer to the memory prefix themselves. For appends, ascending `order` is
33
33
  * the natural left-to-right append sequence. The runtime-injection applier
34
34
  * sorts and applies blocks declaratively so this invariant holds even when
35
- * third-party injectors slot additional blocks at fractional order values.
36
- *
37
- * Third-party plugins may register additional {@link Injector}s at any
38
- * `order` value; the registry's `getInjectors()` returns all injectors
39
- * sorted ascending, so a plugin-registered injector at `order: 25`
40
- * reliably slots between `unified-turn-context` (20) and `pkb` (30).
41
- *
42
- * This module only builds and exports the `Plugin` object; the defaults
43
- * aggregator in `plugins/defaults/index.ts` registers it centrally, either
44
- * explicitly from `daemon/external-plugins-bootstrap.ts` or lazily via the
45
- * registry's default registrar the first time a query reads the registry.
35
+ * injectors slot additional blocks at fractional order values.
36
+ *
37
+ * This module exports the default injectors as a plain ordered array
38
+ * ({@link defaultInjectors}). The chain assembler in
39
+ * `plugins/defaults/memory-retrieval/injector-chain.ts` sorts them by `order`
40
+ * (alongside the memory-v3 injector) into the single sequence
41
+ * `applyRuntimeInjections` walks each turn — injection is not a plugin
42
+ * contribution, so injectors are imported directly rather than aggregated
43
+ * through the registry.
46
44
  */
47
45
 
48
46
  import { resolve } from "node:path";
49
47
 
50
48
  import { getConfig } from "../../../config/loader.js";
49
+ import type { InjectionMatcher } from "../../../context/strip-injections.js";
50
+ import { findConversationOrSubagent } from "../../../daemon/conversation-registry.js";
51
+ import { resolveWorkspaceTopLevelContext } from "../../../daemon/conversation-workspace.js";
52
+ import { readNowScratchpad } from "../../../daemon/now-scratchpad.js";
51
53
  import { getInContextPkbPaths } from "../../../daemon/pkb-context-tracker.js";
52
54
  import { buildPkbReminder } from "../../../daemon/pkb-reminder-builder.js";
55
+ import {
56
+ resolveTrustClass,
57
+ type TrustContext,
58
+ } from "../../../daemon/trust-context.js";
53
59
  import { listComments } from "../../../documents/document-comments-store.js";
60
+ import { getLiveGraphMemory } from "../../../memory/graph/conversation-graph-memory.js";
61
+ import { getPkbAutoInjectList } from "../../../memory/pkb/autoinject.js";
62
+ import { readPkbContext } from "../../../memory/pkb/context.js";
54
63
  import { searchPkbFiles } from "../../../memory/pkb/pkb-search.js";
64
+ import { getPkbRoot, PKB_WORKSPACE_SCOPE } from "../../../memory/pkb/types.js";
65
+ import {
66
+ readMemoryV2StaticContent,
67
+ shouldExposePersonalMemory,
68
+ } from "../../../memory/v2/static-context.js";
69
+ import type { Message } from "../../../providers/types.js";
55
70
  import { getLogger } from "../../../util/logger.js";
71
+ import { getSandboxWorkingDir } from "../../../util/platform.js";
56
72
  import {
57
73
  type InjectionBlock,
58
74
  type Injector,
59
- type Plugin,
60
75
  type TurnContext,
61
76
  type TurnInjectionInputs,
62
77
  } from "../../types.js";
63
- import pkg from "./package.json" with { type: "json" };
64
78
 
65
79
  const pkbReminderLog = getLogger("pkb-reminder");
66
80
 
@@ -79,7 +93,7 @@ const PKB_HINT_ARCHIVE_THRESHOLD = 0.7;
79
93
  * and any future integration code — can assert ordering without re-deriving
80
94
  * the constants.
81
95
  *
82
- * Gaps of 10 between slots leave room for third-party injectors to slot in
96
+ * Gaps of 10 between slots leave room for future injectors to slot in
83
97
  * at granular positions (e.g. `25` between unified-turn-context and pkb)
84
98
  * without renumbering the defaults.
85
99
  */
@@ -113,12 +127,22 @@ Then help the user clean up storage. Prefer safe inspection steps first, such as
113
127
  Do not work on unrelated tasks until enough space is freed to clear the lock or the user explicitly overrides it. Background processes and messages from trusted contacts are blocked while this cleanup mode is active.
114
128
  </disk_pressure_warning>`;
115
129
 
130
+ /**
131
+ * `disk-pressure-warning` injector — order 5, prepend-user-tail.
132
+ *
133
+ * Emits the storage cleanup-mode warning at the very top of the user tail when
134
+ * the turn is restricted to disk-pressure cleanup. Reads the cleanup-mode flag
135
+ * off the live `Conversation` looked up by conversation id — the agent loop
136
+ * sets `diskPressureCleanupModeActive` when it classifies the turn's
137
+ * disk-pressure policy — rather than having the loop thread it as an injection
138
+ * input.
139
+ */
116
140
  const diskPressureWarningInjector: Injector = {
117
141
  name: "disk-pressure-warning",
118
142
  order: DEFAULT_INJECTOR_ORDER.diskPressureWarning,
119
143
  async produce(ctx: TurnContext): Promise<InjectionBlock | null> {
120
- const inputs = readInjectionInputs(ctx);
121
- if (!inputs.diskPressureContext?.cleanupModeActive) return null;
144
+ const conversation = findConversationOrSubagent(ctx.conversationId);
145
+ if (!conversation?.diskPressureCleanupModeActive) return null;
122
146
  return {
123
147
  id: "disk-pressure-warning",
124
148
  text: DISK_PRESSURE_WARNING_PROMPT,
@@ -138,26 +162,52 @@ function isPkbInjectionSilencedByV2(): boolean {
138
162
  return getConfig().memory.v2.enabled;
139
163
  }
140
164
 
165
+ /**
166
+ * Matchers that mark a persisted `<workspace>` top-level injection. Uses the
167
+ * `{ prefix, suffix }` wrapper shape so user-authored text merely starting with
168
+ * `<workspace>\n` is never mistaken for an injection — matching the full-wrapper
169
+ * requirement the compaction strip uses for this block. The legacy
170
+ * `<workspace_top_level>` tag (pre-rename history) counts as present too.
171
+ */
172
+ const WORKSPACE_BLOCK_MATCHERS: readonly InjectionMatcher[] = [
173
+ { prefix: "<workspace>\n", suffix: "\n</workspace>" },
174
+ "<workspace_top_level>",
175
+ ];
176
+
141
177
  /**
142
178
  * `workspace-context` injector — order 10, prepend-user-tail.
143
179
  *
144
180
  * Injects the workspace top-level directory context at the very top of the
145
- * user tail's content so the assistant sees a workspace grounding block
146
- * before any other per-turn context.
181
+ * user tail's content so the assistant sees a workspace grounding block before
182
+ * any other per-turn context.
183
+ *
184
+ * Sources the dirty-guarded top-level cache itself via
185
+ * {@link resolveWorkspaceTopLevelContext} (keyed by conversation id) rather than
186
+ * having the agent loop compute and thread it. Decides inject/skip by presence
187
+ * detection: the block is (re)injected only when it is absent from the working
188
+ * messages — true on the first turn and right after compaction strips it — and
189
+ * skipped on normal cached turns where it already persists in history. This
190
+ * keeps the conversation prefix stable for Anthropic's prefix caching.
147
191
  *
148
192
  * Gating:
149
193
  * - `mode === "full"` (skipped in minimal mode).
150
- * - `workspaceTopLevelContext` is a non-null, non-empty string.
194
+ * - the rendered workspace context is a non-null, non-empty string.
195
+ * - no `<workspace>` block is already present in `runMessages`.
151
196
  */
152
197
  const workspaceContextInjector: Injector = {
153
198
  name: "workspace-context",
154
199
  order: DEFAULT_INJECTOR_ORDER.workspaceContext,
155
- async produce(ctx: TurnContext): Promise<InjectionBlock | null> {
200
+ async produce(
201
+ ctx: TurnContext,
202
+ runMessages?: Message[],
203
+ ): Promise<InjectionBlock | null> {
156
204
  const inputs = readInjectionInputs(ctx);
157
205
  const mode = inputs.mode ?? "full";
158
206
  if (mode !== "full") return null;
159
- const text = inputs.workspaceTopLevelContext;
207
+ const text = resolveWorkspaceTopLevelContext(ctx.conversationId);
160
208
  if (!text) return null;
209
+ if (hasInjectedUserTextBlock(runMessages, WORKSPACE_BLOCK_MATCHERS))
210
+ return null;
161
211
  return {
162
212
  id: "workspace-context",
163
213
  text,
@@ -241,20 +291,33 @@ const unifiedTurnContextInjector: Injector = {
241
291
  *
242
292
  * Gating:
243
293
  * - `mode === "full"`.
244
- * - Non-null, non-empty `pkbContext`.
294
+ * - The personal-memory trust gate admits the actor and the workspace has
295
+ * PKB content (see {@link readGatedPkbContext}).
296
+ * - The `<knowledge_base>` block is not already present in the turn's working
297
+ * messages. The big block is injected once and then persists in history, so
298
+ * it only needs (re)injecting on the first turn and right after compaction
299
+ * strips it — both of which leave the working messages without the block.
300
+ * Skipping when it is present keeps the conversation prefix stable for
301
+ * Anthropic's prefix caching and avoids a duplicate splice.
245
302
  */
246
303
  const pkbContextInjector: Injector = {
247
304
  name: "pkb-context",
248
305
  order: DEFAULT_INJECTOR_ORDER.pkbContext,
249
- async produce(ctx: TurnContext): Promise<InjectionBlock | null> {
306
+ async produce(
307
+ ctx: TurnContext,
308
+ runMessages?: Message[],
309
+ ): Promise<InjectionBlock | null> {
250
310
  const inputs = readInjectionInputs(ctx);
251
311
  const mode = inputs.mode ?? "full";
252
312
  if (mode !== "full") return null;
253
313
  if (isPkbInjectionSilencedByV2()) return null;
254
- if (!inputs.pkbContext) return null;
314
+ const content = readGatedPkbContext(ctx.trust);
315
+ if (!content) return null;
316
+ if (hasInjectedUserTextBlock(runMessages, KNOWLEDGE_BASE_BLOCK_PREFIXES))
317
+ return null;
255
318
  return {
256
319
  id: "pkb-context",
257
- text: buildPkbContextBlock(inputs.pkbContext),
320
+ text: buildPkbContextBlock(content),
258
321
  placement: "after-memory-prefix",
259
322
  };
260
323
  },
@@ -271,18 +334,21 @@ const pkbContextInjector: Injector = {
271
334
  *
272
335
  * Gating:
273
336
  * - `mode === "full"`.
274
- * - `pkbActive === true`.
337
+ * - PKB is active for the turn (see {@link isPkbActive}).
275
338
  */
276
339
  const pkbReminderInjector: Injector = {
277
340
  name: "pkb-reminder",
278
341
  order: DEFAULT_INJECTOR_ORDER.pkbReminder,
279
- async produce(ctx: TurnContext): Promise<InjectionBlock | null> {
342
+ async produce(
343
+ ctx: TurnContext,
344
+ runMessages?: Message[],
345
+ ): Promise<InjectionBlock | null> {
280
346
  const inputs = readInjectionInputs(ctx);
281
347
  const mode = inputs.mode ?? "full";
282
348
  if (mode !== "full") return null;
283
- if (!inputs.pkbActive) return null;
349
+ if (!isPkbActive(ctx.trust)) return null;
284
350
  if (isPkbInjectionSilencedByV2()) return null;
285
- const reminder = await buildPkbReminderWithHints(inputs);
351
+ const reminder = await buildPkbReminderWithHints(ctx, runMessages);
286
352
  return {
287
353
  id: "pkb-reminder",
288
354
  text: reminder,
@@ -291,6 +357,125 @@ const pkbReminderInjector: Injector = {
291
357
  },
292
358
  };
293
359
 
360
+ /**
361
+ * Whether personal-memory content (PKB, NOW.md) may be surfaced this turn: the
362
+ * trust gate admits the actor (guardian-class, or an internal/local flow). All
363
+ * memory-domain injectors share this gate so they apply identical exposure
364
+ * rules without it being threaded in from the agent loop.
365
+ */
366
+ function isPersonalMemoryAllowed(trust: TrustContext): boolean {
367
+ return shouldExposePersonalMemory({
368
+ sourceChannel: trust.sourceChannel,
369
+ isTrustedActor: resolveTrustClass(trust) === "guardian",
370
+ });
371
+ }
372
+
373
+ /**
374
+ * Read the auto-injected PKB content for the turn, gated behind the
375
+ * personal-memory trust gate. Returns the content string when the gate admits
376
+ * the actor and the workspace has PKB content, otherwise `null`. Both the gate
377
+ * and the content are sourced from the turn's trust context and the PKB files
378
+ * directly, so the memory-domain injectors source their own inputs rather than
379
+ * having them threaded in from the agent loop.
380
+ */
381
+ function readGatedPkbContext(trust: TrustContext): string | null {
382
+ return isPersonalMemoryAllowed(trust) ? readPkbContext() : null;
383
+ }
384
+
385
+ /**
386
+ * Read the NOW.md scratchpad content for the turn, gated behind the
387
+ * personal-memory trust gate and the `scratchpadInjection` config toggle.
388
+ * Returns the trimmed content when both gates admit and the file is non-empty,
389
+ * otherwise `null`. Sourced from the trust context and the NOW.md file directly
390
+ * so the `now-md` injector owns its input rather than having it threaded in.
391
+ */
392
+ function readGatedNowScratchpad(trust: TrustContext): string | null {
393
+ if (!isPersonalMemoryAllowed(trust)) return null;
394
+ if (!getConfig().memory.retrieval.scratchpadInjection.enabled) return null;
395
+ return readNowScratchpad();
396
+ }
397
+
398
+ /**
399
+ * Read the v2 static memory content for the turn, gated behind the
400
+ * personal-memory trust gate. Returns the content (essentials/threads/recent/
401
+ * buffer concatenated) when the gate admits and v2 memory is enabled,
402
+ * otherwise `null`. {@link readMemoryV2StaticContent} self-gates on the v2
403
+ * flag + config, so the `memory-v2-static` injector owns its input rather than
404
+ * having it threaded in from the agent loop.
405
+ */
406
+ function readGatedMemoryV2Static(trust: TrustContext): string | null {
407
+ return isPersonalMemoryAllowed(trust) ? readMemoryV2StaticContent() : null;
408
+ }
409
+
410
+ /**
411
+ * Whether PKB is active for the turn: the personal-memory trust gate admits
412
+ * the actor and the workspace has PKB content to surface.
413
+ */
414
+ function isPkbActive(trust: TrustContext): boolean {
415
+ return readGatedPkbContext(trust) !== null;
416
+ }
417
+
418
+ /** Block prefixes that mark a persisted `<knowledge_base>` injection. */
419
+ const KNOWLEDGE_BASE_BLOCK_PREFIXES = [
420
+ "<knowledge_base>",
421
+ "<pkb>", // backward-compat: pre-rename history
422
+ ] as const;
423
+
424
+ /** Block prefixes that mark a persisted NOW.md injection. */
425
+ const NOW_MD_BLOCK_PREFIXES = [
426
+ "<NOW.md Always keep this up to date",
427
+ "<now_scratchpad>", // backward-compat: pre-rename history
428
+ ] as const;
429
+
430
+ /**
431
+ * Matchers that mark a persisted `memory-v2-static` injection. Uses the
432
+ * `{ prefix, suffix }` wrapper shape (not a bare prefix) so user-authored text
433
+ * merely starting with `<info>\n` is never mistaken for an injection — matching
434
+ * the full-wrapper requirement the compaction strip uses for this block.
435
+ *
436
+ * The static block is wrapped in `<info>…</info>` today, but rows persisted
437
+ * before that switch rehydrate verbatim as `<memory>…</memory>` (see
438
+ * `conversation-lifecycle`), so the legacy wrapper counts as present too.
439
+ * Matching `<memory>` cannot wrongly skip a needed injection: the static block
440
+ * is only (re)injected on the first turn (empty history) and right after
441
+ * compaction (which strips both wrappers), and on neither is a `<memory>` block
442
+ * present — the dynamic activation `<memory>` block only survives on normal
443
+ * cached turns, which is exactly when this injector must skip anyway.
444
+ */
445
+ const MEMORY_V2_STATIC_BLOCK_MATCHERS: readonly InjectionMatcher[] = [
446
+ { prefix: "<info>\n", suffix: "\n</info>" },
447
+ { prefix: "<memory>\n", suffix: "\n</memory>" },
448
+ ];
449
+
450
+ /**
451
+ * Whether a block matching any of the given matchers is already present in the
452
+ * turn's working messages. Mirrors `stripUserTextBlocksByPrefix` (a
453
+ * user-message text block whose content matches a bare-prefix or a
454
+ * `{ prefix, suffix }` wrapper matcher), so presence detection stays in
455
+ * lockstep with what compaction strips: a block is present here exactly when
456
+ * compaction would strip it.
457
+ */
458
+ function hasInjectedUserTextBlock(
459
+ runMessages: Message[] | undefined,
460
+ matchers: readonly InjectionMatcher[],
461
+ ): boolean {
462
+ if (!runMessages) return false;
463
+ return runMessages.some(
464
+ (message) =>
465
+ message.role === "user" &&
466
+ message.content.some(
467
+ (block) =>
468
+ block.type === "text" &&
469
+ matchers.some((m) =>
470
+ typeof m === "string"
471
+ ? block.text.startsWith(m)
472
+ : block.text.startsWith(m.prefix) &&
473
+ block.text.endsWith(m.suffix),
474
+ ),
475
+ ),
476
+ );
477
+ }
478
+
294
479
  /**
295
480
  * Render the PKB context block — wraps the raw content in
296
481
  * `<knowledge_base>...</knowledge_base>` while escaping any closing tags
@@ -305,38 +490,40 @@ function buildPkbContextBlock(content: string): string {
305
490
  }
306
491
 
307
492
  /**
308
- * Build the PKB `<system_reminder>` text. When a dense query vector plus
309
- * enough scope metadata is available, run the hybrid PKB search to
493
+ * Build the PKB `<system_reminder>` text. When a dense query vector and the
494
+ * turn's working messages are available, run the hybrid PKB search to
310
495
  * surface up to three relevance hints; fall back to the flat static
311
496
  * reminder on empty results or any error.
497
+ *
498
+ * The dense/sparse query pair is read off the conversation's live graph
499
+ * handle ({@link getLiveGraphMemory}) — the memory-retrieval hook records it
500
+ * there during the turn's retrieval. In-context PKB paths are computed from
501
+ * the turn's working messages (`runMessages`, supplied by the injector chain)
502
+ * resolved against the workspace working directory, so the reminder sources
503
+ * its inputs itself rather than having them threaded through the agent loop.
312
504
  */
313
505
  async function buildPkbReminderWithHints(
314
- inputs: TurnInjectionInputs,
506
+ ctx: TurnContext,
507
+ runMessages?: Message[],
315
508
  ): Promise<string> {
316
509
  let hints: string[] = [];
317
- const queryVector = inputs.pkbQueryVector;
318
- if (
319
- queryVector &&
320
- queryVector.length > 0 &&
321
- inputs.pkbScopeId &&
322
- inputs.pkbConversation &&
323
- inputs.pkbRoot
324
- ) {
510
+ const graphMemory = getLiveGraphMemory(ctx.conversationId);
511
+ const queryVector = graphMemory?.pkbQueryVector;
512
+ if (queryVector && queryVector.length > 0 && runMessages) {
325
513
  try {
514
+ const pkbRoot = getPkbRoot();
326
515
  const results = await searchPkbFiles(
327
516
  queryVector,
328
- inputs.pkbSparseVector,
517
+ graphMemory?.pkbSparseVector,
329
518
  8,
330
- [inputs.pkbScopeId],
519
+ [PKB_WORKSPACE_SCOPE],
331
520
  );
332
- const workingDir = inputs.pkbWorkingDir ?? inputs.pkbRoot;
333
521
  const inContext = getInContextPkbPaths(
334
- inputs.pkbConversation,
335
- inputs.pkbAutoInjectList ?? [],
336
- inputs.pkbRoot,
337
- workingDir,
522
+ { messages: runMessages },
523
+ getPkbAutoInjectList(pkbRoot),
524
+ pkbRoot,
525
+ getSandboxWorkingDir(),
338
526
  );
339
- const pkbRoot = inputs.pkbRoot;
340
527
  // Gate on `denseScore` (cosine, [0, 1]) so the quality bar is stable
341
528
  // regardless of whether sparse was provided. Rank by `hybridScore`
342
529
  // (RRF) when available — that captures the sparse signal for
@@ -395,18 +582,30 @@ async function buildPkbReminderWithHints(
395
582
  * the memory prefix so `now-md` (40) splices after it.
396
583
  *
397
584
  * Gating:
398
- * - `mode === "full"`.
399
- * - `memoryV2Static` is a non-null, non-empty string.
585
+ * - `mode === "full"` (skipped in minimal mode).
586
+ * - The personal-memory trust gate admits the actor and v2 static memory has
587
+ * content (see {@link readGatedMemoryV2Static}).
588
+ * - The `<info>` block is not already present in the turn's working messages.
589
+ * Like `<knowledge_base>`, the block is injected once and then persists in
590
+ * history, so it only needs (re)injecting on the first turn and right after
591
+ * compaction strips it — both of which leave the working messages without
592
+ * the block. Skipping when it is present keeps the conversation prefix
593
+ * stable for Anthropic's prefix caching and avoids a duplicate splice.
400
594
  */
401
595
  const memoryV2StaticInjector: Injector = {
402
596
  name: "memory-v2-static",
403
597
  order: DEFAULT_INJECTOR_ORDER.memoryV2Static,
404
- async produce(ctx: TurnContext): Promise<InjectionBlock | null> {
598
+ async produce(
599
+ ctx: TurnContext,
600
+ runMessages?: Message[],
601
+ ): Promise<InjectionBlock | null> {
405
602
  const inputs = readInjectionInputs(ctx);
406
603
  const mode = inputs.mode ?? "full";
407
604
  if (mode !== "full") return null;
408
- const content = inputs.memoryV2Static;
605
+ const content = readGatedMemoryV2Static(ctx.trust);
409
606
  if (!content) return null;
607
+ if (hasInjectedUserTextBlock(runMessages, MEMORY_V2_STATIC_BLOCK_MATCHERS))
608
+ return null;
410
609
  return {
411
610
  id: "memory-v2-static",
412
611
  text: buildMemoryV2StaticBlock(content),
@@ -438,17 +637,30 @@ function buildMemoryV2StaticBlock(content: string): string {
438
637
  *
439
638
  * Gating:
440
639
  * - `mode === "full"` (skipped in minimal mode).
441
- * - `nowScratchpad` is a non-null, non-empty string.
640
+ * - The personal-memory trust gate admits the actor, the `scratchpadInjection`
641
+ * config toggle is on, and NOW.md has content (see
642
+ * {@link readGatedNowScratchpad}).
643
+ * - The NOW.md block is not already present in the turn's working messages.
644
+ * Like `<knowledge_base>`, the block is injected once and then persists in
645
+ * history, so it only needs (re)injecting on the first turn and right after
646
+ * compaction strips it — both of which leave the working messages without
647
+ * the block. Skipping when it is present keeps the conversation prefix
648
+ * stable for Anthropic's prefix caching and avoids a duplicate splice.
442
649
  */
443
650
  const nowMdInjector: Injector = {
444
651
  name: "now-md",
445
652
  order: DEFAULT_INJECTOR_ORDER.nowMd,
446
- async produce(ctx: TurnContext): Promise<InjectionBlock | null> {
653
+ async produce(
654
+ ctx: TurnContext,
655
+ runMessages?: Message[],
656
+ ): Promise<InjectionBlock | null> {
447
657
  const inputs = readInjectionInputs(ctx);
448
658
  const mode = inputs.mode ?? "full";
449
659
  if (mode !== "full") return null;
450
- const content = inputs.nowScratchpad;
660
+ const content = readGatedNowScratchpad(ctx.trust);
451
661
  if (!content) return null;
662
+ if (hasInjectedUserTextBlock(runMessages, NOW_MD_BLOCK_PREFIXES))
663
+ return null;
452
664
  const text = `<NOW.md Always keep this up to date; keep under 10 lines>\n${content}\n</NOW.md>`;
453
665
  return {
454
666
  id: "now-md",
@@ -675,31 +887,26 @@ const threadFocusInjector: Injector = {
675
887
  };
676
888
 
677
889
  /**
678
- * Bundle every default injector into a single first-party plugin. Registered
679
- * at daemon startup via `external-plugins-bootstrap.ts`.
890
+ * Every default injector in ascending `order`. This is the canonical
891
+ * first-party injection sequence consumed by `applyRuntimeInjections` via the
892
+ * assembled injector chain.
680
893
  *
681
- * Using one plugin per injector would inflate the registry and create
682
- * spurious registration-order dependencies; a single plugin keeps the
683
- * ordering contract entirely in the `order` field.
894
+ * `order` is the source of truth for sequencing (see {@link DEFAULT_INJECTOR_ORDER});
895
+ * the chain assembler sorts by it, so this array's literal order is only a
896
+ * readability convenience.
684
897
  */
685
- export const defaultInjectorsPlugin: Plugin = {
686
- manifest: {
687
- name: pkg.name,
688
- version: pkg.version,
689
- },
690
- injectors: [
691
- diskPressureWarningInjector,
692
- workspaceContextInjector,
693
- backgroundTurnInjector,
694
- unifiedTurnContextInjector,
695
- pkbContextInjector,
696
- pkbReminderInjector,
697
- memoryV2StaticInjector,
698
- nowMdInjector,
699
- activeDocumentsInjector,
700
- documentCommentsInjector,
701
- subagentStatusInjector,
702
- slackMessagesInjector,
703
- threadFocusInjector,
704
- ],
705
- };
898
+ export const defaultInjectors: Injector[] = [
899
+ diskPressureWarningInjector,
900
+ workspaceContextInjector,
901
+ backgroundTurnInjector,
902
+ unifiedTurnContextInjector,
903
+ pkbContextInjector,
904
+ pkbReminderInjector,
905
+ memoryV2StaticInjector,
906
+ nowMdInjector,
907
+ activeDocumentsInjector,
908
+ documentCommentsInjector,
909
+ subagentStatusInjector,
910
+ slackMessagesInjector,
911
+ threadFocusInjector,
912
+ ];
@@ -8,15 +8,15 @@ import { tmpdir } from "node:os";
8
8
  import { join } from "node:path";
9
9
  import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
10
10
 
11
+ import { readPage, writePage } from "../../../../memory/v2/page-store.js";
12
+ import type { ConceptPageFrontmatter } from "../../../../memory/v2/types.js";
11
13
  import type {
12
14
  Message,
13
15
  Provider,
14
16
  ProviderResponse,
15
17
  SendMessageOptions,
16
18
  ToolUseContent,
17
- } from "../../../providers/types.js";
18
- import { readPage, writePage } from "../../v2/page-store.js";
19
- import type { ConceptPageFrontmatter } from "../../v2/types.js";
19
+ } from "../../../../providers/types.js";
20
20
  import type { LeafNode, LeafTree } from "../types.js";
21
21
 
22
22
  // Stub the provider layer before importing `assign.js` so its static import
@@ -24,7 +24,7 @@ import type { LeafNode, LeafTree } from "../types.js";
24
24
  // aren't built in a fresh worktree) never loads. The classifier is
25
25
  // provider-injectable, so every test passes its own stub provider — the real
26
26
  // `getConfiguredProvider` is never exercised here.
27
- mock.module("../../../providers/provider-send-message.js", () => ({
27
+ mock.module("../../../../providers/provider-send-message.js", () => ({
28
28
  getConfiguredProvider: async () => null,
29
29
  extractToolUse: (response: ProviderResponse) =>
30
30
  response.content.find((b): b is ToolUseContent => b.type === "tool_use"),
@@ -42,6 +42,22 @@ describe("computeV3Health", () => {
42
42
  expect(report.unassigned).toEqual(["page-b", "page-c"]);
43
43
  });
44
44
 
45
+ test("excludes synthetic capability slugs from unassigned / novel clusters", () => {
46
+ const t = tree({ "domain-a/topic-x": ["page-a"] });
47
+ const report = computeV3Health({
48
+ tree: t,
49
+ allSlugs: ["page-a", "page-b", "cli-commands/example", "skills/example"],
50
+ });
51
+ // Capability slugs are handled by the always-on capabilities leaf (injected
52
+ // into the live lane tree, absent here), not the persisted tree — so they must
53
+ // not be reported as unassigned or grouped into novel clusters. page-b is the
54
+ // one real unassigned concept page.
55
+ expect(report.unassigned).toEqual(["page-b"]);
56
+ expect(report.novelClusters).toEqual([
57
+ { prefix: "page-b", slugs: ["page-b"], count: 1 },
58
+ ]);
59
+ });
60
+
45
61
  test("flags dangling page refs pointing at missing leaves", () => {
46
62
  const t = tree({ "domain-a/topic-x": ["page-a"] });
47
63
  const report = computeV3Health({
@@ -25,13 +25,13 @@
25
25
 
26
26
  import { beforeEach, describe, expect, mock, test } from "bun:test";
27
27
 
28
+ import { stripAllMemoryInjections } from "../../../../memory/graph/conversation-graph-memory.js";
28
29
  import type {
29
30
  ContentBlock,
30
31
  Message,
31
32
  Provider,
32
33
  ProviderResponse,
33
- } from "../../../providers/types.js";
34
- import { stripAllMemoryInjections } from "../../graph/conversation-graph-memory.js";
34
+ } from "../../../../providers/types.js";
35
35
  import type { NeedleIndex } from "../needle.js";
36
36
  import type {
37
37
  LeafNode,
@@ -49,13 +49,13 @@ import liveTurns from "./fixtures/live-turns.json" with { type: "json" };
49
49
 
50
50
  let providerStub: Provider | null = null;
51
51
 
52
- mock.module("../../../providers/provider-send-message.js", () => ({
52
+ mock.module("../../../../providers/provider-send-message.js", () => ({
53
53
  getConfiguredProvider: async () => providerStub,
54
54
  extractToolUse: (response: ProviderResponse) =>
55
55
  response.content.find((b) => b.type === "tool_use"),
56
56
  }));
57
57
 
58
- mock.module("../../../util/logger.js", () => ({
58
+ mock.module("../../../../util/logger.js", () => ({
59
59
  getLogger: () =>
60
60
  new Proxy({} as Record<string, unknown>, {
61
61
  get: (_t, prop) => (prop === "child" ? () => ({}) : () => {}),
@@ -3,11 +3,11 @@ import { tmpdir } from "node:os";
3
3
  import { join } from "node:path";
4
4
  import { afterEach, beforeEach, describe, expect, test } from "bun:test";
5
5
 
6
- import { setOverridesForTesting } from "../../../__tests__/feature-flag-test-helpers.js";
7
- import type { AssistantConfig } from "../../../config/types.js";
8
- import type { MemoryJob } from "../../jobs-store.js";
9
- import { readPage, writePage } from "../../v2/page-store.js";
10
- import type { ConceptPage } from "../../v2/types.js";
6
+ import { setOverridesForTesting } from "../../../../__tests__/feature-flag-test-helpers.js";
7
+ import type { AssistantConfig } from "../../../../config/types.js";
8
+ import type { MemoryJob } from "../../../../memory/jobs-store.js";
9
+ import { readPage, writePage } from "../../../../memory/v2/page-store.js";
10
+ import type { ConceptPage } from "../../../../memory/v2/types.js";
11
11
  import type { AssignPageResult, AssignPagesOptions } from "../assign.js";
12
12
  import {
13
13
  type ClassifyCandidate,