@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,253 +0,0 @@
1
- /**
2
- * Adapter that wraps a live {@link Conversation} as a {@link WakeTarget}
3
- * for `wakeAgentForOpportunity()`.
4
- *
5
- * Extracted from `server.ts` so that `runtime/agent-wake.ts` can import
6
- * the resolver directly instead of going through a DI callback registered
7
- * at daemon startup.
8
- */
9
-
10
- import type { AgentEvent } from "../agent/loop.js";
11
- import {
12
- addMessage,
13
- getConversation,
14
- provenanceFromTrustContext,
15
- } from "../memory/conversation-crud.js";
16
- import { syncMessageToDisk } from "../memory/conversation-disk-view.js";
17
- import { backfillMessageIdOnLogs } from "../memory/llm-request-log-store.js";
18
- import type { WakeTarget } from "../runtime/agent-wake.js";
19
- import { broadcastMessage } from "../runtime/assistant-event-hub.js";
20
- import { getLogger } from "../util/logger.js";
21
- import type { Conversation } from "./conversation.js";
22
- import type { ServerMessage } from "./message-protocol.js";
23
-
24
- const log = getLogger("wake-target-adapter");
25
-
26
- /**
27
- * Translate a raw {@link AgentEvent} from the agent loop into the
28
- * corresponding {@link ServerMessage} wire frame. The normal user-turn
29
- * path does this via the full state-aware handler in
30
- * `conversation-agent-loop-handlers.ts`; the wake path has no tool
31
- * accounting, title generation, or activity-state tracking to worry
32
- * about, so we only need the subset that produces client-visible
33
- * frames. Events that have no client-visible wire shape (usage, error,
34
- * preview/input-json deltas, etc.) are dropped — they produce no UI.
35
- *
36
- * Keeping this translator co-located with the wake adapter preserves
37
- * the runtime/daemon layering: `runtime/agent-wake.ts` never imports
38
- * `message-protocol.ts` or wire shapes, and the daemon owns all
39
- * translation from agent-loop semantics to client frames.
40
- */
41
- function translateAgentEventToServerMessage(
42
- event: AgentEvent,
43
- conversationId: string,
44
- ): ServerMessage | null {
45
- switch (event.type) {
46
- case "text_delta":
47
- return {
48
- type: "assistant_text_delta",
49
- text: event.text,
50
- conversationId,
51
- };
52
- case "thinking_delta":
53
- return {
54
- type: "assistant_thinking_delta",
55
- thinking: event.thinking,
56
- conversationId,
57
- };
58
- case "tool_use":
59
- return {
60
- type: "tool_use_start",
61
- toolName: event.name,
62
- input: event.input,
63
- conversationId,
64
- toolUseId: event.id,
65
- };
66
- case "tool_use_preview_start":
67
- return {
68
- type: "tool_use_preview_start",
69
- toolUseId: event.toolUseId,
70
- toolName: event.toolName,
71
- conversationId,
72
- };
73
- case "tool_output_chunk":
74
- return {
75
- type: "tool_output_chunk",
76
- chunk: event.chunk,
77
- conversationId,
78
- toolUseId: event.toolUseId,
79
- };
80
- case "tool_result": {
81
- const imageBlocks = event.contentBlocks?.filter(
82
- (b): b is Extract<typeof b, { type: "image" }> => b.type === "image",
83
- );
84
- const imageDataList = imageBlocks?.length
85
- ? imageBlocks.map((b) => b.source.data)
86
- : undefined;
87
- return {
88
- type: "tool_result",
89
- toolName: "",
90
- result: event.content,
91
- isError: event.isError,
92
- diff: event.diff,
93
- status: event.status,
94
- conversationId,
95
- imageData: imageDataList?.[0],
96
- imageDataList,
97
- toolUseId: event.toolUseId,
98
- };
99
- }
100
- case "server_tool_start":
101
- return {
102
- type: "tool_use_start",
103
- toolName: event.name,
104
- input: event.input,
105
- conversationId,
106
- toolUseId: event.toolUseId,
107
- };
108
- case "server_tool_complete": {
109
- let resultText = "";
110
- if (Array.isArray(event.content) && event.content.length > 0) {
111
- resultText = (event.content as unknown[])
112
- .filter(
113
- (r): r is { type: string; title: string; url: string } =>
114
- typeof r === "object" &&
115
- r != null &&
116
- (r as { type?: string }).type === "web_search_result",
117
- )
118
- .map((r) => `${r.title}\n${r.url}`)
119
- .join("\n\n");
120
- }
121
- return {
122
- type: "tool_result",
123
- toolName: "web_search",
124
- result: resultText,
125
- isError: event.isError,
126
- conversationId,
127
- toolUseId: event.toolUseId,
128
- };
129
- }
130
- case "message_complete":
131
- return {
132
- type: "message_complete",
133
- conversationId,
134
- };
135
- case "input_json_delta":
136
- case "usage":
137
- case "error":
138
- case "provider_error":
139
- case "max_tokens_reached":
140
- case "context_compacting":
141
- case "compaction_circuit_open":
142
- case "compaction_circuit_closed":
143
- case "compaction_completed":
144
- case "history_stripped":
145
- case "agent_loop_exit":
146
- return null;
147
- case "llm_call_started":
148
- // The wake path persists its assistant tail via `persistTailMessage`
149
- // (an `addMessage`-shaped call below) rather than via the main
150
- // event-handler's `reserve` → `updateContent` pipeline, so there is
151
- // no row to reserve here. Translation returns null and the wake
152
- // path's existing end-of-turn persist continues to mint the row.
153
- // Following up with full wake-path pre-allocation parity is tracked
154
- // as a B3 follow-up.
155
- return null;
156
- }
157
- }
158
-
159
- /**
160
- * Adapt a live {@link Conversation} to the narrow {@link WakeTarget}
161
- * surface expected by `wakeAgentForOpportunity()`.
162
- */
163
- export function conversationToWakeTarget(
164
- conversation: Conversation,
165
- ): WakeTarget {
166
- return {
167
- conversationId: conversation.conversationId,
168
- agentLoop: conversation.agentLoop,
169
- getMessages: () => conversation.getMessages(),
170
- pushMessage: (msg) => {
171
- conversation.messages.push(msg);
172
- },
173
- onWakeProducedOutput: (source, hint, surfaceId) => {
174
- broadcastMessage({
175
- type: "ui_surface_show",
176
- conversationId: conversation.conversationId,
177
- surfaceId,
178
- surfaceType: "card",
179
- data: {
180
- title: "Conversation Woke",
181
- body: hint,
182
- metadata: [{ label: "Source", value: source }],
183
- },
184
- display: "inline",
185
- });
186
- },
187
- emitAgentEvent: (event) => {
188
- const frame = translateAgentEventToServerMessage(
189
- event,
190
- conversation.conversationId,
191
- );
192
- if (!frame) return;
193
- broadcastMessage(frame);
194
- },
195
- isProcessing: () => conversation.isProcessing(),
196
- markProcessing: (on) => {
197
- conversation.setProcessing(on);
198
- },
199
- setTrustContext: (ctx) => conversation.setTrustContext(ctx),
200
- setWakeAllowedTools: (tools) => {
201
- const previous = conversation.subagentAllowedTools;
202
- conversation.setSubagentAllowedTools(new Set(tools));
203
- return () => {
204
- conversation.setSubagentAllowedTools(previous);
205
- };
206
- },
207
- persistTailMessage: async (message) => {
208
- const turnChannelCtx = conversation.getTurnChannelContext();
209
- const turnInterfaceCtx = conversation.getTurnInterfaceContext();
210
- const metadata: Record<string, unknown> = {
211
- ...provenanceFromTrustContext(conversation.trustContext),
212
- userMessageChannel: turnChannelCtx?.userMessageChannel ?? "vellum",
213
- assistantMessageChannel:
214
- turnChannelCtx?.assistantMessageChannel ?? "vellum",
215
- userMessageInterface: turnInterfaceCtx?.userMessageInterface ?? "web",
216
- assistantMessageInterface:
217
- turnInterfaceCtx?.assistantMessageInterface ?? "web",
218
- };
219
- const persisted = await addMessage(
220
- conversation.conversationId,
221
- message.role,
222
- JSON.stringify(message.content),
223
- { metadata },
224
- );
225
- if (message.role === "assistant") {
226
- try {
227
- backfillMessageIdOnLogs(conversation.conversationId, persisted.id);
228
- } catch (err) {
229
- log.warn(
230
- { err, conversationId: conversation.conversationId },
231
- "wake adapter: backfill messageId on LLM logs failed (non-fatal)",
232
- );
233
- }
234
- }
235
- try {
236
- const convRow = getConversation(conversation.conversationId);
237
- if (convRow) {
238
- syncMessageToDisk(
239
- conversation.conversationId,
240
- persisted.id,
241
- convRow.createdAt,
242
- );
243
- }
244
- } catch (err) {
245
- log.warn(
246
- { err, conversationId: conversation.conversationId },
247
- "wake adapter: syncMessageToDisk failed (non-fatal)",
248
- );
249
- }
250
- },
251
- drainQueue: () => conversation.drainQueue(),
252
- };
253
- }
@@ -1,242 +0,0 @@
1
- /**
2
- * Tests for the v3 page→leaf classifier. Uses a stub provider so no live LLM
3
- * is hit. Pages are written into a temp workspace.
4
- */
5
-
6
- import { mkdtemp, rm } from "node:fs/promises";
7
- import { tmpdir } from "node:os";
8
- import { join } from "node:path";
9
- import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
10
-
11
- import type {
12
- Message,
13
- Provider,
14
- ProviderResponse,
15
- SendMessageOptions,
16
- ToolUseContent,
17
- } from "../../../providers/types.js";
18
- import { readPage, writePage } from "../../v2/page-store.js";
19
- import type { ConceptPageFrontmatter } from "../../v2/types.js";
20
- import type { LeafNode, LeafTree } from "../types.js";
21
-
22
- // Stub the provider layer before importing `assign.js` so its static import
23
- // chain (which transitively pulls in CES/credential workspace packages that
24
- // aren't built in a fresh worktree) never loads. The classifier is
25
- // provider-injectable, so every test passes its own stub provider — the real
26
- // `getConfiguredProvider` is never exercised here.
27
- mock.module("../../../providers/provider-send-message.js", () => ({
28
- getConfiguredProvider: async () => null,
29
- extractToolUse: (response: ProviderResponse) =>
30
- response.content.find((b): b is ToolUseContent => b.type === "tool_use"),
31
- userMessage: (text: string): Message => ({
32
- role: "user",
33
- content: [{ type: "text", text }],
34
- }),
35
- }));
36
-
37
- const { assignPages } = await import("../assign.js");
38
-
39
- function makeLeaf(path: string, description: string): LeafNode {
40
- return {
41
- path,
42
- frontmatter: { path, in_core: false },
43
- description,
44
- members: [],
45
- domain: path.split("/")[0],
46
- };
47
- }
48
-
49
- function makeTree(leaves: LeafNode[]): LeafTree {
50
- return {
51
- leaves: new Map(leaves.map((l) => [l.path, l])),
52
- byPage: new Map(),
53
- };
54
- }
55
-
56
- /** Sorted by path: [1] domain-a/topic-x, [2] domain-a/topic-y, [3] domain-b/topic-z */
57
- function threeLeafTree(): LeafTree {
58
- return makeTree([
59
- makeLeaf("domain-b/topic-z", "about z"),
60
- makeLeaf("domain-a/topic-x", "about x"),
61
- makeLeaf("domain-a/topic-y", "about y"),
62
- ]);
63
- }
64
-
65
- function stubProvider(
66
- handler: (
67
- messages: Message[],
68
- options?: SendMessageOptions,
69
- ) => ProviderResponse | Promise<ProviderResponse>,
70
- ): Provider {
71
- return {
72
- name: "stub",
73
- sendMessage: async (messages, options) => handler(messages, options),
74
- } as Provider;
75
- }
76
-
77
- function response(content: ProviderResponse["content"]): ProviderResponse {
78
- return {
79
- content,
80
- model: "stub-model",
81
- stopReason: "tool_use",
82
- usage: { inputTokens: 0, outputTokens: 0 },
83
- };
84
- }
85
-
86
- function toolResponse(ids: unknown[]): ProviderResponse {
87
- return response([
88
- { type: "tool_use", id: "tu-1", name: "assign_leaves", input: { ids } },
89
- ]);
90
- }
91
-
92
- function textResponse(text: string): ProviderResponse {
93
- return response([{ type: "text", text }]);
94
- }
95
-
96
- let workspaceDir: string;
97
-
98
- beforeEach(async () => {
99
- workspaceDir = await mkdtemp(join(tmpdir(), "v3-assign-"));
100
- });
101
-
102
- afterEach(async () => {
103
- await rm(workspaceDir, { recursive: true, force: true });
104
- });
105
-
106
- async function makePage(
107
- slug: string,
108
- frontmatter: Partial<ConceptPageFrontmatter>,
109
- body = "page body",
110
- ): Promise<void> {
111
- await writePage(workspaceDir, {
112
- slug,
113
- frontmatter: { edges: [], ref_files: [], ref_urls: [], ...frontmatter },
114
- body,
115
- });
116
- }
117
-
118
- describe("assignPages", () => {
119
- test("unions classified picks with prior picks, never overwriting", async () => {
120
- await makePage("page-a", { leaves: ["domain-a/topic-x"] });
121
- // Classifier returns [2] -> domain-a/topic-y and [1] -> already present.
122
- const provider = stubProvider(() => toolResponse([2, 1]));
123
-
124
- const results = await assignPages({
125
- tree: threeLeafTree(),
126
- workspaceDir,
127
- slugs: ["page-a"],
128
- provider,
129
- throttleMs: 0,
130
- });
131
-
132
- expect(results).toEqual([
133
- {
134
- slug: "page-a",
135
- before: ["domain-a/topic-x"],
136
- after: ["domain-a/topic-x", "domain-a/topic-y"],
137
- failed: false,
138
- },
139
- ]);
140
-
141
- const written = await readPage(workspaceDir, "page-a");
142
- expect(written?.frontmatter.leaves).toEqual([
143
- "domain-a/topic-x",
144
- "domain-a/topic-y",
145
- ]);
146
- });
147
-
148
- test("classification failure leaves the page's leaves unchanged", async () => {
149
- await makePage("page-a", { leaves: ["domain-b/topic-z"] });
150
-
151
- // (a) provider throws
152
- const throwing = stubProvider(() => {
153
- throw new Error("boom");
154
- });
155
- let results = await assignPages({
156
- tree: threeLeafTree(),
157
- workspaceDir,
158
- slugs: ["page-a"],
159
- provider: throwing,
160
- throttleMs: 0,
161
- });
162
- expect(results[0]).toEqual({
163
- slug: "page-a",
164
- before: ["domain-b/topic-z"],
165
- after: ["domain-b/topic-z"],
166
- failed: true,
167
- });
168
- expect(
169
- (await readPage(workspaceDir, "page-a"))?.frontmatter.leaves,
170
- ).toEqual(["domain-b/topic-z"]);
171
-
172
- // (b) no tool use
173
- results = await assignPages({
174
- tree: threeLeafTree(),
175
- workspaceDir,
176
- slugs: ["page-a"],
177
- provider: stubProvider(() => textResponse("no tool here")),
178
- throttleMs: 0,
179
- });
180
- expect(results[0].failed).toBe(true);
181
- expect(
182
- (await readPage(workspaceDir, "page-a"))?.frontmatter.leaves,
183
- ).toEqual(["domain-b/topic-z"]);
184
-
185
- // (c) empty ids
186
- results = await assignPages({
187
- tree: threeLeafTree(),
188
- workspaceDir,
189
- slugs: ["page-a"],
190
- provider: stubProvider(() => toolResponse([])),
191
- throttleMs: 0,
192
- });
193
- expect(results[0].failed).toBe(true);
194
- expect(
195
- (await readPage(workspaceDir, "page-a"))?.frontmatter.leaves,
196
- ).toEqual(["domain-b/topic-z"]);
197
- });
198
-
199
- test("deterministic id->path mapping, dropping out-of-range and 0 ids", async () => {
200
- await makePage("page-a", {});
201
- // 0 and 99 are invalid; 3 -> domain-b/topic-z; 1 -> domain-a/topic-x.
202
- const provider = stubProvider(() => toolResponse([0, 99, 3, 1, -1, 2.5]));
203
-
204
- const results = await assignPages({
205
- tree: threeLeafTree(),
206
- workspaceDir,
207
- slugs: ["page-a"],
208
- provider,
209
- throttleMs: 0,
210
- });
211
-
212
- expect(results[0].after).toEqual(["domain-b/topic-z", "domain-a/topic-x"]);
213
- expect(results[0].failed).toBe(false);
214
- });
215
-
216
- test("defaults to pages with empty or missing leaves", async () => {
217
- await makePage("page-empty", { leaves: [] });
218
- await makePage("page-missing", {});
219
- await makePage("page-classified", { leaves: ["domain-a/topic-x"] });
220
-
221
- const seen: string[] = [];
222
- const provider = stubProvider((messages) => {
223
- const text = messages[0]?.content
224
- .map((b) => (b.type === "text" ? b.text : ""))
225
- .join("");
226
- seen.push(text);
227
- return toolResponse([2]);
228
- });
229
-
230
- const results = await assignPages({
231
- tree: threeLeafTree(),
232
- workspaceDir,
233
- provider,
234
- throttleMs: 0,
235
- });
236
-
237
- const slugs = results.map((r) => r.slug).sort();
238
- expect(slugs).toEqual(["page-empty", "page-missing"]);
239
- // The classified page was never sent to the provider.
240
- expect(seen.length).toBe(2);
241
- });
242
- });
@@ -1,118 +0,0 @@
1
- import { describe, expect, test } from "bun:test";
2
-
3
- import {
4
- CAPABILITIES_LEAF_PATH,
5
- type CapabilityResolvers,
6
- injectCapabilitiesLeaf,
7
- isCapabilitySlug,
8
- renderCapabilityContent,
9
- } from "../capabilities.js";
10
- import { buildNeedleIndex } from "../needle.js";
11
- import type { LeafPath, LeafTree, Slug } from "../types.js";
12
-
13
- function emptyTree(): LeafTree {
14
- return { leaves: new Map(), byPage: new Map<Slug, LeafPath[]>() };
15
- }
16
-
17
- describe("isCapabilitySlug", () => {
18
- test("true for skill and CLI-command slugs, false otherwise", () => {
19
- expect(isCapabilitySlug("skills/meet-join")).toBe(true);
20
- expect(isCapabilitySlug("cli-commands/schedules")).toBe(true);
21
- expect(isCapabilitySlug("relationship/vows")).toBe(false);
22
- expect(isCapabilitySlug("some-page")).toBe(false);
23
- });
24
- });
25
-
26
- describe("injectCapabilitiesLeaf", () => {
27
- test("registers an always-on leaf with the synthetic slugs as members", () => {
28
- const tree = emptyTree();
29
- const core = new Set<LeafPath>();
30
- injectCapabilitiesLeaf(tree, core, ["skills/foo", "cli-commands/bar"]);
31
-
32
- const leaf = tree.leaves.get(CAPABILITIES_LEAF_PATH);
33
- expect(leaf?.frontmatter.in_core).toBe(true);
34
- expect(leaf?.members).toEqual(["skills/foo", "cli-commands/bar"]);
35
- expect(core.has(CAPABILITIES_LEAF_PATH)).toBe(true);
36
- });
37
-
38
- test("unions the leaf into each member's byPage entry without dropping existing leaves", () => {
39
- const tree = emptyTree();
40
- tree.byPage.set("skills/foo", ["other/leaf"]);
41
- injectCapabilitiesLeaf(tree, new Set<LeafPath>(), [
42
- "skills/foo",
43
- "cli-commands/bar",
44
- ]);
45
-
46
- expect(tree.byPage.get("skills/foo")).toEqual([
47
- "other/leaf",
48
- CAPABILITIES_LEAF_PATH,
49
- ]);
50
- expect(tree.byPage.get("cli-commands/bar")).toEqual([
51
- CAPABILITIES_LEAF_PATH,
52
- ]);
53
- });
54
-
55
- test("is idempotent — re-injecting does not duplicate the byPage entry", () => {
56
- const tree = emptyTree();
57
- const core = new Set<LeafPath>();
58
- injectCapabilitiesLeaf(tree, core, ["skills/foo"]);
59
- injectCapabilitiesLeaf(tree, core, ["skills/foo"]);
60
- expect(tree.byPage.get("skills/foo")).toEqual([CAPABILITIES_LEAF_PATH]);
61
- });
62
-
63
- test("stays always-on even with no installed skills/commands", () => {
64
- const tree = emptyTree();
65
- const core = new Set<LeafPath>();
66
- injectCapabilitiesLeaf(tree, core, []);
67
- expect(tree.leaves.get(CAPABILITIES_LEAF_PATH)?.members).toEqual([]);
68
- expect(core.has(CAPABILITIES_LEAF_PATH)).toBe(true);
69
- });
70
- });
71
-
72
- describe("renderCapabilityContent", () => {
73
- const resolvers: CapabilityResolvers = {
74
- skill: (slug) =>
75
- slug === "skills/foo" ? { id: "foo", content: "foo capability" } : null,
76
- cli: (slug) =>
77
- slug === "cli-commands/bar"
78
- ? { id: "bar", content: "bar capability" }
79
- : null,
80
- };
81
-
82
- test("renders a skill slug with a Skill header", () => {
83
- expect(renderCapabilityContent("skills/foo", resolvers)).toBe(
84
- "# Skill: foo\nfoo capability",
85
- );
86
- });
87
-
88
- test("renders a CLI-command slug with a CLI header", () => {
89
- expect(renderCapabilityContent("cli-commands/bar", resolvers)).toBe(
90
- "# CLI command: bar\nbar capability",
91
- );
92
- });
93
-
94
- test("degrades to '' for a capability slug the cache cannot resolve", () => {
95
- expect(renderCapabilityContent("skills/missing", resolvers)).toBe("");
96
- });
97
-
98
- test("returns null for a non-capability slug so the caller reads the on-disk page", () => {
99
- expect(renderCapabilityContent("relationship/vows", resolvers)).toBeNull();
100
- });
101
- });
102
-
103
- describe("needle indexes injected capability members", () => {
104
- test("a skill slug is lexically retrievable by its title and summary", async () => {
105
- const tree = emptyTree();
106
- injectCapabilitiesLeaf(tree, new Set<LeafPath>(), ["skills/meet-join"]);
107
-
108
- const needle = await buildNeedleIndex(
109
- tree,
110
- async () => "Join and transcribe a video meeting",
111
- );
112
-
113
- // By slug-derived title token.
114
- expect(needle.query("meet", 5)).toContain("skills/meet-join");
115
- // By summary token.
116
- expect(needle.query("transcribe", 5)).toContain("skills/meet-join");
117
- });
118
- });
@@ -1,39 +0,0 @@
1
- import { mkdtemp, rm } from "node:fs/promises";
2
- import { tmpdir } from "node:os";
3
- import { join } from "node:path";
4
- import { afterEach, describe, expect, test } from "bun:test";
5
-
6
- import { loadCore } from "../core.js";
7
-
8
- const BUNDLED_DATA_DIR = join(import.meta.dir, "..", "data");
9
-
10
- describe("loadCore", () => {
11
- let tmpDirs: string[] = [];
12
-
13
- afterEach(async () => {
14
- await Promise.all(
15
- tmpDirs.map((d) => rm(d, { recursive: true, force: true })),
16
- );
17
- tmpDirs = [];
18
- });
19
-
20
- async function makeTmpDir(): Promise<string> {
21
- const dir = await mkdtemp(join(tmpdir(), "v3-core-"));
22
- tmpDirs.push(dir);
23
- return dir;
24
- }
25
-
26
- test("loads alwaysOn from the supplied dataDir's core.json into a Set", async () => {
27
- const core = await loadCore(BUNDLED_DATA_DIR);
28
- expect(core).toBeInstanceOf(Set);
29
- expect(core.has("domain-a/topic-x")).toBe(true);
30
- expect(core.size).toBe(1);
31
- });
32
-
33
- test("returns empty set when core.json is missing", async () => {
34
- const emptyDataDir = await makeTmpDir();
35
- const core = await loadCore(emptyDataDir);
36
- expect(core).toBeInstanceOf(Set);
37
- expect(core.size).toBe(0);
38
- });
39
- });