@vellumai/assistant 0.8.8 → 0.8.9-dev.202606091853.fbaa2ae

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 (475) hide show
  1. package/ARCHITECTURE.md +6 -6
  2. package/bun.lock +2 -2
  3. package/docs/activation-funnel-telemetry.md +310 -0
  4. package/examples/plugins/echo/README.md +61 -60
  5. package/examples/plugins/echo/hooks/post-tool-use.ts +18 -0
  6. package/examples/plugins/echo/hooks/stop.ts +16 -0
  7. package/examples/plugins/echo/hooks/user-prompt-submit.ts +18 -0
  8. package/examples/plugins/echo/package.json +1 -2
  9. package/examples/plugins/echo/src/emit.ts +19 -0
  10. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +7 -6
  11. package/openapi.yaml +263 -121
  12. package/package.json +2 -2
  13. package/src/__tests__/activation-early-marking.test.ts +120 -0
  14. package/src/__tests__/agent-loop-callsite-precedence.test.ts +69 -14
  15. package/src/__tests__/agent-loop-exit-reason.test.ts +204 -144
  16. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +50 -35
  17. package/src/__tests__/agent-loop-output-hooks.test.ts +357 -0
  18. package/src/__tests__/agent-loop-override-profile.test.ts +25 -6
  19. package/src/__tests__/agent-loop-provider-error-recording.test.ts +41 -21
  20. package/src/__tests__/agent-loop-thinking.test.ts +36 -20
  21. package/src/__tests__/agent-loop.test.ts +441 -96
  22. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +14 -14
  23. package/src/__tests__/agent-wake-override-profile.test.ts +17 -21
  24. package/src/__tests__/anthropic-provider.test.ts +23 -8
  25. package/src/__tests__/app-builder-tool-scripts.test.ts +21 -0
  26. package/src/__tests__/app-control-flow.test.ts +1 -1
  27. package/src/__tests__/app-dir-path-guard.test.ts +1 -0
  28. package/src/__tests__/app-executors.test.ts +132 -0
  29. package/src/__tests__/approval-cascade.test.ts +6 -5
  30. package/src/__tests__/approval-routes-http.test.ts +4 -1
  31. package/src/__tests__/background-workers-disk-pressure.test.ts +1 -1
  32. package/src/__tests__/channel-approval-routes.test.ts +1 -1
  33. package/src/__tests__/channel-approvals.test.ts +1 -1
  34. package/src/__tests__/compaction-circuit.test.ts +258 -0
  35. package/src/__tests__/compaction-direct.test.ts +146 -0
  36. package/src/__tests__/compaction-events.test.ts +7 -7
  37. package/src/__tests__/compaction.benchmark.test.ts +1 -1
  38. package/src/__tests__/compactor-web-search-strip.test.ts +213 -0
  39. package/src/__tests__/context-overflow-reducer.test.ts +265 -125
  40. package/src/__tests__/context-window-manager-compact-retry.test.ts +121 -15
  41. package/src/__tests__/conversation-abort-tool-results.test.ts +7 -5
  42. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +7 -10
  43. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +78 -119
  44. package/src/__tests__/conversation-agent-loop-overflow.test.ts +158 -234
  45. package/src/__tests__/conversation-agent-loop.test.ts +342 -623
  46. package/src/__tests__/conversation-clean-command.test.ts +5 -2
  47. package/src/__tests__/conversation-confirmation-signals.test.ts +6 -5
  48. package/src/__tests__/conversation-crud-inference-profile.test.ts +7 -9
  49. package/src/__tests__/conversation-error.test.ts +15 -1
  50. package/src/__tests__/conversation-history-web-search.test.ts +6 -1
  51. package/src/__tests__/conversation-media-retry.test.ts +1 -1
  52. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +44 -4
  53. package/src/__tests__/conversation-process-callsite.test.ts +15 -15
  54. package/src/__tests__/conversation-provider-retry-repair.test.ts +66 -65
  55. package/src/__tests__/conversation-queue.test.ts +10 -10
  56. package/src/__tests__/conversation-runtime-assembly.test.ts +1059 -231
  57. package/src/__tests__/conversation-runtime-workspace.test.ts +115 -20
  58. package/src/__tests__/conversation-slash-queue.test.ts +7 -5
  59. package/src/__tests__/conversation-slash-unknown.test.ts +7 -5
  60. package/src/__tests__/conversation-speed-override.test.ts +11 -10
  61. package/src/__tests__/conversation-starter-routes.test.ts +14 -6
  62. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +395 -0
  63. package/src/__tests__/conversation-surfaces-app-control.test.ts +48 -1
  64. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +73 -4
  65. package/src/__tests__/conversation-undo.test.ts +2 -2
  66. package/src/__tests__/conversation-workspace-cache-state.test.ts +24 -21
  67. package/src/__tests__/conversation-workspace-injection.test.ts +69 -7
  68. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +15 -12
  69. package/src/__tests__/conversations-import-system-filter.test.ts +101 -0
  70. package/src/__tests__/corrected-target.test.ts +93 -0
  71. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  72. package/src/__tests__/cu-unified-flow.test.ts +36 -0
  73. package/src/__tests__/db-acp-history.test.ts +101 -0
  74. package/src/__tests__/dynamic-page-surface.test.ts +31 -0
  75. package/src/__tests__/empty-response-hook.test.ts +1 -1
  76. package/src/__tests__/file-write-tool.test.ts +63 -0
  77. package/src/__tests__/gateway-only-guard.test.ts +17 -2
  78. package/src/__tests__/guardian-grant-minting.test.ts +1 -1
  79. package/src/__tests__/guardian-routing-invariants.test.ts +93 -4
  80. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
  81. package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
  82. package/src/__tests__/heartbeat-service.test.ts +1 -0
  83. package/src/__tests__/history-repair-hook.test.ts +5 -1
  84. package/src/__tests__/host-app-control-proxy.test.ts +45 -0
  85. package/src/__tests__/host-app-control-routes.test.ts +1 -1
  86. package/src/__tests__/host-cu-routes-targeted.test.ts +3 -3
  87. package/src/__tests__/inference-profile-reaper.test.ts +62 -0
  88. package/src/__tests__/inference-profile-session-handler.test.ts +86 -0
  89. package/src/__tests__/injector-background-turn.test.ts +13 -23
  90. package/src/__tests__/injector-chain.test.ts +268 -44
  91. package/src/__tests__/injector-disk-pressure.test.ts +210 -52
  92. package/src/__tests__/injector-document-comments.test.ts +97 -114
  93. package/src/__tests__/injector-pkb-v2-silenced.test.ts +2 -2
  94. package/src/__tests__/injector-v3-suppression.test.ts +4 -4
  95. package/src/__tests__/list-messages-client-message-id.test.ts +91 -0
  96. package/src/__tests__/list-messages-hidden-metadata.test.ts +38 -0
  97. package/src/__tests__/llm-resolver.test.ts +73 -0
  98. package/src/__tests__/memory-retrieval-hook.test.ts +156 -38
  99. package/src/__tests__/memory-v2-static-injector.test.ts +86 -8
  100. package/src/__tests__/notification-decision-strategy.test.ts +3 -3
  101. package/src/__tests__/parallel-tool.benchmark.test.ts +35 -8
  102. package/src/__tests__/persist-unsendable-image-downscale.test.ts +145 -0
  103. package/src/__tests__/persist-unsendable-image.test.ts +97 -1
  104. package/src/__tests__/plugin-api-shim.test.ts +6 -9
  105. package/src/__tests__/plugin-bootstrap.test.ts +91 -81
  106. package/src/__tests__/plugin-registry.test.ts +3 -49
  107. package/src/__tests__/plugin-skill-contribution.test.ts +15 -14
  108. package/src/__tests__/plugin-tool-contribution.test.ts +7 -4
  109. package/src/__tests__/plugin-types.test.ts +0 -70
  110. package/src/__tests__/post-turn-tool-result-truncation.test.ts +69 -0
  111. package/src/__tests__/pre-model-call-sanitize.test.ts +109 -0
  112. package/src/__tests__/published-app-updater.test.ts +138 -0
  113. package/src/__tests__/reaction-persistence.test.ts +1 -1
  114. package/src/__tests__/send-endpoint-busy.test.ts +4 -1
  115. package/src/__tests__/skill-feature-flags-integration.test.ts +31 -0
  116. package/src/__tests__/steer-tool-repair.test.ts +1 -1
  117. package/src/__tests__/subagent-call-site-routing.test.ts +1 -1
  118. package/src/__tests__/subagent-detail.test.ts +25 -7
  119. package/src/__tests__/subagent-fork-notifications.test.ts +1 -3
  120. package/src/__tests__/subagent-fork-spawn.test.ts +1 -1
  121. package/src/__tests__/subagent-manager-notify.test.ts +1 -3
  122. package/src/__tests__/subagent-notify-parent.test.ts +1 -3
  123. package/src/__tests__/subagent-spawn-tool-fork.test.ts +1 -1
  124. package/src/__tests__/title-generate-hook.test.ts +5 -1
  125. package/src/__tests__/tool-error-hook.test.ts +1 -1
  126. package/src/__tests__/tool-result-truncate-hook.test.ts +1 -1
  127. package/src/__tests__/user-plugin-loader.test.ts +54 -286
  128. package/src/__tests__/web-fetch.test.ts +45 -0
  129. package/src/acp/__tests__/agent-process.test.ts +161 -0
  130. package/src/acp/__tests__/client-handler.test.ts +40 -0
  131. package/src/acp/__tests__/helpers/acp-config-stub.ts +0 -2
  132. package/src/acp/__tests__/helpers/acp-history-db.ts +82 -0
  133. package/src/acp/__tests__/helpers/exec-file-stub.ts +106 -0
  134. package/src/acp/__tests__/prepare-agent-env.test.ts +97 -0
  135. package/src/acp/__tests__/session-manager-persistence.test.ts +95 -28
  136. package/src/acp/__tests__/session-manager-resume.test.ts +888 -0
  137. package/src/acp/agent-process.ts +61 -1
  138. package/src/acp/auto-install.test.ts +280 -0
  139. package/src/acp/auto-install.ts +232 -0
  140. package/src/acp/client-handler.ts +31 -0
  141. package/src/acp/prepare-agent-env.ts +80 -27
  142. package/src/acp/resolve-agent.test.ts +188 -28
  143. package/src/acp/resolve-agent.ts +119 -42
  144. package/src/acp/resume-hint.ts +23 -0
  145. package/src/acp/session-manager.ts +507 -73
  146. package/src/agent/compaction-circuit.ts +60 -102
  147. package/src/agent/loop.ts +403 -251
  148. package/src/api/responses/conversation-message.ts +22 -2
  149. package/src/api/responses/memory-v3-selection-log.ts +19 -10
  150. package/src/approvals/guardian-request-resolvers.ts +27 -1
  151. package/src/background-wake/next-wake.ts +1 -0
  152. package/src/cli/commands/__tests__/memory-v3.test.ts +191 -210
  153. package/src/cli/commands/channel-verification-sessions.ts +6 -6
  154. package/src/cli/commands/db/__tests__/repair.test.ts +3 -1
  155. package/src/cli/commands/memory-v3.ts +57 -199
  156. package/src/cli/commands/plugins.ts +43 -37
  157. package/src/cli/lib/__tests__/install-from-github.test.ts +790 -111
  158. package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +196 -0
  159. package/src/cli/lib/__tests__/plugin-details.test.ts +381 -0
  160. package/src/cli/lib/__tests__/plugin-marketplace.test.ts +270 -0
  161. package/src/cli/lib/__tests__/search-plugins.test.ts +233 -32
  162. package/src/cli/lib/install-from-github.ts +797 -60
  163. package/src/cli/lib/plugin-catalog-cache.ts +84 -0
  164. package/src/cli/lib/plugin-details.ts +416 -0
  165. package/src/cli/lib/plugin-marketplace.ts +215 -0
  166. package/src/cli/lib/search-plugins.ts +201 -29
  167. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  168. package/src/config/acp-defaults.test.ts +10 -0
  169. package/src/config/acp-defaults.ts +9 -3
  170. package/src/config/acp-schema.ts +1 -7
  171. package/src/config/bundled-skills/acp/SKILL.md +80 -41
  172. package/src/config/bundled-skills/acp/TOOLS.json +4 -4
  173. package/src/config/bundled-skills/app-builder/SKILL.md +224 -381
  174. package/src/config/bundled-skills/app-builder/TOOLS.json +72 -2
  175. package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +48 -0
  176. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +57 -0
  177. package/src/config/bundled-skills/app-builder/references/SLIDES.md +38 -0
  178. package/src/config/bundled-skills/app-builder/tools/app-list.ts +62 -0
  179. package/src/config/bundled-skills/app-builder/tools/app-update.ts +18 -0
  180. package/src/config/bundled-skills/document-editor/SKILL.md +28 -23
  181. package/src/config/bundled-skills/document-editor/TOOLS.json +1 -1
  182. package/src/config/bundled-tool-registry.ts +4 -0
  183. package/src/config/call-site-defaults.ts +0 -3
  184. package/src/config/feature-flag-registry.json +10 -16
  185. package/src/config/llm-resolver.ts +39 -7
  186. package/src/config/schemas/__tests__/memory-v3.test.ts +25 -9
  187. package/src/config/schemas/call-site-catalog.ts +0 -21
  188. package/src/config/schemas/heartbeat.ts +9 -0
  189. package/src/config/schemas/llm.ts +17 -3
  190. package/src/config/schemas/memory-v3.ts +58 -8
  191. package/src/config/seed-inference-profiles.ts +18 -0
  192. package/src/context/compactor.ts +22 -4
  193. package/src/context/post-turn-tool-result-truncation.ts +39 -1
  194. package/src/context/strip-injections.ts +8 -2
  195. package/src/daemon/conversation-agent-loop-handlers.ts +18 -36
  196. package/src/daemon/conversation-agent-loop.ts +308 -1297
  197. package/src/daemon/conversation-error.ts +31 -4
  198. package/src/daemon/conversation-history.ts +1 -1
  199. package/src/daemon/conversation-lifecycle.ts +11 -255
  200. package/src/daemon/conversation-media-retry.ts +19 -6
  201. package/src/daemon/conversation-messaging.ts +17 -0
  202. package/src/daemon/conversation-process.ts +22 -141
  203. package/src/daemon/conversation-queue-manager.ts +8 -0
  204. package/src/daemon/conversation-registry.ts +159 -0
  205. package/src/daemon/conversation-runtime-assembly.ts +361 -393
  206. package/src/daemon/conversation-store.ts +9 -90
  207. package/src/daemon/conversation-surfaces.ts +165 -11
  208. package/src/daemon/conversation-workspace.ts +17 -0
  209. package/src/daemon/conversation.ts +444 -62
  210. package/src/daemon/disk-pressure-policy.ts +0 -1
  211. package/src/daemon/external-plugins-bootstrap.ts +36 -46
  212. package/src/daemon/handlers/config-channels.ts +11 -2
  213. package/src/daemon/handlers/conversations.ts +3 -1
  214. package/src/daemon/handlers/skills.ts +4 -1
  215. package/src/daemon/host-app-control-proxy.ts +72 -57
  216. package/src/daemon/host-proxy-preactivation.ts +1 -3
  217. package/src/daemon/lifecycle.ts +21 -7
  218. package/src/daemon/persist-unsendable-image.ts +62 -25
  219. package/src/daemon/process-message.ts +1 -1
  220. package/src/daemon/server.ts +2 -0
  221. package/src/daemon/tool-side-effects.ts +15 -0
  222. package/src/daemon/wake-conversation-ops.ts +269 -0
  223. package/src/embedded/plugin-api.ts +2 -2
  224. package/src/export/__tests__/transcript-formatter.test.ts +5 -0
  225. package/src/heartbeat/__tests__/heartbeat-service.test.ts +3 -0
  226. package/src/heartbeat/heartbeat-run-store.ts +23 -1
  227. package/src/heartbeat/heartbeat-service.ts +26 -0
  228. package/src/ipc/__tests__/browser-ipc.test.ts +1 -1
  229. package/src/ipc/__tests__/ui-request-route.test.ts +3 -3
  230. package/src/ipc/skill-routes/__tests__/memory.test.ts +15 -0
  231. package/src/ipc/skill-routes/memory.ts +4 -2
  232. package/src/memory/__tests__/activation-session-store.test.ts +41 -0
  233. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +87 -0
  234. package/src/memory/__tests__/onboarding-events-store.test.ts +80 -0
  235. package/src/memory/activation-session-store.ts +43 -0
  236. package/src/memory/conversation-crud.ts +29 -19
  237. package/src/memory/conversation-starter-checkpoints.ts +1 -0
  238. package/src/memory/db-init.ts +6 -0
  239. package/src/memory/job-handlers/conversation-starters.ts +13 -2
  240. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -4
  241. package/src/memory/jobs-worker.ts +25 -1
  242. package/src/memory/migrations/272-acp-session-history-cwd.ts +36 -0
  243. package/src/memory/migrations/273-onboarding-events-funnel-columns.ts +46 -0
  244. package/src/memory/migrations/274-create-activation-sessions.ts +15 -0
  245. package/src/memory/migrations/index.ts +3 -0
  246. package/src/memory/onboarding-events-store.ts +66 -18
  247. package/src/memory/schema/acp.ts +4 -0
  248. package/src/memory/schema/infrastructure.ts +13 -0
  249. package/src/memory/v2/__tests__/consolidation-job.test.ts +4 -97
  250. package/src/memory/v2/__tests__/page-store.test.ts +22 -0
  251. package/src/memory/v2/consolidation-job.ts +2 -63
  252. package/src/memory/v2/types.ts +5 -0
  253. package/src/messaging/providers/telegram-bot/api.ts +14 -5
  254. package/src/notifications/__tests__/copy-composer.test.ts +244 -0
  255. package/src/notifications/access-request-copy.ts +298 -0
  256. package/src/notifications/adapters/slack.ts +3 -3
  257. package/src/notifications/adapters/telegram.ts +9 -2
  258. package/src/notifications/copy-composer.ts +49 -267
  259. package/src/notifications/decision-engine.ts +16 -35
  260. package/src/notifications/home-feed-side-effect.ts +1 -6
  261. package/src/plugin-api/constants.ts +4 -0
  262. package/src/plugin-api/index.ts +40 -11
  263. package/src/plugin-api/types.ts +108 -0
  264. package/src/plugins/defaults/compaction/compact.ts +106 -0
  265. package/src/{daemon → plugins/defaults/compaction}/context-overflow-reducer.ts +250 -42
  266. package/src/plugins/defaults/compaction/corrected-target.ts +53 -0
  267. package/src/plugins/defaults/compaction/manager-store.ts +57 -0
  268. package/src/plugins/defaults/compaction/package.json +1 -2
  269. package/src/{context → plugins/defaults/compaction}/window-manager.ts +95 -25
  270. package/src/plugins/defaults/empty-response/package.json +0 -1
  271. package/src/plugins/defaults/history-repair/package.json +0 -1
  272. package/src/plugins/defaults/index.ts +156 -26
  273. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +100 -52
  274. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +285 -0
  275. package/src/plugins/defaults/memory-retrieval/injector-chain.ts +2 -2
  276. package/src/plugins/defaults/{injectors/register.ts → memory-retrieval/injectors.ts} +148 -73
  277. package/src/plugins/defaults/memory-retrieval/package.json +14 -0
  278. package/src/plugins/defaults/memory-retrieval/unified-turn-context.ts +223 -0
  279. package/src/plugins/defaults/memory-v3-shadow/__tests__/capabilities.test.ts +71 -0
  280. package/src/plugins/defaults/memory-v3-shadow/__tests__/dense.test.ts +181 -0
  281. package/src/plugins/defaults/memory-v3-shadow/__tests__/edge.test.ts +247 -0
  282. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/live-integration.test.ts +147 -134
  283. package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +456 -0
  284. package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +662 -0
  285. package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +306 -0
  286. package/src/plugins/defaults/memory-v3-shadow/__tests__/render-injection.test.ts +91 -0
  287. package/src/plugins/defaults/memory-v3-shadow/__tests__/section-dense-store.test.ts +402 -0
  288. package/src/plugins/defaults/memory-v3-shadow/__tests__/section-needle.test.ts +135 -0
  289. package/src/plugins/defaults/memory-v3-shadow/__tests__/sections.test.ts +125 -0
  290. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selection-log-store.test.ts +74 -19
  291. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +446 -0
  292. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +592 -0
  293. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/types.test.ts +2 -24
  294. package/src/plugins/defaults/memory-v3-shadow/capabilities.ts +91 -0
  295. package/src/plugins/defaults/memory-v3-shadow/dense.ts +97 -0
  296. package/src/plugins/defaults/memory-v3-shadow/edge.ts +252 -0
  297. package/src/plugins/defaults/memory-v3-shadow/hooks/post-compact.ts +14 -0
  298. package/src/plugins/defaults/memory-v3-shadow/hooks/user-prompt-submit.ts +19 -0
  299. package/src/plugins/defaults/memory-v3-shadow/injector.ts +76 -0
  300. package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +555 -0
  301. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +266 -0
  302. package/src/plugins/defaults/memory-v3-shadow/package.json +14 -0
  303. package/src/plugins/defaults/memory-v3-shadow/page-content.ts +71 -0
  304. package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +204 -0
  305. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/render-injection.ts +16 -8
  306. package/src/plugins/defaults/memory-v3-shadow/section-dense-store.ts +236 -0
  307. package/src/plugins/defaults/memory-v3-shadow/section-needle.ts +200 -0
  308. package/src/plugins/defaults/memory-v3-shadow/sections.ts +115 -0
  309. package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +156 -0
  310. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +382 -0
  311. package/src/plugins/defaults/memory-v3-shadow/types.ts +92 -0
  312. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/working-set.ts +4 -1
  313. package/src/plugins/defaults/title-generate/package.json +0 -1
  314. package/src/plugins/defaults/tool-error/package.json +0 -1
  315. package/src/plugins/defaults/tool-result-truncate/package.json +0 -1
  316. package/src/plugins/external-api.ts +12 -2
  317. package/src/plugins/pipeline.ts +6 -293
  318. package/src/plugins/registry.ts +9 -37
  319. package/src/plugins/types.ts +76 -381
  320. package/src/plugins/user-loader.ts +30 -127
  321. package/src/prompts/__tests__/system-prompt.test.ts +6 -0
  322. package/src/prompts/system-prompt.ts +61 -10
  323. package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +71 -4
  324. package/src/providers/anthropic/client.ts +9 -10
  325. package/src/providers/inference/kimi-cjk-token-ids.ts +493 -0
  326. package/src/providers/inference/logit-bias.ts +55 -0
  327. package/src/providers/model-catalog.ts +34 -0
  328. package/src/providers/openai/__tests__/vision-not-supported.test.ts +75 -0
  329. package/src/providers/openai/chat-completions-provider.ts +44 -1
  330. package/src/providers/retry.ts +22 -0
  331. package/src/providers/types.ts +6 -0
  332. package/src/runtime/__tests__/agent-wake.test.ts +555 -691
  333. package/src/runtime/__tests__/interactive-ui.test.ts +1 -1
  334. package/src/runtime/agent-wake.ts +108 -209
  335. package/src/runtime/assistant-event-hub.ts +1 -1
  336. package/src/runtime/channel-approvals.ts +1 -1
  337. package/src/runtime/interactive-ui.ts +1 -1
  338. package/src/runtime/routes/__tests__/acp-routes.test.ts +466 -55
  339. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
  340. package/src/runtime/routes/__tests__/plugins-routes.test.ts +423 -73
  341. package/src/runtime/routes/__tests__/stt-routes.test.ts +112 -0
  342. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +5 -4
  343. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +4 -1
  344. package/src/runtime/routes/acp-routes.test.ts +185 -32
  345. package/src/runtime/routes/acp-routes.ts +328 -30
  346. package/src/runtime/routes/app-management-routes.ts +3 -0
  347. package/src/runtime/routes/approval-routes.ts +1 -1
  348. package/src/runtime/routes/browser-routes.ts +1 -1
  349. package/src/runtime/routes/browser-tabs-routes.ts +6 -10
  350. package/src/runtime/routes/channel-verification-routes.ts +14 -5
  351. package/src/runtime/routes/conversation-cli-routes.ts +1 -1
  352. package/src/runtime/routes/conversation-list-routes.ts +1 -1
  353. package/src/runtime/routes/conversation-query-routes.ts +1 -1
  354. package/src/runtime/routes/conversation-routes.ts +30 -2
  355. package/src/runtime/routes/conversation-starter-routes.ts +13 -7
  356. package/src/runtime/routes/conversations-import-routes.ts +24 -7
  357. package/src/runtime/routes/host-app-control-routes.ts +1 -1
  358. package/src/runtime/routes/host-cu-routes.ts +1 -1
  359. package/src/runtime/routes/identity-routes.ts +18 -3
  360. package/src/runtime/routes/inbound-message-handler.ts +1 -1
  361. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +33 -34
  362. package/src/runtime/routes/inference-profile-session-handler.ts +11 -0
  363. package/src/runtime/routes/inference-profile-session-reaper.ts +6 -0
  364. package/src/runtime/routes/memory-v3-routes.ts +65 -305
  365. package/src/runtime/routes/playground/__tests__/force-compact.test.ts +1 -1
  366. package/src/runtime/routes/playground/helpers.ts +1 -1
  367. package/src/runtime/routes/plugins-routes.ts +337 -35
  368. package/src/runtime/routes/stt-routes.ts +45 -12
  369. package/src/runtime/routes/surface-conversation-resolver.ts +4 -3
  370. package/src/runtime/routes/work-items-routes.ts +2 -4
  371. package/src/runtime/routes/workspace-routes.ts +50 -15
  372. package/src/runtime/services/conversation-serializer.ts +1 -1
  373. package/src/runtime/verification-outbound-actions.ts +147 -2
  374. package/src/runtime/verification-templates.ts +29 -3
  375. package/src/services/published-app-updater.ts +30 -8
  376. package/src/signals/cancel.ts +2 -4
  377. package/src/subagent/manager.ts +21 -5
  378. package/src/telemetry/__tests__/activation-funnel.test.ts +95 -0
  379. package/src/telemetry/activation-funnel.ts +167 -0
  380. package/src/telemetry/types.ts +13 -0
  381. package/src/telemetry/usage-telemetry-reporter.test.ts +154 -0
  382. package/src/telemetry/usage-telemetry-reporter.ts +26 -1
  383. package/src/tools/acp/context.ts +20 -0
  384. package/src/tools/acp/list-agents.test.ts +9 -19
  385. package/src/tools/acp/list-agents.ts +3 -15
  386. package/src/tools/acp/spawn.test.ts +173 -202
  387. package/src/tools/acp/spawn.ts +37 -172
  388. package/src/tools/acp/steer.test.ts +105 -8
  389. package/src/tools/acp/steer.ts +48 -17
  390. package/src/tools/apps/executors.ts +166 -50
  391. package/src/tools/browser/browser-execution.ts +12 -2
  392. package/src/tools/filesystem/write.ts +34 -0
  393. package/src/tools/network/web-fetch.ts +65 -24
  394. package/src/tools/skills/load.ts +1 -1
  395. package/src/tools/subagent/spawn.ts +2 -4
  396. package/src/tools/ui-surface/definitions.ts +32 -5
  397. package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +4 -5
  398. package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +69 -45
  399. package/docs/plugins.md +0 -832
  400. package/examples/plugins/echo/register.ts +0 -143
  401. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -405
  402. package/src/__tests__/compaction-pipeline.test.ts +0 -210
  403. package/src/__tests__/compaction-timeout-recovery.test.ts +0 -251
  404. package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -667
  405. package/src/__tests__/pipeline-runner.test.ts +0 -554
  406. package/src/daemon/wake-target-adapter.ts +0 -253
  407. package/src/memory/v3/__tests__/assign.test.ts +0 -242
  408. package/src/memory/v3/__tests__/capabilities.test.ts +0 -118
  409. package/src/memory/v3/__tests__/core.test.ts +0 -39
  410. package/src/memory/v3/__tests__/health.test.ts +0 -219
  411. package/src/memory/v3/__tests__/maintain-job.test.ts +0 -288
  412. package/src/memory/v3/__tests__/needle.test.ts +0 -107
  413. package/src/memory/v3/__tests__/orchestrate.test.ts +0 -436
  414. package/src/memory/v3/__tests__/provider-blocks.test.ts +0 -13
  415. package/src/memory/v3/__tests__/reconcile.test.ts +0 -274
  416. package/src/memory/v3/__tests__/render-injection.test.ts +0 -61
  417. package/src/memory/v3/__tests__/router.test.ts +0 -332
  418. package/src/memory/v3/__tests__/selector.test.ts +0 -470
  419. package/src/memory/v3/__tests__/shadow-plugin.test.ts +0 -432
  420. package/src/memory/v3/__tests__/snapshot.test.ts +0 -168
  421. package/src/memory/v3/__tests__/tree.test.ts +0 -192
  422. package/src/memory/v3/assign.ts +0 -268
  423. package/src/memory/v3/capabilities.ts +0 -124
  424. package/src/memory/v3/core.ts +0 -26
  425. package/src/memory/v3/health.ts +0 -0
  426. package/src/memory/v3/maintain-job.ts +0 -314
  427. package/src/memory/v3/needle.ts +0 -115
  428. package/src/memory/v3/orchestrate.ts +0 -126
  429. package/src/memory/v3/page-content.ts +0 -34
  430. package/src/memory/v3/provider-blocks.ts +0 -26
  431. package/src/memory/v3/reconcile.ts +0 -523
  432. package/src/memory/v3/router.ts +0 -190
  433. package/src/memory/v3/selection-log-store.ts +0 -84
  434. package/src/memory/v3/selector.ts +0 -226
  435. package/src/memory/v3/shadow-plugin.ts +0 -411
  436. package/src/memory/v3/snapshot.ts +0 -209
  437. package/src/memory/v3/tree.ts +0 -174
  438. package/src/memory/v3/types.ts +0 -59
  439. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +0 -187
  440. package/src/plugins/defaults/circuit-breaker/middlewares/circuitBreaker.ts +0 -93
  441. package/src/plugins/defaults/circuit-breaker/package.json +0 -15
  442. package/src/plugins/defaults/circuit-breaker/register.ts +0 -39
  443. package/src/plugins/defaults/compaction/middlewares/compaction.ts +0 -25
  444. package/src/plugins/defaults/compaction/register.ts +0 -35
  445. package/src/plugins/defaults/compaction/terminal.ts +0 -73
  446. package/src/plugins/defaults/empty-response/register.ts +0 -23
  447. package/src/plugins/defaults/history-repair/register.ts +0 -24
  448. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +0 -216
  449. package/src/plugins/defaults/overflow-reduce/middlewares/overflowReduce.ts +0 -126
  450. package/src/plugins/defaults/overflow-reduce/package.json +0 -15
  451. package/src/plugins/defaults/overflow-reduce/register.ts +0 -42
  452. package/src/plugins/defaults/title-generate/register.ts +0 -35
  453. package/src/plugins/defaults/tool-error/register.ts +0 -23
  454. package/src/plugins/defaults/tool-result-truncate/register.ts +0 -24
  455. package/src/proactive-artifact/aux-message-injector.ts +0 -97
  456. package/src/proactive-artifact/decision.test.ts +0 -226
  457. package/src/proactive-artifact/decision.ts +0 -165
  458. package/src/proactive-artifact/index.ts +0 -7
  459. package/src/proactive-artifact/job.test.ts +0 -962
  460. package/src/proactive-artifact/job.ts +0 -372
  461. package/src/proactive-artifact/message-copy.ts +0 -58
  462. package/src/proactive-artifact/trigger-state.test.ts +0 -286
  463. package/src/proactive-artifact/trigger-state.ts +0 -123
  464. package/src/util/map-limit.ts +0 -27
  465. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/eval-turns.json +0 -0
  466. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/live-turns.json +0 -0
  467. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-eviction.test.ts +0 -0
  468. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-skeleton.test.ts +0 -0
  469. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/README.md +0 -0
  470. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/assignments.json +0 -0
  471. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/core.json +0 -0
  472. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-x.md +0 -0
  473. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-y.md +0 -0
  474. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-b/topic-z.md +0 -0
  475. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/llm-retry.ts +0 -0
@@ -11,7 +11,7 @@
11
11
  "properties": {
12
12
  "name": {
13
13
  "type": "string",
14
- "description": "Name of the app"
14
+ "description": "Optional name of the app. When omitted, defaults to the preview card title (or \"New App\" if there is none); rename later via app_update."
15
15
  },
16
16
  "description": {
17
17
  "type": "string",
@@ -74,13 +74,65 @@
74
74
  "change_summary": {
75
75
  "type": "string",
76
76
  "description": "Short summary of what changed, using git conventional commit format (e.g. 'feat: add coin flip app', 'fix: correct button alignment'). Used as the version history entry."
77
+ },
78
+ "icon": {
79
+ "type": "string",
80
+ "description": "Lenient alias. Prefer preview.icon. An emoji or image URL passed here is folded into preview.icon automatically."
81
+ },
82
+ "html": {
83
+ "type": "string",
84
+ "description": "Lenient alias. Prefer source_files. Raw HTML passed here is folded into source_files['src/index.html'] automatically."
85
+ },
86
+ "pages": {
87
+ "description": "Retired. Multi-page apps route inside the Preact app under src/components/. Passing this returns a guidance error."
77
88
  }
78
89
  },
79
- "required": ["name"]
90
+ "required": []
80
91
  },
81
92
  "executor": "tools/app-create.ts",
82
93
  "execution_target": "host"
83
94
  },
95
+ {
96
+ "name": "app_update",
97
+ "description": "Update an existing app: change its name, description, or schema, and/or rewrite source files, then recompile. Use this to iterate on an app you already created instead of calling app_create again (which would make a duplicate). Resolve the app_id with app_list first if you don't have it.",
98
+ "category": "apps",
99
+ "risk": "low",
100
+ "input_schema": {
101
+ "type": "object",
102
+ "properties": {
103
+ "app_id": {
104
+ "type": "string",
105
+ "description": "The ID of the app to update"
106
+ },
107
+ "name": {
108
+ "type": "string",
109
+ "description": "New name for the app. Omit to leave the name unchanged."
110
+ },
111
+ "description": {
112
+ "type": "string",
113
+ "description": "New description for the app. Omit to leave the description unchanged."
114
+ },
115
+ "schema_json": {
116
+ "type": "string",
117
+ "description": "New JSON schema for the app data structure. Omit to leave the schema unchanged."
118
+ },
119
+ "source_files": {
120
+ "type": "object",
121
+ "description": "Map of relative file paths to file contents to write under the app directory (e.g. 'src/main.tsx', 'src/components/App.tsx', 'src/styles.css'). Supply changed source here instead of separate file_write calls. The app is recompiled after writing.",
122
+ "additionalProperties": {
123
+ "type": "string"
124
+ }
125
+ },
126
+ "change_summary": {
127
+ "type": "string",
128
+ "description": "Short summary of what changed, using git conventional commit format (e.g. 'fix: correct totals', 'feat: add dark mode'). Used as the version history entry."
129
+ }
130
+ },
131
+ "required": ["app_id"]
132
+ },
133
+ "executor": "tools/app-update.ts",
134
+ "execution_target": "host"
135
+ },
84
136
  {
85
137
  "name": "app_delete",
86
138
  "description": "Delete a persistent app and all its records.",
@@ -150,6 +202,24 @@
150
202
  },
151
203
  "executor": "tools/app-generate-icon.ts",
152
204
  "execution_target": "host"
205
+ },
206
+ {
207
+ "name": "app_list",
208
+ "description": "List the persistent apps the user has built, returning each app's app_id, name, description, and timestamps (most recently updated first). Pass `query` to resolve an app the user mentions by name to its app_id before calling app_open. Use this whenever the user refers to an existing app and you don't already have its app_id in context.",
209
+ "category": "apps",
210
+ "risk": "low",
211
+ "input_schema": {
212
+ "type": "object",
213
+ "properties": {
214
+ "query": {
215
+ "type": "string",
216
+ "description": "Optional name (or partial name) the user mentioned. When provided, only matching apps are returned: an exact case-insensitive name match if one exists, otherwise substring matches in either direction (e.g. 'habit tracker' resolves 'Habit Tracker'). Omit to list all apps."
217
+ }
218
+ },
219
+ "required": []
220
+ },
221
+ "executor": "tools/app-list.ts",
222
+ "execution_target": "host"
153
223
  }
154
224
  ]
155
225
  }
@@ -0,0 +1,48 @@
1
+ # Design System
2
+
3
+ A design system CSS is auto-injected inside a `@layer`, so your styles always take priority. It provides element defaults and automatic light/dark mode switching via `prefers-color-scheme`.
4
+
5
+ **Use `--v-*` variables and `.v-*` classes** — they handle light/dark mode automatically. No manual dark mode CSS needed.
6
+
7
+ ---
8
+
9
+ ## Design tokens
10
+
11
+ | Category | Tokens |
12
+ | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
13
+ | **Backgrounds** | `--v-bg`, `--v-surface`, `--v-surface-border` |
14
+ | **Text** | `--v-text`, `--v-text-secondary`, `--v-text-muted` |
15
+ | **Accent** | `--v-accent`, `--v-accent-hover` |
16
+ | **Status** | `--v-success`, `--v-danger`, `--v-warning` |
17
+ | **Spacing** | `--v-spacing-xxs` (2px) / `-xs` (4px) / `-sm` (8px) / `-md` (12px) / `-lg` (16px) / `-xl` (24px) / `-xxl` (32px) / `-xxxl` (48px) |
18
+ | **Radius** | `--v-radius-xs` (2px) / `-sm` (4px) / `-md` (8px) / `-lg` (12px) / `-xl` (16px) / `-pill` (999px) |
19
+ | **Shadows** | `--v-shadow-sm`, `--v-shadow-md`, `--v-shadow-lg` |
20
+ | **Typography** | `--v-font-family`, `--v-font-mono`, `--v-font-size-xs` (10px) / `-sm` (11px) / `-base` (14px) / `-lg` (17px) / `-xl` (22px) / `-2xl` (26px), `--v-line-height` |
21
+ | **Animation** | `--v-duration-fast` (0.15s) / `-standard` (0.25s) / `-slow` (0.4s) |
22
+ | **Palettes** | `--v-slate-{950..50}`, `--v-emerald-*`, `--v-violet-*`, `--v-indigo-*`, `--v-rose-*`, `--v-amber-*` |
23
+ | **Constant** | `--v-aux-white` (always `#FFFFFF` in both modes — use for text on filled/accent backgrounds) |
24
+
25
+ ---
26
+
27
+ ## Utility classes
28
+
29
+ `.v-button` (`.secondary` / `.danger` / `.ghost`), `.v-card`, `.v-list` / `.v-list-item`, `.v-badge` (`.success` / `.warning` / `.danger`), `.v-input-row`, `.v-empty-state`, `.v-toggle`.
30
+
31
+ ⚠️ **Never hardcode `color: white` or `color: #fff`.** Use `var(--v-aux-white)` for text on filled/accent backgrounds, or `var(--v-text)` / `var(--v-text-secondary)` for text on surface backgrounds. Hardcoded white causes invisible text on light surfaces.
32
+
33
+ ---
34
+
35
+ ## Custom themes
36
+
37
+ When the user wants a specific branded look, write complete CSS with hardcoded colors and `@media (prefers-color-scheme: dark)` for dark variants. Don't mix `--v-*` auto-switching variables with hardcoded colors in the same element.
38
+
39
+ ---
40
+
41
+ ## Theme detection in JavaScript
42
+
43
+ ```javascript
44
+ console.log(window.vellum.theme.mode); // 'light' or 'dark'
45
+ window.addEventListener("vellum-theme-change", (e) => {
46
+ console.log("Theme:", e.detail.mode);
47
+ });
48
+ ```
@@ -0,0 +1,57 @@
1
+ # Responsive Baseline & Mobile-First Mode
2
+
3
+ Every app must work across phone (~360px) to desktop (~1400px+).
4
+
5
+ ## Mode selection
6
+
7
+ The conversation context's `<turn_context>` block carries an `interface:` field.
8
+
9
+ **If `interface: ios`** (or any future mobile-web / android identifier):
10
+ → Mobile-first build. Design the narrow viewport first, enhance upward.
11
+
12
+ **If `interface: macos` or `web`**:
13
+ → Desktop-first build. Design larger composition first; narrow fallback still meets the universal baseline below.
14
+
15
+ **If field is absent or ambiguous**:
16
+ → Default to desktop-first unless the request implies phone use ("for my iPhone", "a tap-tracker I'll use on the go").
17
+
18
+ ---
19
+
20
+ ## Universal baseline (every build, regardless of interface)
21
+
22
+ ### Viewport & safe areas
23
+
24
+ - Set viewport meta: `<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">`. Never set `user-scalable=no` — it blocks accessibility zoom.
25
+ - Pad the root container with `env(safe-area-inset-*)` so content clears the notch: `padding-top: max(var(--v-spacing-lg), env(safe-area-inset-top))`, mirrored for `-bottom` / `-left` / `-right`.
26
+ - Use `100dvh` (dynamic viewport height), not `100vh`, for full-height containers.
27
+
28
+ ### Form controls
29
+
30
+ - `<input>`, `<textarea>`, `<select>` must be `font-size: 16px` or larger, or iOS Safari will zoom on focus and break the layout. This applies to every build.
31
+ - Add `inputmode` to text fields with structured input: `numeric` for integers, `decimal` for amounts, `email`, `tel`, `url`.
32
+
33
+ ### Touch & hover
34
+
35
+ - Interactive elements must be ≥44×44pt. `.v-button` already meets this; for custom controls, set `min-height: 44px` explicitly.
36
+ - Gate hover affordances behind `@media (hover: hover)` so they don't stick on touch devices.
37
+ - Disable text selection on app chrome with `user-select: none; -webkit-user-select: none`.
38
+
39
+ ### Layout fluidity
40
+
41
+ - Use fluid widths only. No fixed-pixel layouts. Prefer `%`, `fr`, `minmax`, `clamp()` over `px` on container widths.
42
+ - At narrow widths, collapse tables into stacked cards with labels and values arranged vertically.
43
+ - Size `vellum.widgets.*` chart containers in `vw` / `%`, not fixed `px`.
44
+
45
+ ---
46
+
47
+ ## Mobile-first priorities (`interface: ios`)
48
+
49
+ - Default body text to `--v-font-size-lg` (17px), not `--v-font-size-base` (14px).
50
+ - Bump default vertical rhythm one step (e.g. `--v-spacing-md` → `--v-spacing-lg`).
51
+ - One column as the default, not a fallback. Opt into multi-column only above `@media (min-width: 720px)`.
52
+ - Bottom-anchor the primary action: `position: sticky; bottom: env(safe-area-inset-bottom)`.
53
+ - Replace side modals and popovers with bottom sheets.
54
+
55
+ ## Desktop-first priorities (`interface: macos` / `web`)
56
+
57
+ Multi-column composition, hover-rich affordances, denser information, side modals, inline primary actions. The universal baseline above is still the floor — narrow view must still work.
@@ -0,0 +1,38 @@
1
+ # Presentation Slide Design
2
+
3
+ Slides are a different domain from apps. Skip app-specific patterns (contextual headers, search/filter, toast notifications, form validation, custom routes). Slides are static content — build navigation and layouts with custom HTML/CSS.
4
+
5
+ ## Key principles
6
+
7
+ - One idea per slide — understood in 3 seconds
8
+ - Layout variety — 3+ different types per deck, never consecutive same-type
9
+ - 8 layout types: Title, Stats, Bullets, Quote, Comparison, Timeline, Visual/Immersive, Closing/CTA
10
+ - Bold backgrounds — dark, gradient, or strongly tinted
11
+ - Max 6 bullets per slide, max 3 sentences body text
12
+ - Never go below 15px for any visible text
13
+
14
+ ## Navigation
15
+
16
+ Build slide navigation as your own component. Common patterns:
17
+ - Keyboard: `ArrowLeft` / `ArrowRight` / `Space` / `Escape`
18
+ - Click affordances at left/right edges
19
+ - Slide counter pill in a corner (e.g. `3 / 12`)
20
+ - Optional progress bar at the top
21
+
22
+ ## Layout templates
23
+
24
+ - **Title** — Centered headline, optional subtitle, no body. Full-bleed background or gradient.
25
+ - **Stats** — One huge number, label below, supporting paragraph optional.
26
+ - **Bullets** — Heading + 3–6 short bullets. Avoid wall-of-text.
27
+ - **Quote** — Pull quote in large italic type, attribution below, contrasting background.
28
+ - **Comparison** — Two columns (before/after, us/them, problem/solution). Visual symmetry matters.
29
+ - **Timeline** — Horizontal or vertical sequence with dates and milestones.
30
+ - **Visual/Immersive** — Full-bleed image, gradient, or generated graphic with minimal text overlay.
31
+ - **Closing/CTA** — Headline + single call to action. Mirror the title slide aesthetic.
32
+
33
+ ## What to avoid
34
+
35
+ - Generic Keynote / PowerPoint aesthetic (default white background, sans-serif body, bullet lists everywhere)
36
+ - Tiny text below 15px — slides are read across rooms
37
+ - Same layout type used 3+ times in a row — vary the rhythm
38
+ - Body paragraphs longer than 3 sentences — split into multiple slides
@@ -0,0 +1,62 @@
1
+ import * as appStore from "../../../../memory/app-store.js";
2
+ import type {
3
+ ToolContext,
4
+ ToolExecutionResult,
5
+ } from "../../../../tools/types.js";
6
+
7
+ interface AppListEntry {
8
+ app_id: string;
9
+ name: string;
10
+ description?: string;
11
+ updated_at: number;
12
+ created_at: number;
13
+ }
14
+
15
+ function toEntry(app: appStore.AppDefinition): AppListEntry {
16
+ return {
17
+ app_id: app.id,
18
+ name: app.name,
19
+ ...(app.description ? { description: app.description } : {}),
20
+ updated_at: app.updatedAt,
21
+ created_at: app.createdAt,
22
+ };
23
+ }
24
+
25
+ export async function run(
26
+ input: Record<string, unknown>,
27
+ _context: ToolContext,
28
+ ): Promise<ToolExecutionResult> {
29
+ const apps = appStore.listApps();
30
+ const entries = apps.map(toEntry);
31
+
32
+ const query =
33
+ typeof input.query === "string" ? input.query.trim().toLowerCase() : "";
34
+
35
+ if (!query) {
36
+ return {
37
+ content: JSON.stringify({ count: entries.length, apps: entries }),
38
+ isError: false,
39
+ };
40
+ }
41
+
42
+ // Resolve the app the user mentioned by name. Prefer an exact (case-insensitive)
43
+ // name match, then fall back to substring matches in either direction so
44
+ // "habit tracker" resolves "Habit Tracker" and "my budget" resolves "Budget".
45
+ const exact = entries.filter((e) => e.name.toLowerCase() === query);
46
+ const matches =
47
+ exact.length > 0
48
+ ? exact
49
+ : entries.filter((e) => {
50
+ const name = e.name.toLowerCase();
51
+ return name.includes(query) || query.includes(name);
52
+ });
53
+
54
+ return {
55
+ content: JSON.stringify({
56
+ query: input.query,
57
+ match_count: matches.length,
58
+ matches,
59
+ }),
60
+ isError: false,
61
+ };
62
+ }
@@ -0,0 +1,18 @@
1
+ import { setAppCommitMessage } from "../../../../memory/app-git-service.js";
2
+ import * as appStore from "../../../../memory/app-store.js";
3
+ import type { AppUpdateInput } from "../../../../tools/apps/executors.js";
4
+ import { executeAppUpdate } from "../../../../tools/apps/executors.js";
5
+ import type {
6
+ ToolContext,
7
+ ToolExecutionResult,
8
+ } from "../../../../tools/types.js";
9
+
10
+ export async function run(
11
+ input: Record<string, unknown>,
12
+ context: ToolContext,
13
+ ): Promise<ToolExecutionResult> {
14
+ if (typeof input.change_summary === "string" && input.change_summary.trim()) {
15
+ setAppCommitMessage(context.conversationId, input.change_summary.trim());
16
+ }
17
+ return executeAppUpdate(input as unknown as AppUpdateInput, appStore);
18
+ }
@@ -1,44 +1,37 @@
1
1
  ---
2
2
  name: document-editor
3
- description: Rich text document editor with collaborative editing tools — create, read, update, and annotate documents
3
+ description: Use whenever the user wants to write or draft an article, blog post, essay, report, or any long-form content. Creates the content in a rich text editor instead of dumping it in chat, so it can be streamed, reviewed, edited, and exported.
4
4
  compatibility: "Designed for Vellum personal assistants"
5
5
  metadata:
6
- emoji: "📄"
6
+ emoji: "✍️"
7
7
  vellum:
8
- display-name: "Document Editor"
8
+ display-name: "Document Writer"
9
9
  activation-hints:
10
- - "User asks to write, draft, or collaborate on long-form content — use the document editor for a better editing experience"
11
- - "When content will be iterated on, reviewed, or exported, prefer the document editor over inline markdown"
12
- - "When a file attachment contains a draft or document the user wants to iterate on, open it in the editor"
10
+ - "User asks to write, draft, or compose an article, blog post, essay, report, story, or any long-form content — always create it in the document editor, not as a chat reply"
11
+ - "User wants written content they will iterate on, review, or export — use the editor instead of inline markdown"
12
+ - "A file attachment contains a draft or document the user wants to revise — open it in the editor"
13
+ avoid-when:
14
+ - "The user wants an interactive app, dashboard, calculator, game, or anything with state or data — use app-builder instead"
15
+ - "A one or two sentence answer is enough — just reply in chat"
13
16
  ---
14
17
 
15
- Create and edit long-form documents using the built-in rich text editor. Documents open in workspace mode with chat docked to the side.
18
+ Write and edit long-form documents using the built-in rich text editor. Documents open in workspace mode with chat docked to the side. When a request is about writing prose (an article, blog post, report, essay, story, or similar), create it here rather than writing it into the chat response.
16
19
 
17
20
  ## Tools
18
21
 
19
- - **document_open** - Opens an existing document in the editor panel by `surface_id`. Use this when a document exists but isn't visible in the editor — for example after the user switches devices, refreshes the page, or when the editor panel was closed. Fetches the document from storage and sends it to the client.
20
- - **document_create** - Opens a new document editor with an optional title and initial Markdown content. Returns a `surface_id` for subsequent updates.
22
+ - **document_create** - Opens a new document editor with an optional title and initial Markdown content. Returns a `surface_id` for subsequent updates. This is the entry point for any new piece of writing.
21
23
  - **document_update** - Updates content in an open document editor by `surface_id`. Supports `replace` (overwrite) and `append` (add to end) modes.
22
24
  - **document_read** - Reads the current content of a document by `surface_id` when it belongs to the current conversation, or when the current actor is the guardian/local user. Use to verify content before editing.
23
- - **document_list** - Lists documents. Without `query`, lists the current conversation's documents. With `query`, searches by title; guardian/local users can search across conversations, while other actors are scoped to the current conversation.
24
25
  - **document_find** - Searches a document for text or regex patterns. Returns matching lines with line numbers, match positions, and matched text.
25
26
  - **document_replace_text** - Targeted find-and-replace within a document. Supports literal and regex patterns (with backreferences). Optionally limit the number of replacements.
27
+ - **document_list** - Lists documents. Without `query`, lists the current conversation's documents. With `query`, searches by title; guardian/local users can search across conversations, while other actors are scoped to the current conversation.
28
+ - **document_open** - Opens an existing document in the editor panel by `surface_id`. Use this when a document exists but isn't visible in the editor — for example after the user switches devices, refreshes the page, or when the editor panel was closed. Fetches the document from storage and sends it to the client.
26
29
  - **document_delete** - Deletes a document by `surface_id`. Use to clean up unwanted documents.
27
30
 
28
- ## Retrieving existing documents
29
-
30
- When the user asks to see, open, or pull up a document:
31
-
32
- 1. Check the `<active_documents>` block in your context — it lists all documents in this conversation with their `surface_id` and title.
33
- 2. If the document is NOT in `<active_documents>`, call `document_list` with a `query` matching the document title. For guardian/local users, this searches across previous conversations and sessions.
34
- 3. Once you have the `surface_id`, call `document_open` to open the editor panel. This surfaces the editor on the client and returns document metadata (`surface_id`, `title`, `word_count`) — not the full content. If you need the actual document text, follow up with `document_read`.
35
-
36
- **Never** search the filesystem, conversation history, or archives to find a document. Always use `document_list` with a `query`.
37
-
38
- **If the user says they can't see a document you know exists** (e.g. after switching from macOS to web, or after a page refresh), call `document_open` with the `surface_id` to re-surface the editor panel on their current client.
39
-
40
31
  ## Creating a new document
41
32
 
33
+ This is the default path when the user asks you to write something.
34
+
42
35
  1. **Create the document**: Call `document_create` with a title (inferred from the request). Call the tool immediately, not after conversational preamble. Capture the `surface_id` from the response — every subsequent `document_update` call must reference it.
43
36
  2. **Write content in Markdown**: Use proper structure (`#` for titles, `##` for sections), **bold**, _italic_, code blocks, tables, lists, blockquotes as appropriate.
44
37
  3. **CRITICAL - Stream content in chunks**: Call `document_update` MULTIPLE times, not just once. Break content into logical chunks (paragraphs, sections, or every 200-300 words). Call `document_update` with `mode: "append"` for EACH chunk separately. The user experiences real-time content appearing as you write.
@@ -59,6 +52,18 @@ When the user requests changes to a document:
59
52
  - `document_find` + `document_replace_text` — **for everything else**. Fixing typos, renaming terms, swapping sections, reordering content, adjusting formatting, or any edit that touches only part of the document. This is the default choice for edits. It avoids rewriting the entire document and eliminates the risk of accidentally dropping content.
60
53
  4. **Do NOT use `document_update` with `mode: "replace"` for targeted edits.** Rewriting the entire document to change a few words or rearrange sections is wasteful and error-prone.
61
54
 
55
+ ## Retrieving existing documents
56
+
57
+ When the user asks to see, open, or pull up a document:
58
+
59
+ 1. Check the `<active_documents>` block in your context — it lists all documents in this conversation with their `surface_id` and title.
60
+ 2. If the document is NOT in `<active_documents>`, call `document_list` with a `query` matching the document title. For guardian/local users, this searches across previous conversations and sessions.
61
+ 3. Once you have the `surface_id`, call `document_open` to open the editor panel. This surfaces the editor on the client and returns document metadata (`surface_id`, `title`, `word_count`) — not the full content. If you need the actual document text, follow up with `document_read`.
62
+
63
+ **Never** search the filesystem, conversation history, or archives to find a document. Always use `document_list` with a `query`.
64
+
65
+ **If the user says they can't see a document you know exists** (e.g. after switching from macOS to web, or after a page refresh), call `document_open` with the `surface_id` to re-surface the editor panel on their current client.
66
+
62
67
  ## Find & Replace
63
68
 
64
69
  Use `document_find` and `document_replace_text` for surgical edits that target specific text patterns without rewriting the entire document.
@@ -117,7 +122,7 @@ Users can leave inline comments on documents. Open comments are surfaced in a `<
117
122
  ## Anti-Patterns
118
123
 
119
124
  - **Don't use `app_create` for blog posts, articles, or written content.** Use `document_create` — apps are for interactive content with state/data.
120
- - **Don't output the full content in chat.** The content goes in the document editor, not in the chat response. Acknowledge what you're doing and stream to the editor.
125
+ - **Don't write the article into the chat response.** Long-form prose goes in the document editor via `document_create`, not in chat and not into a `.md` file in the workspace. Acknowledge what you're doing and stream to the editor.
121
126
  - **Don't wait to generate everything before sending.** Stream content in chunks via `document_update` with `mode: "append"` so users see progress in real time.
122
127
 
123
128
  ## Usage Notes
@@ -42,7 +42,7 @@
42
42
  },
43
43
  {
44
44
  "name": "document_update",
45
- "description": "Update content in an open document editor. Use this to stream generated content or apply edits.",
45
+ "description": "Append to or fully replace a document's content. Takes the full Markdown in `content` plus a `mode`: \"append\" adds it to the end (use this to stream generated content in chunks), \"replace\" overwrites the entire document. This tool does NOT do targeted edits — for changing specific words, phrases, or sections, use document_replace_text instead. There is no old/new or find/replace parameter here.",
46
46
  "category": "document-editor",
47
47
  "risk": "low",
48
48
  "input_schema": {
@@ -23,7 +23,9 @@ import * as acpSteer from "./bundled-skills/acp/tools/acp-steer.js";
23
23
  import * as appCreate from "./bundled-skills/app-builder/tools/app-create.js";
24
24
  import * as appDelete from "./bundled-skills/app-builder/tools/app-delete.js";
25
25
  import * as appGenerateIcon from "./bundled-skills/app-builder/tools/app-generate-icon.js";
26
+ import * as appList from "./bundled-skills/app-builder/tools/app-list.js";
26
27
  import * as appRefresh from "./bundled-skills/app-builder/tools/app-refresh.js";
28
+ import * as appUpdate from "./bundled-skills/app-builder/tools/app-update.js";
27
29
  // ── app-control ────────────────────────────────────────────────────────────────
28
30
  import * as appControlClick from "./bundled-skills/app-control/tools/app-control-click.js";
29
31
  import * as appControlCombo from "./bundled-skills/app-control/tools/app-control-combo.js";
@@ -139,9 +141,11 @@ export const bundledToolRegistry = new Map<string, SkillToolScript>([
139
141
 
140
142
  // app-builder
141
143
  ["app-builder:tools/app-create.ts", appCreate],
144
+ ["app-builder:tools/app-update.ts", appUpdate],
142
145
  ["app-builder:tools/app-delete.ts", appDelete],
143
146
  ["app-builder:tools/app-refresh.ts", appRefresh],
144
147
  ["app-builder:tools/app-generate-icon.ts", appGenerateIcon],
148
+ ["app-builder:tools/app-list.ts", appList],
145
149
 
146
150
  // app-control
147
151
  ["app-control:tools/app-control-start.ts", appControlStart],
@@ -17,7 +17,6 @@ export const CALL_SITE_DEFAULTS: Record<LLMCallSite, CallSiteDefaultConfig> = {
17
17
  patternScan: { profile: "balanced" },
18
18
  narrativeRefinement: { profile: "balanced" },
19
19
  callAgent: { profile: "balanced" },
20
- proactiveArtifactBuild: { profile: "balanced" },
21
20
  memoryConsolidation: { profile: "balanced" },
22
21
  identityIntro: { profile: "balanced" },
23
22
  emptyStateGreeting: { profile: "balanced" },
@@ -26,7 +25,6 @@ export const CALL_SITE_DEFAULTS: Record<LLMCallSite, CallSiteDefaultConfig> = {
26
25
  profile: "cost-optimized",
27
26
  contextWindow: { maxInputTokens: 1000000 },
28
27
  },
29
- memoryV3RouteL1: { profile: "balanced", temperature: 0 },
30
28
  memoryV3SelectL2: { profile: "balanced", temperature: 0 },
31
29
  recall: {
32
30
  profile: "balanced",
@@ -42,7 +40,6 @@ export const CALL_SITE_DEFAULTS: Record<LLMCallSite, CallSiteDefaultConfig> = {
42
40
  },
43
41
 
44
42
  filingAgent: { profile: "cost-optimized" },
45
- proactiveArtifactDecision: { profile: "cost-optimized" },
46
43
  memoryExtraction: { profile: "cost-optimized" },
47
44
  memoryRetrieval: { profile: "cost-optimized" },
48
45
  memoryRetrospective: { profile: "cost-optimized" },
@@ -26,20 +26,22 @@
26
26
  "defaultEnabled": false
27
27
  },
28
28
  {
29
- "id": "prechat-onboarding-condensed-flow",
29
+ "id": "pre-chat-onboarding-experiment-2026-06-06",
30
30
  "scope": "client",
31
- "key": "prechat-onboarding-condensed-flow",
32
- "label": "Condensed Pre-chat Onboarding",
33
- "description": "Enable the condensed pre-chat onboarding flow for a standard LaunchDarkly percentage rollout.",
34
- "defaultEnabled": false
31
+ "key": "pre-chat-onboarding-experiment-2026-06-06",
32
+ "label": "Pre-chat Onboarding Experiment 2026-06-06",
33
+ "description": "Pre-chat onboarding experiment with control and variant-a arms. Control shows the full funnel; variant-a shows the condensed pared-down flow.",
34
+ "defaultEnabled": "control",
35
+ "values": ["control", "variant-a"]
35
36
  },
36
37
  {
37
38
  "id": "experiment-activation-flow-2026-06-03",
38
39
  "scope": "client",
39
40
  "key": "experiment-activation-flow-2026-06-03",
40
41
  "label": "Activation Flow Experiment 2026-06-03",
41
- "description": "Route allowlisted users to the activation-rail bootstrap template after pre-chat. Off by default and targeted through LaunchDarkly.",
42
- "defaultEnabled": false
42
+ "description": "Multivariate activation-flow experiment. control = standard flow; variant-a = activation rail. Targeted via LaunchDarkly.",
43
+ "defaultEnabled": "control",
44
+ "values": ["control", "variant-a"]
43
45
  },
44
46
  {
45
47
  "id": "local-docker-enabled",
@@ -139,7 +141,7 @@
139
141
  },
140
142
  {
141
143
  "id": "multi-platform-assistant",
142
- "scope": "assistant",
144
+ "scope": "client",
143
145
  "key": "multi-platform-assistant",
144
146
  "label": "Multi-Platform Assistant Switcher",
145
147
  "description": "Enable the menu-bar assistant switcher for managing multiple platform-hosted assistants (new/switch/retire)",
@@ -480,14 +482,6 @@
480
482
  "label": "Self-intro first message",
481
483
  "description": "On the first conversation, send a natural self-introduction (e.g. \"Hi Vela, I'm alex. Nice to meet you.\") on the user's behalf and route it through real LLM inference, instead of serving the canned first greeting. Names come from the onboarding context; falls back to the canned greeting when no name is known. Exposed to clients so pre-hatch onboarding can compute the source-of-truth initial message, and to the assistant so older clients can still be gated server-side. See assistant/src/daemon/first-greeting.ts (buildSelfIntroMessage).",
482
484
  "defaultEnabled": false
483
- },
484
- {
485
- "id": "provider-first-profile-creation",
486
- "scope": "client",
487
- "key": "provider-first-profile-creation",
488
- "label": "Provider-First Profile Creation",
489
- "description": "New profile creation flow: pick (or inline-create) a provider first, then a model, with pre-filled provider and profile name/key, plus a quick-add \"+\" in the chat composer's Model Profile menu. When off, profile creation uses the previous field order and there is no composer quick-add.",
490
- "defaultEnabled": false
491
485
  }
492
486
  ]
493
487
  }
@@ -78,6 +78,15 @@ export function resolveCallSiteConfig(
78
78
  ): z.infer<typeof LLMConfigBase> {
79
79
  const layers: Mergeable[] = [llm.default as Mergeable];
80
80
 
81
+ // Effective logit-bias preset, tracked outside the deep-merge so it ties to
82
+ // the single highest-precedence *profile* that wins resolution rather than
83
+ // inheriting from a lower one. Profile layers are appended low→high, and each
84
+ // one fully determines the preset (a profile that omits `logitBias` clears
85
+ // any value a lower-precedence profile set), so the last profile appended
86
+ // wins — matching the merge's own precedence and including the implicit
87
+ // call-site default selected by `effectiveDefault`.
88
+ const biasRef: LogitBiasRef = { preset: undefined };
89
+
81
90
  const activeFragment = resolveProfileFragment(llm.activeProfile, llm, opts);
82
91
  const overrideFragment = resolveProfileFragment(
83
92
  opts.overrideProfile,
@@ -89,18 +98,32 @@ export function resolveCallSiteConfig(
89
98
  effectiveDefault(callSite, llm, opts.overrideProfile != null);
90
99
 
91
100
  if (callSite === "mainAgent") {
92
- appendCallSiteLayers(layers, callSite, llm, site, opts);
93
- appendProfileLayer(layers, activeFragment);
94
- appendProfileLayer(layers, overrideFragment);
101
+ appendCallSiteLayers(layers, callSite, llm, site, opts, biasRef);
102
+ appendProfileLayer(layers, activeFragment, biasRef);
103
+ appendProfileLayer(layers, overrideFragment, biasRef);
95
104
  } else {
96
- appendProfileLayer(layers, activeFragment);
97
- appendProfileLayer(layers, overrideFragment);
98
- appendCallSiteLayers(layers, callSite, llm, site, opts);
105
+ appendProfileLayer(layers, activeFragment, biasRef);
106
+ appendProfileLayer(layers, overrideFragment, biasRef);
107
+ appendCallSiteLayers(layers, callSite, llm, site, opts, biasRef);
99
108
  }
100
109
 
101
- return finalize(deepMerge(...layers.map(withImpliedProviderForKnownModel)));
110
+ const resolved = finalize(
111
+ deepMerge(...layers.map(withImpliedProviderForKnownModel)),
112
+ );
113
+ // `logitBias` is profile-scoped: the winning profile is its only source.
114
+ // Overwrite — or clear — whatever the deep-merge may have copied from a
115
+ // non-profile layer (`llm.default` or a call-site fragment), so a preset set
116
+ // outside a profile can't apply to a profile that didn't opt in.
117
+ if (biasRef.preset !== undefined) {
118
+ resolved.logitBias = biasRef.preset;
119
+ } else {
120
+ delete (resolved as { logitBias?: unknown }).logitBias;
121
+ }
122
+ return resolved;
102
123
  }
103
124
 
125
+ type LogitBiasRef = { preset: ProfileEntry["logitBias"] };
126
+
104
127
  // ---------------------------------------------------------------------------
105
128
  // Internal helpers
106
129
  // ---------------------------------------------------------------------------
@@ -261,8 +284,10 @@ function withImpliedProviderForKnownModel(source: Mergeable): Mergeable {
261
284
  function appendProfileLayer(
262
285
  layers: Mergeable[],
263
286
  profile: ProfileEntry | undefined,
287
+ biasRef: LogitBiasRef,
264
288
  ): void {
265
289
  if (profile != null) {
290
+ biasRef.preset = profile.logitBias;
266
291
  layers.push(profileConfigFragment(profile));
267
292
  }
268
293
  }
@@ -273,6 +298,7 @@ function appendCallSiteLayers(
273
298
  llm: z.infer<typeof LLMSchema>,
274
299
  site: z.infer<typeof LLMSchema>["callSites"][LLMCallSite] | undefined,
275
300
  opts: ResolveCallSiteOpts,
301
+ biasRef: LogitBiasRef,
276
302
  ): void {
277
303
  if (site != null) {
278
304
  if (site.profile != null) {
@@ -286,6 +312,7 @@ function appendCallSiteLayers(
286
312
  `LLM call site "${callSite}" references undefined profile "${site.profile}"`,
287
313
  );
288
314
  }
315
+ biasRef.preset = profileFragment.logitBias;
289
316
  layers.push(profileConfigFragment(profileFragment));
290
317
  }
291
318
  // Strip the `profile` discriminator before merging — it isn't a
@@ -304,6 +331,11 @@ function profileConfigFragment(profile: ProfileEntry): Mergeable {
304
331
  // profile before this point), but strip it defensively so it can never
305
332
  // leak into the merged `LLMConfigBase`.
306
333
  mix: _mix,
334
+ // `logitBias` is profile-identity metadata, not inheritable config: a
335
+ // preset must apply only to the profile that opted in, never bleed from a
336
+ // lower-precedence (e.g. active) profile into one that merely inherited it.
337
+ // `RetryProvider` resolves it from the applied profile, not the merge.
338
+ logitBias: _logitBias,
307
339
  ...config
308
340
  } = profile;
309
341
  return config as Mergeable;