@vellumai/assistant 0.8.7 → 0.8.8

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 (387) hide show
  1. package/Dockerfile +20 -4
  2. package/docker-entrypoint.sh +4 -2
  3. package/docker-init-apt-root.sh +3 -1
  4. package/docker-kata-apt-env.sh +3 -1
  5. package/docker-kata-runtime-family.sh +12 -0
  6. package/docs/architecture/memory.md +1 -1
  7. package/docs/plugins.md +75 -79
  8. package/examples/plugins/echo/README.md +6 -12
  9. package/examples/plugins/echo/register.ts +0 -41
  10. package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +3 -3
  11. package/openapi.yaml +3381 -348
  12. package/package.json +1 -1
  13. package/scripts/generate-openapi.ts +68 -41
  14. package/src/__tests__/agent-loop-exit-reason.test.ts +34 -39
  15. package/src/__tests__/agent-loop-provider-error-recording.test.ts +1 -1
  16. package/src/__tests__/agent-loop.test.ts +37 -87
  17. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +2 -0
  18. package/src/__tests__/annotate-activity-metadata.test.ts +262 -0
  19. package/src/__tests__/annotate-risk-options.test.ts +2 -3
  20. package/src/__tests__/anthropic-provider.test.ts +95 -2
  21. package/src/__tests__/assistant-event-hub.test.ts +25 -0
  22. package/src/__tests__/assistant-events-sse-shed.test.ts +8 -0
  23. package/src/__tests__/{conversation-stream-state.test.ts → assistant-stream-state.test.ts} +252 -91
  24. package/src/__tests__/auth-fallback-events-store.test.ts +116 -0
  25. package/src/__tests__/background-workers-disk-pressure.test.ts +6 -0
  26. package/src/__tests__/btw-routes.test.ts +62 -3
  27. package/src/__tests__/build-persisted-content.test.ts +184 -0
  28. package/src/__tests__/catalog-files.test.ts +1 -1
  29. package/src/__tests__/clawhub-files.test.ts +1 -1
  30. package/src/__tests__/compaction-pipeline.test.ts +1 -1
  31. package/src/__tests__/compaction.benchmark.test.ts +0 -30
  32. package/src/__tests__/config-watcher.test.ts +1 -1
  33. package/src/__tests__/conversation-abort-tool-results.test.ts +57 -19
  34. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +6 -2
  35. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +10 -4
  36. package/src/__tests__/conversation-agent-loop-overflow.test.ts +313 -1136
  37. package/src/__tests__/conversation-agent-loop.test.ts +596 -1616
  38. package/src/__tests__/conversation-analysis-routes.test.ts +6 -0
  39. package/src/__tests__/conversation-history-web-search.test.ts +11 -1
  40. package/src/__tests__/conversation-pairing.test.ts +4 -31
  41. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +6 -0
  42. package/src/__tests__/conversation-provider-retry-repair.test.ts +26 -5
  43. package/src/__tests__/conversation-queue.test.ts +2 -0
  44. package/src/__tests__/conversation-routes-disk-view.test.ts +3 -0
  45. package/src/__tests__/conversation-routes-slash-commands.test.ts +6 -5
  46. package/src/__tests__/conversation-runtime-assembly.test.ts +170 -229
  47. package/src/__tests__/conversation-runtime-workspace.test.ts +3 -24
  48. package/src/__tests__/conversation-slash-commands.test.ts +8 -42
  49. package/src/__tests__/conversation-slash-queue.test.ts +6 -1
  50. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +84 -0
  51. package/src/__tests__/conversation-sync-tags.test.ts +27 -15
  52. package/src/__tests__/conversation-title-service.test.ts +135 -2
  53. package/src/__tests__/conversation-workspace-injection.test.ts +6 -1
  54. package/src/__tests__/cross-provider-web-search.test.ts +214 -1
  55. package/src/__tests__/db-schedule-syntax-migration.test.ts +5 -0
  56. package/src/__tests__/dm-persistence.test.ts +5 -1
  57. package/src/__tests__/empty-response-hook.test.ts +304 -0
  58. package/src/__tests__/feature-flag-test-helpers.ts +2 -2
  59. package/src/__tests__/gemini-image-service.test.ts +13 -0
  60. package/src/__tests__/helpers/mock-provider.ts +110 -0
  61. package/src/__tests__/helpers/native-web-search-harness.ts +129 -0
  62. package/src/__tests__/history-repair-hook.test.ts +1 -0
  63. package/src/__tests__/identity-intro-cache.test.ts +12 -100
  64. package/src/__tests__/identity-routes.test.ts +248 -7
  65. package/src/__tests__/inbound-slack-persistence.test.ts +5 -1
  66. package/src/__tests__/injector-background-turn.test.ts +2 -8
  67. package/src/__tests__/injector-chain.test.ts +106 -270
  68. package/src/__tests__/injector-disk-pressure.test.ts +3 -12
  69. package/src/__tests__/injector-document-comments.test.ts +2 -2
  70. package/src/__tests__/injector-pkb-v2-silenced.test.ts +30 -22
  71. package/src/__tests__/injector-v3-suppression.test.ts +31 -37
  72. package/src/__tests__/internal-telemetry-routes.test.ts +109 -0
  73. package/src/__tests__/list-messages-page-latest.test.ts +60 -0
  74. package/src/__tests__/list-messages-tool-merge.test.ts +20 -0
  75. package/src/__tests__/llm-usage-store.test.ts +223 -1
  76. package/src/__tests__/memory-retrieval-hook.test.ts +297 -0
  77. package/src/__tests__/memory-v2-static-injector.test.ts +103 -35
  78. package/src/__tests__/native-web-search.test.ts +191 -0
  79. package/src/__tests__/onboarding-template-contract.test.ts +2 -0
  80. package/src/__tests__/openai-image-service.test.ts +17 -0
  81. package/src/__tests__/openai-provider.test.ts +31 -1
  82. package/src/__tests__/persist-unsendable-image.test.ts +215 -0
  83. package/src/__tests__/persistence-secret-redaction.test.ts +1 -0
  84. package/src/__tests__/pipeline-runner.test.ts +29 -39
  85. package/src/__tests__/pkb-autoinject.test.ts +2 -5
  86. package/src/__tests__/plugin-bootstrap.test.ts +13 -28
  87. package/src/__tests__/plugin-registry.test.ts +0 -27
  88. package/src/__tests__/plugin-types.test.ts +2 -125
  89. package/src/__tests__/process-message-display-content.test.ts +6 -2
  90. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +5 -1
  91. package/src/__tests__/resolve-trust-class.test.ts +4 -4
  92. package/src/__tests__/runtime-events-sse-reconnect.test.ts +60 -23
  93. package/src/__tests__/schedule-routes.test.ts +603 -2
  94. package/src/__tests__/schedule-store.test.ts +41 -0
  95. package/src/__tests__/schedule-tools.test.ts +35 -0
  96. package/src/__tests__/server-history-render.test.ts +314 -1
  97. package/src/__tests__/skillssh-files.test.ts +1 -1
  98. package/src/__tests__/system-prompt.test.ts +20 -0
  99. package/src/__tests__/task-scheduler.test.ts +162 -1
  100. package/src/__tests__/terminal-tools.test.ts +6 -1
  101. package/src/__tests__/title-generate-hook.test.ts +319 -0
  102. package/src/__tests__/tool-error-hook.test.ts +278 -0
  103. package/src/__tests__/tool-preview-lifecycle.test.ts +468 -5
  104. package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
  105. package/src/__tests__/tool-result-truncate-hook.test.ts +127 -0
  106. package/src/__tests__/tool-result-truncation.test.ts +0 -2
  107. package/src/__tests__/ui-choice-copy-surfaces.test.ts +254 -0
  108. package/src/__tests__/ui-work-result-surface.test.ts +159 -0
  109. package/src/__tests__/usage-routes.test.ts +285 -1
  110. package/src/__tests__/user-plugin-loader.test.ts +2 -2
  111. package/src/__tests__/voice-session-bridge.test.ts +6 -3
  112. package/src/__tests__/web-search-backend-failure.test.ts +166 -0
  113. package/src/agent/loop.ts +346 -442
  114. package/src/api/events/assistant-thinking-delta.ts +33 -0
  115. package/src/api/events/tool-output-chunk.ts +45 -0
  116. package/src/api/events/tool-use-preview-start.ts +32 -0
  117. package/src/api/events/trace-event.ts +69 -0
  118. package/src/api/index.ts +48 -13
  119. package/src/api/responses/conversation-message.ts +368 -0
  120. package/src/avatar/__tests__/avatar-store.test.ts +34 -29
  121. package/src/cli/commands/__tests__/notifications.test.ts +58 -14
  122. package/src/cli/commands/notifications.ts +112 -60
  123. package/src/config/assistant-feature-flags.ts +22 -11
  124. package/src/config/bundled-skills/app-builder/SKILL.md +3 -20
  125. package/src/config/bundled-skills/app-builder/references/examples/README.md +17 -0
  126. package/src/config/bundled-skills/app-builder/references/examples/expense-tracker.md +515 -0
  127. package/src/config/bundled-skills/app-builder/references/examples/focus-timer.md +342 -0
  128. package/src/config/bundled-skills/app-builder/references/examples/habit-tracker.md +490 -0
  129. package/src/config/bundled-skills/document-editor/SKILL.md +1 -1
  130. package/src/config/bundled-skills/messaging/SKILL.md +0 -7
  131. package/src/config/feature-flag-cache.ts +3 -3
  132. package/src/config/feature-flag-registry.json +35 -3
  133. package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
  134. package/src/config/schemas/__tests__/memory-v3.test.ts +25 -0
  135. package/src/config/schemas/llm.ts +1 -0
  136. package/src/config/schemas/memory-v2.ts +8 -0
  137. package/src/config/schemas/memory-v3.ts +8 -0
  138. package/src/config/schemas/platform.ts +8 -0
  139. package/src/config/seed-inference-profiles.ts +2 -2
  140. package/src/config/skills.ts +13 -0
  141. package/src/context/compactor.ts +1 -1
  142. package/src/context/strip-injections.ts +122 -0
  143. package/src/context/token-estimator.ts +23 -0
  144. package/src/context/tool-result-truncation.ts +0 -23
  145. package/src/context/window-manager.ts +3 -6
  146. package/src/credential-execution/executable-discovery.ts +16 -0
  147. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +6 -0
  148. package/src/daemon/__tests__/inference-profile-notification.test.ts +153 -0
  149. package/src/daemon/__tests__/native-web-search-metadata.test.ts +10 -8
  150. package/src/daemon/assistant-attachments.ts +1 -1
  151. package/src/daemon/config-watcher.ts +2 -2
  152. package/src/daemon/context-overflow-reducer.ts +0 -1
  153. package/src/daemon/conversation-agent-loop-handlers.ts +605 -153
  154. package/src/daemon/conversation-agent-loop.ts +281 -760
  155. package/src/daemon/conversation-history.ts +5 -4
  156. package/src/daemon/conversation-lifecycle.ts +3 -4
  157. package/src/daemon/conversation-messaging.ts +7 -6
  158. package/src/daemon/conversation-process.ts +11 -16
  159. package/src/daemon/conversation-runtime-assembly.ts +130 -347
  160. package/src/daemon/conversation-slash.ts +6 -25
  161. package/src/daemon/conversation-surfaces.ts +222 -4
  162. package/src/daemon/conversation-tool-setup.ts +2 -29
  163. package/src/daemon/conversation.ts +32 -14
  164. package/src/daemon/external-plugins-bootstrap.ts +9 -10
  165. package/src/daemon/handlers/config-a2a.ts +51 -36
  166. package/src/daemon/handlers/config-slack-channel.ts +20 -14
  167. package/src/daemon/handlers/config-telegram.ts +16 -2
  168. package/src/daemon/handlers/shared.ts +156 -84
  169. package/src/daemon/handlers/skills.ts +39 -10
  170. package/src/daemon/lifecycle.ts +4 -0
  171. package/src/daemon/message-types/apps.ts +1 -29
  172. package/src/daemon/message-types/messages.ts +9 -57
  173. package/src/daemon/message-types/skills.ts +2 -0
  174. package/src/daemon/message-types/surfaces.ts +136 -3
  175. package/src/daemon/now-scratchpad.ts +21 -0
  176. package/src/daemon/orphan-reaper.test.ts +210 -0
  177. package/src/daemon/orphan-reaper.ts +240 -0
  178. package/src/daemon/persist-unsendable-image.ts +117 -0
  179. package/src/daemon/process-message.ts +1 -3
  180. package/src/daemon/trace-emitter.ts +6 -4
  181. package/src/daemon/trust-context.ts +19 -0
  182. package/src/daemon/wake-target-adapter.ts +3 -1
  183. package/src/home/home-greeting-cache.ts +24 -1
  184. package/src/ipc/gateway-client.test.ts +2 -2
  185. package/src/ipc/gateway-client.ts +3 -3
  186. package/src/media/gemini-image-service.ts +15 -0
  187. package/src/media/openai-image-service.ts +14 -0
  188. package/src/media/types.ts +34 -0
  189. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +56 -0
  190. package/src/memory/auth-fallback-events-store.ts +94 -0
  191. package/src/memory/conversation-title-service.ts +65 -41
  192. package/src/memory/db-init.ts +4 -0
  193. package/src/memory/graph/__tests__/conversation-graph-memory-registry.test.ts +119 -0
  194. package/src/memory/graph/conversation-graph-memory.ts +65 -0
  195. package/src/memory/jobs-store.ts +33 -0
  196. package/src/memory/jobs-worker.ts +31 -4
  197. package/src/memory/llm-usage-store.ts +224 -50
  198. package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +6 -5
  199. package/src/memory/migrations/270-schedule-source-conversation.ts +13 -0
  200. package/src/memory/migrations/271-create-auth-fallback-events.ts +21 -0
  201. package/src/memory/migrations/index.ts +2 -0
  202. package/src/memory/pkb/autoinject.ts +61 -0
  203. package/src/memory/pkb/context.ts +50 -0
  204. package/src/memory/pkb/types.ts +14 -0
  205. package/src/memory/schedule-attribution-sql.ts +104 -0
  206. package/src/memory/schema/infrastructure.ts +16 -0
  207. package/src/memory/usage-grouped-buckets.ts +6 -1
  208. package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -1
  209. package/src/memory/v2/consolidation-job.ts +1 -1
  210. package/src/memory/v3/__tests__/health.test.ts +16 -0
  211. package/src/memory/v3/__tests__/orchestrate.test.ts +45 -9
  212. package/src/memory/v3/__tests__/provider-blocks.test.ts +13 -0
  213. package/src/memory/v3/__tests__/router.test.ts +101 -29
  214. package/src/memory/v3/__tests__/selector.test.ts +93 -27
  215. package/src/memory/v3/__tests__/shadow-plugin.test.ts +23 -5
  216. package/src/memory/v3/health.ts +0 -0
  217. package/src/memory/v3/llm-retry.ts +32 -0
  218. package/src/memory/v3/orchestrate.ts +26 -14
  219. package/src/memory/v3/provider-blocks.ts +15 -5
  220. package/src/memory/v3/router.ts +48 -42
  221. package/src/memory/v3/selector.ts +57 -42
  222. package/src/memory/v3/shadow-plugin.ts +47 -15
  223. package/src/memory/v3/types.ts +8 -0
  224. package/src/notifications/conversation-pairing.ts +8 -15
  225. package/src/notifications/decision-engine.ts +6 -3
  226. package/src/notifications/home-feed-side-effect.ts +12 -1
  227. package/src/permissions/prompter.ts +4 -0
  228. package/src/plugin-api/constants.ts +4 -0
  229. package/src/plugin-api/index.ts +8 -1
  230. package/src/plugin-api/types.ts +151 -1
  231. package/src/plugins/defaults/empty-response/hooks/stop.ts +126 -0
  232. package/src/plugins/defaults/empty-response/register.ts +8 -13
  233. package/src/plugins/defaults/index.ts +1 -15
  234. package/src/plugins/defaults/injectors/register.ts +243 -74
  235. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +91 -0
  236. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +216 -0
  237. package/src/plugins/defaults/memory-retrieval/injector-chain.ts +35 -0
  238. package/src/plugins/defaults/title-generate/hooks/stop.ts +75 -0
  239. package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +35 -0
  240. package/src/plugins/defaults/title-generate/package.json +1 -1
  241. package/src/plugins/defaults/title-generate/register.ts +18 -18
  242. package/src/plugins/defaults/tool-error/hooks/post-tool-use.ts +118 -0
  243. package/src/plugins/defaults/tool-error/package.json +1 -1
  244. package/src/plugins/defaults/tool-error/register.ts +9 -21
  245. package/src/plugins/defaults/tool-result-truncate/hooks/post-tool-use.ts +32 -0
  246. package/src/plugins/defaults/tool-result-truncate/register.ts +10 -21
  247. package/src/plugins/defaults/tool-result-truncate/terminal.ts +37 -18
  248. package/src/plugins/pipeline.ts +6 -18
  249. package/src/plugins/registry.ts +8 -25
  250. package/src/plugins/types.ts +43 -474
  251. package/src/proactive-artifact/aux-message-injector.ts +3 -3
  252. package/src/proactive-artifact/job.test.ts +7 -12
  253. package/src/prompts/__tests__/system-prompt.test.ts +36 -0
  254. package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +62 -0
  255. package/src/prompts/templates/BOOTSTRAP.md +2 -2
  256. package/src/prompts/templates/system-sections.ts +15 -0
  257. package/src/providers/anthropic/client.ts +37 -29
  258. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +112 -0
  259. package/src/providers/openai/chat-completions-provider.ts +44 -0
  260. package/src/providers/openrouter/client.ts +1 -0
  261. package/src/providers/placeholder-sentinels.ts +35 -0
  262. package/src/runtime/__tests__/agent-wake.test.ts +5 -1
  263. package/src/runtime/agent-wake.ts +2 -2
  264. package/src/runtime/assistant-event-hub.ts +36 -6
  265. package/src/runtime/{conversation-stream-state.ts → assistant-stream-state.ts} +132 -58
  266. package/src/runtime/http-router.ts +16 -21
  267. package/src/runtime/http-types.ts +16 -70
  268. package/src/runtime/pending-interactions.ts +1 -0
  269. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +265 -2
  270. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +31 -1
  271. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +6 -2
  272. package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
  273. package/src/runtime/routes/app-management-routes.ts +6 -117
  274. package/src/runtime/routes/app-routes.ts +13 -15
  275. package/src/runtime/routes/attachment-routes.ts +26 -15
  276. package/src/runtime/routes/avatar-routes.ts +26 -0
  277. package/src/runtime/routes/btw-routes.ts +29 -23
  278. package/src/runtime/routes/consolidation-routes.ts +120 -20
  279. package/src/runtime/routes/conversation-query-routes.ts +2 -0
  280. package/src/runtime/routes/conversation-routes.ts +358 -184
  281. package/src/runtime/routes/documents-routes.ts +4 -0
  282. package/src/runtime/routes/domain-routes.ts +51 -37
  283. package/src/runtime/routes/epoch-millis-range.ts +34 -0
  284. package/src/runtime/routes/events-routes.ts +28 -34
  285. package/src/runtime/routes/gateway-log-routes.ts +26 -4
  286. package/src/runtime/routes/heartbeat-routes.ts +32 -12
  287. package/src/runtime/routes/identity-intro-cache.ts +11 -34
  288. package/src/runtime/routes/identity-routes.ts +208 -17
  289. package/src/runtime/routes/image-generation-routes.ts +40 -2
  290. package/src/runtime/routes/index.ts +2 -0
  291. package/src/runtime/routes/integrations/a2a.ts +12 -10
  292. package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +16 -0
  293. package/src/runtime/routes/integrations/slack/channel.ts +4 -0
  294. package/src/runtime/routes/integrations/slack/share.ts +27 -6
  295. package/src/runtime/routes/integrations/telegram.ts +6 -0
  296. package/src/runtime/routes/integrations/twilio.ts +42 -0
  297. package/src/runtime/routes/internal-telemetry-routes.ts +88 -0
  298. package/src/runtime/routes/log-export-routes.ts +8 -0
  299. package/src/runtime/routes/memory-v2-routes.ts +15 -8
  300. package/src/runtime/routes/memory-v3-routes.ts +50 -28
  301. package/src/runtime/routes/oauth-apps.ts +66 -12
  302. package/src/runtime/routes/oauth-providers.ts +44 -5
  303. package/src/runtime/routes/platform-routes.ts +81 -5
  304. package/src/runtime/routes/playground/__tests__/force-compact.test.ts +6 -4
  305. package/src/runtime/routes/playground/force-compact.ts +1 -1
  306. package/src/runtime/routes/rename-conversation-routes.ts +5 -0
  307. package/src/runtime/routes/schedule-routes.ts +152 -42
  308. package/src/runtime/routes/secret-routes.ts +14 -2
  309. package/src/runtime/routes/skills-routes.ts +43 -14
  310. package/src/runtime/routes/tool-call-confirmation-enrichment.test.ts +161 -0
  311. package/src/runtime/routes/tool-call-confirmation-enrichment.ts +107 -0
  312. package/src/runtime/routes/trust-rules-routes.ts +26 -2
  313. package/src/runtime/routes/tts-routes.ts +35 -0
  314. package/src/runtime/routes/types.ts +66 -8
  315. package/src/runtime/routes/usage-routes.ts +47 -39
  316. package/src/runtime/routes/webhook-routes.ts +41 -2
  317. package/src/runtime/routes/workspace-routes.ts +4 -0
  318. package/src/runtime/services/__tests__/analyze-conversation.test.ts +6 -0
  319. package/src/runtime/services/analyze-conversation.ts +2 -2
  320. package/src/schedule/schedule-store.ts +20 -1
  321. package/src/schedule/schedule-usage-store.ts +83 -0
  322. package/src/schedule/scheduler.ts +12 -5
  323. package/src/skills/catalog-files.ts +2 -2
  324. package/src/skills/catalog-install.ts +3 -0
  325. package/src/skills/categories-cache.ts +118 -0
  326. package/src/skills/clawhub-files.ts +1 -2
  327. package/src/skills/skillssh-files.ts +1 -2
  328. package/src/telemetry/types.ts +29 -1
  329. package/src/telemetry/usage-telemetry-reporter.test.ts +112 -3
  330. package/src/telemetry/usage-telemetry-reporter.ts +57 -2
  331. package/src/tools/executor.ts +1 -53
  332. package/src/tools/network/__tests__/web-search-metadata.test.ts +7 -1
  333. package/src/tools/network/__tests__/web-search.test.ts +11 -3
  334. package/src/tools/network/web-search-error.test.ts +248 -0
  335. package/src/tools/network/web-search-error.ts +267 -0
  336. package/src/tools/network/web-search.ts +207 -48
  337. package/src/tools/schedule/create.ts +2 -0
  338. package/src/tools/terminal/safe-env.ts +10 -1
  339. package/src/tools/ui-surface/definitions.ts +9 -1
  340. package/src/tts/__tests__/provider-catalog-consistency.test.ts +85 -1
  341. package/src/tts/provider-catalog.ts +76 -1
  342. package/src/util/mutex.ts +47 -0
  343. package/src/workspace/git-service.ts +1 -42
  344. package/src/workspace/migrations/095-bump-heartbeat-interval-30m-to-60m.ts +51 -0
  345. package/src/workspace/migrations/096-reduce-quality-profile-effort.ts +72 -0
  346. package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +93 -0
  347. package/src/workspace/migrations/registry.ts +6 -0
  348. package/src/__tests__/bootstrap-turn-cleanup.test.ts +0 -44
  349. package/src/__tests__/empty-response-pipeline.test.ts +0 -423
  350. package/src/__tests__/llm-call-pipeline.test.ts +0 -287
  351. package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -418
  352. package/src/__tests__/persistence-pipeline.test.ts +0 -503
  353. package/src/__tests__/title-generate-pipeline.test.ts +0 -211
  354. package/src/__tests__/token-estimate-pipeline.test.ts +0 -479
  355. package/src/__tests__/tool-error-pipeline.test.ts +0 -241
  356. package/src/__tests__/tool-execute-pipeline.test.ts +0 -417
  357. package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -341
  358. package/src/daemon/bootstrap-turn-cleanup.ts +0 -45
  359. package/src/gallery/default-gallery.ts +0 -1359
  360. package/src/gallery/gallery-manifest.ts +0 -28
  361. package/src/home/feature-gate.ts +0 -22
  362. package/src/plugins/defaults/empty-response/middlewares/emptyResponse.ts +0 -22
  363. package/src/plugins/defaults/empty-response/terminal.ts +0 -106
  364. package/src/plugins/defaults/injectors/package.json +0 -15
  365. package/src/plugins/defaults/llm-call/middlewares/llmCall.ts +0 -17
  366. package/src/plugins/defaults/llm-call/package.json +0 -15
  367. package/src/plugins/defaults/llm-call/register.ts +0 -45
  368. package/src/plugins/defaults/memory-retrieval/middlewares/memoryRetrieval.ts +0 -17
  369. package/src/plugins/defaults/memory-retrieval/package.json +0 -15
  370. package/src/plugins/defaults/memory-retrieval/register.ts +0 -181
  371. package/src/plugins/defaults/persistence/middlewares/persistence.ts +0 -19
  372. package/src/plugins/defaults/persistence/package.json +0 -15
  373. package/src/plugins/defaults/persistence/register.ts +0 -38
  374. package/src/plugins/defaults/persistence/terminal.ts +0 -83
  375. package/src/plugins/defaults/title-generate/terminal.ts +0 -31
  376. package/src/plugins/defaults/token-estimate/middlewares/tokenEstimate.ts +0 -23
  377. package/src/plugins/defaults/token-estimate/package.json +0 -15
  378. package/src/plugins/defaults/token-estimate/register.ts +0 -34
  379. package/src/plugins/defaults/token-estimate/terminal.ts +0 -40
  380. package/src/plugins/defaults/tool-error/middlewares/toolError.ts +0 -21
  381. package/src/plugins/defaults/tool-error/terminal.ts +0 -47
  382. package/src/plugins/defaults/tool-execute/middlewares/toolExecute.ts +0 -23
  383. package/src/plugins/defaults/tool-execute/package.json +0 -15
  384. package/src/plugins/defaults/tool-execute/register.ts +0 -49
  385. package/src/plugins/defaults/tool-result-truncate/middlewares/toolResultTruncate.ts +0 -23
  386. package/src/plugins/defaults/tool-result-truncate/types.ts +0 -22
  387. package/src/skills/category-inference.ts +0 -111
@@ -1,418 +0,0 @@
1
- /**
2
- * Tests for the `memoryRetrieval` plugin pipeline (PR 20).
3
- *
4
- * Covers the default terminal behavior, timeout handling, and custom-plugin
5
- * substitution. Uses `mock.module` to stub the workspace PKB/NOW readers
6
- * so the test doesn't touch the developer's real `~/.vellum`. The memory
7
- * graph handle is a hand-rolled fake passed as a dependency — the default
8
- * retriever only needs `prepareMemory`.
9
- */
10
-
11
- import { beforeEach, describe, expect, mock, test } from "bun:test";
12
-
13
- // Stub PKB/NOW readers BEFORE importing the module under test so the
14
- // bindings resolve through the mock.
15
- const readPkbContextMock = mock((): string | null => "pkb-default");
16
- const readNowContextMock = mock((): string | null => "now-default");
17
- mock.module("../daemon/conversation-runtime-assembly.js", () => ({
18
- readPkbContext: readPkbContextMock,
19
- readNowScratchpad: readNowContextMock,
20
- }));
21
-
22
- import type { AssistantConfig } from "../config/schema.js";
23
- import type { ServerMessage } from "../daemon/message-protocol.js";
24
- import type { TrustContext } from "../daemon/trust-context.js";
25
- import type { ConversationGraphMemory } from "../memory/graph/conversation-graph-memory.js";
26
- import {
27
- asDefaultGraphPayload,
28
- DEFAULT_MEMORY_GRAPH_KIND,
29
- type DefaultMemoryRetrievalDeps,
30
- defaultMemoryRetrievalPlugin,
31
- runDefaultMemoryRetrieval,
32
- } from "../plugins/defaults/memory-retrieval/register.js";
33
- import { DEFAULT_TIMEOUTS, runPipeline } from "../plugins/pipeline.js";
34
- import {
35
- getMiddlewaresFor,
36
- registerPlugin,
37
- resetPluginRegistryForTests,
38
- } from "../plugins/registry.js";
39
- import {
40
- type MemoryArgs,
41
- type MemoryResult,
42
- type Middleware,
43
- type Plugin,
44
- PluginTimeoutError,
45
- type TurnContext,
46
- } from "../plugins/types.js";
47
- import type { Message } from "../providers/types.js";
48
-
49
- const trust: TrustContext = {
50
- sourceChannel: "vellum",
51
- trustClass: "guardian",
52
- };
53
-
54
- function makeTurnCtx(overrides: Partial<TurnContext> = {}): TurnContext {
55
- return {
56
- requestId: "req-test",
57
- conversationId: "conv-test",
58
- turnIndex: 0,
59
- trust,
60
- ...overrides,
61
- };
62
- }
63
-
64
- function makeMemoryArgs(overrides: Partial<MemoryArgs> = {}): MemoryArgs {
65
- return {
66
- conversationId: "conv-test",
67
- trustContext: trust,
68
- turnIndex: 0,
69
- signal: new AbortController().signal,
70
- ...overrides,
71
- };
72
- }
73
-
74
- /**
75
- * Fake graph-memory whose `prepareMemory` returns a canonical result. The
76
- * default retriever threads this return value through
77
- * `MemoryResult.memoryGraphBlocks[0].result`, so tests can assert the block
78
- * shape by comparing the embedded object identity.
79
- */
80
- function makeFakeGraphMemory(overrides?: {
81
- messages?: Message[];
82
- injectedTokens?: number;
83
- injectedBlockText?: string | null;
84
- }): {
85
- memory: ConversationGraphMemory;
86
- prepareMemoryMock: ReturnType<typeof mock>;
87
- } {
88
- const returnValue = {
89
- runMessages: overrides?.messages ?? [],
90
- injectedTokens: overrides?.injectedTokens ?? 0,
91
- latencyMs: 0,
92
- mode: "none" as const,
93
- injectedBlockText:
94
- overrides?.injectedBlockText === undefined
95
- ? null
96
- : overrides.injectedBlockText,
97
- metrics: null,
98
- };
99
- const prepareMemoryMock = mock(async () => returnValue);
100
- const memory = {
101
- prepareMemory: prepareMemoryMock,
102
- } as unknown as ConversationGraphMemory;
103
- return { memory, prepareMemoryMock };
104
- }
105
-
106
- function makeDeps(
107
- overrides: Partial<DefaultMemoryRetrievalDeps> = {},
108
- ): DefaultMemoryRetrievalDeps {
109
- const { memory } = makeFakeGraphMemory();
110
- return {
111
- messages: [],
112
- graphMemory: memory,
113
- config: {} as AssistantConfig,
114
- onEvent: () => {},
115
- isTrustedActor: true,
116
- ...overrides,
117
- };
118
- }
119
-
120
- beforeEach(() => {
121
- resetPluginRegistryForTests();
122
- readPkbContextMock.mockReset();
123
- readNowContextMock.mockReset();
124
- readPkbContextMock.mockImplementation(() => "pkb-default");
125
- readNowContextMock.mockImplementation(() => "now-default");
126
- });
127
-
128
- describe("runDefaultMemoryRetrieval", () => {
129
- test("returns PKB, NOW, and a single graph block when the actor is trusted", async () => {
130
- const { memory, prepareMemoryMock } = makeFakeGraphMemory();
131
- const deps = makeDeps({ graphMemory: memory, isTrustedActor: true });
132
-
133
- const result = await runDefaultMemoryRetrieval(makeMemoryArgs(), deps);
134
-
135
- expect(result.pkbContent).toBe("pkb-default");
136
- expect(result.nowContent).toBe("now-default");
137
- expect(result.memoryGraphBlocks).toHaveLength(1);
138
- expect(prepareMemoryMock).toHaveBeenCalledTimes(1);
139
-
140
- const payload = asDefaultGraphPayload(result.memoryGraphBlocks);
141
- expect(payload).not.toBeNull();
142
- expect(payload?.kind).toBe(DEFAULT_MEMORY_GRAPH_KIND);
143
- // The default retriever forwards the graph-memory return value
144
- // verbatim under `payload.result` — consumers in the agent loop
145
- // rely on that identity.
146
- expect(payload?.result.mode).toBe("none");
147
- });
148
-
149
- test("skips graph retrieval for untrusted actors", async () => {
150
- const { memory, prepareMemoryMock } = makeFakeGraphMemory();
151
- const deps = makeDeps({ graphMemory: memory, isTrustedActor: false });
152
-
153
- const result = await runDefaultMemoryRetrieval(makeMemoryArgs(), deps);
154
-
155
- expect(prepareMemoryMock).not.toHaveBeenCalled();
156
- expect(result.memoryGraphBlocks).toEqual([]);
157
- expect(result.pkbContent).toBe("pkb-default");
158
- expect(result.nowContent).toBe("now-default");
159
- });
160
-
161
- test("propagates errors from prepareMemory rather than swallowing them", async () => {
162
- // Memory is critical — failures must surface to the caller (the agent
163
- // loop) rather than silently degrading to an empty memory block.
164
- const failingPrepare = mock(
165
- (
166
- _msgs: Message[],
167
- _cfg: AssistantConfig,
168
- _signal: AbortSignal,
169
- _onEvent: (msg: ServerMessage) => void,
170
- ) => Promise.reject(new Error("retrieval failed")),
171
- );
172
- const graphMemory = {
173
- prepareMemory: failingPrepare,
174
- } as unknown as ConversationGraphMemory;
175
- const deps = makeDeps({ graphMemory, isTrustedActor: true });
176
-
177
- await expect(
178
- runDefaultMemoryRetrieval(makeMemoryArgs(), deps),
179
- ).rejects.toThrow("retrieval failed");
180
- });
181
-
182
- test("passes through null PKB and NOW when the files are absent", async () => {
183
- readPkbContextMock.mockImplementation(() => null);
184
- readNowContextMock.mockImplementation(() => null);
185
- const deps = makeDeps();
186
-
187
- const result = await runDefaultMemoryRetrieval(makeMemoryArgs(), deps);
188
-
189
- expect(result.pkbContent).toBeNull();
190
- expect(result.nowContent).toBeNull();
191
- });
192
- });
193
-
194
- describe("asDefaultGraphPayload", () => {
195
- test("returns null when the blocks array is empty", () => {
196
- expect(asDefaultGraphPayload([])).toBeNull();
197
- });
198
-
199
- test("returns null when the first block lacks the default discriminator", () => {
200
- expect(asDefaultGraphPayload([{ kind: "custom" }])).toBeNull();
201
- expect(asDefaultGraphPayload([{}])).toBeNull();
202
- expect(asDefaultGraphPayload([null])).toBeNull();
203
- });
204
-
205
- test("narrows blocks whose first entry carries the default discriminator", () => {
206
- const payload = {
207
- kind: DEFAULT_MEMORY_GRAPH_KIND,
208
- result: { mode: "per-turn" } as never,
209
- };
210
- expect(asDefaultGraphPayload([payload])).toBe(payload);
211
- });
212
- });
213
-
214
- describe("memoryRetrieval pipeline — default vs custom plugin", () => {
215
- test("default (no plugins registered) matches current retrieval exactly", async () => {
216
- const deps = makeDeps();
217
- const args = makeMemoryArgs();
218
- const terminalDirect = await runDefaultMemoryRetrieval(args, deps);
219
-
220
- // With an empty registry the pipeline runs the terminal directly. Use a
221
- // fresh graph handle so `prepareMemory` call counts don't leak across
222
- // the two invocations.
223
- const deps2 = makeDeps();
224
- const terminalViaPipeline = await runPipeline(
225
- "memoryRetrieval",
226
- getMiddlewaresFor("memoryRetrieval"),
227
- (innerArgs: MemoryArgs) => runDefaultMemoryRetrieval(innerArgs, deps2),
228
- args,
229
- makeTurnCtx(),
230
- DEFAULT_TIMEOUTS.memoryRetrieval,
231
- );
232
-
233
- expect(terminalViaPipeline.pkbContent).toBe(terminalDirect.pkbContent);
234
- expect(terminalViaPipeline.nowContent).toBe(terminalDirect.nowContent);
235
- expect(terminalViaPipeline.memoryGraphBlocks).toHaveLength(
236
- terminalDirect.memoryGraphBlocks.length,
237
- );
238
- });
239
-
240
- test("with the default plugin registered, pipeline still produces default output", async () => {
241
- registerPlugin(defaultMemoryRetrievalPlugin);
242
- const deps = makeDeps();
243
- const args = makeMemoryArgs();
244
-
245
- const result = await runPipeline(
246
- "memoryRetrieval",
247
- getMiddlewaresFor("memoryRetrieval"),
248
- (innerArgs: MemoryArgs) => runDefaultMemoryRetrieval(innerArgs, deps),
249
- args,
250
- makeTurnCtx(),
251
- DEFAULT_TIMEOUTS.memoryRetrieval,
252
- );
253
-
254
- expect(result.pkbContent).toBe("pkb-default");
255
- expect(result.nowContent).toBe("now-default");
256
- expect(result.memoryGraphBlocks).toHaveLength(1);
257
- expect(asDefaultGraphPayload(result.memoryGraphBlocks)).not.toBeNull();
258
- });
259
-
260
- test("custom plugin can replace all three sources via short-circuit", async () => {
261
- const customBlock = { kind: "custom.source", text: "replacement" };
262
- const customMiddleware: Middleware<MemoryArgs, MemoryResult> =
263
- async function customRetriever() {
264
- // Skip `next` entirely — the terminal never runs.
265
- return {
266
- pkbContent: "pkb-custom",
267
- nowContent: "now-custom",
268
- memoryGraphBlocks: [customBlock],
269
- };
270
- };
271
-
272
- const customPlugin: Plugin = {
273
- manifest: {
274
- name: "custom-memory-retrieval",
275
- version: "0.0.1",
276
- },
277
- middleware: { memoryRetrieval: customMiddleware },
278
- };
279
- registerPlugin(customPlugin);
280
-
281
- const deps = makeDeps();
282
- const args = makeMemoryArgs();
283
-
284
- const result = await runPipeline(
285
- "memoryRetrieval",
286
- getMiddlewaresFor("memoryRetrieval"),
287
- (innerArgs: MemoryArgs) => runDefaultMemoryRetrieval(innerArgs, deps),
288
- args,
289
- makeTurnCtx(),
290
- DEFAULT_TIMEOUTS.memoryRetrieval,
291
- );
292
-
293
- expect(result.pkbContent).toBe("pkb-custom");
294
- expect(result.nowContent).toBe("now-custom");
295
- expect(result.memoryGraphBlocks).toEqual([customBlock]);
296
- // The terminal never ran, so the stubbed readers were NOT invoked.
297
- expect(readPkbContextMock).not.toHaveBeenCalled();
298
- expect(readNowContextMock).not.toHaveBeenCalled();
299
- // And `asDefaultGraphPayload` must return null because the custom
300
- // plugin supplied a block without the default discriminator — this is
301
- // what drives the agent-loop escape hatch.
302
- expect(asDefaultGraphPayload(result.memoryGraphBlocks)).toBeNull();
303
- });
304
-
305
- test("timeout: terminal that hangs past the budget fails with PluginTimeoutError", async () => {
306
- // Hang-prone middleware that never resolves; the runner arms a 5s timer
307
- // by default, but the test overrides to a much smaller budget to keep
308
- // the suite fast.
309
- const hanging: Middleware<MemoryArgs, MemoryResult> =
310
- async function hangingRetriever(_args, _next) {
311
- return new Promise<MemoryResult>(() => {
312
- // Never resolves — simulates a retriever that blocks on I/O.
313
- });
314
- };
315
-
316
- const plugin: Plugin = {
317
- manifest: {
318
- name: "hanging-memory-plugin",
319
- version: "0.0.1",
320
- },
321
- middleware: { memoryRetrieval: hanging },
322
- };
323
- registerPlugin(plugin);
324
-
325
- const deps = makeDeps();
326
- const args = makeMemoryArgs();
327
-
328
- let caught: unknown;
329
- try {
330
- await runPipeline(
331
- "memoryRetrieval",
332
- getMiddlewaresFor("memoryRetrieval"),
333
- (innerArgs: MemoryArgs) => runDefaultMemoryRetrieval(innerArgs, deps),
334
- args,
335
- makeTurnCtx(),
336
- 30, // tiny pipeline budget to keep the test fast
337
- );
338
- } catch (err) {
339
- caught = err;
340
- }
341
-
342
- expect(caught).toBeInstanceOf(PluginTimeoutError);
343
- const timeoutErr = caught as PluginTimeoutError;
344
- expect(timeoutErr.pipeline).toBe("memoryRetrieval");
345
- // The runner records whatever `ctx.pluginName` is set to when the
346
- // timer fires. The default pipeline doesn't bind a plugin name, so
347
- // the attribution is undefined — still fail the turn cleanly.
348
- expect(timeoutErr.message).toContain("memoryRetrieval");
349
- });
350
-
351
- test("pipeline timeout aborts the signal threaded into prepareMemory", async () => {
352
- // Verifies that the pipeline's abort-linker swaps `MemoryArgs.signal`
353
- // for a linked signal so a pipeline timeout aborts `prepareMemory`
354
- // and prevents graph-state mutation / event emission after the
355
- // pipeline has already errored.
356
- let capturedSignal: AbortSignal | undefined;
357
- const hangingPrepare = mock(
358
- (
359
- _msgs: Message[],
360
- _cfg: AssistantConfig,
361
- signal: AbortSignal,
362
- _onEvent: (msg: ServerMessage) => void,
363
- ) => {
364
- capturedSignal = signal;
365
- return new Promise((_resolve, reject) => {
366
- signal.addEventListener("abort", () => reject(new Error("aborted")));
367
- });
368
- },
369
- );
370
- const graphMemory = {
371
- prepareMemory: hangingPrepare,
372
- } as unknown as ConversationGraphMemory;
373
- const deps = makeDeps({ graphMemory });
374
- const outerController = new AbortController();
375
- const args = makeMemoryArgs({ signal: outerController.signal });
376
-
377
- let caught: unknown;
378
- try {
379
- await runPipeline(
380
- "memoryRetrieval",
381
- getMiddlewaresFor("memoryRetrieval"),
382
- (innerArgs: MemoryArgs) => runDefaultMemoryRetrieval(innerArgs, deps),
383
- args,
384
- makeTurnCtx(),
385
- 30,
386
- );
387
- } catch (err) {
388
- caught = err;
389
- }
390
-
391
- expect(caught).toBeInstanceOf(PluginTimeoutError);
392
- expect(capturedSignal).toBeDefined();
393
- // The signal the terminal observed must be the pipeline's linked
394
- // signal (not the caller's bare signal), and it must be aborted so
395
- // `prepareMemory` stops work instead of running to completion after
396
- // the race has already rejected.
397
- expect(capturedSignal).not.toBe(outerController.signal);
398
- expect(capturedSignal!.aborted).toBe(true);
399
- });
400
-
401
- test("onEvent is invoked by the default retriever's terminal path", async () => {
402
- const received: ServerMessage[] = [];
403
- const { memory } = makeFakeGraphMemory();
404
- const deps = makeDeps({
405
- graphMemory: memory,
406
- onEvent: (msg) => received.push(msg),
407
- isTrustedActor: true,
408
- });
409
-
410
- await runDefaultMemoryRetrieval(makeMemoryArgs(), deps);
411
-
412
- // The fake graph doesn't emit events, but the event sink must be
413
- // forwarded intact so the real retriever can use it. Verify by
414
- // reaching into the mock assertion above (prepareMemoryMock called
415
- // with `onEvent`).
416
- expect(received).toEqual([]);
417
- });
418
- });