@vellumai/assistant 0.8.10 → 0.8.11-staging.1

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 (400) hide show
  1. package/bun.lock +62 -1
  2. package/docs/workspace-tools.md +196 -0
  3. package/examples/plugins/echo/README.md +3 -3
  4. package/knip.json +1 -0
  5. package/openapi.yaml +460 -128
  6. package/package.json +2 -1
  7. package/scripts/build-plugin-api.ts +299 -0
  8. package/src/__tests__/agent-loop-callsite-precedence.test.ts +7 -0
  9. package/src/__tests__/agent-loop-compaction-events.test.ts +197 -0
  10. package/src/__tests__/agent-loop-exit-reason.test.ts +93 -96
  11. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +2 -0
  12. package/src/__tests__/agent-loop-output-hooks.test.ts +274 -1
  13. package/src/__tests__/agent-loop-override-profile.test.ts +3 -0
  14. package/src/__tests__/agent-loop-provider-error-recording.test.ts +4 -0
  15. package/src/__tests__/agent-loop-thinking.test.ts +4 -0
  16. package/src/__tests__/agent-loop.test.ts +578 -5
  17. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +0 -1
  18. package/src/__tests__/approval-cascade.test.ts +1 -0
  19. package/src/__tests__/background-workers-disk-pressure.test.ts +0 -2
  20. package/src/__tests__/btw-routes.test.ts +0 -1
  21. package/src/__tests__/build-persisted-content.test.ts +75 -1
  22. package/src/__tests__/catalog-install-normalize.test.ts +141 -0
  23. package/src/__tests__/ces-startup-timeout.test.ts +60 -0
  24. package/src/__tests__/compaction-events.test.ts +1 -0
  25. package/src/__tests__/config-managed-gemini-defaults.test.ts +2 -46
  26. package/src/__tests__/context-overflow-reducer.test.ts +264 -124
  27. package/src/__tests__/context-window-manager-overflow-rung.test.ts +351 -0
  28. package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
  29. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +13 -5
  30. package/src/__tests__/conversation-agent-loop-overflow.test.ts +284 -455
  31. package/src/__tests__/conversation-agent-loop.test.ts +131 -551
  32. package/src/__tests__/conversation-app-control-instantiation.test.ts +13 -0
  33. package/src/__tests__/conversation-confirmation-signals.test.ts +1 -0
  34. package/src/__tests__/conversation-fork-crud.test.ts +259 -0
  35. package/src/__tests__/conversation-history-web-search.test.ts +1 -1
  36. package/src/__tests__/conversation-lifecycle.test.ts +257 -1
  37. package/src/__tests__/conversation-process-callsite.test.ts +1 -0
  38. package/src/__tests__/conversation-provider-retry-repair.test.ts +38 -377
  39. package/src/__tests__/conversation-queue.test.ts +1 -39
  40. package/src/__tests__/conversation-runtime-assembly.test.ts +119 -8
  41. package/src/__tests__/conversation-skill-tools.test.ts +491 -5
  42. package/src/__tests__/conversation-slash-queue.test.ts +1 -1
  43. package/src/__tests__/conversation-slash-unknown.test.ts +1 -0
  44. package/src/__tests__/conversation-speed-override.test.ts +1 -0
  45. package/src/__tests__/conversation-store.test.ts +74 -0
  46. package/src/__tests__/conversation-surfaces-app-control.test.ts +4 -1
  47. package/src/__tests__/conversation-tool-setup-attribution.test.ts +323 -0
  48. package/src/__tests__/conversation-tool-setup-tools-disabled.test.ts +34 -0
  49. package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -0
  50. package/src/__tests__/conversation-workspace-injection.test.ts +1 -1
  51. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -0
  52. package/src/__tests__/corrected-target.test.ts +93 -0
  53. package/src/__tests__/credential-execution-feature-gates.test.ts +3 -5
  54. package/src/__tests__/credential-execution-tools.test.ts +23 -11
  55. package/src/__tests__/credential-security-invariants.test.ts +6 -1
  56. package/src/__tests__/db-schedule-syntax-migration.test.ts +80 -0
  57. package/src/__tests__/device-id.test.ts +70 -1
  58. package/src/__tests__/embedding-managed-proxy-selection.test.ts +6 -40
  59. package/src/__tests__/empty-response-hook.test.ts +242 -66
  60. package/src/__tests__/external-plugin-loader.test.ts +0 -31
  61. package/src/__tests__/get-skill-detail-audit.test.ts +43 -1
  62. package/src/__tests__/guardian-routing-invariants.test.ts +91 -0
  63. package/src/__tests__/history-repair-hook.test.ts +228 -3
  64. package/src/__tests__/host-app-control-proxy.test.ts +45 -0
  65. package/src/__tests__/host-browser-proxy.test.ts +254 -9
  66. package/src/__tests__/identity-routes.test.ts +1 -0
  67. package/src/__tests__/image-recovery-hook.test.ts +387 -0
  68. package/src/__tests__/injector-chain.test.ts +5 -4
  69. package/src/__tests__/injector-v3-suppression.test.ts +373 -47
  70. package/src/__tests__/intent-routing.test.ts +7 -0
  71. package/src/__tests__/memory-retrieval-hook.test.ts +117 -15
  72. package/src/__tests__/notification-decision-strategy.test.ts +3 -3
  73. package/src/__tests__/oauth-store.test.ts +0 -85
  74. package/src/__tests__/{context-overflow-policy.test.ts → overflow-policy.test.ts} +1 -1
  75. package/src/__tests__/parallel-tool.benchmark.test.ts +4 -0
  76. package/src/__tests__/persist-unsendable-image-downscale.test.ts +29 -9
  77. package/src/__tests__/persist-unsendable-image.test.ts +4 -4
  78. package/src/__tests__/persistence-secret-redaction.test.ts +78 -0
  79. package/src/__tests__/plugin-bootstrap.test.ts +82 -73
  80. package/src/__tests__/plugin-tool-contribution.test.ts +7 -4
  81. package/src/__tests__/plugin-types.test.ts +0 -8
  82. package/src/__tests__/provider-catalog-visibility.test.ts +1 -9
  83. package/src/__tests__/prune-old-conversations-job.test.ts +99 -0
  84. package/src/__tests__/registry.test.ts +240 -1
  85. package/src/__tests__/require-fresh-approval.test.ts +3 -0
  86. package/src/__tests__/schedule-routes.test.ts +116 -1
  87. package/src/__tests__/schedule-store.test.ts +28 -0
  88. package/src/__tests__/schedule-tools.test.ts +94 -1
  89. package/src/__tests__/server-history-render.test.ts +39 -0
  90. package/src/__tests__/skill-projection-feature-flag.test.ts +13 -0
  91. package/src/__tests__/skill-projection.benchmark.test.ts +25 -7
  92. package/src/__tests__/skills.test.ts +202 -0
  93. package/src/__tests__/slim-skill-category.test.ts +195 -0
  94. package/src/__tests__/strip-memory-injections.test.ts +33 -39
  95. package/src/__tests__/test-support/tool-invocation-seed.ts +79 -0
  96. package/src/__tests__/title-generate-hook.test.ts +9 -7
  97. package/src/__tests__/tool-audit-listener.test.ts +264 -1
  98. package/src/__tests__/tool-error-hook.test.ts +4 -3
  99. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -0
  100. package/src/__tests__/tool-executor-lifecycle-events.test.ts +273 -0
  101. package/src/__tests__/tool-result-truncate-hook.test.ts +1 -0
  102. package/src/__tests__/tool-start-timestamp.test.ts +218 -0
  103. package/src/__tests__/tools-get-route.test.ts +202 -0
  104. package/src/__tests__/workspace-tool-loader.test.ts +319 -0
  105. package/src/__tests__/workspace-tools-watcher-flag.test.ts +70 -0
  106. package/src/agent/loop.ts +569 -319
  107. package/src/api/events/tool-result.ts +9 -0
  108. package/src/api/events/tool-use-start.ts +7 -0
  109. package/src/api/index.ts +10 -0
  110. package/src/api/responses/conversation-message.ts +135 -27
  111. package/src/api/responses/memory-v3-selection-log.ts +4 -4
  112. package/src/approvals/guardian-request-resolvers.ts +26 -0
  113. package/src/browser-session/backends/host-bridge.ts +29 -0
  114. package/src/browser-session/index.ts +1 -0
  115. package/src/browser-session/types.ts +5 -1
  116. package/src/cli/commands/__tests__/schedules.test.ts +62 -4
  117. package/src/cli/commands/__tests__/skills.test.ts +53 -0
  118. package/src/cli/commands/channel-verification-sessions.ts +6 -6
  119. package/src/cli/commands/inference-providers.ts +0 -8
  120. package/src/cli/commands/plugins.ts +2 -2
  121. package/src/cli/commands/schedules.ts +27 -4
  122. package/src/cli/commands/skills.ts +187 -146
  123. package/src/cli/commands/tools.ts +106 -0
  124. package/src/cli/lib/__tests__/install-from-github.test.ts +256 -328
  125. package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +6 -2
  126. package/src/cli/lib/__tests__/plugin-details.test.ts +10 -16
  127. package/src/cli/lib/__tests__/plugin-marketplace.test.ts +2 -2
  128. package/src/cli/lib/__tests__/search-plugins.test.ts +145 -240
  129. package/src/cli/lib/install-from-github.ts +187 -117
  130. package/src/cli/lib/plugin-catalog-cache.ts +9 -9
  131. package/src/cli/lib/plugin-details.ts +38 -68
  132. package/src/cli/lib/plugin-marketplace.ts +42 -14
  133. package/src/cli/lib/search-plugins.ts +29 -129
  134. package/src/cli/program.ts +2 -0
  135. package/src/config/bundled-skills/acp/SKILL.md +1 -0
  136. package/src/config/bundled-skills/app-builder/SKILL.md +1 -0
  137. package/src/config/bundled-skills/app-control/SKILL.md +1 -0
  138. package/src/config/bundled-skills/computer-use/SKILL.md +1 -0
  139. package/src/config/bundled-skills/contacts/SKILL.md +1 -0
  140. package/src/config/bundled-skills/document-editor/SKILL.md +1 -0
  141. package/src/config/bundled-skills/followups/SKILL.md +1 -0
  142. package/src/config/bundled-skills/image-studio/SKILL.md +1 -0
  143. package/src/config/bundled-skills/media-processing/SKILL.md +1 -0
  144. package/src/config/bundled-skills/messaging/SKILL.md +1 -0
  145. package/src/config/bundled-skills/phone-calls/SKILL.md +1 -0
  146. package/src/config/bundled-skills/playbooks/SKILL.md +1 -0
  147. package/src/config/bundled-skills/schedule/SKILL.md +1 -0
  148. package/src/config/bundled-skills/schedule/TOOLS.json +11 -3
  149. package/src/config/bundled-skills/sequences/SKILL.md +1 -0
  150. package/src/config/bundled-skills/settings/SKILL.md +1 -0
  151. package/src/config/bundled-skills/skill-management/SKILL.md +101 -1
  152. package/src/config/bundled-skills/subagent/SKILL.md +1 -0
  153. package/src/config/bundled-skills/transcribe/SKILL.md +1 -0
  154. package/src/config/env-registry.ts +23 -0
  155. package/src/config/feature-flag-registry.json +17 -81
  156. package/src/config/loader.ts +5 -22
  157. package/src/config/schema.ts +2 -0
  158. package/src/config/schemas/__tests__/compaction-logs.test.ts +56 -0
  159. package/src/config/schemas/__tests__/memory-v2.test.ts +0 -1
  160. package/src/config/schemas/__tests__/memory-v3.test.ts +61 -1
  161. package/src/config/schemas/compaction-logs.ts +79 -0
  162. package/src/config/schemas/memory-v2.ts +0 -8
  163. package/src/config/schemas/memory-v3.ts +104 -33
  164. package/src/config/seed-inference-profiles.ts +1 -1
  165. package/src/config/skills.ts +117 -47
  166. package/src/context/compactor.ts +11 -0
  167. package/src/context/strip-injections.ts +38 -4
  168. package/src/credential-execution/feature-gates.ts +0 -21
  169. package/src/credential-execution/startup-timeout.ts +32 -4
  170. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +18 -0
  171. package/src/daemon/conversation-agent-loop-handlers.ts +140 -91
  172. package/src/daemon/conversation-agent-loop.ts +123 -658
  173. package/src/daemon/conversation-error.ts +6 -33
  174. package/src/daemon/conversation-lifecycle.ts +1 -1
  175. package/src/daemon/conversation-runtime-assembly.ts +183 -22
  176. package/src/daemon/conversation-skill-tools.ts +137 -8
  177. package/src/daemon/conversation-slash.ts +0 -14
  178. package/src/daemon/conversation-store.ts +2 -19
  179. package/src/daemon/conversation-tool-setup.ts +87 -1
  180. package/src/daemon/conversation.ts +119 -50
  181. package/src/daemon/external-plugins-bootstrap.ts +36 -95
  182. package/src/daemon/handlers/config-channels.ts +11 -2
  183. package/src/daemon/handlers/shared.ts +9 -1
  184. package/src/daemon/handlers/skills.ts +10 -4
  185. package/src/daemon/host-app-control-proxy.ts +72 -57
  186. package/src/daemon/host-browser-proxy.ts +117 -22
  187. package/src/daemon/lifecycle.ts +34 -5
  188. package/src/daemon/message-protocol.ts +0 -7
  189. package/src/daemon/message-types/schedules.ts +1 -0
  190. package/src/daemon/message-types/skills.ts +17 -0
  191. package/src/daemon/providers-setup.ts +3 -0
  192. package/src/daemon/server.ts +3 -3
  193. package/src/daemon/tool-setup-types.ts +9 -3
  194. package/src/daemon/trust-context.ts +23 -0
  195. package/src/daemon/workspace-tools-watcher.ts +324 -0
  196. package/src/events/tool-audit-listener.ts +78 -16
  197. package/src/events/tool-metrics-listener.ts +2 -5
  198. package/src/memory/__tests__/compaction-log-writer-clickhouse.test.ts +227 -0
  199. package/src/memory/__tests__/conversation-queries.test.ts +176 -0
  200. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +20 -32
  201. package/src/memory/compaction-log-writer-clickhouse.ts +418 -0
  202. package/src/memory/conversation-crud.ts +134 -3
  203. package/src/memory/conversation-queries.ts +64 -7
  204. package/src/memory/db-init.ts +14 -0
  205. package/src/memory/embedding-backend.test.ts +130 -1
  206. package/src/memory/embedding-backend.ts +79 -106
  207. package/src/memory/embedding-gemini.ts +5 -0
  208. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +12 -0
  209. package/src/memory/graph/__tests__/handle-remember-v2.test.ts +19 -0
  210. package/src/memory/graph/conversation-graph-memory.ts +36 -25
  211. package/src/memory/graph/tool-handlers.ts +3 -0
  212. package/src/memory/job-handlers/cleanup.ts +3 -1
  213. package/src/memory/jobs-store.ts +0 -28
  214. package/src/memory/jobs-worker.ts +10 -22
  215. package/src/memory/memory-marker.ts +29 -0
  216. package/src/memory/memory-retrospective-startup-cleanup.ts +1 -1
  217. package/src/memory/migrations/268-add-memory-v3-selections.ts +6 -0
  218. package/src/memory/migrations/270-schedule-description.ts +36 -0
  219. package/src/memory/migrations/275-tool-invocations-add-skill-id.test.ts +81 -0
  220. package/src/memory/migrations/275-tool-invocations-add-skill-id.ts +20 -0
  221. package/src/memory/migrations/276-tool-invocations-created-at-id-index.test.ts +68 -0
  222. package/src/memory/migrations/276-tool-invocations-created-at-id-index.ts +20 -0
  223. package/src/memory/migrations/277-add-memory-v3-ever-injected.ts +29 -0
  224. package/src/memory/migrations/278-tool-invocations-telemetry-columns.test.ts +96 -0
  225. package/src/memory/migrations/278-tool-invocations-telemetry-columns.ts +39 -0
  226. package/src/memory/migrations/279-create-skill-loaded-events.test.ts +84 -0
  227. package/src/memory/migrations/279-create-skill-loaded-events.ts +26 -0
  228. package/src/memory/migrations/280-conversations-surfaced-at.test.ts +88 -0
  229. package/src/memory/migrations/280-conversations-surfaced-at.ts +24 -0
  230. package/src/memory/migrations/index.ts +10 -0
  231. package/src/memory/migrations/registry.ts +8 -0
  232. package/src/memory/schema/conversations.ts +16 -0
  233. package/src/memory/schema/infrastructure.ts +26 -0
  234. package/src/memory/skill-loaded-events-store.test.ts +160 -0
  235. package/src/memory/skill-loaded-events-store.ts +95 -0
  236. package/src/memory/tool-executed-events-store.test.ts +219 -0
  237. package/src/memory/tool-executed-events-store.ts +102 -0
  238. package/src/memory/tool-usage-store.ts +15 -3
  239. package/src/memory/v2/__tests__/consolidation-job.test.ts +117 -12
  240. package/src/memory/v2/__tests__/consolidation-prompt-flag-gating-guard.test.ts +189 -0
  241. package/src/memory/v2/__tests__/injected-block-slugs.test.ts +90 -0
  242. package/src/memory/v2/__tests__/page-store.test.ts +33 -0
  243. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +88 -15
  244. package/src/memory/v2/activation-store.ts +50 -1
  245. package/src/memory/v2/consolidation-job.ts +113 -29
  246. package/src/memory/v2/injected-block-slugs.ts +79 -0
  247. package/src/memory/v2/injection.ts +6 -1
  248. package/src/memory/v2/prompts/consolidation.ts +414 -13
  249. package/src/memory/v2/router.ts +2 -28
  250. package/src/memory/v2/static-context.ts +1 -1
  251. package/src/memory/v2/types.ts +16 -0
  252. package/src/notifications/__tests__/copy-composer.test.ts +244 -0
  253. package/src/notifications/access-request-copy.ts +298 -0
  254. package/src/notifications/adapters/slack.ts +3 -3
  255. package/src/notifications/adapters/telegram.ts +2 -1
  256. package/src/notifications/copy-composer.ts +49 -267
  257. package/src/notifications/decision-engine.ts +16 -35
  258. package/src/notifications/home-feed-side-effect.ts +1 -6
  259. package/src/oauth/oauth-store.ts +0 -9
  260. package/src/permissions/checker.test.ts +83 -1
  261. package/src/permissions/checker.ts +25 -2
  262. package/src/permissions/gateway-threshold-reader.test.ts +182 -0
  263. package/src/permissions/gateway-threshold-reader.ts +80 -0
  264. package/src/platform/client.ts +1 -3
  265. package/src/platform/feature-gate.ts +3 -12
  266. package/src/plugin-api/constants.ts +4 -2
  267. package/src/plugin-api/index.ts +63 -11
  268. package/src/plugin-api/types.ts +236 -71
  269. package/src/plugins/defaults/compaction/compact.ts +66 -2
  270. package/src/plugins/defaults/compaction/context-overflow-reducer.ts +240 -32
  271. package/src/plugins/defaults/compaction/corrected-target.ts +53 -0
  272. package/src/{daemon/context-overflow-policy.ts → plugins/defaults/compaction/overflow-policy.ts} +1 -1
  273. package/src/plugins/defaults/compaction/window-manager.ts +303 -1
  274. package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +173 -0
  275. package/src/plugins/defaults/empty-response/hooks/stop.ts +11 -115
  276. package/src/plugins/defaults/empty-response/nudge-state-store.ts +46 -0
  277. package/src/plugins/defaults/history-repair/hooks/post-model-call.ts +50 -0
  278. package/src/plugins/defaults/history-repair/hooks/stop.ts +22 -0
  279. package/src/plugins/defaults/history-repair/repair-state-store.ts +51 -0
  280. package/src/plugins/defaults/history-repair/terminal.ts +39 -2
  281. package/src/plugins/defaults/image-recovery/detect.ts +25 -0
  282. package/src/plugins/defaults/image-recovery/hooks/post-model-call.ts +73 -0
  283. package/src/plugins/defaults/image-recovery/hooks/stop.ts +22 -0
  284. package/src/plugins/defaults/image-recovery/image-recovery-state-store.ts +48 -0
  285. package/src/plugins/defaults/image-recovery/package.json +14 -0
  286. package/src/{daemon/persist-unsendable-image.ts → plugins/defaults/image-recovery/recover.ts} +67 -14
  287. package/src/plugins/defaults/index.ts +71 -5
  288. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +76 -112
  289. package/src/plugins/defaults/memory-retrieval/hooks/{user-prompt-submit-temp.ts → user-prompt-submit.ts} +83 -74
  290. package/src/plugins/defaults/memory-retrieval/injector-chain.ts +14 -8
  291. package/src/plugins/defaults/memory-retrieval/injectors.ts +2 -18
  292. package/src/plugins/defaults/memory-retrieval/package.json +14 -0
  293. package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +1157 -0
  294. package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +683 -0
  295. package/src/plugins/defaults/memory-v3-shadow/__tests__/live-integration.test.ts +161 -140
  296. package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +160 -0
  297. package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +335 -316
  298. package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +145 -53
  299. package/src/plugins/defaults/memory-v3-shadow/__tests__/render-injection.test.ts +38 -1
  300. package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +18 -8
  301. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +112 -71
  302. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +192 -51
  303. package/src/plugins/defaults/memory-v3-shadow/__tests__/types.test.ts +4 -16
  304. package/src/plugins/defaults/memory-v3-shadow/card.test.ts +173 -0
  305. package/src/plugins/defaults/memory-v3-shadow/card.ts +116 -0
  306. package/src/plugins/defaults/memory-v3-shadow/core-set.test.ts +104 -0
  307. package/src/plugins/defaults/memory-v3-shadow/core-set.ts +59 -0
  308. package/src/plugins/defaults/memory-v3-shadow/ever-injected-store.test.ts +305 -0
  309. package/src/plugins/defaults/memory-v3-shadow/ever-injected-store.ts +278 -0
  310. package/src/plugins/defaults/memory-v3-shadow/hot-set.test.ts +138 -0
  311. package/src/plugins/defaults/memory-v3-shadow/hot-set.ts +85 -0
  312. package/src/plugins/defaults/memory-v3-shadow/injector.ts +331 -24
  313. package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +119 -13
  314. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +169 -114
  315. package/src/plugins/defaults/memory-v3-shadow/page-content.ts +47 -16
  316. package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +144 -66
  317. package/src/plugins/defaults/memory-v3-shadow/prune.test.ts +758 -0
  318. package/src/plugins/defaults/memory-v3-shadow/prune.ts +471 -0
  319. package/src/plugins/defaults/memory-v3-shadow/render-injection.ts +68 -16
  320. package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +19 -12
  321. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +96 -43
  322. package/src/plugins/defaults/memory-v3-shadow/types.ts +34 -17
  323. package/src/plugins/defaults/title-generate/hooks/stop.ts +9 -11
  324. package/src/plugins/pipeline.ts +8 -5
  325. package/src/plugins/types.ts +5 -51
  326. package/src/providers/cache-control.ts +26 -0
  327. package/src/providers/inference/__tests__/base-url-route-validation.test.ts +1 -2
  328. package/src/providers/model-catalog.ts +13 -1
  329. package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +147 -0
  330. package/src/providers/openai/chat-completions-provider.ts +46 -0
  331. package/src/providers/openai/responses-provider.ts +45 -0
  332. package/src/providers/registry.ts +0 -8
  333. package/src/runtime/__tests__/agent-wake.test.ts +0 -1
  334. package/src/runtime/agent-wake.ts +13 -0
  335. package/src/runtime/routes/__tests__/acp-routes.test.ts +151 -0
  336. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +12 -50
  337. package/src/runtime/routes/__tests__/conversation-surface-routes.test.ts +322 -0
  338. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +0 -62
  339. package/src/runtime/routes/__tests__/plugins-routes.test.ts +31 -11
  340. package/src/runtime/routes/acp-routes.test.ts +106 -0
  341. package/src/runtime/routes/acp-routes.ts +248 -2
  342. package/src/runtime/routes/browser-tabs-routes.ts +1 -1
  343. package/src/runtime/routes/channel-verification-routes.ts +14 -5
  344. package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +0 -14
  345. package/src/runtime/routes/consolidation-routes.ts +6 -82
  346. package/src/runtime/routes/conversation-list-routes.ts +6 -0
  347. package/src/runtime/routes/conversation-management-routes.ts +71 -0
  348. package/src/runtime/routes/identity-routes.ts +8 -0
  349. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +33 -34
  350. package/src/runtime/routes/inference-provider-connection-routes.ts +0 -45
  351. package/src/runtime/routes/plugins-routes.ts +34 -45
  352. package/src/runtime/routes/schedule-routes.ts +43 -5
  353. package/src/runtime/routes/settings-routes.ts +140 -15
  354. package/src/runtime/routes/skills-routes.ts +18 -6
  355. package/src/runtime/services/__tests__/conversation-serializer.test.ts +140 -0
  356. package/src/runtime/services/conversation-serializer.ts +38 -1
  357. package/src/runtime/verification-outbound-actions.ts +147 -2
  358. package/src/runtime/verification-templates.ts +29 -3
  359. package/src/schedule/schedule-store.ts +19 -0
  360. package/src/skills/catalog-install.ts +77 -13
  361. package/src/tasks/task-scheduler.ts +1 -0
  362. package/src/telemetry/types.ts +66 -1
  363. package/src/telemetry/usage-telemetry-reporter.test.ts +542 -13
  364. package/src/telemetry/usage-telemetry-reporter.ts +213 -20
  365. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +49 -2
  366. package/src/tools/browser/__tests__/browser-status.test.ts +29 -5
  367. package/src/tools/browser/browser-execution.ts +27 -9
  368. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +380 -4
  369. package/src/tools/browser/cdp-client/__tests__/host-bridge-cdp-client.test.ts +107 -0
  370. package/src/tools/browser/cdp-client/__tests__/types.test.ts +6 -1
  371. package/src/tools/browser/cdp-client/factory.ts +217 -17
  372. package/src/tools/browser/cdp-client/host-bridge-cdp-client.ts +67 -0
  373. package/src/tools/browser/cdp-client/types.ts +22 -2
  374. package/src/tools/credential-execution/make-authenticated-request.ts +2 -1
  375. package/src/tools/credential-execution/manage-secure-command-tool.ts +169 -164
  376. package/src/tools/credential-execution/run-authenticated-command.ts +2 -1
  377. package/src/tools/executor.ts +39 -7
  378. package/src/tools/registry.ts +387 -5
  379. package/src/tools/schedule/create.ts +16 -0
  380. package/src/tools/schedule/list.ts +12 -4
  381. package/src/tools/schedule/update.ts +12 -0
  382. package/src/tools/skills/load.ts +11 -6
  383. package/src/tools/terminal/safe-env.ts +2 -0
  384. package/src/tools/types.ts +65 -9
  385. package/src/tools/workspace-tools/loader.ts +673 -0
  386. package/src/usage/attribution.ts +28 -0
  387. package/src/util/device-id.ts +17 -3
  388. package/src/util/platform.ts +16 -0
  389. package/tsconfig.plugin-api.json +13 -0
  390. package/src/__tests__/plugin-external-api.test.ts +0 -68
  391. package/src/__tests__/plugin-skill-contribution.test.ts +0 -355
  392. package/src/daemon/message-types/browser.ts +0 -10
  393. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +0 -187
  394. package/src/plugins/defaults/memory-v3-shadow/__tests__/fixtures/eval-turns.json +0 -36
  395. package/src/plugins/defaults/memory-v3-shadow/__tests__/fixtures/live-turns.json +0 -37
  396. package/src/plugins/defaults/memory-v3-shadow/__tests__/working-set-eviction.test.ts +0 -106
  397. package/src/plugins/defaults/memory-v3-shadow/__tests__/working-set-skeleton.test.ts +0 -44
  398. package/src/plugins/defaults/memory-v3-shadow/working-set.ts +0 -91
  399. package/src/plugins/external-api.ts +0 -114
  400. package/src/plugins/plugin-skill-contributions.ts +0 -292
@@ -1,10 +1,11 @@
1
1
  ---
2
2
  name: skill-management
3
- description: Create and delete custom managed skills
3
+ description: Create, edit, and delete custom managed skills in the user's workspace. Use whenever the user wants to author a new skill from a description, scaffold a SKILL.md, or remove a skill they no longer need.
4
4
  metadata:
5
5
  emoji: "\U0001F9E9"
6
6
  vellum:
7
7
  display-name: "Skill Management"
8
+ category: "system"
8
9
  activation-hints:
9
10
  - "User wants to scaffold a new managed skill in their workspace from a description"
10
11
  - "User wants to delete or list the custom skills they have defined"
@@ -15,9 +16,108 @@ metadata:
15
16
 
16
17
  Manage the lifecycle of custom managed skills in `{workspaceDir}/skills`.
17
18
 
19
+ ## When to Use
20
+
21
+ USE THIS SKILL WHEN:
22
+ - The user says "build me a skill" or "create a skill for X"
23
+ - The user wants to scaffold, edit, or delete a SKILL.md in their workspace
24
+ - The user wants a repeatable workflow captured as an invocable skill
25
+
26
+ Do NOT use this skill when the user just wants to run an existing skill. That is normal activation, not management.
27
+
18
28
  ## Capabilities
19
29
 
20
30
  - **Scaffold** a new managed skill with YAML frontmatter and markdown body
31
+ - **Edit** an existing skill by scaffolding over it (rewrites the SKILL.md in place)
21
32
  - **Delete** an existing managed skill directory
22
33
 
23
34
  Skills created via `scaffold_managed_skill` become available for `skill_load` when a valid top-level `SKILL.md` is written under the skill directory.
35
+
36
+ ## Step 1 - Align with the user before building
37
+
38
+ Ask before doing anything. Do not scaffold a skill until you have confirmed with the user:
39
+
40
+ - What the skill should do
41
+ - When it should activate (the trigger phrases, in their words)
42
+ - The major steps it performs
43
+ - Any destructive steps and the done condition
44
+
45
+ > ✓ Checkpoint: Have you confirmed scope with the user? If you are guessing at any of the four points above, ask first. Do not scaffold on assumption.
46
+
47
+ ## Step 2 - Write a description AND activation-hints, always both
48
+
49
+ The description is what makes the skill discoverable. It must cover both what the skill does and when to reach for it, phrased the way the user would say it.
50
+
51
+ ```yaml
52
+ description: Build anything visual — apps, landing pages, dashboards, trackers,
53
+ calculators, games, tools, slide decks, or data visualizations. Use whenever
54
+ the user wants something built that they can see and interact with.
55
+ ```
56
+
57
+ **Every skill must also ship `activation-hints` in its frontmatter. This is not optional.** Keep `activation-hints` separate from the description: the description sells the skill, the hints list the concrete trigger phrases the user confirmed in Step 1.
58
+
59
+ ```yaml
60
+ metadata:
61
+ vellum:
62
+ activation-hints:
63
+ - "build me an app"
64
+ - "make a dashboard"
65
+ - "create a landing page"
66
+ ```
67
+
68
+ > ✓ Checkpoint: Does the frontmatter have both a description and an `activation-hints` list? If hints are missing, go back and add them before writing the body.
69
+
70
+ ## Step 3 - Structure the body so it survives weak models
71
+
72
+ Strong models tolerate loose structure. Weaker models drift. Build every body with these patterns.
73
+
74
+ **Open with a `## When to Use` block.** User language, not jargon. This is what makes the model recognize when the skill applies.
75
+
76
+ **Put critical warnings at the point of action.** A warning at the top of a file is forgotten by the time the model is 200 lines deep. Do not trust the top-of-file warning. Repeat the danger where the dangerous action happens.
77
+
78
+ ```markdown
79
+ ## Step 5 - Apply the JSON blob
80
+
81
+ ⚠️ CRITICAL: Use the complete blob below. Setting even one key
82
+ wipes the entire block. Copy the whole thing or fail.
83
+ ```
84
+
85
+ **Add explicit checkpoints between major steps, sparingly.** Long executions blur together. The model finishes step 3 and slides into step 4 without re-anchoring. A checkpoint forces a re-read. Use them between major sections, not on every step.
86
+
87
+ **Make branching explicit with `If / →`, and always name the default.** Prose hides decisions. The model reads linearly and walks past a branch without registering it. Every `If` must cover the default case. Implicit fall-through ("otherwise figure it out") creates drift.
88
+
89
+ ```markdown
90
+ If the user already has a draft → restructure it into the template.
91
+ If not → build the steps from their description (default).
92
+ ```
93
+
94
+ ## Step 4 - Define done by binding tool calls to artifacts
95
+
96
+ Without an explicit done condition, the model invents one. It stops too early ("the file was created, done") or overshoots ("let me add one more feature"). Both are drift.
97
+
98
+ Each completion criterion must bind a **tool call** to the **user-visible artifact** it produces. Do not write criteria the model can satisfy by narration alone.
99
+
100
+ ```markdown
101
+ ## SKILL COMPLETE WHEN
102
+
103
+ - [ ] `scaffold_managed_skill` wrote the SKILL.md and returned its path
104
+ - [ ] User confirmed the skill loads via `skill_load`
105
+ - [ ] User saw the trigger phrases that will activate it
106
+ ```
107
+
108
+ > ✓ Checkpoint: Before scaffolding, confirm the body has a `## When to Use` block, point-of-action warnings on any dangerous step, explicit `If / →` branches with named defaults, and artifact-bound completion criteria.
109
+
110
+ ## Step 5 - Keep SKILL.md under 500 lines
111
+
112
+ Past 500 lines the model loses things in the middle. Warnings get buried, branching loses visibility, and the file fights the task for the same context budget. If a skill is growing past 500 lines, split reference material into separate files the skill points to.
113
+
114
+ ## Step 6 - Test the skill before calling it done
115
+
116
+ After scaffolding, load the skill and confirm it activates on the intended trigger and follows its own steps. If it does not activate or drifts, fix the body and test again.
117
+
118
+ How you exercise it depends on what the skill does:
119
+
120
+ - **If the skill performs side effects** (sends messages, deletes data, makes purchases, mutates external state) → do not trigger a live run during creation. Confirm it loads and activates on the intended trigger (static check), then ask the user before exercising it for real.
121
+ - **Otherwise** (read-only or local-only skills) → run it against a realistic prompt directly. This is the default.
122
+
123
+ > ⚠️ CRITICAL: Do not tell the user a skill is ready until you have confirmed it loads and activates on the intended trigger. A skill that was never loaded is a skill that was never tested. Never perform user-visible side effects just to test a skill without the user's consent.
@@ -6,6 +6,7 @@ metadata:
6
6
  emoji: "🤖"
7
7
  vellum:
8
8
  display-name: "Subagent"
9
+ category: "system"
9
10
  activation-hints:
10
11
  - "Spawn a background worker that runs in parallel with the main turn"
11
12
  - "Delegate a self-contained research or implementation task off the main thread"
@@ -6,6 +6,7 @@ metadata:
6
6
  emoji: "🎙️"
7
7
  vellum:
8
8
  display-name: "Transcribe"
9
+ category: "voice"
9
10
  activation-hints:
10
11
  - "User has an audio or video file on disk they want converted to text"
11
12
  - "User wants speech-to-text on a recording, voice memo, podcast, or meeting capture"
@@ -72,6 +72,27 @@ export function isPlatformRemote(): boolean {
72
72
  return getIsPlatform();
73
73
  }
74
74
 
75
+ /**
76
+ * VELLUM_DISABLE_PLATFORM — boolean, default: false
77
+ * When true, all outbound platform API calls in local mode are suppressed.
78
+ * The daemon, gateway, and web UI each no-op platform requests with a
79
+ * debug log. Has no effect when IS_PLATFORM is true (platform-managed
80
+ * instances always connect to the platform).
81
+ */
82
+ export function getDisablePlatform(): boolean {
83
+ return flag("VELLUM_DISABLE_PLATFORM");
84
+ }
85
+
86
+ /**
87
+ * VELLUM_DEVICE_ID — string, default: undefined
88
+ * Host-stable device id injected by the CLI into containerized deployments,
89
+ * where the container fs cannot persist device.json across recreation.
90
+ * Takes precedence over device.json resolution in util/device-id.ts.
91
+ */
92
+ export function getDeviceIdOverride(): string | undefined {
93
+ return str("VELLUM_DEVICE_ID");
94
+ }
95
+
75
96
  /**
76
97
  * VELLUM_WORKSPACE_DIR — string, default: undefined
77
98
  * Overrides the default workspace directory.
@@ -191,6 +212,8 @@ const KNOWN_VELLUM_VARS = new Set([
191
212
  "VELLUM_DEBUG",
192
213
  "VELLUM_DESKTOP_APP",
193
214
  "VELLUM_DEV",
215
+ "VELLUM_DEVICE_ID",
216
+ "VELLUM_DISABLE_PLATFORM",
194
217
  "VELLUM_DOCS_BASE_URL",
195
218
  "VELLUM_ENVIRONMENT",
196
219
  "VELLUM_HATCHED_BY",
@@ -59,6 +59,14 @@
59
59
  "description": "Enable the A2A (Agent-to-Agent) channel for inter-assistant communication via the open A2A protocol",
60
60
  "defaultEnabled": false
61
61
  },
62
+ {
63
+ "id": "workspace-tools-watcher",
64
+ "scope": "assistant",
65
+ "key": "workspace-tools-watcher",
66
+ "label": "Workspace tools file watcher",
67
+ "description": "Hot-reload workspace tool overrides under `<workspaceDir>/tools/` by watching the directory and re-registering tools as files change. When disabled, workspace tools still load from disk once at daemon startup, but live edits require a restart to take effect.",
68
+ "defaultEnabled": false
69
+ },
62
70
  {
63
71
  "id": "settings-developer-nav",
64
72
  "scope": "assistant",
@@ -72,7 +80,7 @@
72
80
  "scope": "assistant",
73
81
  "key": "system-schedule-toggles",
74
82
  "label": "System Schedule Toggles",
75
- "description": "Show Heartbeat and Consolidation pause toggles on the schedules settings page. The toggles only pause automatic runs; manual Run now remains available.",
83
+ "description": "Show the Heartbeat pause toggle on the schedules settings page. The toggle only pauses automatic runs; manual Run now remains available.",
76
84
  "defaultEnabled": false
77
85
  },
78
86
  {
@@ -115,22 +123,6 @@
115
123
  "description": "Surface credential grant and audit inspection endpoints for reviewing active grants and access logs",
116
124
  "defaultEnabled": false
117
125
  },
118
- {
119
- "id": "chatgpt-subscription-auth",
120
- "scope": "assistant",
121
- "key": "chatgpt-subscription-auth",
122
- "label": "ChatGPT Subscription Auth",
123
- "description": "Enable ChatGPT subscription OAuth as a provider auth type for OpenAI models, using the Codex device-code flow.",
124
- "defaultEnabled": false
125
- },
126
- {
127
- "id": "deploy-to-vercel",
128
- "scope": "assistant",
129
- "key": "deploy-to-vercel",
130
- "label": "Deploy to Vercel",
131
- "description": "Enable the Deploy to Vercel / Publish option in the app workspace header share menu",
132
- "defaultEnabled": false
133
- },
134
126
  {
135
127
  "id": "settings-embedding-provider",
136
128
  "scope": "assistant",
@@ -163,14 +155,6 @@
163
155
  "description": "Auto-expand completed tool call step groups instead of showing them collapsed",
164
156
  "defaultEnabled": false
165
157
  },
166
- {
167
- "id": "sounds",
168
- "scope": "assistant",
169
- "key": "sounds",
170
- "label": "Sounds",
171
- "description": "Enable the Sounds tab in Settings and all app sound playback (event sounds, random ambient sounds)",
172
- "defaultEnabled": false
173
- },
174
158
  {
175
159
  "id": "message-tts",
176
160
  "scope": "assistant",
@@ -179,14 +163,6 @@
179
163
  "description": "Show a speaker button on assistant messages to generate and play the message as audio via Fish Audio TTS",
180
164
  "defaultEnabled": false
181
165
  },
182
- {
183
- "id": "openai-compatible-endpoints",
184
- "scope": "assistant",
185
- "key": "openai-compatible-endpoints",
186
- "label": "OpenAI-Compatible Endpoints",
187
- "description": "Enable user-configured OpenAI-compatible inference endpoints with custom base URLs and model identifiers",
188
- "defaultEnabled": false
189
- },
190
166
  {
191
167
  "id": "backward-releases",
192
168
  "scope": "assistant",
@@ -235,14 +211,6 @@
235
211
  "description": "Enable assistant sandboxing via Apple Containers on macOS 26+, providing a lightweight native sandbox without third-party dependencies",
236
212
  "defaultEnabled": false
237
213
  },
238
- {
239
- "id": "managed-gemini-embeddings-enabled",
240
- "scope": "assistant",
241
- "key": "managed-gemini-embeddings-enabled",
242
- "label": "Managed Gemini Embeddings Enabled",
243
- "description": "Route embedding requests through the platform runtime proxy using Vellum-managed Gemini credentials when available",
244
- "defaultEnabled": false
245
- },
246
214
  {
247
215
  "id": "bookmarks",
248
216
  "scope": "client",
@@ -299,14 +267,6 @@
299
267
  "description": "Expose the developer-only Compaction Playground tab in macOS Settings and enable the /playground/* HTTP endpoints for exercising compaction conditions. Dev-only; default off.",
300
268
  "defaultEnabled": false
301
269
  },
302
- {
303
- "id": "account-deletion",
304
- "scope": "assistant",
305
- "key": "account-deletion",
306
- "label": "Account Deletion",
307
- "description": "Surfaces the user-initiated account deletion flow in client settings.",
308
- "defaultEnabled": true
309
- },
310
270
  {
311
271
  "id": "app-control",
312
272
  "scope": "assistant",
@@ -331,14 +291,6 @@
331
291
  "description": "Enable the external-plugin install path: the `assistant plugins` CLI subcommand and the declarative external-plugin loader convention (`<workspaceDir>/plugins/<name>/` directories containing `package.json` plus interface dirs). Gates an unstable surface that may change shape before stabilizing.",
332
292
  "defaultEnabled": false
333
293
  },
334
- {
335
- "id": "provider-zai",
336
- "scope": "assistant",
337
- "key": "provider-zai",
338
- "label": "z.ai Provider",
339
- "description": "Enable the z.ai (Zhipu AI) provider and its GLM models in the provider picker and model selection UI",
340
- "defaultEnabled": false
341
- },
342
294
  {
343
295
  "id": "velvet-theme",
344
296
  "scope": "client",
@@ -371,22 +323,6 @@
371
323
  "description": "Enable pull-to-refresh gesture in the chat view.",
372
324
  "defaultEnabled": false
373
325
  },
374
- {
375
- "id": "doctor",
376
- "scope": "client",
377
- "key": "doctor",
378
- "label": "Doctor",
379
- "description": "Enable the Doctor diagnostic tab in Debug settings.",
380
- "defaultEnabled": false
381
- },
382
- {
383
- "id": "home-page",
384
- "scope": "client",
385
- "key": "home-page",
386
- "label": "Home Page",
387
- "description": "Enable the Home page as the default landing view.",
388
- "defaultEnabled": false
389
- },
390
326
  {
391
327
  "id": "platform-notifications",
392
328
  "scope": "client",
@@ -395,6 +331,14 @@
395
331
  "description": "Enable the Notifications tab in settings.",
396
332
  "defaultEnabled": false
397
333
  },
334
+ {
335
+ "id": "centralized-assistant-status",
336
+ "scope": "client",
337
+ "key": "centralized-assistant-status",
338
+ "label": "Centralized Assistant Status",
339
+ "description": "Enable client polling of the centralized assistant operational status endpoint.",
340
+ "defaultEnabled": false
341
+ },
398
342
  {
399
343
  "id": "preview-channel",
400
344
  "scope": "client",
@@ -443,14 +387,6 @@
443
387
  "description": "Expose the developer-only Memory Router Playground tab in macOS Settings and the /assistant/memory-router-playground web page for dry-running v4 router config overrides against the live page index. Dev-only; default off.",
444
388
  "defaultEnabled": false
445
389
  },
446
- {
447
- "id": "platform-features-in-local-mode",
448
- "scope": "assistant",
449
- "key": "platform-features-in-local-mode",
450
- "label": "Platform Features in Local Mode",
451
- "description": "When enabled, the assistant can call the Vellum platform API from local mode. When disabled, all platform API clients in the daemon, gateway, CES, and web UI no-op with a debug log instead of making outbound requests.",
452
- "defaultEnabled": true
453
- },
454
390
  {
455
391
  "id": "memory-v3-shadow",
456
392
  "scope": "assistant",
@@ -14,7 +14,6 @@ import {
14
14
  getWorkspaceConfigPath,
15
15
  getWorkspaceDir,
16
16
  } from "../util/platform.js";
17
- import { isAssistantFeatureFlagEnabled } from "./assistant-feature-flags.js";
18
17
  import { AssistantConfigSchema } from "./schema.js";
19
18
  import type { AssistantConfig } from "./types.js";
20
19
 
@@ -692,16 +691,15 @@ export function loadConfig(): AssistantConfig {
692
691
 
693
692
  if (suppressConfigDiskWritesDepth === 0) {
694
693
  // Managed Gemini embedding defaults migration.
695
- // When on a managed platform (IS_PLATFORM=true) with the feature flag
696
- // enabled and no explicit embedding provider chosen (provider=auto),
697
- // persist Gemini embedding defaults into the raw config file.
694
+ // When on a managed platform (IS_PLATFORM=true) and no explicit embedding
695
+ // provider chosen (provider=auto), persist Gemini embedding defaults into
696
+ // the raw config file.
698
697
  // Idempotent: once provider=gemini is written, subsequent loads skip this.
699
698
  if (config.memory.embeddings.provider === "auto") {
700
699
  try {
701
700
  if (
702
- (process.env.IS_PLATFORM === "true" ||
703
- process.env.IS_PLATFORM === "1") &&
704
- isManagedGeminiFFEnabled(config)
701
+ process.env.IS_PLATFORM === "true" ||
702
+ process.env.IS_PLATFORM === "1"
705
703
  ) {
706
704
  setNestedValue(fileConfig, "memory.embeddings.provider", "gemini");
707
705
  setNestedValue(
@@ -797,21 +795,6 @@ export function loadConfig(): AssistantConfig {
797
795
  }
798
796
  }
799
797
 
800
- /**
801
- * Check whether the managed-gemini-embeddings-enabled feature flag is on.
802
- * Wrapped in a try/catch so a flag-resolver failure never breaks config loading.
803
- */
804
- function isManagedGeminiFFEnabled(config: AssistantConfig): boolean {
805
- try {
806
- return isAssistantFeatureFlagEnabled(
807
- "managed-gemini-embeddings-enabled",
808
- config,
809
- );
810
- } catch {
811
- return false;
812
- }
813
- }
814
-
815
798
  export function getConfig(): AssistantConfig {
816
799
  return loadConfig();
817
800
  }
@@ -27,6 +27,7 @@ import {
27
27
  WhatsAppConfigSchema,
28
28
  } from "./schemas/channels.js";
29
29
  import { CompactionConfigSchema } from "./schemas/compaction.js";
30
+ import { CompactionLogsConfigSchema } from "./schemas/compaction-logs.js";
30
31
  import { ConversationsConfigSchema } from "./schemas/conversations.js";
31
32
  import { FilingConfigSchema } from "./schemas/filing.js";
32
33
  import { HeartbeatConfigSchema } from "./schemas/heartbeat.js";
@@ -107,6 +108,7 @@ export const AssistantConfigSchema = z
107
108
  compaction: CompactionConfigSchema.default(
108
109
  CompactionConfigSchema.parse({}),
109
110
  ),
111
+ compactionLogs: CompactionLogsConfigSchema,
110
112
  twilio: TwilioConfigSchema.default(TwilioConfigSchema.parse({})),
111
113
  calls: CallsConfigSchema.default(CallsConfigSchema.parse({})),
112
114
  whatsapp: WhatsAppConfigSchema.default(WhatsAppConfigSchema.parse({})),
@@ -0,0 +1,56 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import { CompactionLogsConfigSchema } from "../compaction-logs.js";
4
+
5
+ describe("CompactionLogsConfigSchema", () => {
6
+ test("parses undefined to the disabled default", () => {
7
+ expect(CompactionLogsConfigSchema.parse(undefined)).toEqual({
8
+ destination: "none",
9
+ });
10
+ });
11
+
12
+ test("parses an explicit none destination", () => {
13
+ expect(CompactionLogsConfigSchema.parse({ destination: "none" })).toEqual({
14
+ destination: "none",
15
+ });
16
+ });
17
+
18
+ test("parses an explicit clickhouse destination with defaulted connection fields", () => {
19
+ expect(
20
+ CompactionLogsConfigSchema.parse({ destination: "clickhouse" }),
21
+ ).toEqual({
22
+ destination: "clickhouse",
23
+ clickhouse: {
24
+ database: "default",
25
+ table: "compaction_logs",
26
+ user: "default",
27
+ },
28
+ });
29
+ });
30
+
31
+ test("parses explicit clickhouse connection overrides", () => {
32
+ expect(
33
+ CompactionLogsConfigSchema.parse({
34
+ destination: "clickhouse",
35
+ clickhouse: {
36
+ database: "analytics",
37
+ table: "compactions",
38
+ user: "writer",
39
+ },
40
+ }),
41
+ ).toEqual({
42
+ destination: "clickhouse",
43
+ clickhouse: {
44
+ database: "analytics",
45
+ table: "compactions",
46
+ user: "writer",
47
+ },
48
+ });
49
+ });
50
+
51
+ test("rejects an unknown destination", () => {
52
+ expect(() =>
53
+ CompactionLogsConfigSchema.parse({ destination: "sqlite" }),
54
+ ).toThrow();
55
+ });
56
+ });
@@ -23,7 +23,6 @@ describe("MemoryV2ConfigSchema", () => {
23
23
  bm25_k1: 1.2,
24
24
  bm25_b: 0.4,
25
25
  consolidation_interval_hours: 4,
26
- consolidation_enabled: true,
27
26
  consolidation_max_buffer_lines: 100,
28
27
  max_page_chars: 5000,
29
28
  consolidation_prompt_path: null,
@@ -6,13 +6,73 @@ describe("MemoryV3ConfigSchema", () => {
6
6
  test("parses an empty object to documented defaults", () => {
7
7
  const parsed = MemoryV3ConfigSchema.parse({});
8
8
  expect(parsed).toEqual({
9
- workingSet: { maxPages: 150, evictWindow: 5 },
9
+ prune: { maxResidentBytes: 393216, targetResidentBytes: 262144 },
10
+ hotSet: { k: 40, halfLifeDays: 14 },
11
+ spotlight: { n: 6, windowTurns: 2 },
10
12
  needleK: 100,
11
13
  denseK: 100,
12
14
  edge: { hubDegree: 30, seedCount: 18, perSeed: 6, cap: 45 },
13
15
  });
14
16
  });
15
17
 
18
+ test("accepts and ignores the retired workingSet key from legacy configs", () => {
19
+ // Existing user config files may still carry the removed `workingSet`
20
+ // sub-config; it must parse (unknown-key strip), not throw.
21
+ const parsed = MemoryV3ConfigSchema.parse({
22
+ workingSet: { maxPages: 150, evictWindow: 5 },
23
+ needleK: 50,
24
+ });
25
+ expect(parsed.needleK).toBe(50);
26
+ expect("workingSet" in parsed).toBe(false);
27
+ });
28
+
29
+ test("prune: accepts partial overrides and enforces target < max", () => {
30
+ const parsed = MemoryV3ConfigSchema.parse({
31
+ prune: { maxResidentBytes: 500000 },
32
+ });
33
+ expect(parsed.prune).toEqual({
34
+ maxResidentBytes: 500000,
35
+ targetResidentBytes: 262144,
36
+ });
37
+ // target must be strictly below max (defaults included in the check).
38
+ expect(() =>
39
+ MemoryV3ConfigSchema.parse({
40
+ prune: { maxResidentBytes: 100000 },
41
+ }),
42
+ ).toThrow();
43
+ expect(() =>
44
+ MemoryV3ConfigSchema.parse({
45
+ prune: { maxResidentBytes: 1000, targetResidentBytes: 1000 },
46
+ }),
47
+ ).toThrow();
48
+ expect(() =>
49
+ MemoryV3ConfigSchema.parse({
50
+ prune: { maxResidentBytes: 0 },
51
+ }),
52
+ ).toThrow();
53
+ expect(() =>
54
+ MemoryV3ConfigSchema.parse({
55
+ prune: { targetResidentBytes: 1.5 },
56
+ }),
57
+ ).toThrow();
58
+ });
59
+
60
+ test("accepts a partial spotlight override and rejects invalid knobs", () => {
61
+ const parsed = MemoryV3ConfigSchema.parse({ spotlight: { n: 3 } });
62
+ expect(parsed.spotlight).toEqual({ n: 3, windowTurns: 2 });
63
+ // windowTurns: 0 is valid — current turn only, no carried window.
64
+ expect(
65
+ MemoryV3ConfigSchema.parse({ spotlight: { windowTurns: 0 } }).spotlight,
66
+ ).toEqual({ n: 6, windowTurns: 0 });
67
+ expect(() => MemoryV3ConfigSchema.parse({ spotlight: { n: 0 } })).toThrow();
68
+ expect(() =>
69
+ MemoryV3ConfigSchema.parse({ spotlight: { windowTurns: -1 } }),
70
+ ).toThrow();
71
+ expect(() =>
72
+ MemoryV3ConfigSchema.parse({ spotlight: { n: 1.5 } }),
73
+ ).toThrow();
74
+ });
75
+
16
76
  test("accepts explicit lane-K overrides", () => {
17
77
  const parsed = MemoryV3ConfigSchema.parse({ needleK: 50, denseK: 75 });
18
78
  expect(parsed.needleK).toBe(50);
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Configuration for the compaction log destination.
3
+ *
4
+ * Compaction logging is **off by default** (`destination: "none"`). An
5
+ * assistant can opt into a ClickHouse-only destination; there is no SQLite
6
+ * destination — compaction events are derived from the agent loop's
7
+ * compaction start/end events and written straight to ClickHouse.
8
+ *
9
+ * When `destination === "clickhouse"` the URL and password are resolved
10
+ * from the credential store (`clickhouse:url`, `clickhouse:password`),
11
+ * matching the `llmRequestLogs.clickhouse` convention. The connection
12
+ * options below describe everything else (database/table/user).
13
+ *
14
+ * The shape is a discriminated union on `destination` so the `clickhouse`
15
+ * block only exists on the ClickHouse branch — there's no stray defaults
16
+ * sitting around when logging is disabled.
17
+ */
18
+ import { z } from "zod";
19
+
20
+ export const CompactionLogsClickHouseConfigSchema = z
21
+ .object({
22
+ database: z
23
+ .string({ error: "compactionLogs.clickhouse.database must be a string" })
24
+ .min(1, "compactionLogs.clickhouse.database cannot be empty")
25
+ .default("default")
26
+ .describe("ClickHouse database containing the compaction logs table"),
27
+ table: z
28
+ .string({ error: "compactionLogs.clickhouse.table must be a string" })
29
+ .min(1, "compactionLogs.clickhouse.table cannot be empty")
30
+ .default("compaction_logs")
31
+ .describe("ClickHouse table name to write compaction logs to"),
32
+ user: z
33
+ .string({ error: "compactionLogs.clickhouse.user must be a string" })
34
+ .min(1, "compactionLogs.clickhouse.user cannot be empty")
35
+ .default("default")
36
+ .describe("ClickHouse user (password is read from credential store)"),
37
+ })
38
+ .describe(
39
+ "ClickHouse connection settings used when `destination` is `clickhouse`",
40
+ );
41
+
42
+ const NoneCompactionLogsConfigSchema = z
43
+ .object({
44
+ destination: z.literal("none"),
45
+ })
46
+ .describe("Compaction logging disabled (default).");
47
+
48
+ const ClickHouseCompactionLogsConfigSchema = z
49
+ .object({
50
+ destination: z.literal("clickhouse"),
51
+ clickhouse: CompactionLogsClickHouseConfigSchema.default(
52
+ CompactionLogsClickHouseConfigSchema.parse({}),
53
+ ),
54
+ })
55
+ .describe(
56
+ "Write compaction logs to ClickHouse. Requires the `clickhouse:url` and `clickhouse:password` credentials to be set.",
57
+ );
58
+
59
+ // The default is baked into the export so the schema matches the sibling
60
+ // pattern across `assistant/src/config/schemas/*` — `Schema.parse(undefined)`
61
+ // returns documented defaults. The discriminated union has no inherent
62
+ // default (no shared discriminator value), so we explicitly select the
63
+ // `none` branch.
64
+ //
65
+ // Note: `CompactionLogsConfigSchema.parse({})` still throws — a discriminated
66
+ // union cannot pick a branch without a discriminator. Use `parse(undefined)`
67
+ // or omit the field entirely to get the default.
68
+ export const CompactionLogsConfigSchema = z
69
+ .discriminatedUnion("destination", [
70
+ NoneCompactionLogsConfigSchema,
71
+ ClickHouseCompactionLogsConfigSchema,
72
+ ])
73
+ .default({ destination: "none" })
74
+ .describe("Compaction log destination configuration");
75
+
76
+ export type CompactionLogsConfig = z.infer<typeof CompactionLogsConfigSchema>;
77
+ export type CompactionLogsClickHouseConfig = z.infer<
78
+ typeof CompactionLogsClickHouseConfigSchema
79
+ >;
@@ -194,14 +194,6 @@ export const MemoryV2ConfigSchema = z
194
194
  .describe(
195
195
  "Hours between scheduled consolidation runs that synthesize buffered memories into concept pages",
196
196
  ),
197
- consolidation_enabled: z
198
- .boolean({
199
- error: "memory.v2.consolidation_enabled must be a boolean",
200
- })
201
- .default(true)
202
- .describe(
203
- "Whether automatic scheduled consolidation runs are enabled. Manual run-now requests remain available while memory.v2.enabled is true.",
204
- ),
205
197
  consolidation_max_buffer_lines: z
206
198
  .number({
207
199
  error: "memory.v2.consolidation_max_buffer_lines must be a number",