@vellumai/assistant 0.8.1 → 0.8.3

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 (630) hide show
  1. package/ARCHITECTURE.md +13 -19
  2. package/Dockerfile +75 -1
  3. package/bun.lock +11 -1
  4. package/docker-entrypoint.sh +17 -0
  5. package/docker-init-apt-root.sh +167 -0
  6. package/docker-kata-apt-env.sh +39 -0
  7. package/docs/plugins.md +88 -47
  8. package/docs/skills.md +9 -7
  9. package/examples/plugins/echo/README.md +27 -27
  10. package/examples/plugins/echo/package.json +3 -0
  11. package/examples/plugins/echo/register.ts +31 -31
  12. package/node_modules/@vellumai/slack-text/src/index.test.ts +114 -14
  13. package/node_modules/@vellumai/slack-text/src/index.ts +82 -18
  14. package/openapi.yaml +642 -5
  15. package/package.json +3 -1
  16. package/scripts/generate-openapi.ts +83 -10
  17. package/scripts/sync-llm-catalog.ts +2 -2
  18. package/scripts/sync-web-search-catalog.ts +47 -25
  19. package/src/__tests__/agent-image-optimize.test.ts +11 -3
  20. package/src/__tests__/agent-loop-exit-reason.test.ts +272 -0
  21. package/src/__tests__/agent-loop-provider-error-recording.test.ts +195 -0
  22. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +131 -0
  23. package/src/__tests__/anthropic-provider.test.ts +45 -0
  24. package/src/__tests__/app-builder-tool-scripts.test.ts +9 -3
  25. package/src/__tests__/app-executors.test.ts +220 -4
  26. package/src/__tests__/auto-analysis-end-to-end.test.ts +35 -0
  27. package/src/__tests__/bundled-asset.test.ts +6 -6
  28. package/src/__tests__/channel-availability-routes.test.ts +206 -0
  29. package/src/__tests__/channel-delivery-store.test.ts +289 -1
  30. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -1
  31. package/src/__tests__/clawhub.test.ts +75 -16
  32. package/src/__tests__/compactor-tail-resolution.test.ts +147 -0
  33. package/src/__tests__/config-get-vision-flag.test.ts +136 -0
  34. package/src/__tests__/config-loader-backfill.test.ts +115 -18
  35. package/src/__tests__/config-schema.test.ts +21 -0
  36. package/src/__tests__/config-set-route.test.ts +80 -0
  37. package/src/__tests__/config-sounds-sync.test.ts +97 -0
  38. package/src/__tests__/config-watcher-skill-reseed.test.ts +453 -0
  39. package/src/__tests__/context-search-conversations-source.test.ts +117 -2
  40. package/src/__tests__/context-search-memory-v2-source.test.ts +0 -1
  41. package/src/__tests__/context-search-workspace-source.test.ts +7 -0
  42. package/src/__tests__/context-token-estimator.test.ts +31 -65
  43. package/src/__tests__/conversation-abort-tool-results.test.ts +4 -1
  44. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
  45. package/src/__tests__/conversation-agent-loop-overflow.test.ts +92 -92
  46. package/src/__tests__/conversation-agent-loop.test.ts +59 -1
  47. package/src/__tests__/conversation-error.test.ts +42 -3
  48. package/src/__tests__/conversation-fork-crud.test.ts +82 -0
  49. package/src/__tests__/conversation-inference-profile-route.test.ts +40 -4
  50. package/src/__tests__/conversation-lifecycle.test.ts +173 -0
  51. package/src/__tests__/conversation-media-retry.test.ts +19 -8
  52. package/src/__tests__/conversation-message-sync-tags.test.ts +97 -0
  53. package/src/__tests__/conversation-pairing.test.ts +54 -0
  54. package/src/__tests__/conversation-process-callsite.test.ts +4 -1
  55. package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -1
  56. package/src/__tests__/conversation-queue.test.ts +4 -1
  57. package/src/__tests__/conversation-runtime-assembly.test.ts +102 -13
  58. package/src/__tests__/conversation-slash-queue.test.ts +59 -1
  59. package/src/__tests__/conversation-slash-unknown.test.ts +4 -1
  60. package/src/__tests__/conversation-surfaces-table-action.test.ts +360 -0
  61. package/src/__tests__/conversation-sync-tags.test.ts +235 -0
  62. package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
  63. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
  64. package/src/__tests__/credential-security-invariants.test.ts +3 -2
  65. package/src/__tests__/date-context.test.ts +45 -0
  66. package/src/__tests__/db-slack-external-content-normalization.test.ts +301 -0
  67. package/src/__tests__/delete-managed-skill-tool.test.ts +55 -13
  68. package/src/__tests__/disk-pressure-tools.test.ts +1 -0
  69. package/src/__tests__/dm-backfill.test.ts +121 -10
  70. package/src/__tests__/document-tool-security.test.ts +258 -0
  71. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
  72. package/src/__tests__/edit-propagation.test.ts +33 -0
  73. package/src/__tests__/empty-response-pipeline.test.ts +0 -4
  74. package/src/__tests__/external-plugin-loader.test.ts +151 -55
  75. package/src/__tests__/filing-service.test.ts +140 -0
  76. package/src/__tests__/get-skill-detail-audit.test.ts +0 -4
  77. package/src/__tests__/guardian-action-no-hardcoded-copy.test.ts +0 -1
  78. package/src/__tests__/guardian-dispatch.test.ts +1 -0
  79. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +43 -62
  80. package/src/__tests__/heartbeat-service.test.ts +24 -164
  81. package/src/__tests__/helpers/channel-test-adapter.ts +0 -2
  82. package/src/__tests__/helpers/tar-fixtures.ts +39 -0
  83. package/src/__tests__/helpers/wait-for.ts +21 -0
  84. package/src/__tests__/history-repair-pipeline.test.ts +0 -3
  85. package/src/__tests__/history-repair.test.ts +73 -0
  86. package/src/__tests__/host-app-control-proxy.test.ts +507 -10
  87. package/src/__tests__/host-proxy-preactivation.test.ts +200 -13
  88. package/src/__tests__/image-credentials.test.ts +1 -1
  89. package/src/__tests__/inbound-slack-persistence.test.ts +2 -0
  90. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +1 -1
  91. package/src/__tests__/inference-profile-reaper.test.ts +4 -2
  92. package/src/__tests__/inference-profile-session-handler.test.ts +18 -6
  93. package/src/__tests__/inference-profile-session-ipc.test.ts +17 -5
  94. package/src/__tests__/injector-background-turn.test.ts +153 -0
  95. package/src/__tests__/injector-chain.test.ts +15 -8
  96. package/src/__tests__/install-skill-routing.test.ts +155 -37
  97. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +99 -3
  98. package/src/__tests__/list-messages-page-latest.test.ts +55 -0
  99. package/src/__tests__/llm-call-pipeline.test.ts +0 -3
  100. package/src/__tests__/llm-callsite-catalog.test.ts +25 -0
  101. package/src/__tests__/llm-catalog-parity.test.ts +58 -13
  102. package/src/__tests__/llm-request-log-agent-loop-exit-reason.test.ts +116 -0
  103. package/src/__tests__/llm-request-log-error-payload.test.ts +138 -0
  104. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +36 -0
  105. package/src/__tests__/llm-request-log-source-factory.test.ts +29 -53
  106. package/src/__tests__/llm-resolver.test.ts +255 -2
  107. package/src/__tests__/llm-usage-store.test.ts +114 -0
  108. package/src/__tests__/managed-profile-guard.test.ts +41 -29
  109. package/src/__tests__/managed-skill-lifecycle.test.ts +109 -18
  110. package/src/__tests__/managed-store.test.ts +84 -192
  111. package/src/__tests__/media-generate-image.test.ts +1 -1
  112. package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -2
  113. package/src/__tests__/messages-after-tiebreaker.test.ts +122 -0
  114. package/src/__tests__/notification-decision-fallback.test.ts +0 -91
  115. package/src/__tests__/notification-decision-strategy.test.ts +14 -31
  116. package/src/__tests__/notification-deep-link.test.ts +15 -0
  117. package/src/__tests__/notification-guardian-path.test.ts +1 -2
  118. package/src/__tests__/notification-platform-adapter.test.ts +5 -4
  119. package/src/__tests__/notification-telegram-adapter.test.ts +1 -0
  120. package/src/__tests__/notification-vellum-adapter.test.ts +113 -0
  121. package/src/__tests__/oauth-commands-routes.test.ts +168 -16
  122. package/src/__tests__/oauth-provider-profiles.test.ts +9 -0
  123. package/src/__tests__/openai-provider.test.ts +242 -3
  124. package/src/__tests__/openai-responses-cutover-guard.test.ts +17 -9
  125. package/src/__tests__/openrouter-provider-only.test.ts +51 -3
  126. package/src/__tests__/openrouter-token-estimation.test.ts +34 -25
  127. package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -2
  128. package/src/__tests__/persistence-pipeline.test.ts +0 -2
  129. package/src/__tests__/{managed-proxy-context.test.ts → platform-proxy-context.test.ts} +7 -2
  130. package/src/__tests__/platform.test.ts +2 -0
  131. package/src/__tests__/plugin-api-shim.test.ts +125 -0
  132. package/src/__tests__/plugin-bootstrap.test.ts +10 -36
  133. package/src/__tests__/plugin-external-api.test.ts +68 -0
  134. package/src/__tests__/plugin-registry.test.ts +0 -77
  135. package/src/__tests__/plugin-route-contribution.test.ts +0 -1
  136. package/src/__tests__/plugin-skill-contribution.test.ts +0 -2
  137. package/src/__tests__/plugin-tool-contribution.test.ts +16 -15
  138. package/src/__tests__/plugin-types.test.ts +3 -13
  139. package/src/__tests__/process-message-background-slack.test.ts +8 -1
  140. package/src/__tests__/process-message-display-content.test.ts +421 -0
  141. package/src/__tests__/provider-catalog-visibility.test.ts +158 -0
  142. package/src/__tests__/provider-error-scenarios.test.ts +111 -0
  143. package/src/__tests__/{provider-managed-proxy-integration.test.ts → provider-platform-proxy-integration.test.ts} +33 -31
  144. package/src/__tests__/scaffold-managed-skill-tool.test.ts +65 -13
  145. package/src/__tests__/schedule-routes.test.ts +50 -3
  146. package/src/__tests__/schedule-store.test.ts +94 -0
  147. package/src/__tests__/scheduler-reuse-conversation.test.ts +54 -7
  148. package/src/__tests__/schema-transforms.test.ts +20 -0
  149. package/src/__tests__/search-skills-unified.test.ts +0 -5
  150. package/src/__tests__/{secret-routes-managed-proxy.test.ts → secret-routes-platform-proxy.test.ts} +1 -1
  151. package/src/__tests__/server-history-render.test.ts +43 -0
  152. package/src/__tests__/skill-load-feature-flag.test.ts +0 -12
  153. package/src/__tests__/skill-load-tool.test.ts +27 -89
  154. package/src/__tests__/skill-memory.test.ts +23 -3
  155. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -38
  156. package/src/__tests__/skills-files-catalog-fallback.test.ts +0 -3
  157. package/src/__tests__/skills-install-extract.test.ts +49 -38
  158. package/src/__tests__/skills-install-staging.test.ts +159 -0
  159. package/src/__tests__/skills-uninstall.test.ts +9 -41
  160. package/src/__tests__/skills.test.ts +51 -58
  161. package/src/__tests__/slack-channel-config.test.ts +9 -0
  162. package/src/__tests__/subagent-tool-filtering.test.ts +50 -0
  163. package/src/__tests__/system-prompt.test.ts +670 -63
  164. package/src/__tests__/terminal-tools.test.ts +28 -1
  165. package/src/__tests__/thread-backfill.test.ts +557 -27
  166. package/src/__tests__/title-generate-pipeline.test.ts +0 -13
  167. package/src/__tests__/token-estimate-pipeline.test.ts +0 -3
  168. package/src/__tests__/tool-error-pipeline.test.ts +0 -3
  169. package/src/__tests__/tool-execute-pipeline.test.ts +0 -5
  170. package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
  171. package/src/__tests__/tool-executor.test.ts +16 -4
  172. package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -12
  173. package/src/__tests__/turn-events-store.test.ts +256 -0
  174. package/src/__tests__/twilio-routes.test.ts +4 -0
  175. package/src/__tests__/user-plugin-loader.test.ts +0 -7
  176. package/src/__tests__/voice-session-bridge.test.ts +198 -0
  177. package/src/__tests__/web-search-catalog-parity.test.ts +32 -10
  178. package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +115 -3
  179. package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +50 -0
  180. package/src/__tests__/workspace-migration-073-repair-recall-callsite-empty-profile.test.ts +153 -0
  181. package/src/__tests__/workspace-migration-085-memory-v2-bm25-b-reembed-disabled-v2-pages.test.ts +220 -0
  182. package/src/__tests__/workspace-migration-086-revert-stale-gemini-mis-rewrites.test.ts +269 -0
  183. package/src/__tests__/workspace-migration-087-memory-router-balanced-profile.test.ts +228 -0
  184. package/src/__tests__/workspace-migration-remove-legacy-skills-index.test.ts +309 -0
  185. package/src/__tests__/workspace-migrations-runner.test.ts +111 -3
  186. package/src/a2a/__tests__/agent-card.test.ts +98 -0
  187. package/src/a2a/__tests__/e2e-a2a-channel.test.ts +597 -0
  188. package/src/a2a/__tests__/protocol-helpers.test.ts +113 -0
  189. package/src/a2a/__tests__/task-store.test.ts +246 -0
  190. package/src/a2a/agent-card.ts +58 -0
  191. package/src/a2a/feature-gate.ts +8 -0
  192. package/src/a2a/protocol-constants.ts +21 -0
  193. package/src/a2a/protocol-errors.ts +50 -0
  194. package/src/a2a/protocol-types.ts +162 -0
  195. package/src/a2a/task-store.ts +168 -0
  196. package/src/acp/resolve-agent.ts +1 -1
  197. package/src/agent/image-optimize.ts +13 -5
  198. package/src/agent/loop.ts +167 -18
  199. package/src/calls/voice-session-bridge.ts +61 -42
  200. package/src/channels/config.ts +9 -0
  201. package/src/channels/types.ts +122 -0
  202. package/src/cli/__tests__/unknown-command.test.ts +24 -0
  203. package/src/cli/commands/__tests__/changelog.test.ts +304 -319
  204. package/src/cli/{__tests__ → commands/__tests__}/notifications.test.ts +201 -28
  205. package/src/cli/commands/__tests__/schedules.test.ts +960 -0
  206. package/src/cli/commands/changelog.ts +106 -42
  207. package/src/cli/commands/conversations.ts +102 -17
  208. package/src/cli/commands/default-action.ts +10 -53
  209. package/src/cli/commands/notifications.ts +388 -346
  210. package/src/cli/commands/plugins.ts +252 -0
  211. package/src/cli/commands/schedules.ts +683 -0
  212. package/src/cli/commands/telemetry.ts +40 -0
  213. package/src/cli/lib/__tests__/cli-colors.test.ts +48 -0
  214. package/src/cli/lib/__tests__/confirm-prompt.test.ts +159 -0
  215. package/src/cli/lib/__tests__/install-from-github.test.ts +355 -0
  216. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +154 -0
  217. package/src/cli/lib/__tests__/search-plugins.test.ts +261 -0
  218. package/src/cli/lib/__tests__/uninstall-plugin.test.ts +124 -0
  219. package/src/cli/lib/__tests__/unknown-command.test.ts +106 -0
  220. package/src/cli/lib/cli-colors.ts +12 -0
  221. package/src/cli/lib/confirm-prompt.ts +79 -0
  222. package/src/cli/lib/install-from-github.ts +303 -0
  223. package/src/cli/lib/list-installed-plugins.ts +137 -0
  224. package/src/cli/lib/search-plugins.ts +163 -0
  225. package/src/cli/lib/uninstall-plugin.ts +82 -0
  226. package/src/cli/lib/unknown-command.ts +111 -0
  227. package/src/cli/program.ts +52 -2
  228. package/src/config/assistant-feature-flags.ts +24 -54
  229. package/src/config/bundled-skills/app-builder/SKILL.md +140 -22
  230. package/src/config/bundled-skills/app-builder/TOOLS.json +7 -0
  231. package/src/config/bundled-skills/computer-use/TOOLS.json +15 -52
  232. package/src/config/bundled-skills/document/SKILL.md +23 -3
  233. package/src/config/bundled-skills/document/TOOLS.json +53 -0
  234. package/src/config/bundled-skills/document/tools/document-delete.ts +12 -0
  235. package/src/config/bundled-skills/document/tools/document-list.ts +12 -0
  236. package/src/config/bundled-skills/document/tools/document-read.ts +12 -0
  237. package/src/config/bundled-skills/phone-calls/SKILL.md +1 -1
  238. package/src/config/bundled-skills/skill-management/SKILL.md +2 -2
  239. package/src/config/bundled-skills/skill-management/TOOLS.json +7 -7
  240. package/src/config/bundled-tool-registry.ts +6 -0
  241. package/src/config/call-site-defaults.ts +105 -0
  242. package/src/config/feature-flag-registry.json +41 -9
  243. package/src/config/llm-resolver.ts +52 -1
  244. package/src/config/loader.ts +64 -38
  245. package/src/config/schema.ts +9 -10
  246. package/src/config/schemas/__tests__/llm-request-logs.test.ts +36 -0
  247. package/src/config/schemas/__tests__/memory-v2.test.ts +3 -3
  248. package/src/config/schemas/channels.ts +17 -0
  249. package/src/config/schemas/compaction.ts +28 -0
  250. package/src/config/schemas/conversations.ts +10 -0
  251. package/src/config/schemas/heartbeat.ts +23 -0
  252. package/src/config/schemas/llm-request-logs.ts +31 -7
  253. package/src/config/schemas/llm.ts +1 -0
  254. package/src/config/schemas/memory-retrieval.ts +18 -0
  255. package/src/config/schemas/memory-retrospective.ts +1 -1
  256. package/src/config/schemas/memory-v2.ts +4 -4
  257. package/src/config/schemas/memory.ts +3 -1
  258. package/src/config/schemas/tools.ts +14 -0
  259. package/src/config/seed-inference-profiles.ts +99 -29
  260. package/src/config/skills.ts +3 -96
  261. package/src/context/compactor.ts +1107 -0
  262. package/src/context/token-estimator.ts +34 -36
  263. package/src/context/window-manager.ts +197 -1520
  264. package/src/credential-execution/managed-catalog.ts +37 -0
  265. package/src/credential-health/credential-health-service.ts +280 -19
  266. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +33 -18
  267. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +138 -0
  268. package/src/daemon/__tests__/conversation-tool-setup.test.ts +74 -0
  269. package/src/daemon/approval-generators.ts +8 -6
  270. package/src/daemon/config-watcher.ts +94 -31
  271. package/src/daemon/conversation-agent-loop-handlers.ts +78 -0
  272. package/src/daemon/conversation-agent-loop.ts +198 -11
  273. package/src/daemon/conversation-error.ts +171 -37
  274. package/src/daemon/conversation-lifecycle.ts +53 -40
  275. package/src/daemon/conversation-messaging.ts +25 -6
  276. package/src/daemon/conversation-process.ts +49 -12
  277. package/src/daemon/conversation-runtime-assembly.ts +25 -1
  278. package/src/daemon/conversation-slash.ts +12 -5
  279. package/src/daemon/conversation-store.ts +11 -4
  280. package/src/daemon/conversation-tool-setup.ts +39 -7
  281. package/src/daemon/conversation.ts +33 -8
  282. package/src/daemon/date-context.ts +40 -0
  283. package/src/daemon/external-plugins-bootstrap.ts +217 -181
  284. package/src/daemon/first-greeting.ts +22 -2
  285. package/src/daemon/guardian-action-generators.ts +1 -125
  286. package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +248 -0
  287. package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +154 -0
  288. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +133 -0
  289. package/src/daemon/handlers/__tests__/config-a2a.test.ts +95 -0
  290. package/src/daemon/handlers/config-a2a.ts +289 -0
  291. package/src/daemon/handlers/config-model.ts +6 -5
  292. package/src/daemon/handlers/config-slack-channel.ts +15 -3
  293. package/src/daemon/handlers/conversations.ts +1 -0
  294. package/src/daemon/handlers/shared.ts +14 -5
  295. package/src/daemon/handlers/skills.ts +111 -108
  296. package/src/daemon/history-repair.ts +28 -1
  297. package/src/daemon/host-app-control-proxy.ts +153 -27
  298. package/src/daemon/host-proxy-preactivation.ts +85 -18
  299. package/src/daemon/lifecycle.ts +89 -91
  300. package/src/daemon/meet-host-supervisor.ts +5 -4
  301. package/src/daemon/memory-v2-startup.ts +85 -0
  302. package/src/daemon/message-protocol.ts +1 -0
  303. package/src/daemon/message-types/conversations.ts +25 -0
  304. package/src/daemon/message-types/messages.ts +61 -0
  305. package/src/daemon/message-types/notifications.ts +21 -0
  306. package/src/daemon/message-types/subagents.ts +1 -0
  307. package/src/daemon/message-types/sync.ts +1 -0
  308. package/src/daemon/pkb-reminder-builder.test.ts +11 -54
  309. package/src/daemon/pkb-reminder-builder.ts +5 -20
  310. package/src/daemon/plugin-source-watcher.ts +146 -0
  311. package/src/daemon/process-message.ts +24 -3
  312. package/src/daemon/server.ts +11 -2
  313. package/src/daemon/skill-memory-refresh.ts +33 -0
  314. package/src/daemon/wake-target-adapter.ts +2 -0
  315. package/src/documents/document-store.ts +221 -3
  316. package/src/embedded/plugin-api.ts +40 -0
  317. package/src/export/__tests__/transcript-formatter.test.ts +121 -0
  318. package/src/export/transcript-formatter.ts +54 -20
  319. package/src/filing/filing-service.ts +39 -0
  320. package/src/heartbeat/__tests__/heartbeat-service.test.ts +135 -6
  321. package/src/heartbeat/heartbeat-run-store.ts +2 -1
  322. package/src/heartbeat/heartbeat-service.ts +73 -189
  323. package/src/home/__tests__/feed-types.test.ts +80 -0
  324. package/src/home/feed-types.ts +36 -2
  325. package/src/home/post-connect-feed.ts +1 -0
  326. package/src/index.ts +18 -1
  327. package/src/ipc/cli-client.ts +147 -45
  328. package/src/live-voice/__tests__/live-voice-stt.test.ts +57 -0
  329. package/src/mcp/client.ts +20 -4
  330. package/src/media/image-credentials.ts +3 -3
  331. package/src/memory/__tests__/bookmark-crud.test.ts +33 -27
  332. package/src/memory/__tests__/conversation-queries.test.ts +483 -0
  333. package/src/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +113 -0
  334. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +2 -50
  335. package/src/memory/__tests__/memory-retrospective-job.test.ts +87 -4
  336. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +119 -14
  337. package/src/memory/__tests__/message-content.test.ts +35 -0
  338. package/src/memory/bookmark-crud.ts +42 -10
  339. package/src/memory/context-search/sources/conversations.ts +62 -2
  340. package/src/memory/context-search/sources/workspace.ts +4 -0
  341. package/src/memory/conversation-crud.ts +63 -19
  342. package/src/memory/conversation-queries.ts +197 -11
  343. package/src/memory/conversation-title-service.ts +26 -4
  344. package/src/memory/db-init.ts +12 -0
  345. package/src/memory/delivery-crud.ts +152 -5
  346. package/src/memory/embedding-backend.ts +4 -4
  347. package/src/memory/external-conversation-store.ts +66 -5
  348. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +150 -12
  349. package/src/memory/graph/conversation-graph-memory.ts +49 -21
  350. package/src/memory/graph/tools.ts +9 -40
  351. package/src/memory/indexer.ts +34 -29
  352. package/src/memory/invite-store.ts +53 -0
  353. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +73 -0
  354. package/src/memory/jobs/embed-concept-page.ts +20 -11
  355. package/src/memory/jobs-worker.ts +6 -1
  356. package/src/memory/llm-request-log-source-clickhouse.ts +24 -12
  357. package/src/memory/llm-request-log-source.ts +19 -52
  358. package/src/memory/llm-request-log-store.ts +92 -1
  359. package/src/memory/llm-usage-store.ts +125 -5
  360. package/src/memory/memory-retrospective-enqueue.ts +1 -20
  361. package/src/memory/memory-retrospective-job.ts +33 -6
  362. package/src/memory/memory-retrospective-startup-cleanup.ts +72 -5
  363. package/src/memory/message-content.ts +1 -1
  364. package/src/memory/migrations/109-external-conversation-bindings.ts +15 -4
  365. package/src/memory/migrations/229-delete-private-conversations.test.ts +38 -1
  366. package/src/memory/migrations/229-delete-private-conversations.ts +7 -0
  367. package/src/memory/migrations/247-external-conversation-binding-thread-id.ts +78 -0
  368. package/src/memory/migrations/248-create-onboarding-events.ts +21 -0
  369. package/src/memory/migrations/249-normalize-slack-external-content.ts +240 -0
  370. package/src/memory/migrations/250-provider-connection-base-url-and-models.ts +28 -0
  371. package/src/memory/migrations/251-a2a-tasks.ts +49 -0
  372. package/src/memory/migrations/252-llm-request-log-agent-loop-exit-reason.ts +32 -0
  373. package/src/memory/migrations/index.ts +9 -0
  374. package/src/memory/migrations/registry.ts +16 -0
  375. package/src/memory/onboarding-events-store.ts +106 -0
  376. package/src/memory/schema/a2a.ts +15 -0
  377. package/src/memory/schema/bookmarks.ts +0 -2
  378. package/src/memory/schema/calls.ts +1 -0
  379. package/src/memory/schema/index.ts +1 -0
  380. package/src/memory/schema/inference.ts +3 -3
  381. package/src/memory/schema/infrastructure.ts +13 -0
  382. package/src/memory/turn-events-store.ts +127 -2
  383. package/src/memory/v2/__tests__/activation-store.test.ts +25 -23
  384. package/src/memory/v2/__tests__/activation.test.ts +0 -8
  385. package/src/memory/v2/__tests__/cli-command-store.test.ts +404 -0
  386. package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +25 -4
  387. package/src/memory/v2/__tests__/injection.test.ts +288 -11
  388. package/src/memory/v2/__tests__/migration.test.ts +87 -0
  389. package/src/memory/v2/__tests__/page-index.test.ts +83 -0
  390. package/src/memory/v2/__tests__/prompts-router.test.ts +58 -6
  391. package/src/memory/v2/__tests__/qdrant.test.ts +66 -3
  392. package/src/memory/v2/__tests__/router.test.ts +15 -0
  393. package/src/memory/v2/__tests__/skill-store.test.ts +387 -8
  394. package/src/memory/v2/__tests__/static-context.test.ts +12 -1
  395. package/src/memory/v2/activation-store.ts +14 -16
  396. package/src/memory/v2/cli-command-content.ts +19 -0
  397. package/src/memory/v2/cli-command-store.ts +304 -0
  398. package/src/memory/v2/frontmatter-sweep.ts +7 -1
  399. package/src/memory/v2/injection.ts +81 -26
  400. package/src/memory/v2/migration.ts +49 -19
  401. package/src/memory/v2/page-index.ts +63 -8
  402. package/src/memory/v2/prompts/router.ts +11 -8
  403. package/src/memory/v2/prompts/sweep.ts +2 -2
  404. package/src/memory/v2/qdrant.ts +135 -7
  405. package/src/memory/v2/router.ts +9 -8
  406. package/src/memory/v2/skill-store.ts +120 -35
  407. package/src/memory/v2/static-context.ts +4 -4
  408. package/src/memory/v2/types.ts +23 -0
  409. package/src/messaging/providers/a2a/__tests__/deliver.test.ts +274 -0
  410. package/src/messaging/providers/a2a/deliver.ts +156 -0
  411. package/src/messaging/providers/gmail/client.ts +9 -2
  412. package/src/messaging/providers/index.ts +11 -2
  413. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +45 -5
  414. package/src/messaging/providers/slack/__tests__/download.test.ts +231 -0
  415. package/src/messaging/providers/slack/adapter.ts +43 -5
  416. package/src/messaging/providers/slack/client.ts +27 -0
  417. package/src/messaging/providers/slack/deep-link.ts +65 -0
  418. package/src/messaging/providers/slack/download.ts +104 -0
  419. package/src/messaging/providers/slack/message-metadata.test.ts +32 -0
  420. package/src/messaging/providers/slack/message-metadata.ts +27 -0
  421. package/src/messaging/providers/slack/render-transcript.test.ts +134 -0
  422. package/src/messaging/providers/slack/render-transcript.ts +69 -5
  423. package/src/messaging/providers/slack/types.ts +20 -1
  424. package/src/notifications/__tests__/broadcaster.test.ts +203 -0
  425. package/src/notifications/__tests__/decision-engine.test.ts +283 -0
  426. package/src/notifications/__tests__/deterministic-checks.test.ts +286 -0
  427. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +1 -0
  428. package/src/notifications/__tests__/home-feed-side-effect.test.ts +430 -7
  429. package/src/notifications/adapters/macos.ts +12 -2
  430. package/src/notifications/broadcaster.ts +29 -4
  431. package/src/notifications/conversation-pairing.ts +2 -1
  432. package/src/notifications/copy-composer.ts +17 -64
  433. package/src/notifications/decision-engine.ts +113 -45
  434. package/src/notifications/deterministic-checks.ts +96 -0
  435. package/src/notifications/emit-signal.ts +21 -1
  436. package/src/notifications/home-feed-side-effect.ts +138 -5
  437. package/src/notifications/signal.ts +3 -5
  438. package/src/notifications/types.ts +8 -0
  439. package/src/oauth/connection-resolver.ts +8 -4
  440. package/src/oauth/platform-connection.test.ts +43 -3
  441. package/src/oauth/platform-connection.ts +19 -6
  442. package/src/oauth/seed-providers.ts +10 -1
  443. package/src/permissions/checker.ts +2 -0
  444. package/src/permissions/ipc-risk-types.ts +1 -0
  445. package/src/permissions/question-prompter.test.ts +416 -0
  446. package/src/permissions/question-prompter.ts +294 -0
  447. package/src/platform/client.test.ts +1 -1
  448. package/src/platform/client.ts +1 -1
  449. package/src/plugin-api/constants.ts +26 -0
  450. package/src/plugin-api/index.ts +34 -1
  451. package/src/plugin-api/types.ts +104 -22
  452. package/src/plugins/defaults/circuit-breaker.ts +0 -5
  453. package/src/plugins/defaults/compaction.ts +0 -4
  454. package/src/plugins/defaults/empty-response.ts +0 -2
  455. package/src/plugins/defaults/history-repair.ts +0 -2
  456. package/src/plugins/defaults/injectors.ts +74 -22
  457. package/src/plugins/defaults/llm-call.ts +0 -2
  458. package/src/plugins/defaults/memory-retrieval.ts +0 -1
  459. package/src/plugins/defaults/overflow-reduce.ts +0 -1
  460. package/src/plugins/defaults/persistence.ts +0 -2
  461. package/src/plugins/defaults/title-generate.ts +0 -5
  462. package/src/plugins/defaults/token-estimate.ts +0 -2
  463. package/src/plugins/defaults/tool-error.ts +0 -7
  464. package/src/plugins/defaults/tool-execute.ts +0 -2
  465. package/src/plugins/defaults/tool-result-truncate.ts +0 -4
  466. package/src/plugins/ensure-plugin-api-shim.ts +96 -0
  467. package/src/plugins/external-api.ts +104 -0
  468. package/src/plugins/external-plugin-loader.ts +187 -42
  469. package/src/plugins/feature-gate.ts +22 -0
  470. package/src/plugins/pipeline.ts +37 -0
  471. package/src/plugins/registry.ts +48 -80
  472. package/src/plugins/types.ts +40 -26
  473. package/src/plugins/user-loader.ts +21 -2
  474. package/src/proactive-artifact/aux-message-injector.ts +11 -0
  475. package/src/proactive-artifact/job.test.ts +37 -5
  476. package/src/prompts/__tests__/system-prompt.test.ts +10 -43
  477. package/src/prompts/__tests__/task-progress-hint-section.test.ts +95 -0
  478. package/src/prompts/normalize-onboarding.ts +27 -0
  479. package/src/prompts/sections.ts +302 -0
  480. package/src/prompts/system-prompt.ts +63 -174
  481. package/src/prompts/templates/BOOTSTRAP.md +17 -1
  482. package/src/prompts/templates/system-sections.ts +164 -0
  483. package/src/providers/__tests__/inference.test.ts +24 -7
  484. package/src/providers/anthropic/client.ts +28 -28
  485. package/src/providers/call-site-routing.ts +24 -6
  486. package/src/providers/connection-resolution.ts +68 -11
  487. package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +74 -0
  488. package/src/providers/inference/__tests__/connections-openai-compatible.test.ts +175 -0
  489. package/src/providers/inference/__tests__/connections-status-label.test.ts +15 -0
  490. package/src/providers/inference/adapter-factory.ts +32 -6
  491. package/src/providers/inference/auth.ts +12 -0
  492. package/src/providers/inference/backfill.ts +14 -1
  493. package/src/providers/inference/connections.ts +159 -34
  494. package/src/providers/inference/resolve-auth.ts +14 -4
  495. package/src/providers/model-catalog.ts +249 -12
  496. package/src/providers/model-intents.ts +3 -3
  497. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +235 -0
  498. package/src/providers/openai/chat-completions-provider.ts +169 -8
  499. package/src/providers/openrouter/client.ts +49 -4
  500. package/src/providers/{managed-proxy → platform-proxy}/constants.ts +4 -2
  501. package/src/providers/{managed-proxy → platform-proxy}/context.ts +3 -3
  502. package/src/providers/provider-availability.ts +17 -2
  503. package/src/providers/provider-catalog-visibility.ts +38 -0
  504. package/src/providers/provider-send-message.ts +27 -12
  505. package/src/providers/registry.ts +52 -15
  506. package/src/providers/retry.ts +47 -1
  507. package/src/runtime/__tests__/agent-wake.test.ts +152 -0
  508. package/src/runtime/agent-wake.ts +103 -15
  509. package/src/runtime/auth/route-policy.ts +21 -1
  510. package/src/runtime/btw-sidechain.ts +2 -0
  511. package/src/runtime/http-server.ts +7 -16
  512. package/src/runtime/http-types.ts +19 -47
  513. package/src/runtime/migrations/origin-mode.ts +1 -1
  514. package/src/runtime/pending-interactions.ts +1 -0
  515. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +17 -0
  516. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +258 -0
  517. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +5 -1
  518. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +172 -23
  519. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +275 -44
  520. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +12 -0
  521. package/src/runtime/routes/__tests__/question-routes.test.ts +395 -0
  522. package/src/runtime/routes/__tests__/tts-routes.test.ts +64 -1
  523. package/src/runtime/routes/acp-routes-list.test.ts +143 -0
  524. package/src/runtime/routes/acp-routes.ts +5 -3
  525. package/src/runtime/routes/auth-routes.ts +1 -1
  526. package/src/runtime/routes/bookmark-routes.ts +5 -3
  527. package/src/runtime/routes/btw-routes.ts +5 -1
  528. package/src/runtime/routes/channel-availability-routes.ts +126 -0
  529. package/src/runtime/routes/consolidation-routes.ts +100 -0
  530. package/src/runtime/routes/conversation-cli-routes.ts +44 -3
  531. package/src/runtime/routes/conversation-list-routes.ts +3 -20
  532. package/src/runtime/routes/conversation-management-routes.ts +17 -42
  533. package/src/runtime/routes/conversation-query-routes.ts +99 -35
  534. package/src/runtime/routes/conversation-routes.ts +97 -11
  535. package/src/runtime/routes/documents-routes.ts +25 -86
  536. package/src/runtime/routes/group-routes.ts +5 -0
  537. package/src/runtime/routes/inbound-conversation.ts +28 -8
  538. package/src/runtime/routes/inbound-message-handler.ts +236 -41
  539. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +111 -0
  540. package/src/runtime/routes/inbound-stages/background-dispatch.ts +32 -1
  541. package/src/runtime/routes/inbound-stages/edit-intercept.ts +17 -4
  542. package/src/runtime/routes/index.ts +8 -0
  543. package/src/runtime/routes/inference-profile-session-handler.ts +17 -44
  544. package/src/runtime/routes/inference-profile-session-reaper.ts +7 -21
  545. package/src/runtime/routes/inference-provider-connection-routes.ts +199 -22
  546. package/src/runtime/routes/integrations/a2a.ts +235 -0
  547. package/src/runtime/routes/integrations/slack/share.ts +4 -52
  548. package/src/runtime/routes/integrations/slack/token.ts +43 -0
  549. package/src/runtime/routes/integrations/twilio.ts +6 -13
  550. package/src/runtime/routes/llm-call-sites-routes.ts +11 -1
  551. package/src/runtime/routes/notification-routes.ts +1 -1
  552. package/src/runtime/routes/oauth-commands-routes.ts +105 -15
  553. package/src/runtime/routes/oauth-lifecycle-routes.ts +43 -0
  554. package/src/runtime/routes/question-routes.ts +259 -0
  555. package/src/runtime/routes/rename-conversation-routes.ts +2 -33
  556. package/src/runtime/routes/schedule-routes.ts +4 -7
  557. package/src/runtime/routes/subagents-routes.ts +98 -18
  558. package/src/runtime/routes/telemetry-routes.ts +27 -0
  559. package/src/runtime/routes/tts-routes.ts +27 -2
  560. package/src/runtime/routes/workspace-routes.test.ts +43 -0
  561. package/src/runtime/routes/workspace-routes.ts +28 -0
  562. package/src/runtime/services/conversation-serializer.ts +39 -7
  563. package/src/runtime/sync/resource-sync-events.ts +93 -1
  564. package/src/schedule/schedule-store.ts +27 -2
  565. package/src/schedule/scheduler.ts +9 -1
  566. package/src/security/__tests__/untrusted-content.test.ts +86 -0
  567. package/src/security/untrusted-content.ts +93 -8
  568. package/src/skills/catalog-files.ts +1 -1
  569. package/src/skills/catalog-install.ts +233 -116
  570. package/src/skills/clawhub.ts +70 -13
  571. package/src/skills/managed-store.ts +4 -119
  572. package/src/skills/skillssh-registry.ts +27 -48
  573. package/src/subagent/manager.ts +17 -7
  574. package/src/telemetry/types.ts +113 -1
  575. package/src/telemetry/usage-telemetry-reporter.test.ts +312 -5
  576. package/src/telemetry/usage-telemetry-reporter.ts +113 -7
  577. package/src/tools/apps/executors.ts +58 -7
  578. package/src/tools/ask-question/ask-question-tool.test.ts +509 -0
  579. package/src/tools/ask-question/ask-question-tool.ts +304 -0
  580. package/src/tools/browser/browser-execution.ts +15 -11
  581. package/src/tools/computer-use/definitions.ts +3 -3
  582. package/src/tools/credentials/vault.ts +1 -1
  583. package/src/tools/document/document-tool.ts +124 -1
  584. package/src/tools/filesystem/edit.ts +1 -1
  585. package/src/tools/filesystem/list.ts +1 -1
  586. package/src/tools/filesystem/read.ts +1 -1
  587. package/src/tools/filesystem/write.ts +5 -2
  588. package/src/tools/host-filesystem/transfer.ts +1 -1
  589. package/src/tools/host-terminal/host-shell.ts +1 -1
  590. package/src/tools/memory/register.ts +1 -9
  591. package/src/tools/permission-checker.ts +1 -1
  592. package/src/tools/registry.ts +17 -7
  593. package/src/tools/schedule/create.ts +2 -2
  594. package/src/tools/schema-transforms.ts +7 -2
  595. package/src/tools/side-effects.ts +1 -0
  596. package/src/tools/skills/delete-managed.ts +4 -4
  597. package/src/tools/skills/execute.ts +1 -1
  598. package/src/tools/skills/scaffold-managed.ts +3 -2
  599. package/src/tools/subagent/notify-parent.ts +1 -1
  600. package/src/tools/system/request-permission.ts +2 -2
  601. package/src/tools/terminal/safe-env.ts +60 -1
  602. package/src/tools/tool-manifest.ts +2 -0
  603. package/src/tools/types.ts +107 -21
  604. package/src/tools/ui-surface/definitions.ts +6 -5
  605. package/src/tts/__tests__/provider-adapters.test.ts +76 -2
  606. package/src/tts/providers/elevenlabs-provider.ts +75 -1
  607. package/src/types/onboarding-context.ts +2 -0
  608. package/src/util/errors.ts +17 -0
  609. package/src/util/platform.ts +10 -0
  610. package/src/watcher/__tests__/engine.test.ts +22 -0
  611. package/src/watcher/engine.ts +6 -2
  612. package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +80 -15
  613. package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +35 -22
  614. package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +3 -1
  615. package/src/workspace/migrations/083-system-prompt-prefix-to-file.ts +191 -0
  616. package/src/workspace/migrations/084-remove-legacy-skills-index.ts +276 -0
  617. package/src/workspace/migrations/085-memory-v2-bm25-b-reembed-disabled-v2-pages.ts +137 -0
  618. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +198 -0
  619. package/src/workspace/migrations/087-memory-router-balanced-profile.ts +91 -0
  620. package/src/workspace/migrations/registry.ts +10 -0
  621. package/src/workspace/migrations/runner.ts +39 -9
  622. package/src/workspace/migrations/types.ts +4 -0
  623. package/examples/plugins/echo/bun.lock +0 -25
  624. package/src/__tests__/context-window-manager.test.ts +0 -2481
  625. package/src/__tests__/guardian-action-conversation-turn.test.ts +0 -441
  626. package/src/context/__tests__/compact-prompt.test.ts +0 -63
  627. package/src/context/prompts/compact.md +0 -26
  628. package/src/memory/graph/__tests__/remember-description.test.ts +0 -55
  629. package/src/prompts/__tests__/build-cli-reference-section.test.ts +0 -37
  630. package/src/runtime/guardian-action-conversation-turn.ts +0 -99
@@ -42,12 +42,10 @@ mock.module("../config/loader.js", () => ({
42
42
  },
43
43
  }));
44
44
 
45
- const { applyRuntimeInjections, composeInjectorChain } = await import(
46
- "../daemon/conversation-runtime-assembly.js"
47
- );
48
- const { DEFAULT_INJECTOR_ORDER, defaultInjectorsPlugin } = await import(
49
- "../plugins/defaults/injectors.js"
50
- );
45
+ const { applyRuntimeInjections, composeInjectorChain } =
46
+ await import("../daemon/conversation-runtime-assembly.js");
47
+ const { DEFAULT_INJECTOR_ORDER, defaultInjectorsPlugin } =
48
+ await import("../plugins/defaults/injectors.js");
51
49
  import {
52
50
  getInjectors,
53
51
  registerPlugin,
@@ -80,7 +78,6 @@ function wrapInPlugin(name: string, injectors: Injector[]): Plugin {
80
78
  manifest: {
81
79
  name,
82
80
  version: "0.0.1",
83
- requires: { pluginRuntime: "v1" },
84
81
  },
85
82
  injectors,
86
83
  };
@@ -91,18 +88,20 @@ describe("injector chain", () => {
91
88
  resetPluginRegistryForTests();
92
89
  });
93
90
 
94
- test("defaultInjectorsPlugin registers the ten defaults in the documented order", () => {
91
+ test("defaultInjectorsPlugin registers the defaults in the documented order", () => {
95
92
  registerPlugin(defaultInjectorsPlugin);
96
93
 
97
94
  const names = getInjectors().map((i) => i.name);
98
95
  expect(names).toEqual([
99
96
  "disk-pressure-warning",
100
97
  "workspace-context",
98
+ "background-turn",
101
99
  "unified-turn-context",
102
100
  "pkb-context",
103
101
  "pkb-reminder",
104
102
  "memory-v2-static",
105
103
  "now-md",
104
+ "active-documents",
106
105
  "subagent-status",
107
106
  "slack-messages",
108
107
  "thread-focus",
@@ -119,6 +118,9 @@ describe("injector chain", () => {
119
118
  expect(byName.get("workspace-context")).toBe(
120
119
  DEFAULT_INJECTOR_ORDER.workspaceContext,
121
120
  );
121
+ expect(byName.get("background-turn")).toBe(
122
+ DEFAULT_INJECTOR_ORDER.backgroundTurn,
123
+ );
122
124
  expect(byName.get("unified-turn-context")).toBe(
123
125
  DEFAULT_INJECTOR_ORDER.unifiedTurnContext,
124
126
  );
@@ -128,6 +130,9 @@ describe("injector chain", () => {
128
130
  DEFAULT_INJECTOR_ORDER.memoryV2Static,
129
131
  );
130
132
  expect(byName.get("now-md")).toBe(DEFAULT_INJECTOR_ORDER.nowMd);
133
+ expect(byName.get("active-documents")).toBe(
134
+ DEFAULT_INJECTOR_ORDER.activeDocuments,
135
+ );
131
136
  expect(byName.get("subagent-status")).toBe(
132
137
  DEFAULT_INJECTOR_ORDER.subagentStatus,
133
138
  );
@@ -153,12 +158,14 @@ describe("injector chain", () => {
153
158
  expect(names).toEqual([
154
159
  "disk-pressure-warning", // 5
155
160
  "workspace-context", // 10
161
+ "background-turn", // 15
156
162
  "unified-turn-context", // 20
157
163
  "plugin-25", // 25 — slots in
158
164
  "pkb-context", // 30
159
165
  "pkb-reminder", // 35
160
166
  "memory-v2-static", // 38
161
167
  "now-md", // 40
168
+ "active-documents", // 45
162
169
  "subagent-status", // 50
163
170
  "slack-messages", // 60
164
171
  "thread-focus", // 70
@@ -1,3 +1,5 @@
1
+ import { mkdirSync, rmSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
1
3
  import { beforeEach, describe, expect, mock, test } from "bun:test";
2
4
 
3
5
  // ---------------------------------------------------------------------------
@@ -16,10 +18,13 @@ const mockCatalogSkills = mock(
16
18
  const mockClawhubInstall = mock(
17
19
  async (
18
20
  _slug: string,
19
- _opts?: { version?: string },
20
- ): Promise<{ success: boolean; error?: string; skillName?: string }> => ({
21
- success: true,
22
- }),
21
+ _opts?: { version?: string; projectRoot?: string },
22
+ ): Promise<{
23
+ success: boolean;
24
+ error?: string;
25
+ skillId?: string;
26
+ skillDir?: string;
27
+ }> => ({ success: true }),
23
28
  );
24
29
  const mockInstallExternalSkill = mock(
25
30
  async (
@@ -38,13 +43,27 @@ const mockEnsureSkillEntry = mock(
38
43
  enabled: false,
39
44
  }),
40
45
  );
46
+ const TEST_SKILLS_DIR = "/tmp/test-skills";
47
+ const installedSkillIds = new Set<string>();
48
+ const stagedSkillDirs = new Set<string>();
49
+ let stagingCounter = 0;
41
50
 
42
51
  // ---------------------------------------------------------------------------
43
52
  // Mock modules — before importing module under test
44
53
  // ---------------------------------------------------------------------------
45
54
 
46
55
  mock.module("../config/skills.js", () => ({
47
- loadSkillCatalog: mockCatalogSkills,
56
+ loadSkillCatalog: () => [
57
+ ...mockCatalogSkills(),
58
+ ...[...installedSkillIds].map((id) => ({
59
+ id,
60
+ displayName: id,
61
+ description: `Installed ${id}`,
62
+ source: "managed",
63
+ directoryPath: join(TEST_SKILLS_DIR, id),
64
+ skillFilePath: join(TEST_SKILLS_DIR, id, "SKILL.md"),
65
+ })),
66
+ ],
48
67
  }));
49
68
 
50
69
  mock.module("../skills/clawhub.js", () => ({
@@ -96,15 +115,30 @@ mock.module("../providers/provider-send-message.js", () => ({
96
115
  getConfiguredProvider: async () => null,
97
116
  userMessage: () => ({}),
98
117
  }));
99
- mock.module("../runtime/routes/workspace-utils.js", () => ({
100
- isTextMimeType: () => true,
101
- }));
102
118
  mock.module("../skills/catalog-cache.js", () => ({
103
119
  getCatalog: mockGetCatalog,
104
120
  }));
105
121
  mock.module("../skills/catalog-install.js", () => ({
122
+ commitStagedSkillInstall: (skillId: string, stagedDir: string) => {
123
+ if (!stagedSkillDirs.has(stagedDir)) {
124
+ throw new Error(
125
+ `Installed skill "${skillId}" is missing SKILL.md at the skill root`,
126
+ );
127
+ }
128
+ stagedSkillDirs.delete(stagedDir);
129
+ installedSkillIds.add(skillId);
130
+ },
131
+ createSkillInstallStagingDir: () => {
132
+ const stagingDir = join(
133
+ TEST_SKILLS_DIR,
134
+ ".install-staging",
135
+ `project-${stagingCounter++}`,
136
+ );
137
+ mkdirSync(join(stagingDir, "skills"), { recursive: true });
138
+ return stagingDir;
139
+ },
140
+ installSkillDependenciesIfPresent: () => {},
106
141
  installSkillLocally: mockInstallSkillLocally,
107
- upsertSkillsIndex: () => {},
108
142
  }));
109
143
  mock.module("../skills/catalog-search.js", () => ({
110
144
  filterByQuery: () => [],
@@ -112,7 +146,6 @@ mock.module("../skills/catalog-search.js", () => ({
112
146
  mock.module("../skills/managed-store.js", () => ({
113
147
  createManagedSkill: () => ({ created: true }),
114
148
  deleteManagedSkill: () => ({ deleted: true }),
115
- removeSkillsIndexEntry: () => {},
116
149
  validateManagedSkillId: () => null,
117
150
  }));
118
151
  mock.module("../memory/graph/capability-seed.js", () => ({
@@ -121,7 +154,7 @@ mock.module("../memory/graph/capability-seed.js", () => ({
121
154
  seedUninstalledCatalogSkillMemories: async () => {},
122
155
  }));
123
156
  mock.module("../util/platform.js", () => ({
124
- getWorkspaceSkillsDir: () => "/tmp/test-skills",
157
+ getWorkspaceSkillsDir: () => TEST_SKILLS_DIR,
125
158
  }));
126
159
  mock.module("../daemon/handlers/shared.js", () => ({
127
160
  CONFIG_RELOAD_DEBOUNCE_MS: 100,
@@ -141,13 +174,17 @@ import { installSkill } from "../daemon/handlers/skills.js";
141
174
  // Helpers
142
175
  // ---------------------------------------------------------------------------
143
176
 
144
-
145
177
  // ---------------------------------------------------------------------------
146
178
  // Tests
147
179
  // ---------------------------------------------------------------------------
148
180
 
149
181
  describe("installSkill routing", () => {
150
182
  beforeEach(() => {
183
+ rmSync(TEST_SKILLS_DIR, { recursive: true, force: true });
184
+ mkdirSync(TEST_SKILLS_DIR, { recursive: true });
185
+ installedSkillIds.clear();
186
+ stagedSkillDirs.clear();
187
+ stagingCounter = 0;
151
188
  mockCatalogSkills.mockReset();
152
189
  mockClawhubInstall.mockReset();
153
190
  mockInstallExternalSkill.mockReset();
@@ -158,7 +195,12 @@ describe("installSkill routing", () => {
158
195
 
159
196
  // Defaults
160
197
  mockCatalogSkills.mockReturnValue([]);
161
- mockClawhubInstall.mockResolvedValue({ success: true });
198
+ mockClawhubInstall.mockImplementation(async (slug, opts) => {
199
+ const skillId = slug.includes("/") ? slug.split("/").pop()! : slug;
200
+ const projectRoot = opts?.projectRoot ?? TEST_SKILLS_DIR;
201
+ const skillDir = stageClawhubSkill(projectRoot, skillId);
202
+ return { success: true, skillId, skillDir };
203
+ });
162
204
  mockInstallExternalSkill.mockResolvedValue(undefined);
163
205
  mockGetCatalog.mockResolvedValue([]);
164
206
  mockInstallSkillLocally.mockResolvedValue(undefined);
@@ -166,13 +208,38 @@ describe("installSkill routing", () => {
166
208
  mockEnsureSkillEntry.mockReturnValue({ enabled: false });
167
209
  });
168
210
 
169
- test("install with origin: 'skillssh' and multi-segment slug routes to installExternalSkill", async () => {
170
- const result = await installSkill(
171
- {
172
- slug: "vercel-labs/agent-skills/react-best-practices",
173
- origin: "skillssh",
174
- },
211
+ function writeInstalledSkill(skillId: string): void {
212
+ const skillDir = join(TEST_SKILLS_DIR, skillId);
213
+ mkdirSync(skillDir, { recursive: true });
214
+ writeFileSync(
215
+ join(skillDir, "SKILL.md"),
216
+ `---
217
+ name: "${skillId}"
218
+ description: "Installed test skill."
219
+ ---
220
+
221
+ Body.
222
+ `,
223
+ "utf-8",
175
224
  );
225
+ installedSkillIds.add(skillId);
226
+ }
227
+
228
+ function stageClawhubSkill(projectRoot: string, skillId: string): string {
229
+ const skillDir = join(projectRoot, "skills", skillId);
230
+ stagedSkillDirs.add(skillDir);
231
+ return skillDir;
232
+ }
233
+
234
+ test("install with origin: 'skillssh' and multi-segment slug routes to installExternalSkill", async () => {
235
+ mockInstallExternalSkill.mockImplementation(async () => {
236
+ writeInstalledSkill("react-best-practices");
237
+ });
238
+
239
+ const result = await installSkill({
240
+ slug: "vercel-labs/agent-skills/react-best-practices",
241
+ origin: "skillssh",
242
+ });
176
243
 
177
244
  expect(result.success).toBe(true);
178
245
  expect(mockInstallExternalSkill).toHaveBeenCalledTimes(1);
@@ -189,11 +256,21 @@ describe("installSkill routing", () => {
189
256
  });
190
257
 
191
258
  test("install without origin falls through to clawhub for simple slugs", async () => {
259
+ mockClawhubInstall.mockImplementation(async (slug: string) => {
260
+ const skillDir = stageClawhubSkill(
261
+ join(TEST_SKILLS_DIR, ".install-staging", "project-0"),
262
+ slug,
263
+ );
264
+ return { success: true, skillId: slug, skillDir };
265
+ });
266
+
192
267
  const result = await installSkill({ slug: "some-clawhub-skill" });
193
268
 
194
269
  expect(result.success).toBe(true);
195
270
  expect(mockClawhubInstall).toHaveBeenCalledTimes(1);
196
271
  expect(mockClawhubInstall).toHaveBeenCalledWith("some-clawhub-skill", {
272
+ contactId: undefined,
273
+ projectRoot: join(TEST_SKILLS_DIR, ".install-staging", "project-0"),
197
274
  version: undefined,
198
275
  });
199
276
  // Should not have called installExternalSkill
@@ -201,19 +278,51 @@ describe("installSkill routing", () => {
201
278
  });
202
279
 
203
280
  test("install with origin: 'clawhub' routes directly to clawhub without trying skills.sh", async () => {
204
- const result = await installSkill(
205
- { slug: "my-skill", origin: "clawhub" },
206
- );
281
+ mockClawhubInstall.mockImplementation(async (slug: string) => {
282
+ const skillDir = stageClawhubSkill(
283
+ join(TEST_SKILLS_DIR, ".install-staging", "project-0"),
284
+ slug,
285
+ );
286
+ return { success: true, skillId: slug, skillDir };
287
+ });
288
+
289
+ const result = await installSkill({ slug: "my-skill", origin: "clawhub" });
207
290
 
208
291
  expect(result.success).toBe(true);
209
292
  expect(mockClawhubInstall).toHaveBeenCalledTimes(1);
210
293
  expect(mockInstallExternalSkill).not.toHaveBeenCalled();
211
294
  });
212
295
 
296
+ test("clawhub install fails when the installed skill root is not discoverable", async () => {
297
+ mockClawhubInstall.mockResolvedValue({
298
+ success: true,
299
+ skillId: "missing-root-skill",
300
+ skillDir: join(
301
+ TEST_SKILLS_DIR,
302
+ ".install-staging",
303
+ "project-0",
304
+ "skills",
305
+ "missing-root-skill",
306
+ ),
307
+ });
308
+
309
+ const result = await installSkill({
310
+ slug: "missing-root-skill",
311
+ origin: "clawhub",
312
+ });
313
+
314
+ expect(result.success).toBe(false);
315
+ if (!result.success) {
316
+ expect(result.error).toContain("missing SKILL.md");
317
+ }
318
+ });
319
+
213
320
  test("multi-segment slug without explicit origin auto-routes to skills.sh", async () => {
214
- const result = await installSkill(
215
- { slug: "owner/repo/my-skill" },
216
- );
321
+ mockInstallExternalSkill.mockImplementation(async () => {
322
+ writeInstalledSkill("my-skill");
323
+ });
324
+
325
+ const result = await installSkill({ slug: "owner/repo/my-skill" });
217
326
 
218
327
  expect(result.success).toBe(true);
219
328
  expect(mockInstallExternalSkill).toHaveBeenCalledTimes(1);
@@ -229,11 +338,21 @@ describe("installSkill routing", () => {
229
338
  });
230
339
 
231
340
  test("multi-segment slug with origin: 'clawhub' skips skills.sh and routes to clawhub", async () => {
341
+ mockClawhubInstall.mockImplementation(async (slug: string) => {
342
+ const skillId = slug.split("/").pop()!;
343
+ const skillDir = stageClawhubSkill(
344
+ join(TEST_SKILLS_DIR, ".install-staging", "project-0"),
345
+ skillId,
346
+ );
347
+ return { success: true, skillId, skillDir };
348
+ });
349
+
232
350
  // Even though the slug looks like skills.sh format, explicit origin: "clawhub"
233
351
  // should override the auto-detection and go to clawhub
234
- const result = await installSkill(
235
- { slug: "owner/repo/my-skill", origin: "clawhub" },
236
- );
352
+ const result = await installSkill({
353
+ slug: "owner/repo/my-skill",
354
+ origin: "clawhub",
355
+ });
237
356
 
238
357
  expect(result.success).toBe(true);
239
358
  expect(mockClawhubInstall).toHaveBeenCalledTimes(1);
@@ -251,9 +370,10 @@ describe("installSkill routing", () => {
251
370
  },
252
371
  ]);
253
372
 
254
- const result = await installSkill(
255
- { slug: "bundled-skill", origin: "skillssh" },
256
- );
373
+ const result = await installSkill({
374
+ slug: "bundled-skill",
375
+ origin: "skillssh",
376
+ });
257
377
 
258
378
  expect(result.success).toBe(true);
259
379
  // Should have auto-enabled via ensureSkillEntry, not called external install
@@ -266,12 +386,10 @@ describe("installSkill routing", () => {
266
386
  new Error("Skill not found in repo"),
267
387
  );
268
388
 
269
- const result = await installSkill(
270
- {
271
- slug: "owner/repo/nonexistent-skill",
272
- origin: "skillssh",
273
- },
274
- );
389
+ const result = await installSkill({
390
+ slug: "owner/repo/nonexistent-skill",
391
+ origin: "skillssh",
392
+ });
275
393
 
276
394
  expect(result.success).toBe(false);
277
395
  if (!result.success) {
@@ -23,6 +23,7 @@ import type { AssistantConfig } from "../config/schema.js";
23
23
 
24
24
  interface TestState {
25
25
  seedCallCount: number;
26
+ seedCallOpts: Array<{ throwOnError?: boolean } | undefined>;
26
27
  seedShouldReject: Error | null;
27
28
  warnCalls: Array<{ obj: unknown; msg: unknown }>;
28
29
  infoCalls: Array<{ obj: unknown; msg: unknown }>;
@@ -34,10 +35,14 @@ interface TestState {
34
35
  listPagesResult: string[];
35
36
  enqueueCalls: Array<{ type: string; payload: Record<string, unknown> }>;
36
37
  clearSentinelCallCount: number;
38
+ // BM25 corpus-stats rebuild + reseed mocks.
39
+ corpusStatsBuildCount: number;
40
+ corpusStatsThrows: Error | null;
37
41
  }
38
42
 
39
43
  const state: TestState = {
40
44
  seedCallCount: 0,
45
+ seedCallOpts: [],
41
46
  seedShouldReject: null,
42
47
  warnCalls: [],
43
48
  infoCalls: [],
@@ -48,6 +53,8 @@ const state: TestState = {
48
53
  listPagesResult: [],
49
54
  enqueueCalls: [],
50
55
  clearSentinelCallCount: 0,
56
+ corpusStatsBuildCount: 0,
57
+ corpusStatsThrows: null,
51
58
  };
52
59
 
53
60
  // ---------------------------------------------------------------------------
@@ -55,12 +62,22 @@ const state: TestState = {
55
62
  // ---------------------------------------------------------------------------
56
63
 
57
64
  mock.module("../memory/v2/skill-store.js", () => ({
58
- seedV2SkillEntries: async (): Promise<void> => {
65
+ seedV2SkillEntries: async (opts?: {
66
+ throwOnError?: boolean;
67
+ }): Promise<void> => {
59
68
  state.seedCallCount += 1;
69
+ state.seedCallOpts.push(opts);
60
70
  if (state.seedShouldReject) throw state.seedShouldReject;
61
71
  },
62
72
  }));
63
73
 
74
+ // Mock the sibling CLI-command seeder so `rebuildBm25CorpusStatsAndReseedSkills`
75
+ // (which runs both reseeds in parallel) does not invoke the real Qdrant-backed
76
+ // implementation and emit warnings that break the no-warnings assertions below.
77
+ mock.module("../memory/v2/cli-command-store.js", () => ({
78
+ seedV2CliCommandEntries: async (): Promise<void> => {},
79
+ }));
80
+
64
81
  mock.module("../memory/v2/qdrant.js", () => ({
65
82
  ensureConceptPageCollection: async (): Promise<{ migrated: boolean }> => {
66
83
  state.ensureCollectionCallCount += 1;
@@ -81,6 +98,13 @@ mock.module("../memory/v2/page-store.js", () => ({
81
98
  state.listPagesResult.length > 0,
82
99
  }));
83
100
 
101
+ mock.module("../memory/v2/sparse-bm25.js", () => ({
102
+ rebuildConceptPageCorpusStats: async (): Promise<void> => {
103
+ state.corpusStatsBuildCount += 1;
104
+ if (state.corpusStatsThrows) throw state.corpusStatsThrows;
105
+ },
106
+ }));
107
+
84
108
  mock.module("../memory/jobs-store.js", () => ({
85
109
  enqueueMemoryJob: (
86
110
  type: string,
@@ -113,8 +137,11 @@ mock.module("../util/logger.js", () => ({
113
137
  }),
114
138
  }));
115
139
 
116
- const { maybeSeedMemoryV2Skills, maybeRebuildMemoryV2Concepts } =
117
- await import("../daemon/memory-v2-startup.js");
140
+ const {
141
+ maybeSeedMemoryV2Skills,
142
+ maybeRebuildMemoryV2Concepts,
143
+ rebuildBm25CorpusStatsAndReseedSkills,
144
+ } = await import("../daemon/memory-v2-startup.js");
118
145
 
119
146
  // ---------------------------------------------------------------------------
120
147
  // Test fixtures
@@ -149,6 +176,7 @@ async function flushMicrotasks(): Promise<void> {
149
176
 
150
177
  function resetState(): void {
151
178
  state.seedCallCount = 0;
179
+ state.seedCallOpts = [];
152
180
  state.seedShouldReject = null;
153
181
  state.warnCalls = [];
154
182
  state.infoCalls = [];
@@ -159,6 +187,8 @@ function resetState(): void {
159
187
  state.listPagesResult = [];
160
188
  state.enqueueCalls = [];
161
189
  state.clearSentinelCallCount = 0;
190
+ state.corpusStatsBuildCount = 0;
191
+ state.corpusStatsThrows = null;
162
192
  }
163
193
 
164
194
  describe("maybeSeedMemoryV2Skills (daemon startup gate)", () => {
@@ -274,3 +304,69 @@ describe("maybeRebuildMemoryV2Concepts (daemon startup gate)", () => {
274
304
  );
275
305
  });
276
306
  });
307
+
308
+ describe("rebuildBm25CorpusStatsAndReseedSkills", () => {
309
+ beforeEach(resetState);
310
+
311
+ test("builds corpus stats then re-seeds skills when v2 is enabled", async () => {
312
+ await rebuildBm25CorpusStatsAndReseedSkills(makeConfig(true));
313
+
314
+ expect(state.corpusStatsBuildCount).toBe(1);
315
+ expect(state.seedCallCount).toBe(1);
316
+ // Must pass throwOnError: true so a swallowed internal seed failure
317
+ // cannot trip the unconditional success log in the caller.
318
+ expect(state.seedCallOpts[0]).toEqual({ throwOnError: true });
319
+ expect(state.warnCalls).toHaveLength(0);
320
+ });
321
+
322
+ test("skips both corpus stats and skill reseed when v2 is disabled", async () => {
323
+ await rebuildBm25CorpusStatsAndReseedSkills(makeConfig(false));
324
+
325
+ expect(state.corpusStatsBuildCount).toBe(0);
326
+ expect(state.seedCallCount).toBe(0);
327
+ expect(state.warnCalls).toHaveLength(0);
328
+ });
329
+
330
+ test("skips the reseed and logs a warning when the corpus-stats build throws", async () => {
331
+ state.corpusStatsThrows = new Error("listPages failed");
332
+
333
+ // Must not throw — fire-and-forget startup must not block.
334
+ let thrown: unknown = null;
335
+ try {
336
+ await rebuildBm25CorpusStatsAndReseedSkills(makeConfig(true));
337
+ } catch (err) {
338
+ thrown = err;
339
+ }
340
+ expect(thrown).toBeNull();
341
+
342
+ expect(state.corpusStatsBuildCount).toBe(1);
343
+ expect(state.seedCallCount).toBe(0);
344
+ const corpusWarn = state.warnCalls.find(
345
+ (w) =>
346
+ typeof w.msg === "string" &&
347
+ w.msg.includes("BM25 corpus-stats rebuild failed"),
348
+ );
349
+ expect(corpusWarn).toBeTruthy();
350
+ });
351
+
352
+ test("swallows skill-reseed rejections after a successful corpus-stats build", async () => {
353
+ state.seedShouldReject = new Error("reseed failed");
354
+
355
+ let thrown: unknown = null;
356
+ try {
357
+ await rebuildBm25CorpusStatsAndReseedSkills(makeConfig(true));
358
+ } catch (err) {
359
+ thrown = err;
360
+ }
361
+ expect(thrown).toBeNull();
362
+
363
+ expect(state.corpusStatsBuildCount).toBe(1);
364
+ expect(state.seedCallCount).toBe(1);
365
+ const reseedWarn = state.warnCalls.find(
366
+ (w) =>
367
+ typeof w.msg === "string" &&
368
+ w.msg.includes("Failed to re-seed v2 skill entries"),
369
+ );
370
+ expect(reseedWarn).toBeTruthy();
371
+ });
372
+ });
@@ -25,6 +25,10 @@ mock.module("../config/loader.js", () => ({
25
25
  provider: "test",
26
26
  memory: { enabled: false },
27
27
  rateLimit: { maxRequestsPerMinute: 0 },
28
+ slack: {
29
+ teamId: "T123",
30
+ teamUrl: "https://example.slack.com/",
31
+ },
28
32
  }),
29
33
  }));
30
34
 
@@ -32,6 +36,7 @@ import { createConversation } from "../memory/conversation-crud.js";
32
36
  import { getDb } from "../memory/db-connection.js";
33
37
  import { initializeDb } from "../memory/db-init.js";
34
38
  import { messages } from "../memory/schema.js";
39
+ import { writeSlackMetadata } from "../messaging/providers/slack/message-metadata.js";
35
40
  import { handleListMessages } from "../runtime/routes/conversation-routes.js";
36
41
  import { BadRequestError } from "../runtime/routes/errors.js";
37
42
 
@@ -82,6 +87,13 @@ interface MessagePayload {
82
87
  role: string;
83
88
  content: string;
84
89
  timestamp: string;
90
+ slackMessage?: {
91
+ channelId: string;
92
+ channelTs: string;
93
+ threadTs?: string;
94
+ messageLink?: { appUrl?: string; webUrl?: string };
95
+ threadLink?: { appUrl?: string; webUrl?: string };
96
+ };
85
97
  }
86
98
 
87
99
  interface ListResponse {
@@ -194,6 +206,49 @@ describe("handleListMessages page=latest", () => {
194
206
  expect(body.oldestMessageId).toBeNull();
195
207
  });
196
208
 
209
+ test("messages expose Slack message and thread links from slackMeta", () => {
210
+ const conv = createConversation();
211
+ const db = getDb();
212
+ db.insert(messages)
213
+ .values({
214
+ id: "msg-slack",
215
+ conversationId: conv.id,
216
+ role: "user",
217
+ content: JSON.stringify([{ type: "text", text: "Slack reply" }]),
218
+ metadata: JSON.stringify({
219
+ slackMeta: writeSlackMetadata({
220
+ source: "slack",
221
+ channelId: "C123ABCDEF",
222
+ channelTs: "1710000000.000200",
223
+ threadTs: "1710000000.000100",
224
+ eventKind: "message",
225
+ }),
226
+ }),
227
+ createdAt: 1,
228
+ })
229
+ .run();
230
+
231
+ const body = callList({ conversationId: conv.id, page: "latest" });
232
+
233
+ expect(body.messages[0].slackMessage).toEqual({
234
+ channelId: "C123ABCDEF",
235
+ channelTs: "1710000000.000200",
236
+ threadTs: "1710000000.000100",
237
+ messageLink: {
238
+ appUrl:
239
+ "slack://channel?team=T123&id=C123ABCDEF&message=1710000000.000200",
240
+ webUrl:
241
+ "https://example.slack.com/archives/C123ABCDEF/p1710000000000200",
242
+ },
243
+ threadLink: {
244
+ appUrl:
245
+ "slack://channel?team=T123&id=C123ABCDEF&message=1710000000.000100",
246
+ webUrl:
247
+ "https://example.slack.com/archives/C123ABCDEF/p1710000000000100",
248
+ },
249
+ });
250
+ });
251
+
197
252
  test("page=latest on unresolved conversationKey returns null metadata contract", () => {
198
253
  const body = callList({
199
254
  conversationKey: "no-such-key",
@@ -157,7 +157,6 @@ describe("llmCall pipeline", () => {
157
157
  manifest: {
158
158
  name: "spy-llm",
159
159
  version: "0.0.1",
160
- requires: { pluginRuntime: "v1" },
161
160
  },
162
161
  middleware: {
163
162
  llmCall: async (args, next, _ctx) => {
@@ -209,7 +208,6 @@ describe("llmCall pipeline", () => {
209
208
  manifest: {
210
209
  name: "spy-llm-after-default",
211
210
  version: "0.0.1",
212
- requires: { pluginRuntime: "v1" },
213
211
  },
214
212
  middleware: {
215
213
  llmCall: async (args, next, _ctx) => {
@@ -255,7 +253,6 @@ describe("llmCall pipeline", () => {
255
253
  manifest: {
256
254
  name: "short-circuit-llm",
257
255
  version: "0.0.1",
258
- requires: { pluginRuntime: "v1" },
259
256
  },
260
257
  middleware: { llmCall: shortCircuit },
261
258
  };