@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,341 +0,0 @@
1
- /**
2
- * Tests for the `toolResultTruncate` plugin pipeline (PR 17).
3
- *
4
- * Covers:
5
- * - The default terminal delegates to `truncateToolResultText`, producing
6
- * byte-for-byte identical output to calling the helper directly across
7
- * short, long, and newline-bounded inputs (property-style).
8
- * - The pipeline routes through `runPipeline` with the
9
- * `DEFAULT_TIMEOUTS.toolResultTruncate` budget and returns a
10
- * `{ content, truncated }` pair whose `truncated` flag matches whether
11
- * the content actually changed.
12
- * - Plugins registered alongside the default can short-circuit or decorate
13
- * the terminal's output.
14
- * - A user plugin registered AFTER the default still runs — the default
15
- * plugin's middleware is a passthrough, so the onion composition cannot
16
- * shadow late-registered middleware.
17
- */
18
-
19
- import { beforeEach, describe, expect, test } from "bun:test";
20
-
21
- import type { TrustContext } from "../daemon/trust-context.js";
22
- import { defaultToolResultTruncatePlugin } from "../plugins/defaults/tool-result-truncate/register.js";
23
- import {
24
- defaultToolResultTruncateTerminal,
25
- MIN_KEEP_CHARS,
26
- truncateToolResultText,
27
- TRUNCATION_SUFFIX,
28
- } from "../plugins/defaults/tool-result-truncate/terminal.js";
29
- import type {
30
- ToolResultTruncateArgs,
31
- ToolResultTruncateResult,
32
- } from "../plugins/defaults/tool-result-truncate/types.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 { type Middleware, type TurnContext } from "../plugins/types.js";
40
-
41
- // ---------------------------------------------------------------------------
42
- // Fixtures
43
- // ---------------------------------------------------------------------------
44
-
45
- const trust: TrustContext = {
46
- sourceChannel: "vellum",
47
- trustClass: "guardian",
48
- };
49
-
50
- function makeCtx(overrides: Partial<TurnContext> = {}): TurnContext {
51
- return {
52
- requestId: "req-test",
53
- conversationId: "conv-test",
54
- turnIndex: 0,
55
- trust,
56
- ...overrides,
57
- };
58
- }
59
-
60
- describe("toolResultTruncate pipeline", () => {
61
- beforeEach(() => {
62
- resetPluginRegistryForTests();
63
- });
64
-
65
- // -------------------------------------------------------------------------
66
- // Default terminal — isolated (no pipeline runner)
67
- // -------------------------------------------------------------------------
68
-
69
- describe("default terminal", () => {
70
- test("passes short content through unchanged with truncated=false", () => {
71
- const content = "hello world";
72
- const result = defaultToolResultTruncateTerminal({
73
- content,
74
- maxChars: 100,
75
- });
76
- expect(result.content).toBe(content);
77
- expect(result.truncated).toBe(false);
78
- });
79
-
80
- test("truncates oversize content and reports truncated=true", () => {
81
- const content = "a".repeat(10_000);
82
- const maxChars = 5_000;
83
- const expected = truncateToolResultText(content, maxChars);
84
- const result = defaultToolResultTruncateTerminal({ content, maxChars });
85
- expect(result.content).toBe(expected);
86
- expect(result.truncated).toBe(true);
87
- expect(result.content).toContain(TRUNCATION_SUFFIX);
88
- });
89
-
90
- test("snaps to newline boundary identically to truncateToolResultText", () => {
91
- const lines = Array.from(
92
- { length: 1_000 },
93
- (_, i) => `line ${i}: ${"x".repeat(20)}`,
94
- ).join("\n");
95
- const maxChars = 5_000;
96
- const expected = truncateToolResultText(lines, maxChars);
97
- const result = defaultToolResultTruncateTerminal({
98
- content: lines,
99
- maxChars,
100
- });
101
- expect(result.content).toBe(expected);
102
- expect(result.truncated).toBe(true);
103
- });
104
-
105
- test("returns truncated=false when effectiveMax keeps the full text (maxChars < MIN_KEEP_CHARS case)", () => {
106
- const textLength = MIN_KEEP_CHARS - TRUNCATION_SUFFIX.length - 10;
107
- const content = "a".repeat(textLength);
108
- const maxChars = 100;
109
- const expected = truncateToolResultText(content, maxChars);
110
- const result = defaultToolResultTruncateTerminal({ content, maxChars });
111
- // Helper returns the original text unchanged in this case.
112
- expect(expected).toBe(content);
113
- expect(result.content).toBe(content);
114
- expect(result.truncated).toBe(false);
115
- });
116
- });
117
-
118
- // -------------------------------------------------------------------------
119
- // End-to-end: default plugin routed through runPipeline
120
- // -------------------------------------------------------------------------
121
-
122
- describe("runPipeline with the default plugin registered", () => {
123
- async function runDefault(
124
- content: string,
125
- maxChars: number,
126
- ): Promise<ToolResultTruncateResult> {
127
- registerPlugin(defaultToolResultTruncatePlugin);
128
- const middlewares = getMiddlewaresFor("toolResultTruncate");
129
- return runPipeline<ToolResultTruncateArgs, ToolResultTruncateResult>(
130
- "toolResultTruncate",
131
- middlewares,
132
- async (args) => defaultToolResultTruncateTerminal(args),
133
- { content, maxChars },
134
- makeCtx(),
135
- DEFAULT_TIMEOUTS.toolResultTruncate,
136
- );
137
- }
138
-
139
- test("short content round-trip matches truncateToolResultText", async () => {
140
- const content = "quick brown fox";
141
- const maxChars = 200;
142
- const expected = truncateToolResultText(content, maxChars);
143
- const result = await runDefault(content, maxChars);
144
- expect(result.content).toBe(expected);
145
- expect(result.truncated).toBe(false);
146
- });
147
-
148
- test("long content round-trip matches truncateToolResultText", async () => {
149
- const content = "z".repeat(50_000);
150
- const maxChars = 10_000;
151
- const expected = truncateToolResultText(content, maxChars);
152
- const result = await runDefault(content, maxChars);
153
- expect(result.content).toBe(expected);
154
- expect(result.truncated).toBe(true);
155
- expect(result.content).toContain(TRUNCATION_SUFFIX);
156
- });
157
-
158
- test("newline-bounded content round-trip matches truncateToolResultText", async () => {
159
- const lines = Array.from(
160
- { length: 500 },
161
- (_, i) => `line ${i}: ${"y".repeat(40)}`,
162
- ).join("\n");
163
- const maxChars = 4_000;
164
- const expected = truncateToolResultText(lines, maxChars);
165
- const result = await runDefault(lines, maxChars);
166
- expect(result.content).toBe(expected);
167
- expect(result.truncated).toBe(true);
168
- });
169
-
170
- test("property test: default pipeline output equals direct truncateToolResultText across varied inputs", async () => {
171
- // Deterministic pseudo-random over a fixed seed — bun's test runner
172
- // doesn't ship a property-test library, so we hand-roll a tiny LCG
173
- // that produces enough spread for a meaningful regression signal
174
- // without introducing a dependency.
175
- let seed = 0xc0ffee;
176
- const rand = () => {
177
- seed = (seed * 1664525 + 1013904223) & 0xffffffff;
178
- return (seed >>> 0) / 0x100000000;
179
- };
180
- const alphabet = "abcdefghijklmnopqrstuvwxyz \n";
181
-
182
- const cases: Array<{ content: string; maxChars: number }> = [];
183
- for (let i = 0; i < 40; i++) {
184
- // Lengths span short, boundary, and long relative to the maxChars
185
- // budget so the property covers pass-through, newline-snap, and
186
- // pure tail-drop paths.
187
- const length = Math.floor(rand() * 20_000);
188
- let content = "";
189
- for (let j = 0; j < length; j++) {
190
- content += alphabet[Math.floor(rand() * alphabet.length)];
191
- }
192
- const maxChars = 1_000 + Math.floor(rand() * 9_000);
193
- cases.push({ content, maxChars });
194
- }
195
-
196
- // Register once outside the loop — registry is reset in `beforeEach`,
197
- // so the per-case reset lives in the loop instead.
198
- for (const { content, maxChars } of cases) {
199
- resetPluginRegistryForTests();
200
- registerPlugin(defaultToolResultTruncatePlugin);
201
- const middlewares = getMiddlewaresFor("toolResultTruncate");
202
- const result = await runPipeline<
203
- ToolResultTruncateArgs,
204
- ToolResultTruncateResult
205
- >(
206
- "toolResultTruncate",
207
- middlewares,
208
- async (args) => defaultToolResultTruncateTerminal(args),
209
- { content, maxChars },
210
- makeCtx(),
211
- DEFAULT_TIMEOUTS.toolResultTruncate,
212
- );
213
- const expected = truncateToolResultText(content, maxChars);
214
- expect(result.content).toBe(expected);
215
- expect(result.truncated).toBe(expected !== content);
216
- }
217
- });
218
- });
219
-
220
- // -------------------------------------------------------------------------
221
- // Middleware composition — an outer plugin can intercept / transform
222
- // -------------------------------------------------------------------------
223
-
224
- describe("middleware composition", () => {
225
- test("an outer plugin can short-circuit the default with its own content", async () => {
226
- const shortCircuit: Middleware<
227
- ToolResultTruncateArgs,
228
- ToolResultTruncateResult
229
- > = async (_args, _next, _ctx) => {
230
- return { content: "SUMMARY", truncated: true };
231
- };
232
- registerPlugin({
233
- manifest: {
234
- name: "short-circuit",
235
- version: "1.0.0",
236
- },
237
- middleware: { toolResultTruncate: shortCircuit },
238
- });
239
- registerPlugin(defaultToolResultTruncatePlugin);
240
-
241
- const middlewares = getMiddlewaresFor("toolResultTruncate");
242
- const result = await runPipeline<
243
- ToolResultTruncateArgs,
244
- ToolResultTruncateResult
245
- >(
246
- "toolResultTruncate",
247
- middlewares,
248
- async (args) => defaultToolResultTruncateTerminal(args),
249
- { content: "a".repeat(10_000), maxChars: 5_000 },
250
- makeCtx(),
251
- DEFAULT_TIMEOUTS.toolResultTruncate,
252
- );
253
-
254
- expect(result.content).toBe("SUMMARY");
255
- expect(result.truncated).toBe(true);
256
- });
257
-
258
- test("an outer plugin can observe and mutate the default's output", async () => {
259
- const prefixer: Middleware<
260
- ToolResultTruncateArgs,
261
- ToolResultTruncateResult
262
- > = async (args, next, _ctx) => {
263
- const inner = await next(args);
264
- return { ...inner, content: `[wrapped] ${inner.content}` };
265
- };
266
- registerPlugin({
267
- manifest: {
268
- name: "prefixer",
269
- version: "1.0.0",
270
- },
271
- middleware: { toolResultTruncate: prefixer },
272
- });
273
- registerPlugin(defaultToolResultTruncatePlugin);
274
-
275
- const middlewares = getMiddlewaresFor("toolResultTruncate");
276
- const content = "hello";
277
- const result = await runPipeline<
278
- ToolResultTruncateArgs,
279
- ToolResultTruncateResult
280
- >(
281
- "toolResultTruncate",
282
- middlewares,
283
- async (args) => defaultToolResultTruncateTerminal(args),
284
- { content, maxChars: 100 },
285
- makeCtx(),
286
- DEFAULT_TIMEOUTS.toolResultTruncate,
287
- );
288
-
289
- expect(result.content).toBe(`[wrapped] ${content}`);
290
- expect(result.truncated).toBe(false);
291
- });
292
-
293
- test("user plugin registered AFTER the default still runs (no shadowing)", async () => {
294
- // Production registration order: defaults load first via the
295
- // side-effect imports in `defaults/index.ts`, then user plugins
296
- // register on top (via `bootstrapPlugins()` or hot-reload). The
297
- // user's middleware ends up at a deeper onion layer than the
298
- // default. If the default's middleware were to bypass `next` and
299
- // call the terminal directly, the user middleware would never run
300
- // — this test guards against that regression.
301
- registerPlugin(defaultToolResultTruncatePlugin);
302
-
303
- let userMiddlewareRan = false;
304
- const userMiddleware: Middleware<
305
- ToolResultTruncateArgs,
306
- ToolResultTruncateResult
307
- > = async (args, next) => {
308
- userMiddlewareRan = true;
309
- return next(args);
310
- };
311
- registerPlugin({
312
- manifest: {
313
- name: "late-user-plugin",
314
- version: "0.0.1",
315
- },
316
- middleware: { toolResultTruncate: userMiddleware },
317
- });
318
-
319
- const middlewares = getMiddlewaresFor("toolResultTruncate");
320
- const content = "a".repeat(10_000);
321
- const maxChars = 5_000;
322
- const result = await runPipeline<
323
- ToolResultTruncateArgs,
324
- ToolResultTruncateResult
325
- >(
326
- "toolResultTruncate",
327
- middlewares,
328
- async (args) => defaultToolResultTruncateTerminal(args),
329
- { content, maxChars },
330
- makeCtx(),
331
- DEFAULT_TIMEOUTS.toolResultTruncate,
332
- );
333
-
334
- expect(userMiddlewareRan).toBe(true);
335
- // Terminal still runs after the user passthrough, so output matches
336
- // the direct helper.
337
- expect(result.content).toBe(truncateToolResultText(content, maxChars));
338
- expect(result.truncated).toBe(true);
339
- });
340
- });
341
- });
@@ -1,45 +0,0 @@
1
- import { getMessages, type MessageRow } from "../memory/conversation-crud.js";
2
- import { cleanupBootstrapFiles } from "../prompts/bootstrap-cleanup.js";
3
- import { getLogger } from "../util/logger.js";
4
-
5
- export const BOOTSTRAP_CLEANUP_USER_TURN_THRESHOLD = 4;
6
-
7
- const log = getLogger("bootstrap-turn-cleanup");
8
-
9
- function isWakeUpGreetingMessage(content: string): boolean {
10
- return content.toLowerCase().includes("wake up, my friend");
11
- }
12
-
13
- export function countBootstrapUserTurns(
14
- messages: Pick<MessageRow, "role" | "content">[],
15
- ): number {
16
- return messages.filter(
17
- (message) =>
18
- message.role === "user" && !isWakeUpGreetingMessage(message.content),
19
- ).length;
20
- }
21
-
22
- export function shouldCleanupBootstrapAfterTurn(
23
- messages: Pick<MessageRow, "role" | "content">[],
24
- threshold = BOOTSTRAP_CLEANUP_USER_TURN_THRESHOLD,
25
- ): boolean {
26
- return countBootstrapUserTurns(messages) >= threshold;
27
- }
28
-
29
- export function cleanupBootstrapAfterTurnThreshold(
30
- conversationId: string,
31
- ): boolean {
32
- let messages: MessageRow[];
33
- try {
34
- messages = getMessages(conversationId);
35
- } catch (err) {
36
- log.warn({ err, conversationId }, "Failed to inspect bootstrap turn count");
37
- return false;
38
- }
39
-
40
- if (!shouldCleanupBootstrapAfterTurn(messages)) return false;
41
-
42
- return cleanupBootstrapFiles(
43
- `first conversation reached ${BOOTSTRAP_CLEANUP_USER_TURN_THRESHOLD} user turns`,
44
- );
45
- }