@vellumai/assistant 0.8.8 → 0.8.9-dev.202606091926.ebb2d62

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 (490) hide show
  1. package/ARCHITECTURE.md +6 -6
  2. package/bun.lock +2 -2
  3. package/docs/activation-funnel-telemetry.md +310 -0
  4. package/examples/plugins/echo/README.md +61 -60
  5. package/examples/plugins/echo/hooks/post-tool-use.ts +18 -0
  6. package/examples/plugins/echo/hooks/stop.ts +16 -0
  7. package/examples/plugins/echo/hooks/user-prompt-submit.ts +18 -0
  8. package/examples/plugins/echo/package.json +1 -2
  9. package/examples/plugins/echo/src/emit.ts +19 -0
  10. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +7 -6
  11. package/openapi.yaml +273 -121
  12. package/package.json +2 -2
  13. package/scripts/sync-llm-catalog.ts +2 -0
  14. package/src/__tests__/activation-early-marking.test.ts +120 -0
  15. package/src/__tests__/agent-loop-callsite-precedence.test.ts +69 -14
  16. package/src/__tests__/agent-loop-exit-reason.test.ts +204 -144
  17. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +50 -35
  18. package/src/__tests__/agent-loop-output-hooks.test.ts +357 -0
  19. package/src/__tests__/agent-loop-override-profile.test.ts +25 -6
  20. package/src/__tests__/agent-loop-provider-error-recording.test.ts +41 -21
  21. package/src/__tests__/agent-loop-thinking.test.ts +36 -20
  22. package/src/__tests__/agent-loop.test.ts +441 -96
  23. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +14 -14
  24. package/src/__tests__/agent-wake-override-profile.test.ts +17 -21
  25. package/src/__tests__/anthropic-provider.test.ts +23 -8
  26. package/src/__tests__/app-builder-tool-scripts.test.ts +21 -0
  27. package/src/__tests__/app-control-flow.test.ts +1 -1
  28. package/src/__tests__/app-dir-path-guard.test.ts +1 -0
  29. package/src/__tests__/app-executors.test.ts +132 -0
  30. package/src/__tests__/approval-cascade.test.ts +6 -5
  31. package/src/__tests__/approval-routes-http.test.ts +4 -1
  32. package/src/__tests__/background-workers-disk-pressure.test.ts +1 -1
  33. package/src/__tests__/build-persisted-content.test.ts +75 -1
  34. package/src/__tests__/channel-approval-routes.test.ts +1 -1
  35. package/src/__tests__/channel-approvals.test.ts +1 -1
  36. package/src/__tests__/compaction-circuit.test.ts +258 -0
  37. package/src/__tests__/compaction-direct.test.ts +146 -0
  38. package/src/__tests__/compaction-events.test.ts +7 -7
  39. package/src/__tests__/compaction.benchmark.test.ts +1 -1
  40. package/src/__tests__/compactor-web-search-strip.test.ts +213 -0
  41. package/src/__tests__/config-managed-gemini-defaults.test.ts +2 -46
  42. package/src/__tests__/context-overflow-reducer.test.ts +265 -125
  43. package/src/__tests__/context-window-manager-compact-retry.test.ts +121 -15
  44. package/src/__tests__/conversation-abort-tool-results.test.ts +7 -5
  45. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +7 -10
  46. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +78 -119
  47. package/src/__tests__/conversation-agent-loop-overflow.test.ts +158 -234
  48. package/src/__tests__/conversation-agent-loop.test.ts +342 -623
  49. package/src/__tests__/conversation-clean-command.test.ts +5 -2
  50. package/src/__tests__/conversation-confirmation-signals.test.ts +6 -5
  51. package/src/__tests__/conversation-crud-inference-profile.test.ts +7 -9
  52. package/src/__tests__/conversation-error.test.ts +15 -1
  53. package/src/__tests__/conversation-history-web-search.test.ts +6 -1
  54. package/src/__tests__/conversation-media-retry.test.ts +1 -1
  55. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +44 -4
  56. package/src/__tests__/conversation-process-callsite.test.ts +15 -15
  57. package/src/__tests__/conversation-provider-retry-repair.test.ts +66 -65
  58. package/src/__tests__/conversation-queue.test.ts +10 -10
  59. package/src/__tests__/conversation-runtime-assembly.test.ts +1059 -231
  60. package/src/__tests__/conversation-runtime-workspace.test.ts +115 -20
  61. package/src/__tests__/conversation-slash-queue.test.ts +7 -5
  62. package/src/__tests__/conversation-slash-unknown.test.ts +7 -5
  63. package/src/__tests__/conversation-speed-override.test.ts +11 -10
  64. package/src/__tests__/conversation-starter-routes.test.ts +14 -6
  65. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +395 -0
  66. package/src/__tests__/conversation-surfaces-app-control.test.ts +48 -1
  67. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +73 -4
  68. package/src/__tests__/conversation-undo.test.ts +2 -2
  69. package/src/__tests__/conversation-workspace-cache-state.test.ts +24 -21
  70. package/src/__tests__/conversation-workspace-injection.test.ts +69 -7
  71. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +15 -12
  72. package/src/__tests__/conversations-import-system-filter.test.ts +101 -0
  73. package/src/__tests__/corrected-target.test.ts +93 -0
  74. package/src/__tests__/credential-execution-feature-gates.test.ts +5 -4
  75. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  76. package/src/__tests__/cu-unified-flow.test.ts +36 -0
  77. package/src/__tests__/db-acp-history.test.ts +101 -0
  78. package/src/__tests__/dynamic-page-surface.test.ts +31 -0
  79. package/src/__tests__/embedding-managed-proxy-selection.test.ts +6 -40
  80. package/src/__tests__/empty-response-hook.test.ts +1 -1
  81. package/src/__tests__/file-write-tool.test.ts +63 -0
  82. package/src/__tests__/gateway-only-guard.test.ts +17 -2
  83. package/src/__tests__/guardian-grant-minting.test.ts +1 -1
  84. package/src/__tests__/guardian-routing-invariants.test.ts +93 -4
  85. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
  86. package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
  87. package/src/__tests__/heartbeat-service.test.ts +1 -0
  88. package/src/__tests__/history-repair-hook.test.ts +5 -1
  89. package/src/__tests__/host-app-control-proxy.test.ts +45 -0
  90. package/src/__tests__/host-app-control-routes.test.ts +1 -1
  91. package/src/__tests__/host-cu-routes-targeted.test.ts +3 -3
  92. package/src/__tests__/inference-profile-reaper.test.ts +62 -0
  93. package/src/__tests__/inference-profile-session-handler.test.ts +86 -0
  94. package/src/__tests__/injector-background-turn.test.ts +13 -23
  95. package/src/__tests__/injector-chain.test.ts +268 -44
  96. package/src/__tests__/injector-disk-pressure.test.ts +210 -52
  97. package/src/__tests__/injector-document-comments.test.ts +97 -114
  98. package/src/__tests__/injector-pkb-v2-silenced.test.ts +2 -2
  99. package/src/__tests__/injector-v3-suppression.test.ts +4 -4
  100. package/src/__tests__/list-messages-client-message-id.test.ts +91 -0
  101. package/src/__tests__/list-messages-hidden-metadata.test.ts +38 -0
  102. package/src/__tests__/llm-catalog-parity.test.ts +4 -0
  103. package/src/__tests__/llm-resolver.test.ts +73 -0
  104. package/src/__tests__/memory-retrieval-hook.test.ts +156 -38
  105. package/src/__tests__/memory-v2-static-injector.test.ts +86 -8
  106. package/src/__tests__/notification-decision-strategy.test.ts +3 -3
  107. package/src/__tests__/parallel-tool.benchmark.test.ts +35 -8
  108. package/src/__tests__/persist-unsendable-image-downscale.test.ts +145 -0
  109. package/src/__tests__/persist-unsendable-image.test.ts +97 -1
  110. package/src/__tests__/persistence-secret-redaction.test.ts +78 -0
  111. package/src/__tests__/plugin-api-shim.test.ts +6 -9
  112. package/src/__tests__/plugin-bootstrap.test.ts +91 -81
  113. package/src/__tests__/plugin-registry.test.ts +3 -49
  114. package/src/__tests__/plugin-skill-contribution.test.ts +15 -14
  115. package/src/__tests__/plugin-tool-contribution.test.ts +7 -4
  116. package/src/__tests__/plugin-types.test.ts +0 -70
  117. package/src/__tests__/post-turn-tool-result-truncation.test.ts +69 -0
  118. package/src/__tests__/pre-model-call-sanitize.test.ts +109 -0
  119. package/src/__tests__/published-app-updater.test.ts +138 -0
  120. package/src/__tests__/reaction-persistence.test.ts +1 -1
  121. package/src/__tests__/retry-thinking-adaptive-only.test.ts +245 -0
  122. package/src/__tests__/send-endpoint-busy.test.ts +4 -1
  123. package/src/__tests__/server-history-render.test.ts +39 -0
  124. package/src/__tests__/skill-feature-flags-integration.test.ts +31 -0
  125. package/src/__tests__/steer-tool-repair.test.ts +1 -1
  126. package/src/__tests__/subagent-call-site-routing.test.ts +1 -1
  127. package/src/__tests__/subagent-detail.test.ts +25 -7
  128. package/src/__tests__/subagent-fork-notifications.test.ts +1 -3
  129. package/src/__tests__/subagent-fork-spawn.test.ts +1 -1
  130. package/src/__tests__/subagent-manager-notify.test.ts +1 -3
  131. package/src/__tests__/subagent-notify-parent.test.ts +1 -3
  132. package/src/__tests__/subagent-spawn-tool-fork.test.ts +1 -1
  133. package/src/__tests__/title-generate-hook.test.ts +5 -1
  134. package/src/__tests__/tool-error-hook.test.ts +1 -1
  135. package/src/__tests__/tool-result-truncate-hook.test.ts +1 -1
  136. package/src/__tests__/tool-start-timestamp.test.ts +218 -0
  137. package/src/__tests__/user-plugin-loader.test.ts +54 -286
  138. package/src/__tests__/web-fetch.test.ts +45 -0
  139. package/src/acp/__tests__/agent-process.test.ts +161 -0
  140. package/src/acp/__tests__/client-handler.test.ts +40 -0
  141. package/src/acp/__tests__/helpers/acp-config-stub.ts +0 -2
  142. package/src/acp/__tests__/helpers/acp-history-db.ts +82 -0
  143. package/src/acp/__tests__/helpers/exec-file-stub.ts +106 -0
  144. package/src/acp/__tests__/prepare-agent-env.test.ts +97 -0
  145. package/src/acp/__tests__/session-manager-persistence.test.ts +95 -28
  146. package/src/acp/__tests__/session-manager-resume.test.ts +888 -0
  147. package/src/acp/agent-process.ts +61 -1
  148. package/src/acp/auto-install.test.ts +280 -0
  149. package/src/acp/auto-install.ts +232 -0
  150. package/src/acp/client-handler.ts +31 -0
  151. package/src/acp/prepare-agent-env.ts +80 -27
  152. package/src/acp/resolve-agent.test.ts +188 -28
  153. package/src/acp/resolve-agent.ts +119 -42
  154. package/src/acp/resume-hint.ts +23 -0
  155. package/src/acp/session-manager.ts +507 -73
  156. package/src/agent/compaction-circuit.ts +60 -102
  157. package/src/agent/loop.ts +403 -251
  158. package/src/api/events/tool-result.ts +9 -0
  159. package/src/api/events/tool-use-start.ts +7 -0
  160. package/src/api/responses/conversation-message.ts +72 -13
  161. package/src/api/responses/memory-v3-selection-log.ts +19 -10
  162. package/src/approvals/guardian-request-resolvers.ts +27 -1
  163. package/src/background-wake/next-wake.ts +1 -0
  164. package/src/cli/commands/__tests__/memory-v3.test.ts +191 -210
  165. package/src/cli/commands/channel-verification-sessions.ts +6 -6
  166. package/src/cli/commands/db/__tests__/repair.test.ts +3 -1
  167. package/src/cli/commands/memory-v3.ts +57 -199
  168. package/src/cli/commands/plugins.ts +43 -37
  169. package/src/cli/lib/__tests__/install-from-github.test.ts +790 -111
  170. package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +196 -0
  171. package/src/cli/lib/__tests__/plugin-details.test.ts +381 -0
  172. package/src/cli/lib/__tests__/plugin-marketplace.test.ts +270 -0
  173. package/src/cli/lib/__tests__/search-plugins.test.ts +233 -32
  174. package/src/cli/lib/install-from-github.ts +797 -60
  175. package/src/cli/lib/plugin-catalog-cache.ts +84 -0
  176. package/src/cli/lib/plugin-details.ts +416 -0
  177. package/src/cli/lib/plugin-marketplace.ts +215 -0
  178. package/src/cli/lib/search-plugins.ts +201 -29
  179. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  180. package/src/config/acp-defaults.test.ts +10 -0
  181. package/src/config/acp-defaults.ts +9 -3
  182. package/src/config/acp-schema.ts +1 -7
  183. package/src/config/bundled-skills/acp/SKILL.md +80 -41
  184. package/src/config/bundled-skills/acp/TOOLS.json +4 -4
  185. package/src/config/bundled-skills/app-builder/SKILL.md +224 -381
  186. package/src/config/bundled-skills/app-builder/TOOLS.json +72 -2
  187. package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +48 -0
  188. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +57 -0
  189. package/src/config/bundled-skills/app-builder/references/SLIDES.md +38 -0
  190. package/src/config/bundled-skills/app-builder/tools/app-list.ts +62 -0
  191. package/src/config/bundled-skills/app-builder/tools/app-update.ts +18 -0
  192. package/src/config/bundled-skills/document-editor/SKILL.md +28 -23
  193. package/src/config/bundled-skills/document-editor/TOOLS.json +1 -1
  194. package/src/config/bundled-tool-registry.ts +4 -0
  195. package/src/config/call-site-defaults.ts +0 -3
  196. package/src/config/feature-flag-registry.json +10 -56
  197. package/src/config/llm-resolver.ts +39 -7
  198. package/src/config/loader.ts +5 -22
  199. package/src/config/schemas/__tests__/memory-v3.test.ts +25 -9
  200. package/src/config/schemas/call-site-catalog.ts +0 -21
  201. package/src/config/schemas/heartbeat.ts +9 -0
  202. package/src/config/schemas/llm.ts +17 -3
  203. package/src/config/schemas/memory-v3.ts +58 -8
  204. package/src/config/seed-inference-profiles.ts +18 -0
  205. package/src/context/compactor.ts +22 -4
  206. package/src/context/post-turn-tool-result-truncation.ts +39 -1
  207. package/src/context/strip-injections.ts +8 -2
  208. package/src/daemon/conversation-agent-loop-handlers.ts +120 -42
  209. package/src/daemon/conversation-agent-loop.ts +308 -1297
  210. package/src/daemon/conversation-error.ts +31 -4
  211. package/src/daemon/conversation-history.ts +1 -1
  212. package/src/daemon/conversation-lifecycle.ts +11 -255
  213. package/src/daemon/conversation-media-retry.ts +19 -6
  214. package/src/daemon/conversation-messaging.ts +17 -0
  215. package/src/daemon/conversation-process.ts +22 -141
  216. package/src/daemon/conversation-queue-manager.ts +8 -0
  217. package/src/daemon/conversation-registry.ts +159 -0
  218. package/src/daemon/conversation-runtime-assembly.ts +361 -393
  219. package/src/daemon/conversation-store.ts +9 -90
  220. package/src/daemon/conversation-surfaces.ts +165 -11
  221. package/src/daemon/conversation-workspace.ts +17 -0
  222. package/src/daemon/conversation.ts +444 -62
  223. package/src/daemon/disk-pressure-policy.ts +0 -1
  224. package/src/daemon/external-plugins-bootstrap.ts +36 -46
  225. package/src/daemon/handlers/config-channels.ts +11 -2
  226. package/src/daemon/handlers/conversations.ts +3 -1
  227. package/src/daemon/handlers/shared.ts +9 -1
  228. package/src/daemon/handlers/skills.ts +4 -1
  229. package/src/daemon/host-app-control-proxy.ts +72 -57
  230. package/src/daemon/host-proxy-preactivation.ts +1 -3
  231. package/src/daemon/lifecycle.ts +21 -7
  232. package/src/daemon/persist-unsendable-image.ts +62 -25
  233. package/src/daemon/process-message.ts +1 -1
  234. package/src/daemon/server.ts +2 -0
  235. package/src/daemon/tool-side-effects.ts +15 -0
  236. package/src/daemon/wake-conversation-ops.ts +269 -0
  237. package/src/embedded/plugin-api.ts +2 -2
  238. package/src/export/__tests__/transcript-formatter.test.ts +5 -0
  239. package/src/heartbeat/__tests__/heartbeat-service.test.ts +3 -0
  240. package/src/heartbeat/heartbeat-run-store.ts +23 -1
  241. package/src/heartbeat/heartbeat-service.ts +26 -0
  242. package/src/ipc/__tests__/browser-ipc.test.ts +1 -1
  243. package/src/ipc/__tests__/ui-request-route.test.ts +3 -3
  244. package/src/ipc/skill-routes/__tests__/memory.test.ts +15 -0
  245. package/src/ipc/skill-routes/memory.ts +4 -2
  246. package/src/memory/__tests__/activation-session-store.test.ts +41 -0
  247. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +87 -0
  248. package/src/memory/__tests__/onboarding-events-store.test.ts +80 -0
  249. package/src/memory/activation-session-store.ts +43 -0
  250. package/src/memory/conversation-crud.ts +29 -19
  251. package/src/memory/conversation-starter-checkpoints.ts +1 -0
  252. package/src/memory/db-init.ts +6 -0
  253. package/src/memory/embedding-backend.ts +5 -22
  254. package/src/memory/job-handlers/conversation-starters.ts +13 -2
  255. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -4
  256. package/src/memory/jobs-worker.ts +25 -1
  257. package/src/memory/migrations/272-acp-session-history-cwd.ts +36 -0
  258. package/src/memory/migrations/273-onboarding-events-funnel-columns.ts +46 -0
  259. package/src/memory/migrations/274-create-activation-sessions.ts +15 -0
  260. package/src/memory/migrations/index.ts +3 -0
  261. package/src/memory/onboarding-events-store.ts +66 -18
  262. package/src/memory/schema/acp.ts +4 -0
  263. package/src/memory/schema/infrastructure.ts +13 -0
  264. package/src/memory/v2/__tests__/consolidation-job.test.ts +4 -97
  265. package/src/memory/v2/__tests__/page-store.test.ts +22 -0
  266. package/src/memory/v2/consolidation-job.ts +2 -63
  267. package/src/memory/v2/types.ts +5 -0
  268. package/src/messaging/providers/telegram-bot/api.ts +14 -5
  269. package/src/notifications/__tests__/copy-composer.test.ts +244 -0
  270. package/src/notifications/access-request-copy.ts +298 -0
  271. package/src/notifications/adapters/slack.ts +3 -3
  272. package/src/notifications/adapters/telegram.ts +9 -2
  273. package/src/notifications/copy-composer.ts +49 -267
  274. package/src/notifications/decision-engine.ts +16 -35
  275. package/src/notifications/home-feed-side-effect.ts +1 -6
  276. package/src/plugin-api/constants.ts +4 -0
  277. package/src/plugin-api/index.ts +40 -11
  278. package/src/plugin-api/types.ts +108 -0
  279. package/src/plugins/defaults/compaction/compact.ts +106 -0
  280. package/src/{daemon → plugins/defaults/compaction}/context-overflow-reducer.ts +250 -42
  281. package/src/plugins/defaults/compaction/corrected-target.ts +53 -0
  282. package/src/plugins/defaults/compaction/manager-store.ts +57 -0
  283. package/src/plugins/defaults/compaction/package.json +1 -2
  284. package/src/{context → plugins/defaults/compaction}/window-manager.ts +95 -25
  285. package/src/plugins/defaults/empty-response/package.json +0 -1
  286. package/src/plugins/defaults/history-repair/package.json +0 -1
  287. package/src/plugins/defaults/index.ts +156 -26
  288. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +100 -52
  289. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +285 -0
  290. package/src/plugins/defaults/memory-retrieval/injector-chain.ts +2 -2
  291. package/src/plugins/defaults/{injectors/register.ts → memory-retrieval/injectors.ts} +148 -73
  292. package/src/plugins/defaults/memory-retrieval/package.json +14 -0
  293. package/src/plugins/defaults/memory-retrieval/unified-turn-context.ts +223 -0
  294. package/src/plugins/defaults/memory-v3-shadow/__tests__/capabilities.test.ts +71 -0
  295. package/src/plugins/defaults/memory-v3-shadow/__tests__/dense.test.ts +181 -0
  296. package/src/plugins/defaults/memory-v3-shadow/__tests__/edge.test.ts +247 -0
  297. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/live-integration.test.ts +147 -134
  298. package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +456 -0
  299. package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +662 -0
  300. package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +306 -0
  301. package/src/plugins/defaults/memory-v3-shadow/__tests__/render-injection.test.ts +91 -0
  302. package/src/plugins/defaults/memory-v3-shadow/__tests__/section-dense-store.test.ts +402 -0
  303. package/src/plugins/defaults/memory-v3-shadow/__tests__/section-needle.test.ts +135 -0
  304. package/src/plugins/defaults/memory-v3-shadow/__tests__/sections.test.ts +125 -0
  305. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selection-log-store.test.ts +74 -19
  306. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +446 -0
  307. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +592 -0
  308. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/types.test.ts +2 -24
  309. package/src/plugins/defaults/memory-v3-shadow/capabilities.ts +91 -0
  310. package/src/plugins/defaults/memory-v3-shadow/dense.ts +97 -0
  311. package/src/plugins/defaults/memory-v3-shadow/edge.ts +252 -0
  312. package/src/plugins/defaults/memory-v3-shadow/hooks/post-compact.ts +14 -0
  313. package/src/plugins/defaults/memory-v3-shadow/hooks/user-prompt-submit.ts +19 -0
  314. package/src/plugins/defaults/memory-v3-shadow/injector.ts +76 -0
  315. package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +555 -0
  316. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +266 -0
  317. package/src/plugins/defaults/memory-v3-shadow/package.json +14 -0
  318. package/src/plugins/defaults/memory-v3-shadow/page-content.ts +71 -0
  319. package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +204 -0
  320. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/render-injection.ts +16 -8
  321. package/src/plugins/defaults/memory-v3-shadow/section-dense-store.ts +236 -0
  322. package/src/plugins/defaults/memory-v3-shadow/section-needle.ts +200 -0
  323. package/src/plugins/defaults/memory-v3-shadow/sections.ts +115 -0
  324. package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +156 -0
  325. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +382 -0
  326. package/src/plugins/defaults/memory-v3-shadow/types.ts +92 -0
  327. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/working-set.ts +4 -1
  328. package/src/plugins/defaults/title-generate/package.json +0 -1
  329. package/src/plugins/defaults/tool-error/package.json +0 -1
  330. package/src/plugins/defaults/tool-result-truncate/package.json +0 -1
  331. package/src/plugins/external-api.ts +12 -2
  332. package/src/plugins/pipeline.ts +6 -293
  333. package/src/plugins/registry.ts +9 -37
  334. package/src/plugins/types.ts +76 -381
  335. package/src/plugins/user-loader.ts +30 -127
  336. package/src/prompts/__tests__/system-prompt.test.ts +6 -0
  337. package/src/prompts/system-prompt.ts +61 -10
  338. package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +71 -4
  339. package/src/providers/anthropic/client.ts +9 -10
  340. package/src/providers/inference/kimi-cjk-token-ids.ts +493 -0
  341. package/src/providers/inference/logit-bias.ts +55 -0
  342. package/src/providers/model-catalog.ts +57 -0
  343. package/src/providers/openai/__tests__/vision-not-supported.test.ts +75 -0
  344. package/src/providers/openai/chat-completions-provider.ts +44 -1
  345. package/src/providers/retry.ts +57 -7
  346. package/src/providers/types.ts +6 -0
  347. package/src/runtime/__tests__/agent-wake.test.ts +555 -691
  348. package/src/runtime/__tests__/interactive-ui.test.ts +1 -1
  349. package/src/runtime/agent-wake.ts +108 -209
  350. package/src/runtime/assistant-event-hub.ts +1 -1
  351. package/src/runtime/channel-approvals.ts +1 -1
  352. package/src/runtime/interactive-ui.ts +1 -1
  353. package/src/runtime/routes/__tests__/acp-routes.test.ts +466 -55
  354. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
  355. package/src/runtime/routes/__tests__/plugins-routes.test.ts +423 -73
  356. package/src/runtime/routes/__tests__/stt-routes.test.ts +112 -0
  357. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +5 -4
  358. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +4 -1
  359. package/src/runtime/routes/acp-routes.test.ts +185 -32
  360. package/src/runtime/routes/acp-routes.ts +328 -30
  361. package/src/runtime/routes/app-management-routes.ts +3 -0
  362. package/src/runtime/routes/approval-routes.ts +1 -1
  363. package/src/runtime/routes/browser-routes.ts +1 -1
  364. package/src/runtime/routes/browser-tabs-routes.ts +6 -10
  365. package/src/runtime/routes/channel-verification-routes.ts +14 -5
  366. package/src/runtime/routes/conversation-cli-routes.ts +1 -1
  367. package/src/runtime/routes/conversation-list-routes.ts +1 -1
  368. package/src/runtime/routes/conversation-query-routes.ts +1 -1
  369. package/src/runtime/routes/conversation-routes.ts +30 -2
  370. package/src/runtime/routes/conversation-starter-routes.ts +13 -7
  371. package/src/runtime/routes/conversations-import-routes.ts +24 -7
  372. package/src/runtime/routes/host-app-control-routes.ts +1 -1
  373. package/src/runtime/routes/host-cu-routes.ts +1 -1
  374. package/src/runtime/routes/identity-routes.ts +18 -3
  375. package/src/runtime/routes/inbound-message-handler.ts +1 -1
  376. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +33 -34
  377. package/src/runtime/routes/inference-profile-session-handler.ts +11 -0
  378. package/src/runtime/routes/inference-profile-session-reaper.ts +6 -0
  379. package/src/runtime/routes/memory-v3-routes.ts +65 -305
  380. package/src/runtime/routes/playground/__tests__/force-compact.test.ts +1 -1
  381. package/src/runtime/routes/playground/helpers.ts +1 -1
  382. package/src/runtime/routes/plugins-routes.ts +337 -35
  383. package/src/runtime/routes/stt-routes.ts +45 -12
  384. package/src/runtime/routes/surface-conversation-resolver.ts +4 -3
  385. package/src/runtime/routes/work-items-routes.ts +2 -4
  386. package/src/runtime/routes/workspace-routes.ts +50 -15
  387. package/src/runtime/services/conversation-serializer.ts +1 -1
  388. package/src/runtime/verification-outbound-actions.ts +147 -2
  389. package/src/runtime/verification-templates.ts +29 -3
  390. package/src/services/published-app-updater.ts +30 -8
  391. package/src/signals/cancel.ts +2 -4
  392. package/src/subagent/manager.ts +21 -5
  393. package/src/telemetry/__tests__/activation-funnel.test.ts +95 -0
  394. package/src/telemetry/activation-funnel.ts +167 -0
  395. package/src/telemetry/types.ts +13 -0
  396. package/src/telemetry/usage-telemetry-reporter.test.ts +154 -0
  397. package/src/telemetry/usage-telemetry-reporter.ts +26 -1
  398. package/src/tools/acp/context.ts +20 -0
  399. package/src/tools/acp/list-agents.test.ts +9 -19
  400. package/src/tools/acp/list-agents.ts +3 -15
  401. package/src/tools/acp/spawn.test.ts +173 -202
  402. package/src/tools/acp/spawn.ts +37 -172
  403. package/src/tools/acp/steer.test.ts +105 -8
  404. package/src/tools/acp/steer.ts +48 -17
  405. package/src/tools/apps/executors.ts +166 -50
  406. package/src/tools/browser/browser-execution.ts +12 -2
  407. package/src/tools/filesystem/write.ts +34 -0
  408. package/src/tools/network/web-fetch.ts +65 -24
  409. package/src/tools/skills/load.ts +1 -1
  410. package/src/tools/subagent/spawn.ts +2 -4
  411. package/src/tools/ui-surface/definitions.ts +32 -5
  412. package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +4 -5
  413. package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +69 -45
  414. package/docs/plugins.md +0 -832
  415. package/examples/plugins/echo/register.ts +0 -143
  416. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -405
  417. package/src/__tests__/compaction-pipeline.test.ts +0 -210
  418. package/src/__tests__/compaction-timeout-recovery.test.ts +0 -251
  419. package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -667
  420. package/src/__tests__/pipeline-runner.test.ts +0 -554
  421. package/src/daemon/wake-target-adapter.ts +0 -253
  422. package/src/memory/v3/__tests__/assign.test.ts +0 -242
  423. package/src/memory/v3/__tests__/capabilities.test.ts +0 -118
  424. package/src/memory/v3/__tests__/core.test.ts +0 -39
  425. package/src/memory/v3/__tests__/health.test.ts +0 -219
  426. package/src/memory/v3/__tests__/maintain-job.test.ts +0 -288
  427. package/src/memory/v3/__tests__/needle.test.ts +0 -107
  428. package/src/memory/v3/__tests__/orchestrate.test.ts +0 -436
  429. package/src/memory/v3/__tests__/provider-blocks.test.ts +0 -13
  430. package/src/memory/v3/__tests__/reconcile.test.ts +0 -274
  431. package/src/memory/v3/__tests__/render-injection.test.ts +0 -61
  432. package/src/memory/v3/__tests__/router.test.ts +0 -332
  433. package/src/memory/v3/__tests__/selector.test.ts +0 -470
  434. package/src/memory/v3/__tests__/shadow-plugin.test.ts +0 -432
  435. package/src/memory/v3/__tests__/snapshot.test.ts +0 -168
  436. package/src/memory/v3/__tests__/tree.test.ts +0 -192
  437. package/src/memory/v3/assign.ts +0 -268
  438. package/src/memory/v3/capabilities.ts +0 -124
  439. package/src/memory/v3/core.ts +0 -26
  440. package/src/memory/v3/health.ts +0 -0
  441. package/src/memory/v3/maintain-job.ts +0 -314
  442. package/src/memory/v3/needle.ts +0 -115
  443. package/src/memory/v3/orchestrate.ts +0 -126
  444. package/src/memory/v3/page-content.ts +0 -34
  445. package/src/memory/v3/provider-blocks.ts +0 -26
  446. package/src/memory/v3/reconcile.ts +0 -523
  447. package/src/memory/v3/router.ts +0 -190
  448. package/src/memory/v3/selection-log-store.ts +0 -84
  449. package/src/memory/v3/selector.ts +0 -226
  450. package/src/memory/v3/shadow-plugin.ts +0 -411
  451. package/src/memory/v3/snapshot.ts +0 -209
  452. package/src/memory/v3/tree.ts +0 -174
  453. package/src/memory/v3/types.ts +0 -59
  454. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +0 -187
  455. package/src/plugins/defaults/circuit-breaker/middlewares/circuitBreaker.ts +0 -93
  456. package/src/plugins/defaults/circuit-breaker/package.json +0 -15
  457. package/src/plugins/defaults/circuit-breaker/register.ts +0 -39
  458. package/src/plugins/defaults/compaction/middlewares/compaction.ts +0 -25
  459. package/src/plugins/defaults/compaction/register.ts +0 -35
  460. package/src/plugins/defaults/compaction/terminal.ts +0 -73
  461. package/src/plugins/defaults/empty-response/register.ts +0 -23
  462. package/src/plugins/defaults/history-repair/register.ts +0 -24
  463. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +0 -216
  464. package/src/plugins/defaults/overflow-reduce/middlewares/overflowReduce.ts +0 -126
  465. package/src/plugins/defaults/overflow-reduce/package.json +0 -15
  466. package/src/plugins/defaults/overflow-reduce/register.ts +0 -42
  467. package/src/plugins/defaults/title-generate/register.ts +0 -35
  468. package/src/plugins/defaults/tool-error/register.ts +0 -23
  469. package/src/plugins/defaults/tool-result-truncate/register.ts +0 -24
  470. package/src/proactive-artifact/aux-message-injector.ts +0 -97
  471. package/src/proactive-artifact/decision.test.ts +0 -226
  472. package/src/proactive-artifact/decision.ts +0 -165
  473. package/src/proactive-artifact/index.ts +0 -7
  474. package/src/proactive-artifact/job.test.ts +0 -962
  475. package/src/proactive-artifact/job.ts +0 -372
  476. package/src/proactive-artifact/message-copy.ts +0 -58
  477. package/src/proactive-artifact/trigger-state.test.ts +0 -286
  478. package/src/proactive-artifact/trigger-state.ts +0 -123
  479. package/src/util/map-limit.ts +0 -27
  480. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/eval-turns.json +0 -0
  481. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/live-turns.json +0 -0
  482. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-eviction.test.ts +0 -0
  483. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-skeleton.test.ts +0 -0
  484. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/README.md +0 -0
  485. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/assignments.json +0 -0
  486. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/core.json +0 -0
  487. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-x.md +0 -0
  488. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-y.md +0 -0
  489. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-b/topic-z.md +0 -0
  490. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/llm-retry.ts +0 -0
@@ -4,9 +4,9 @@
4
4
  * SCOPE / ALTITUDE. A full daemon-assembly integration (plugin registry → flag
5
5
  * read → runtime assembly → provider call) is too heavy and too mock-fragile
6
6
  * for a unit test. Instead this composes the REAL v3 live-path units with a
7
- * mocked routing/selection provider and synthetic fixtures:
7
+ * mocked select provider + stubbed dense lane and synthetic fixtures:
8
8
  *
9
- * orchestrate (routeL1 + selectAcrossLeaves over a shared WorkingSet)
9
+ * orchestrate (needle ∪ dense ∪ edge → selectPool over a shared WorkingSet)
10
10
  * → renderMemoryBlock (the rendered `<memory>` working-set block)
11
11
  * → stripAllMemoryInjections (all-turns history strip)
12
12
  *
@@ -16,108 +16,103 @@
16
16
  * message so exactly one block exists. Driving these real units across turns
17
17
  * exercises carry-forward, eviction, single-source, and strip-all end-to-end at
18
18
  * the v3 layer without the daemon. The provider is stubbed (no network).
19
- *
20
- * Mock-leak safety: the only `mock.module` here stub the provider + logger,
21
- * which are pure inputs to orchestrate and carry no real behavior siblings
22
- * depend on (orchestrate.test.ts installs the identical stubs). No
23
- * snapshot-real-modules dance is needed because nothing is partially stubbed.
24
19
  */
25
20
 
26
- import { beforeEach, describe, expect, mock, test } from "bun:test";
21
+ import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
27
22
 
23
+ import { stripAllMemoryInjections } from "../../../../memory/graph/conversation-graph-memory.js";
24
+ import type { PageIndexEntry } from "../../../../memory/v2/page-index.js";
28
25
  import type {
29
26
  ContentBlock,
30
27
  Message,
31
28
  Provider,
32
29
  ProviderResponse,
33
- } from "../../../providers/types.js";
34
- import { stripAllMemoryInjections } from "../../graph/conversation-graph-memory.js";
35
- import type { NeedleIndex } from "../needle.js";
36
- import type {
37
- LeafNode,
38
- LeafPath,
39
- LeafTree,
40
- Slug,
41
- TurnContext,
42
- } from "../types.js";
43
- import liveTurns from "./fixtures/live-turns.json" with { type: "json" };
30
+ } from "../../../../providers/types.js";
31
+ import type { EdgeGraph } from "../edge.js";
32
+ import { buildEdgeGraph } from "../edge.js";
33
+ import { buildSectionNeedle } from "../section-needle.js";
34
+ import { buildSectionIndex } from "../sections.js";
35
+ import type { MemoryRoutingTurn, SectionIndex, Slug } from "../types.js";
44
36
 
45
37
  // ---------------------------------------------------------------------------
46
- // Provider mock installed BEFORE the orchestrator import so router.ts and
47
- // selector.ts observe it at load time. Mirrors orchestrate.test.ts.
38
+ // Module stubs installed BEFORE the orchestrator import.
48
39
  // ---------------------------------------------------------------------------
49
40
 
50
41
  let providerStub: Provider | null = null;
51
42
 
52
- mock.module("../../../providers/provider-send-message.js", () => ({
43
+ mock.module("../../../../providers/provider-send-message.js", () => ({
53
44
  getConfiguredProvider: async () => providerStub,
54
45
  extractToolUse: (response: ProviderResponse) =>
55
46
  response.content.find((b) => b.type === "tool_use"),
56
47
  }));
57
48
 
58
- mock.module("../../../util/logger.js", () => ({
49
+ mock.module("../../../../util/logger.js", () => ({
59
50
  getLogger: () =>
60
51
  new Proxy({} as Record<string, unknown>, {
61
52
  get: (_t, prop) => (prop === "child" ? () => ({}) : () => {}),
62
53
  }),
63
54
  }));
64
55
 
56
+ // The dense lane never hits in this fixture — the needle drives the pool. The
57
+ // stub DELEGATES to the real `denseLane` unless this file's tests are running
58
+ // (`denseMockActive`), so the process-global `mock.module` cannot leak fake
59
+ // behavior into dense.test.ts (which exercises the real lane).
60
+ const realDense = { ...(await import("../dense.js")) };
61
+ let denseMockActive = false;
62
+ mock.module("../dense.js", () => ({
63
+ ...realDense,
64
+ denseLane: async (...args: Parameters<typeof realDense.denseLane>) =>
65
+ denseMockActive ? [] : realDense.denseLane(...args),
66
+ }));
67
+
65
68
  const { orchestrate } = await import("../orchestrate.js");
66
69
  const { WorkingSet } = await import("../working-set.js");
67
70
  const { renderMemoryBlock } = await import("../render-injection.js");
68
71
 
69
72
  // ---------------------------------------------------------------------------
70
- // Fixture types + helpers.
73
+ // Fixtures: a tiny corpus whose section text contains a distinctive term per
74
+ // page so a query selects exactly that page via the needle.
71
75
  // ---------------------------------------------------------------------------
72
76
 
73
- interface LeafSelection {
74
- ids: number[];
75
- pinned_ids: number[];
76
- }
77
- interface LiveTurn {
78
- name: string;
79
- currentMessage: string;
80
- routeIds: number[];
81
- leafSelections: Record<LeafPath, LeafSelection>;
82
- }
83
- const TURNS = (liveTurns as unknown as { turns: LiveTurn[] }).turns;
84
-
85
- function makeLeaf(path: LeafPath, members: Slug[]): LeafNode {
86
- return {
87
- path,
88
- frontmatter: { path, in_core: false },
89
- description: `description for ${path}`,
90
- members,
91
- domain: path.split("/")[0],
92
- };
93
- }
94
-
95
- /**
96
- * Synthetic tree. Sorted leaf order is [domain-a/topic-x, domain-a/topic-y],
97
- * so L1 id 1 → topic-x, id 2 → topic-y.
98
- */
99
- function makeTree(): LeafTree {
100
- const leaves: LeafNode[] = [
101
- makeLeaf("domain-a/topic-x", ["page-a", "page-b"]),
102
- makeLeaf("domain-a/topic-y", ["page-c"]),
103
- ];
104
- const byPage = new Map<Slug, LeafPath[]>();
105
- for (const leaf of leaves) {
106
- for (const slug of leaf.members) {
107
- byPage.set(slug, [...(byPage.get(slug) ?? []), leaf.path]);
108
- }
109
- }
110
- return { leaves: new Map(leaves.map((n) => [n.path, n])), byPage };
77
+ const PAGES: Record<Slug, string> = {
78
+ "page-a": "lead a\n## Body\napple content for page a",
79
+ "page-b": "lead b\n## Body\nbanana content for page b",
80
+ "page-c": "lead c\n## Body\ncherry content for page c",
81
+ };
82
+ const SLUGS = Object.keys(PAGES);
83
+
84
+ function makeEntries(): PageIndexEntry[] {
85
+ return SLUGS.map((slug, i) => ({
86
+ id: i + 1,
87
+ slug,
88
+ summary: `summary of ${slug}`,
89
+ edges: [],
90
+ leaves: [],
91
+ modifiedAt: 0,
92
+ }));
111
93
  }
112
94
 
113
- const summaryOf = async (slug: Slug): Promise<string> => `summary of ${slug}`;
114
- /** Deterministic per-slug body so the rendered `<memory>` block is assertable. */
95
+ const config = {} as never;
115
96
  const contentOf = async (slug: Slug): Promise<string> => `body for ${slug}`;
116
97
 
117
- /** Needle that never hits — routing alone drives the open set in this fixture. */
118
- const emptyNeedle: NeedleIndex = { query: () => [] };
98
+ async function buildLanes(): Promise<{
99
+ sectionIndex: SectionIndex;
100
+ needle: ReturnType<typeof buildSectionNeedle>;
101
+ edgeGraph: EdgeGraph;
102
+ }> {
103
+ const sectionIndex = await buildSectionIndex(SLUGS, async (s) => PAGES[s]!);
104
+ const needle = buildSectionNeedle(sectionIndex);
105
+ const edgeGraph = await buildEdgeGraph(
106
+ makeEntries(),
107
+ async (s) => PAGES[s]!, // no `links:` frontmatter → edge graph is empty
108
+ );
109
+ return { sectionIndex, needle, edgeGraph };
110
+ }
119
111
 
120
- function makeTurn(turnNumber: number, currentMessage: string): TurnContext {
112
+ function makeTurn(
113
+ turnNumber: number,
114
+ currentMessage: string,
115
+ ): MemoryRoutingTurn {
121
116
  return {
122
117
  conversationId: "conv-xyz",
123
118
  turnNumber,
@@ -126,71 +121,72 @@ function makeTurn(turnNumber: number, currentMessage: string): TurnContext {
126
121
  };
127
122
  }
128
123
 
129
- function toolUseResponse(
130
- name: string,
131
- input: Record<string, unknown>,
132
- ): ProviderResponse {
124
+ function toolUseResponse(input: Record<string, unknown>): ProviderResponse {
133
125
  return {
134
126
  model: "stub-model",
135
127
  stopReason: "tool_use",
136
128
  usage: { inputTokens: 0, outputTokens: 0 },
137
- content: [{ type: "tool_use", id: "tu-1", name, input }],
129
+ content: [{ type: "tool_use", id: "tu-1", name: "select_pages", input }],
138
130
  };
139
131
  }
140
132
 
141
- /** Last `<leaf>X</leaf>` tag found in an L2 request, or undefined. */
142
- function leafFromMessages(messages: Message[]): LeafPath | undefined {
133
+ /** Parse the numbered `<candidates>` block into an ordered slug list. */
134
+ function candidateSlugs(messages: Message[]): Slug[] {
143
135
  for (const msg of messages) {
144
136
  for (const block of msg.content) {
145
- if (block.type === "text") {
146
- const m = /<leaf>([^<]+)<\/leaf>/.exec(block.text);
147
- if (m) return m[1];
148
- }
137
+ if (block.type !== "text") continue;
138
+ const m = /<candidates>\n([\s\S]*?)\n<\/candidates>/.exec(block.text);
139
+ if (!m) continue;
140
+ return m[1]
141
+ .split("\n")
142
+ .map((line) => /^\[\d+\] (\S+) —/.exec(line)?.[1])
143
+ .filter((s): s is string => !!s);
149
144
  }
150
145
  }
151
- return undefined;
146
+ return [];
152
147
  }
153
148
 
154
- /**
155
- * Build a provider that answers L1 `open_leaves` with `routeIds` and each L2
156
- * `select_pages` call with the per-leaf selection from the fixture turn.
157
- */
158
- function providerForTurn(turn: LiveTurn): Provider {
149
+ /** Provider that selects (and optionally pins) the pooled candidates in `keep`. */
150
+ function selectProvider(keep: Slug[], pin: Slug[] = []): Provider {
159
151
  return {
160
152
  name: "stub",
161
- sendMessage: async (messages, options) => {
162
- const toolName = options?.tools?.[0]?.name;
163
- if (toolName === "open_leaves") {
164
- return toolUseResponse("open_leaves", { ids: turn.routeIds });
165
- }
166
- const leaf = leafFromMessages(messages);
167
- const sel = (leaf ? turn.leafSelections[leaf] : undefined) ?? {
168
- ids: [],
169
- pinned_ids: [],
170
- };
171
- return toolUseResponse("select_pages", {
172
- ids: sel.ids,
173
- pinned_ids: sel.pinned_ids,
153
+ sendMessage: async (messages) => {
154
+ const pool = candidateSlugs(messages);
155
+ const ids: number[] = [];
156
+ const pinned_ids: number[] = [];
157
+ pool.forEach((slug, i) => {
158
+ if (keep.includes(slug)) ids.push(i + 1);
159
+ if (pin.includes(slug)) pinned_ids.push(i + 1);
174
160
  });
161
+ return toolUseResponse({ ids, pinned_ids });
175
162
  },
176
163
  };
177
164
  }
178
165
 
179
166
  /** Run one turn through orchestrate over the shared working set + render it. */
180
167
  async function runTurn(
181
- turn: LiveTurn,
182
168
  turnNumber: number,
183
- deps: { tree: LeafTree; workingSet: InstanceType<typeof WorkingSet> },
169
+ query: string,
170
+ keep: Slug[],
171
+ pin: Slug[],
172
+ deps: {
173
+ lanes: Awaited<ReturnType<typeof buildLanes>>;
174
+ workingSet: InstanceType<typeof WorkingSet>;
175
+ },
184
176
  ) {
185
- providerStub = providerForTurn(turn);
186
- const result = await orchestrate(makeTurn(turnNumber, turn.currentMessage), {
187
- tree: deps.tree,
188
- core: new Set(),
189
- needle: emptyNeedle,
177
+ providerStub = selectProvider(keep, pin);
178
+ const result = await orchestrate(makeTurn(turnNumber, query), {
179
+ sectionIndex: deps.lanes.sectionIndex,
180
+ needle: deps.lanes.needle,
181
+ denseConfig: config,
182
+ edgeGraph: deps.lanes.edgeGraph,
190
183
  workingSet: deps.workingSet,
191
- pageSummary: summaryOf,
192
184
  });
193
- const block = await renderMemoryBlock(result.finalInjection, contentOf);
185
+ const block = await renderMemoryBlock(
186
+ result.finalInjection,
187
+ result.sectionBySlug,
188
+ contentOf,
189
+ );
194
190
  return { result, block };
195
191
  }
196
192
 
@@ -200,9 +196,14 @@ function countMemoryBlocks(text: string): number {
200
196
  }
201
197
 
202
198
  beforeEach(() => {
199
+ denseMockActive = true;
203
200
  providerStub = null;
204
201
  });
205
202
 
203
+ afterAll(() => {
204
+ denseMockActive = false;
205
+ });
206
+
206
207
  // ---------------------------------------------------------------------------
207
208
  // Carry-forward: a page pinned in turn 1 appears in turn 2's injected block
208
209
  // WITHOUT being re-selected in turn 2 (same WorkingSet reused across turns).
@@ -210,20 +211,23 @@ beforeEach(() => {
210
211
 
211
212
  describe("memory-v3 live — carry-forward across turns", () => {
212
213
  test("a page pinned in turn 1 is injected in turn 2 without re-selection", async () => {
213
- const tree = makeTree();
214
+ const lanes = await buildLanes();
214
215
  const workingSet = new WorkingSet();
215
216
 
216
- const t1 = await runTurn(TURNS[0], 1, { tree, workingSet });
217
- // page-a was selected (and pinned) this turn and rendered into the block.
217
+ const t1 = await runTurn(1, "apple", ["page-a"], ["page-a"], {
218
+ lanes,
219
+ workingSet,
220
+ });
218
221
  expect(t1.result.currentSelections.map((s) => s.slug)).toContain("page-a");
219
222
  expect(t1.block).toContain("body for page-a");
220
223
 
221
- const t2 = await runTurn(TURNS[1], 2, { tree, workingSet });
222
- // Turn 2 opens a DIFFERENT leaf (topic-y) and never re-selects page-a…
224
+ const t2 = await runTurn(2, "cherry", ["page-c"], [], {
225
+ lanes,
226
+ workingSet,
227
+ });
223
228
  expect(t2.result.currentSelections.map((s) => s.slug)).not.toContain(
224
229
  "page-a",
225
230
  );
226
- // …yet page-a carries forward into the injected block via the working set.
227
231
  expect(t2.result.finalInjection).toContain("page-a");
228
232
  expect(t2.block).toContain("body for page-a");
229
233
  });
@@ -236,24 +240,36 @@ describe("memory-v3 live — carry-forward across turns", () => {
236
240
 
237
241
  describe("memory-v3 live — eviction reflected in the injected block", () => {
238
242
  test("a stale non-pinned page drops out; the pinned page persists", async () => {
239
- const tree = makeTree();
243
+ const lanes = await buildLanes();
240
244
  // Small window: a non-pinned entry unseen for >2 turns evicts. page-b is
241
245
  // selected only in turn 1, so by turn 4 (4-1=3 > 2) it ages out; pinned
242
246
  // page-a never evicts; page-c is re-selected every later turn.
243
247
  const workingSet = new WorkingSet(150, 2);
244
248
 
245
- const t1 = await runTurn(TURNS[0], 1, { tree, workingSet });
249
+ const t1 = await runTurn(
250
+ 1,
251
+ "apple banana",
252
+ ["page-a", "page-b"],
253
+ ["page-a"],
254
+ { lanes, workingSet },
255
+ );
246
256
  expect(t1.result.finalInjection).toContain("page-b");
247
257
  expect(t1.block).toContain("body for page-b");
248
258
 
249
- // Turns 2–3 keep page-b inside the window (3-1=2, not > 2).
250
- await runTurn(TURNS[1], 2, { tree, workingSet });
251
- const t3 = await runTurn(TURNS[2], 3, { tree, workingSet });
259
+ // Turns 2–3 keep page-b inside the window (3-1=2, not > 2); re-select page-c.
260
+ await runTurn(2, "cherry", ["page-c"], [], { lanes, workingSet });
261
+ const t3 = await runTurn(3, "cherry", ["page-c"], [], {
262
+ lanes,
263
+ workingSet,
264
+ });
252
265
  expect(t3.result.finalInjection).toContain("page-b");
253
266
 
254
267
  // Turn 4: page-b is now stale (4-1=3 > 2) and must be gone from the block;
255
268
  // pinned page-a and freshly-selected page-c remain.
256
- const t4 = await runTurn(TURNS[3], 4, { tree, workingSet });
269
+ const t4 = await runTurn(4, "cherry", ["page-c"], [], {
270
+ lanes,
271
+ workingSet,
272
+ });
257
273
  expect(t4.result.finalInjection).not.toContain("page-b");
258
274
  expect(t4.block).not.toContain("body for page-b");
259
275
  expect(t4.result.finalInjection).toContain("page-a");
@@ -263,17 +279,20 @@ describe("memory-v3 live — eviction reflected in the injected block", () => {
263
279
 
264
280
  // ---------------------------------------------------------------------------
265
281
  // Single source: orchestrate → render produces exactly one coherent `<memory>`
266
- // block per turn. (Assembly-level v2 suppression is covered by the assembly
267
- // tests; here we assert the v3 producer never emits more than one block.)
282
+ // block per turn.
268
283
  // ---------------------------------------------------------------------------
269
284
 
270
285
  describe("memory-v3 live — single memory source", () => {
271
286
  test("each turn renders exactly one <memory> block", async () => {
272
- const tree = makeTree();
287
+ const lanes = await buildLanes();
273
288
  const workingSet = new WorkingSet();
274
289
 
275
- for (const [i, turn] of TURNS.entries()) {
276
- const { block } = await runTurn(turn, i + 1, { tree, workingSet });
290
+ const queries = ["apple", "banana", "cherry"];
291
+ for (const [i, query] of queries.entries()) {
292
+ const { block } = await runTurn(i + 1, query, [SLUGS[i]!], [], {
293
+ lanes,
294
+ workingSet,
295
+ });
277
296
  expect(countMemoryBlocks(block)).toBe(1);
278
297
  expect(block.startsWith("<memory>\n")).toBe(true);
279
298
  expect(block.endsWith("\n</memory>")).toBe(true);
@@ -288,10 +307,9 @@ describe("memory-v3 live — single memory source", () => {
288
307
 
289
308
  describe("memory-v3 live — all-turns history strip", () => {
290
309
  test("historical <memory> blocks strip back to byte-stable user history", async () => {
291
- const tree = makeTree();
310
+ const lanes = await buildLanes();
292
311
  const workingSet = new WorkingSet();
293
312
 
294
- // The canonical (un-injected) user history the strip must converge to.
295
313
  const baseHistory: Message[] = [
296
314
  { role: "user", content: [{ type: "text", text: "first user message" }] },
297
315
  { role: "assistant", content: [{ type: "text", text: "ok" }] },
@@ -303,17 +321,14 @@ describe("memory-v3 live — all-turns history strip", () => {
303
321
  { role: "user", content: [{ type: "text", text: "third user message" }] },
304
322
  ];
305
323
 
306
- // Simulate prior turns having injected a v3 `<memory>` block onto EVERY
307
- // historical user message (prepended, as the live path does).
308
324
  const memBlock = (text: string): ContentBlock => ({ type: "text", text });
325
+ const queries = ["apple", "banana", "cherry"];
309
326
  let injected: Message[] = baseHistory;
310
- for (let turnNumber = 1; turnNumber <= TURNS.length; turnNumber++) {
311
- const { block } = await runTurn(TURNS[turnNumber - 1], turnNumber, {
312
- tree,
327
+ for (const [i, query] of queries.entries()) {
328
+ const { block } = await runTurn(i + 1, query, [SLUGS[i]!], [], {
329
+ lanes,
313
330
  workingSet,
314
331
  });
315
- // Re-inject this turn's freshly-rendered block onto each user message,
316
- // after stripping the prior turn's block (what the live assembly does).
317
332
  const stripped = stripAllMemoryInjections(injected);
318
333
  injected = stripped.map((m) =>
319
334
  m.role === "user"
@@ -322,8 +337,6 @@ describe("memory-v3 live — all-turns history strip", () => {
322
337
  );
323
338
  }
324
339
 
325
- // After a final all-turns strip, history is byte-identical to the canonical
326
- // base — every injected block was recognized and removed.
327
340
  const finalStripped = stripAllMemoryInjections(injected);
328
341
  expect(finalStripped).toEqual(baseHistory);
329
342
  });