@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
@@ -1,436 +0,0 @@
1
- /**
2
- * Tests for `assistant/src/memory/v3/orchestrate.ts`.
3
- *
4
- * The orchestrator composes four lanes: L1 routing + BM25 needle (parallel) →
5
- * open set (routed ∪ core ∪ needle-owning leaves) → bounded per-leaf L2
6
- * selection → carry-forward working set (record + evict) → final injection.
7
- *
8
- * The provider is stubbed (no network). A single stub answers BOTH the L1
9
- * `open_leaves` call and the per-leaf L2 `select_pages` calls by inspecting the
10
- * forced tool name and, for L2, the `<leaf>...</leaf>` tag in the prompt. The
11
- * needle is a hand-built fake so we control its hits directly.
12
- */
13
-
14
- import { beforeEach, describe, expect, mock, test } from "bun:test";
15
-
16
- import type {
17
- Message,
18
- Provider,
19
- ProviderResponse,
20
- } from "../../../providers/types.js";
21
- import type { NeedleIndex } from "../needle.js";
22
- import type {
23
- LeafNode,
24
- LeafPath,
25
- LeafTree,
26
- Slug,
27
- TurnContext,
28
- } from "../types.js";
29
- import evalTurns from "./fixtures/eval-turns.json" with { type: "json" };
30
-
31
- // ---------------------------------------------------------------------------
32
- // Provider mock installed BEFORE the orchestrator import so router.ts and
33
- // selector.ts observe it at load time.
34
- // ---------------------------------------------------------------------------
35
-
36
- let providerStub: Provider | null = null;
37
-
38
- mock.module("../../../providers/provider-send-message.js", () => ({
39
- getConfiguredProvider: async () => providerStub,
40
- extractToolUse: (response: ProviderResponse) =>
41
- response.content.find((b) => b.type === "tool_use"),
42
- }));
43
-
44
- mock.module("../../../util/logger.js", () => ({
45
- getLogger: () =>
46
- new Proxy({} as Record<string, unknown>, {
47
- get: (_t, prop) => (prop === "child" ? () => ({}) : () => {}),
48
- }),
49
- }));
50
-
51
- const { orchestrate, DEFAULT_NEEDLE_K } = await import("../orchestrate.js");
52
- const { WorkingSet } = await import("../working-set.js");
53
-
54
- // ---------------------------------------------------------------------------
55
- // Fixture types + helpers.
56
- // ---------------------------------------------------------------------------
57
-
58
- interface LeafSelection {
59
- ids: number[];
60
- pinned_ids: number[];
61
- }
62
- interface EvalTurn {
63
- name: string;
64
- currentMessage: string;
65
- routeIds: number[];
66
- leafSelections: Record<LeafPath, LeafSelection>;
67
- expectedOpenedLeaves: LeafPath[];
68
- expectedFinalInjection: Slug[];
69
- }
70
- const TURNS = (evalTurns as { turns: EvalTurn[] }).turns;
71
-
72
- function makeLeaf(path: LeafPath, members: Slug[]): LeafNode {
73
- return {
74
- path,
75
- frontmatter: { path, in_core: false },
76
- description: `description for ${path}`,
77
- members,
78
- domain: path.split("/")[0],
79
- };
80
- }
81
-
82
- /**
83
- * Synthetic tree. Sorted leaf order is [domain-a/topic-x, domain-a/topic-y],
84
- * so L1 id 1 → topic-x, id 2 → topic-y.
85
- */
86
- function makeTree(): LeafTree {
87
- const leaves: LeafNode[] = [
88
- makeLeaf("domain-a/topic-x", ["page-a", "page-b"]),
89
- makeLeaf("domain-a/topic-y", ["page-c"]),
90
- ];
91
- const byPage = new Map<Slug, LeafPath[]>();
92
- for (const leaf of leaves) {
93
- for (const slug of leaf.members) {
94
- byPage.set(slug, [...(byPage.get(slug) ?? []), leaf.path]);
95
- }
96
- }
97
- return { leaves: new Map(leaves.map((n) => [n.path, n])), byPage };
98
- }
99
-
100
- const summaryOf = async (slug: Slug): Promise<string> => `summary of ${slug}`;
101
-
102
- /** Needle that returns a fixed slug list, ignoring the query. */
103
- function fakeNeedle(hits: Slug[]): NeedleIndex {
104
- return { query: (_text, k) => hits.slice(0, k) };
105
- }
106
-
107
- function makeTurn(turnNumber: number, currentMessage: string): TurnContext {
108
- return {
109
- conversationId: "conv-xyz",
110
- turnNumber,
111
- currentMessage,
112
- recentContext: "prior context",
113
- };
114
- }
115
-
116
- function toolUseResponse(
117
- name: string,
118
- input: Record<string, unknown>,
119
- ): ProviderResponse {
120
- return {
121
- model: "stub-model",
122
- stopReason: "tool_use",
123
- usage: { inputTokens: 0, outputTokens: 0 },
124
- content: [{ type: "tool_use", id: "tu-1", name, input }],
125
- };
126
- }
127
-
128
- /** Last `<leaf>X</leaf>` tag found in an L2 request, or undefined. */
129
- function leafFromMessages(messages: Message[]): LeafPath | undefined {
130
- for (const msg of messages) {
131
- for (const block of msg.content) {
132
- if (block.type === "text") {
133
- const m = /<leaf>([^<]+)<\/leaf>/.exec(block.text);
134
- if (m) return m[1];
135
- }
136
- }
137
- }
138
- return undefined;
139
- }
140
-
141
- /**
142
- * Build a provider that answers L1 `open_leaves` with `routeIds` and each L2
143
- * `select_pages` call with the per-leaf selection from the fixture turn.
144
- */
145
- function providerForTurn(turn: EvalTurn): Provider {
146
- return {
147
- name: "stub",
148
- sendMessage: async (messages, options) => {
149
- const toolName = options?.tools?.[0]?.name;
150
- if (toolName === "open_leaves") {
151
- return toolUseResponse("open_leaves", { ids: turn.routeIds });
152
- }
153
- // L2 select_pages — pick the selection for the leaf under selection.
154
- const leaf = leafFromMessages(messages);
155
- const sel = (leaf ? turn.leafSelections[leaf] : undefined) ?? {
156
- ids: [],
157
- pinned_ids: [],
158
- };
159
- return toolUseResponse("select_pages", {
160
- ids: sel.ids,
161
- pinned_ids: sel.pinned_ids,
162
- });
163
- },
164
- };
165
- }
166
-
167
- beforeEach(() => {
168
- providerStub = null;
169
- });
170
-
171
- // ---------------------------------------------------------------------------
172
- // Integration: drive the whole fixture sequence through ONE shared WorkingSet.
173
- // ---------------------------------------------------------------------------
174
-
175
- describe("orchestrate — fixture sequence (carry-forward)", () => {
176
- test("each turn's finalInjection matches the fixture", async () => {
177
- const tree = makeTree();
178
- const workingSet = new WorkingSet();
179
- const needle = fakeNeedle([]);
180
-
181
- for (const turn of TURNS) {
182
- providerStub = providerForTurn(turn);
183
- const result = await orchestrate(
184
- makeTurn(TURNS.indexOf(turn) + 1, turn.currentMessage),
185
- { tree, core: new Set(), needle, workingSet, pageSummary: summaryOf },
186
- );
187
- expect(result.openedLeaves).toEqual(turn.expectedOpenedLeaves);
188
- expect(result.finalInjection).toEqual(turn.expectedFinalInjection);
189
- }
190
- });
191
-
192
- test("a slug pinned in turn 1 carries into turn 2 without re-selection", async () => {
193
- const tree = makeTree();
194
- const workingSet = new WorkingSet();
195
- const needle = fakeNeedle([]);
196
-
197
- // Turn 1 selects+pins page-a.
198
- providerStub = providerForTurn(TURNS[0]);
199
- await orchestrate(makeTurn(1, TURNS[0].currentMessage), {
200
- tree,
201
- core: new Set(),
202
- needle,
203
- workingSet,
204
- pageSummary: summaryOf,
205
- });
206
-
207
- // Turn 2 opens a DIFFERENT leaf and never re-selects page-a.
208
- providerStub = providerForTurn(TURNS[1]);
209
- const t2 = await orchestrate(makeTurn(2, TURNS[1].currentMessage), {
210
- tree,
211
- core: new Set(),
212
- needle,
213
- workingSet,
214
- pageSummary: summaryOf,
215
- });
216
-
217
- expect(t2.currentSelections.map((s) => s.slug)).not.toContain("page-a");
218
- expect(t2.finalInjection).toContain("page-a");
219
- });
220
-
221
- test("carry-forward survives a turn whose selections fill the cap", async () => {
222
- const tree = makeTree();
223
- // Cap of 1: under a naive record-then-cap order this turn's own selection
224
- // would evict the carried page before injection. Snapshotting the carry
225
- // BEFORE recording this turn keeps the earlier page in the injection.
226
- const workingSet = new WorkingSet(1);
227
- const needle = fakeNeedle([]);
228
- const stub = (selectIds: number[]): Provider => ({
229
- name: "stub",
230
- sendMessage: async (_messages, options) =>
231
- options?.tools?.[0]?.name === "open_leaves"
232
- ? toolUseResponse("open_leaves", { ids: [1] })
233
- : toolUseResponse("select_pages", { ids: selectIds, pinned_ids: [] }),
234
- });
235
-
236
- providerStub = stub([1]); // turn 1 → page-a
237
- await orchestrate(makeTurn(1, "page a"), {
238
- tree,
239
- core: new Set(),
240
- needle,
241
- workingSet,
242
- pageSummary: summaryOf,
243
- });
244
-
245
- providerStub = stub([2]); // turn 2 → page-b, never re-selects page-a
246
- const t2 = await orchestrate(makeTurn(2, "page b"), {
247
- tree,
248
- core: new Set(),
249
- needle,
250
- workingSet,
251
- pageSummary: summaryOf,
252
- });
253
-
254
- expect(t2.currentSelections.map((s) => s.slug)).toEqual(["page-b"]);
255
- expect(t2.finalInjection).toContain("page-a"); // carried despite the cap
256
- });
257
- });
258
-
259
- // ---------------------------------------------------------------------------
260
- // Lane composition: needle and core fold into the open set.
261
- // ---------------------------------------------------------------------------
262
-
263
- describe("orchestrate — open set composition", () => {
264
- test("needle hits add their owning leaves to the open set", async () => {
265
- const tree = makeTree();
266
- // L1 routes only topic-x; the needle hit page-c lives in topic-y, so the
267
- // open set must include topic-y too.
268
- providerStub = {
269
- name: "stub",
270
- sendMessage: async (messages, options) => {
271
- if (options?.tools?.[0]?.name === "open_leaves") {
272
- return toolUseResponse("open_leaves", { ids: [1] });
273
- }
274
- const leaf = leafFromMessages(messages);
275
- const ids = leaf === "domain-a/topic-y" ? [1] : [];
276
- return toolUseResponse("select_pages", { ids, pinned_ids: [] });
277
- },
278
- };
279
- const result = await orchestrate(makeTurn(1, "anything"), {
280
- tree,
281
- core: new Set(),
282
- needle: fakeNeedle(["page-c"]),
283
- workingSet: new WorkingSet(),
284
- pageSummary: summaryOf,
285
- });
286
- expect(result.openedLeaves).toContain("domain-a/topic-y");
287
- expect(result.finalInjection).toContain("page-c");
288
- });
289
-
290
- test("core leaves are always opened even when routing abstains", async () => {
291
- const tree = makeTree();
292
- // L1 abstains (empty ids); only the core leaf should open.
293
- providerStub = {
294
- name: "stub",
295
- sendMessage: async (messages, options) => {
296
- if (options?.tools?.[0]?.name === "open_leaves") {
297
- return toolUseResponse("open_leaves", { ids: [] });
298
- }
299
- const leaf = leafFromMessages(messages);
300
- const ids = leaf === "domain-a/topic-y" ? [1] : [];
301
- return toolUseResponse("select_pages", { ids, pinned_ids: [] });
302
- },
303
- };
304
- const result = await orchestrate(makeTurn(1, "nothing topical"), {
305
- tree,
306
- core: new Set(["domain-a/topic-y"]),
307
- needle: fakeNeedle([]),
308
- workingSet: new WorkingSet(),
309
- pageSummary: summaryOf,
310
- });
311
- expect(result.openedLeaves).toEqual(["domain-a/topic-y"]);
312
- // page-c (topic-y member) is core, so the working set must NOT retain it.
313
- expect(result.workingSetUnion.has("page-c")).toBe(false);
314
- // It still injects this turn via the current selection.
315
- expect(result.finalInjection).toContain("page-c");
316
- });
317
- });
318
-
319
- // ---------------------------------------------------------------------------
320
- // Edge cases.
321
- // ---------------------------------------------------------------------------
322
-
323
- describe("orchestrate — edge cases", () => {
324
- test("empty needle results do not break orchestration", async () => {
325
- const tree = makeTree();
326
- providerStub = providerForTurn(TURNS[0]);
327
- const result = await orchestrate(makeTurn(1, "tell me about page a"), {
328
- tree,
329
- core: new Set(),
330
- needle: fakeNeedle([]),
331
- workingSet: new WorkingSet(),
332
- pageSummary: summaryOf,
333
- });
334
- expect(result.openedLeaves).toEqual(["domain-a/topic-x"]);
335
- expect(result.finalInjection).toEqual(["page-a", "page-b"]);
336
- });
337
-
338
- test("omitted L1 ids opens only the deterministic lanes, not the whole tree", async () => {
339
- const tree = makeTree();
340
- // L1 omits ids → routeL1 opens NO routed leaves; only the needle/core lanes
341
- // drive the open set, so the whole tree is never fanned out (topic-y, which
342
- // nothing routes or needles to, stays closed).
343
- providerStub = {
344
- name: "stub",
345
- sendMessage: async (_messages, options) => {
346
- if (options?.tools?.[0]?.name === "open_leaves") {
347
- return toolUseResponse("open_leaves", {}); // omitted ids → []
348
- }
349
- return toolUseResponse("select_pages", {}); // omitted → all members
350
- },
351
- };
352
- const result = await orchestrate(makeTurn(1, "x"), {
353
- tree,
354
- core: new Set(),
355
- needle: fakeNeedle(["page-a"]), // needle opens domain-a/topic-x only
356
- workingSet: new WorkingSet(),
357
- pageSummary: summaryOf,
358
- });
359
- expect(result.openedLeaves).toEqual(["domain-a/topic-x"]);
360
- expect(result.finalInjection).toEqual(["page-a", "page-b"]);
361
- });
362
-
363
- test("pinned current-turn selections land in the working set", async () => {
364
- const tree = makeTree();
365
- providerStub = providerForTurn(TURNS[0]); // pins page-a
366
- const ws = new WorkingSet();
367
- await orchestrate(makeTurn(1, "tell me about page a"), {
368
- tree,
369
- core: new Set(),
370
- needle: fakeNeedle([]),
371
- workingSet: ws,
372
- pageSummary: summaryOf,
373
- });
374
- expect(ws.union().has("page-a")).toBe(true);
375
- expect(ws.union().has("page-b")).toBe(true);
376
- });
377
-
378
- test("a page in multiple opened leaves is deduped with pinned ORed", async () => {
379
- // Build a tree where page-shared belongs to BOTH leaves; pin it in one.
380
- const leaves: LeafNode[] = [
381
- makeLeaf("domain-a/topic-x", ["page-shared"]),
382
- makeLeaf("domain-a/topic-y", ["page-shared"]),
383
- ];
384
- const byPage = new Map<Slug, LeafPath[]>([
385
- ["page-shared", ["domain-a/topic-x", "domain-a/topic-y"]],
386
- ]);
387
- const tree: LeafTree = {
388
- leaves: new Map(leaves.map((n) => [n.path, n])),
389
- byPage,
390
- };
391
- providerStub = {
392
- name: "stub",
393
- sendMessage: async (messages, options) => {
394
- if (options?.tools?.[0]?.name === "open_leaves") {
395
- return toolUseResponse("open_leaves", { ids: [1, 2] });
396
- }
397
- const leaf = leafFromMessages(messages);
398
- // Pin only in topic-x; select (unpinned) in topic-y.
399
- const pinned_ids = leaf === "domain-a/topic-x" ? [1] : [];
400
- return toolUseResponse("select_pages", { ids: [1], pinned_ids });
401
- },
402
- };
403
- const result = await orchestrate(makeTurn(1, "x"), {
404
- tree,
405
- core: new Set(),
406
- needle: fakeNeedle([]),
407
- workingSet: new WorkingSet(),
408
- pageSummary: summaryOf,
409
- });
410
- // One deduped selection, pinned because it was pinned in topic-x.
411
- expect(result.currentSelections).toEqual([
412
- { slug: "page-shared", pinned: true },
413
- ]);
414
- expect(result.finalInjection).toEqual(["page-shared"]);
415
- });
416
-
417
- test("needleK defaults to DEFAULT_NEEDLE_K", async () => {
418
- const tree = makeTree();
419
- let seenK = -1;
420
- const needle: NeedleIndex = {
421
- query: (_text, k) => {
422
- seenK = k;
423
- return [];
424
- },
425
- };
426
- providerStub = providerForTurn(TURNS[0]);
427
- await orchestrate(makeTurn(1, "x"), {
428
- tree,
429
- core: new Set(),
430
- needle,
431
- workingSet: new WorkingSet(),
432
- pageSummary: summaryOf,
433
- });
434
- expect(seenK).toBe(DEFAULT_NEEDLE_K);
435
- });
436
- });
@@ -1,13 +0,0 @@
1
- import { describe, expect, test } from "bun:test";
2
-
3
- import { cachedTextBlock } from "../provider-blocks.js";
4
-
5
- describe("cachedTextBlock", () => {
6
- test("stamps an ephemeral cache_control with a 1h TTL", () => {
7
- const block = cachedTextBlock("stable leaf block");
8
- expect(block).toMatchObject({ type: "text", text: "stable leaf block" });
9
- expect(
10
- (block as unknown as { cache_control?: unknown }).cache_control,
11
- ).toEqual({ type: "ephemeral", ttl: "1h" });
12
- });
13
- });