@vellumai/assistant 0.8.8 → 0.8.9-staging.2

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 (360) hide show
  1. package/ARCHITECTURE.md +6 -6
  2. package/bun.lock +2 -2
  3. package/examples/plugins/echo/README.md +61 -60
  4. package/examples/plugins/echo/hooks/post-tool-use.ts +18 -0
  5. package/examples/plugins/echo/hooks/stop.ts +16 -0
  6. package/examples/plugins/echo/hooks/user-prompt-submit.ts +18 -0
  7. package/examples/plugins/echo/package.json +1 -2
  8. package/examples/plugins/echo/src/emit.ts +19 -0
  9. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +7 -6
  10. package/openapi.yaml +235 -6
  11. package/package.json +2 -2
  12. package/src/__tests__/agent-loop-callsite-precedence.test.ts +69 -14
  13. package/src/__tests__/agent-loop-exit-reason.test.ts +204 -144
  14. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +50 -35
  15. package/src/__tests__/agent-loop-output-hooks.test.ts +357 -0
  16. package/src/__tests__/agent-loop-override-profile.test.ts +25 -6
  17. package/src/__tests__/agent-loop-provider-error-recording.test.ts +41 -21
  18. package/src/__tests__/agent-loop-thinking.test.ts +36 -20
  19. package/src/__tests__/agent-loop.test.ts +441 -96
  20. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +14 -14
  21. package/src/__tests__/agent-wake-override-profile.test.ts +17 -21
  22. package/src/__tests__/anthropic-provider.test.ts +1 -1
  23. package/src/__tests__/app-builder-tool-scripts.test.ts +21 -0
  24. package/src/__tests__/app-control-flow.test.ts +1 -1
  25. package/src/__tests__/app-dir-path-guard.test.ts +1 -0
  26. package/src/__tests__/app-executors.test.ts +132 -0
  27. package/src/__tests__/approval-cascade.test.ts +5 -4
  28. package/src/__tests__/approval-routes-http.test.ts +4 -1
  29. package/src/__tests__/background-workers-disk-pressure.test.ts +1 -1
  30. package/src/__tests__/channel-approval-routes.test.ts +1 -1
  31. package/src/__tests__/channel-approvals.test.ts +1 -1
  32. package/src/__tests__/compaction-circuit.test.ts +258 -0
  33. package/src/__tests__/compaction-direct.test.ts +132 -0
  34. package/src/__tests__/compaction-events.test.ts +5 -5
  35. package/src/__tests__/compactor-web-search-strip.test.ts +213 -0
  36. package/src/__tests__/context-overflow-reducer.test.ts +1 -1
  37. package/src/__tests__/conversation-abort-tool-results.test.ts +6 -4
  38. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +7 -10
  39. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +78 -119
  40. package/src/__tests__/conversation-agent-loop-overflow.test.ts +142 -218
  41. package/src/__tests__/conversation-agent-loop.test.ts +297 -586
  42. package/src/__tests__/conversation-clean-command.test.ts +5 -2
  43. package/src/__tests__/conversation-confirmation-signals.test.ts +5 -4
  44. package/src/__tests__/conversation-crud-inference-profile.test.ts +7 -9
  45. package/src/__tests__/conversation-history-web-search.test.ts +1 -1
  46. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +4 -4
  47. package/src/__tests__/conversation-process-callsite.test.ts +14 -14
  48. package/src/__tests__/conversation-provider-retry-repair.test.ts +70 -65
  49. package/src/__tests__/conversation-queue.test.ts +9 -9
  50. package/src/__tests__/conversation-runtime-assembly.test.ts +923 -231
  51. package/src/__tests__/conversation-runtime-workspace.test.ts +115 -20
  52. package/src/__tests__/conversation-slash-queue.test.ts +6 -4
  53. package/src/__tests__/conversation-slash-unknown.test.ts +6 -4
  54. package/src/__tests__/conversation-speed-override.test.ts +10 -9
  55. package/src/__tests__/conversation-starter-routes.test.ts +14 -6
  56. package/src/__tests__/conversation-workspace-cache-state.test.ts +23 -20
  57. package/src/__tests__/conversation-workspace-injection.test.ts +68 -6
  58. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +14 -11
  59. package/src/__tests__/conversations-import-system-filter.test.ts +101 -0
  60. package/src/__tests__/credential-security-invariants.test.ts +0 -1
  61. package/src/__tests__/db-acp-history.test.ts +101 -0
  62. package/src/__tests__/dynamic-page-surface.test.ts +31 -0
  63. package/src/__tests__/empty-response-hook.test.ts +1 -1
  64. package/src/__tests__/file-write-tool.test.ts +63 -0
  65. package/src/__tests__/gateway-only-guard.test.ts +12 -2
  66. package/src/__tests__/guardian-grant-minting.test.ts +1 -1
  67. package/src/__tests__/guardian-routing-invariants.test.ts +2 -4
  68. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
  69. package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
  70. package/src/__tests__/heartbeat-service.test.ts +1 -0
  71. package/src/__tests__/history-repair-hook.test.ts +1 -1
  72. package/src/__tests__/host-app-control-routes.test.ts +1 -1
  73. package/src/__tests__/host-cu-routes-targeted.test.ts +3 -3
  74. package/src/__tests__/inference-profile-reaper.test.ts +62 -0
  75. package/src/__tests__/inference-profile-session-handler.test.ts +86 -0
  76. package/src/__tests__/injector-background-turn.test.ts +13 -23
  77. package/src/__tests__/injector-chain.test.ts +268 -44
  78. package/src/__tests__/injector-disk-pressure.test.ts +210 -52
  79. package/src/__tests__/injector-document-comments.test.ts +97 -114
  80. package/src/__tests__/injector-pkb-v2-silenced.test.ts +2 -2
  81. package/src/__tests__/injector-v3-suppression.test.ts +4 -4
  82. package/src/__tests__/list-messages-client-message-id.test.ts +91 -0
  83. package/src/__tests__/list-messages-hidden-metadata.test.ts +38 -0
  84. package/src/__tests__/memory-retrieval-hook.test.ts +131 -26
  85. package/src/__tests__/memory-v2-static-injector.test.ts +86 -8
  86. package/src/__tests__/parallel-tool.benchmark.test.ts +35 -8
  87. package/src/__tests__/plugin-api-shim.test.ts +6 -9
  88. package/src/__tests__/plugin-bootstrap.test.ts +12 -23
  89. package/src/__tests__/plugin-registry.test.ts +3 -49
  90. package/src/__tests__/plugin-types.test.ts +0 -70
  91. package/src/__tests__/pre-model-call-sanitize.test.ts +109 -0
  92. package/src/__tests__/reaction-persistence.test.ts +1 -1
  93. package/src/__tests__/send-endpoint-busy.test.ts +4 -1
  94. package/src/__tests__/skill-feature-flags-integration.test.ts +33 -0
  95. package/src/__tests__/steer-tool-repair.test.ts +1 -1
  96. package/src/__tests__/subagent-call-site-routing.test.ts +1 -1
  97. package/src/__tests__/subagent-detail.test.ts +25 -7
  98. package/src/__tests__/subagent-fork-notifications.test.ts +1 -3
  99. package/src/__tests__/subagent-fork-spawn.test.ts +1 -1
  100. package/src/__tests__/subagent-manager-notify.test.ts +1 -3
  101. package/src/__tests__/subagent-notify-parent.test.ts +1 -3
  102. package/src/__tests__/subagent-spawn-tool-fork.test.ts +1 -1
  103. package/src/__tests__/title-generate-hook.test.ts +1 -1
  104. package/src/__tests__/tool-error-hook.test.ts +1 -1
  105. package/src/__tests__/tool-result-truncate-hook.test.ts +1 -1
  106. package/src/__tests__/user-plugin-loader.test.ts +54 -286
  107. package/src/acp/__tests__/agent-process.test.ts +161 -0
  108. package/src/acp/__tests__/client-handler.test.ts +40 -0
  109. package/src/acp/__tests__/helpers/acp-history-db.ts +82 -0
  110. package/src/acp/__tests__/helpers/exec-file-stub.ts +106 -0
  111. package/src/acp/__tests__/prepare-agent-env.test.ts +97 -0
  112. package/src/acp/__tests__/session-manager-persistence.test.ts +95 -28
  113. package/src/acp/__tests__/session-manager-resume.test.ts +888 -0
  114. package/src/acp/agent-process.ts +61 -1
  115. package/src/acp/auto-install.test.ts +280 -0
  116. package/src/acp/auto-install.ts +232 -0
  117. package/src/acp/client-handler.ts +31 -0
  118. package/src/acp/feature-gate.test.ts +48 -0
  119. package/src/acp/feature-gate.ts +34 -0
  120. package/src/acp/prepare-agent-env.ts +80 -27
  121. package/src/acp/resolve-agent.test.ts +225 -9
  122. package/src/acp/resolve-agent.ts +122 -17
  123. package/src/acp/resume-hint.ts +23 -0
  124. package/src/acp/session-manager.ts +507 -73
  125. package/src/agent/compaction-circuit.ts +60 -102
  126. package/src/agent/loop.ts +414 -248
  127. package/src/api/responses/conversation-message.ts +14 -1
  128. package/src/approvals/guardian-request-resolvers.ts +1 -1
  129. package/src/background-wake/next-wake.ts +1 -0
  130. package/src/cli/commands/db/__tests__/repair.test.ts +3 -1
  131. package/src/cli/commands/plugins.ts +43 -37
  132. package/src/cli/lib/__tests__/install-from-github.test.ts +429 -111
  133. package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +196 -0
  134. package/src/cli/lib/__tests__/plugin-details.test.ts +372 -0
  135. package/src/cli/lib/__tests__/plugin-marketplace.test.ts +220 -0
  136. package/src/cli/lib/__tests__/search-plugins.test.ts +226 -32
  137. package/src/cli/lib/install-from-github.ts +464 -55
  138. package/src/cli/lib/plugin-catalog-cache.ts +84 -0
  139. package/src/cli/lib/plugin-details.ts +409 -0
  140. package/src/cli/lib/plugin-marketplace.ts +197 -0
  141. package/src/cli/lib/search-plugins.ts +195 -29
  142. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  143. package/src/config/acp-defaults.test.ts +10 -0
  144. package/src/config/acp-defaults.ts +6 -0
  145. package/src/config/bundled-skills/acp/SKILL.md +85 -33
  146. package/src/config/bundled-skills/acp/TOOLS.json +4 -4
  147. package/src/config/bundled-skills/app-builder/SKILL.md +224 -381
  148. package/src/config/bundled-skills/app-builder/TOOLS.json +72 -2
  149. package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +48 -0
  150. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +57 -0
  151. package/src/config/bundled-skills/app-builder/references/SLIDES.md +38 -0
  152. package/src/config/bundled-skills/app-builder/tools/app-list.ts +62 -0
  153. package/src/config/bundled-skills/app-builder/tools/app-update.ts +18 -0
  154. package/src/config/bundled-skills/document-editor/SKILL.md +28 -23
  155. package/src/config/bundled-skills/document-editor/TOOLS.json +1 -1
  156. package/src/config/bundled-tool-registry.ts +4 -0
  157. package/src/config/call-site-defaults.ts +0 -2
  158. package/src/config/feature-flag-registry.json +15 -6
  159. package/src/config/schemas/call-site-catalog.ts +0 -14
  160. package/src/config/schemas/heartbeat.ts +9 -0
  161. package/src/config/schemas/llm.ts +0 -2
  162. package/src/context/compactor.ts +22 -4
  163. package/src/context/strip-injections.ts +8 -2
  164. package/src/context/window-manager.ts +27 -13
  165. package/src/daemon/conversation-agent-loop-handlers.ts +10 -35
  166. package/src/daemon/conversation-agent-loop.ts +175 -1055
  167. package/src/daemon/conversation-lifecycle.ts +11 -255
  168. package/src/daemon/conversation-process.ts +8 -136
  169. package/src/daemon/conversation-registry.ts +159 -0
  170. package/src/daemon/conversation-runtime-assembly.ts +293 -392
  171. package/src/daemon/conversation-store.ts +9 -90
  172. package/src/daemon/conversation-surfaces.ts +24 -8
  173. package/src/daemon/conversation-workspace.ts +17 -0
  174. package/src/daemon/conversation.ts +404 -57
  175. package/src/daemon/disk-pressure-policy.ts +0 -1
  176. package/src/daemon/external-plugins-bootstrap.ts +14 -19
  177. package/src/daemon/handlers/conversations.ts +3 -1
  178. package/src/daemon/handlers/skills.ts +4 -1
  179. package/src/daemon/host-proxy-preactivation.ts +1 -3
  180. package/src/daemon/lifecycle.ts +21 -7
  181. package/src/daemon/server.ts +2 -0
  182. package/src/daemon/wake-conversation-ops.ts +269 -0
  183. package/src/embedded/plugin-api.ts +2 -2
  184. package/src/export/__tests__/transcript-formatter.test.ts +5 -0
  185. package/src/heartbeat/__tests__/heartbeat-service.test.ts +3 -0
  186. package/src/heartbeat/heartbeat-run-store.ts +23 -1
  187. package/src/heartbeat/heartbeat-service.ts +26 -0
  188. package/src/ipc/__tests__/browser-ipc.test.ts +1 -1
  189. package/src/ipc/__tests__/ui-request-route.test.ts +3 -3
  190. package/src/ipc/skill-routes/__tests__/memory.test.ts +15 -0
  191. package/src/ipc/skill-routes/memory.ts +4 -2
  192. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +87 -0
  193. package/src/memory/conversation-crud.ts +29 -19
  194. package/src/memory/conversation-starter-checkpoints.ts +1 -0
  195. package/src/memory/db-init.ts +2 -0
  196. package/src/memory/job-handlers/conversation-starters.ts +13 -2
  197. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -4
  198. package/src/memory/jobs-worker.ts +25 -1
  199. package/src/memory/migrations/272-acp-session-history-cwd.ts +36 -0
  200. package/src/memory/migrations/index.ts +1 -0
  201. package/src/memory/schema/acp.ts +4 -0
  202. package/src/memory/v2/__tests__/consolidation-job.test.ts +3 -3
  203. package/src/memory/v2/consolidation-job.ts +13 -4
  204. package/src/plugin-api/constants.ts +4 -0
  205. package/src/plugin-api/index.ts +6 -5
  206. package/src/plugin-api/types.ts +75 -0
  207. package/src/plugins/defaults/compaction/compact.ts +59 -0
  208. package/src/{daemon → plugins/defaults/compaction}/context-overflow-reducer.ts +7 -7
  209. package/src/plugins/defaults/compaction/manager-store.ts +57 -0
  210. package/src/plugins/defaults/compaction/package.json +1 -2
  211. package/src/plugins/defaults/empty-response/package.json +0 -1
  212. package/src/plugins/defaults/history-repair/package.json +0 -1
  213. package/src/plugins/defaults/index.ts +135 -26
  214. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +100 -52
  215. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +184 -74
  216. package/src/plugins/defaults/memory-retrieval/injector-chain.ts +2 -2
  217. package/src/plugins/defaults/{injectors/register.ts → memory-retrieval/injectors.ts} +148 -73
  218. package/src/plugins/defaults/memory-retrieval/unified-turn-context.ts +223 -0
  219. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/assign.test.ts +4 -4
  220. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/live-integration.test.ts +9 -6
  221. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/maintain-job.test.ts +5 -5
  222. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/orchestrate.test.ts +8 -5
  223. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/reconcile.test.ts +2 -2
  224. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/render-injection.test.ts +1 -1
  225. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/router.test.ts +10 -5
  226. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selection-log-store.test.ts +8 -8
  227. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selector.test.ts +5 -5
  228. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/shadow-plugin.test.ts +16 -17
  229. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/types.test.ts +2 -2
  230. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/assign.ts +9 -5
  231. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/capabilities.ts +5 -2
  232. package/src/plugins/defaults/memory-v3-shadow/hooks/post-compact.ts +14 -0
  233. package/src/plugins/defaults/memory-v3-shadow/hooks/user-prompt-submit.ts +19 -0
  234. package/src/plugins/defaults/memory-v3-shadow/injector.ts +75 -0
  235. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/maintain-job.ts +15 -8
  236. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/orchestrate.ts +2 -2
  237. package/src/plugins/defaults/memory-v3-shadow/package.json +14 -0
  238. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/page-content.ts +2 -2
  239. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/provider-blocks.ts +1 -1
  240. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/reconcile.ts +7 -3
  241. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/render-injection.ts +1 -1
  242. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/router.ts +5 -5
  243. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/selection-log-store.ts +4 -4
  244. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/selector.ts +7 -7
  245. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/shadow-plugin.ts +32 -94
  246. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/tree.ts +1 -1
  247. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/types.ts +1 -1
  248. package/src/plugins/defaults/title-generate/package.json +0 -1
  249. package/src/plugins/defaults/tool-error/package.json +0 -1
  250. package/src/plugins/defaults/tool-result-truncate/package.json +0 -1
  251. package/src/plugins/pipeline.ts +6 -293
  252. package/src/plugins/registry.ts +9 -37
  253. package/src/plugins/types.ts +76 -381
  254. package/src/plugins/user-loader.ts +30 -127
  255. package/src/prompts/__tests__/system-prompt.test.ts +6 -0
  256. package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +35 -3
  257. package/src/runtime/__tests__/agent-wake.test.ts +555 -691
  258. package/src/runtime/__tests__/interactive-ui.test.ts +1 -1
  259. package/src/runtime/agent-wake.ts +108 -209
  260. package/src/runtime/assistant-event-hub.ts +1 -1
  261. package/src/runtime/channel-approvals.ts +1 -1
  262. package/src/runtime/interactive-ui.ts +1 -1
  263. package/src/runtime/routes/__tests__/acp-routes.test.ts +315 -55
  264. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
  265. package/src/runtime/routes/__tests__/plugins-routes.test.ts +423 -73
  266. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +5 -4
  267. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +4 -1
  268. package/src/runtime/routes/acp-routes.test.ts +89 -25
  269. package/src/runtime/routes/acp-routes.ts +81 -29
  270. package/src/runtime/routes/approval-routes.ts +1 -1
  271. package/src/runtime/routes/browser-routes.ts +1 -1
  272. package/src/runtime/routes/browser-tabs-routes.ts +6 -10
  273. package/src/runtime/routes/conversation-cli-routes.ts +1 -1
  274. package/src/runtime/routes/conversation-list-routes.ts +1 -1
  275. package/src/runtime/routes/conversation-query-routes.ts +1 -1
  276. package/src/runtime/routes/conversation-routes.ts +28 -2
  277. package/src/runtime/routes/conversation-starter-routes.ts +13 -7
  278. package/src/runtime/routes/conversations-import-routes.ts +24 -7
  279. package/src/runtime/routes/host-app-control-routes.ts +1 -1
  280. package/src/runtime/routes/host-cu-routes.ts +1 -1
  281. package/src/runtime/routes/identity-routes.ts +18 -3
  282. package/src/runtime/routes/inbound-message-handler.ts +1 -1
  283. package/src/runtime/routes/inference-profile-session-handler.ts +11 -0
  284. package/src/runtime/routes/inference-profile-session-reaper.ts +6 -0
  285. package/src/runtime/routes/memory-v3-routes.ts +16 -6
  286. package/src/runtime/routes/playground/helpers.ts +1 -1
  287. package/src/runtime/routes/plugins-routes.ts +337 -35
  288. package/src/runtime/routes/surface-conversation-resolver.ts +4 -3
  289. package/src/runtime/routes/work-items-routes.ts +2 -4
  290. package/src/runtime/services/conversation-serializer.ts +1 -1
  291. package/src/signals/cancel.ts +2 -4
  292. package/src/subagent/manager.ts +21 -5
  293. package/src/tools/acp/context.ts +20 -0
  294. package/src/tools/acp/list-agents.test.ts +8 -2
  295. package/src/tools/acp/spawn.test.ts +176 -195
  296. package/src/tools/acp/spawn.ts +37 -172
  297. package/src/tools/acp/steer.test.ts +105 -8
  298. package/src/tools/acp/steer.ts +48 -17
  299. package/src/tools/apps/executors.ts +166 -50
  300. package/src/tools/filesystem/write.ts +34 -0
  301. package/src/tools/subagent/spawn.ts +2 -4
  302. package/src/tools/ui-surface/definitions.ts +25 -5
  303. package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +4 -5
  304. package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +69 -45
  305. package/docs/plugins.md +0 -832
  306. package/examples/plugins/echo/register.ts +0 -143
  307. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -405
  308. package/src/__tests__/compaction-pipeline.test.ts +0 -210
  309. package/src/__tests__/compaction-timeout-recovery.test.ts +0 -251
  310. package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -667
  311. package/src/__tests__/pipeline-runner.test.ts +0 -554
  312. package/src/__tests__/plugin-external-api.test.ts +0 -68
  313. package/src/daemon/wake-target-adapter.ts +0 -253
  314. package/src/plugins/defaults/circuit-breaker/middlewares/circuitBreaker.ts +0 -93
  315. package/src/plugins/defaults/circuit-breaker/package.json +0 -15
  316. package/src/plugins/defaults/circuit-breaker/register.ts +0 -39
  317. package/src/plugins/defaults/compaction/middlewares/compaction.ts +0 -25
  318. package/src/plugins/defaults/compaction/register.ts +0 -35
  319. package/src/plugins/defaults/compaction/terminal.ts +0 -73
  320. package/src/plugins/defaults/empty-response/register.ts +0 -23
  321. package/src/plugins/defaults/history-repair/register.ts +0 -24
  322. package/src/plugins/defaults/overflow-reduce/middlewares/overflowReduce.ts +0 -126
  323. package/src/plugins/defaults/overflow-reduce/package.json +0 -15
  324. package/src/plugins/defaults/overflow-reduce/register.ts +0 -42
  325. package/src/plugins/defaults/title-generate/register.ts +0 -35
  326. package/src/plugins/defaults/tool-error/register.ts +0 -23
  327. package/src/plugins/defaults/tool-result-truncate/register.ts +0 -24
  328. package/src/plugins/external-api.ts +0 -104
  329. package/src/proactive-artifact/aux-message-injector.ts +0 -97
  330. package/src/proactive-artifact/decision.test.ts +0 -226
  331. package/src/proactive-artifact/decision.ts +0 -165
  332. package/src/proactive-artifact/index.ts +0 -7
  333. package/src/proactive-artifact/job.test.ts +0 -962
  334. package/src/proactive-artifact/job.ts +0 -372
  335. package/src/proactive-artifact/message-copy.ts +0 -58
  336. package/src/proactive-artifact/trigger-state.test.ts +0 -286
  337. package/src/proactive-artifact/trigger-state.ts +0 -123
  338. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/capabilities.test.ts +0 -0
  339. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/core.test.ts +0 -0
  340. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/eval-turns.json +0 -0
  341. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/live-turns.json +0 -0
  342. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/health.test.ts +0 -0
  343. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/needle.test.ts +0 -0
  344. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/provider-blocks.test.ts +0 -0
  345. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/snapshot.test.ts +0 -0
  346. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/tree.test.ts +0 -0
  347. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-eviction.test.ts +0 -0
  348. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-skeleton.test.ts +0 -0
  349. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/core.ts +0 -0
  350. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/README.md +0 -0
  351. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/assignments.json +0 -0
  352. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/core.json +0 -0
  353. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-x.md +0 -0
  354. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-y.md +0 -0
  355. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-b/topic-z.md +0 -0
  356. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/health.ts +0 -0
  357. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/llm-retry.ts +0 -0
  358. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/needle.ts +0 -0
  359. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/snapshot.ts +0 -0
  360. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/working-set.ts +0 -0
@@ -1,39 +1,23 @@
1
1
  /**
2
- * User plugin loader — discovers plugins under `<workspaceDir>/plugins/*` via
3
- * one of two paths, gated by the contents of each candidate directory.
2
+ * User plugin loader — discovers plugins under `<workspaceDir>/plugins/*` and
3
+ * registers each one.
4
4
  *
5
- * **External plugin framework path** (`package.json` present **and** no
6
- * `register.{ts,js}`): the harness delegates to {@link loadExternalPlugin},
7
- * which builds a `Plugin` from the directory's interface dirs (`hooks/`,
8
- * `tools/`) and registers it directly. This path is opt-in by the plugin
9
- * author and currently experimental — see
10
- * `assistant/src/plugins/external-plugin-loader.ts` for the full
11
- * convention.
12
- *
13
- * **Legacy path** (`register.{ts,js}` present): the file is dynamic-imported
14
- * and expected to call {@link registerPlugin} at import time as a side
15
- * effect, populating the registry before {@link bootstrapPlugins} runs.
16
- *
17
- * The legacy path takes precedence when a directory contains both
18
- * `package.json` and `register.{ts,js}` — a migration-friendly default
19
- * that keeps existing plugins (including the in-repo `examples/plugins/echo`
20
- * reference) working unchanged while we iterate the external-plugin
21
- * convention. A directory matching neither path is skipped silently.
5
+ * A plugin directory is recognized by a `package.json` manifest. The harness
6
+ * delegates to {@link loadExternalPlugin}, which builds a `Plugin` from the
7
+ * directory's interface dirs (`hooks/`, `tools/`) and registers it directly.
8
+ * The full convention lives in
9
+ * `assistant/src/plugins/external-plugin-loader.ts`. A directory with no
10
+ * `package.json` is skipped silently.
22
11
  *
23
12
  * The loader deliberately:
24
13
  *
25
14
  * - Uses `getWorkspaceDir()` so each instance loads its own plugin set
26
15
  * when `VELLUM_WORKSPACE_DIR` is set.
27
- * - Prefers `.js` over `.ts` per surface file (compiled-binary semantics).
28
- * The external loader applies the same rule per surface file; the
29
- * legacy path picks between `register.js` and `register.ts`.
16
+ * - Prefers `.js` over `.ts` per surface file (compiled-binary semantics);
17
+ * the rule is applied by {@link loadExternalPlugin}.
30
18
  * - Treats any error from a plugin load as a per-plugin isolation
31
- * boundary. {@link loadExternalPlugin} owns its own try/catch/timeout;
32
- * the legacy path is wrapped here. One bad user plugin must not crash
33
- * the daemon.
34
- * - Bounds each plugin load with {@link USER_PLUGIN_IMPORT_TIMEOUT_MS}
35
- * so a plugin whose top-level `await` hangs or whose module evaluation
36
- * never resolves cannot stall daemon startup.
19
+ * boundary. {@link loadExternalPlugin} owns its own try/catch/timeout, so
20
+ * one bad user plugin must not crash the daemon.
37
21
  *
38
22
  * Call order relative to the rest of the plugin system:
39
23
  *
@@ -46,7 +30,6 @@
46
30
 
47
31
  import { existsSync, readdirSync, statSync } from "node:fs";
48
32
  import { join } from "node:path";
49
- import { pathToFileURL } from "node:url";
50
33
 
51
34
  import { getLogger } from "../util/logger.js";
52
35
  import { getWorkspacePluginsDir } from "../util/platform.js";
@@ -57,27 +40,24 @@ import { closeRegistration } from "./registry.js";
57
40
  const log = getLogger("user-plugin-loader");
58
41
 
59
42
  /**
60
- * Upper bound on how long a single user plugin's dynamic `import()` may take.
61
- * A plugin with a hanging top-level `await` (or a never-resolving module
62
- * evaluation) would otherwise block daemon startup indefinitely, since a raw
63
- * `try/catch` only isolates thrown errors not hung promises. Ten seconds is
64
- * generous relative to a typical side-effect registration (milliseconds) and
65
- * matches the per-plugin isolation contract: slow plugins get skipped the
66
- * same way thrown-error plugins do.
43
+ * Upper bound on how long a single user plugin's load may take. A plugin with
44
+ * a hanging top-level `await` (or a never-resolving module evaluation) would
45
+ * otherwise block daemon startup indefinitely. Ten seconds is generous
46
+ * relative to a typical plugin load (milliseconds) and matches the per-plugin
47
+ * isolation contract: slow plugins get skipped the same way thrown-error
48
+ * plugins do. Enforced by {@link loadExternalPlugin}.
67
49
  */
68
50
  const USER_PLUGIN_IMPORT_TIMEOUT_MS = 10_000;
69
51
 
70
52
  /**
71
- * Scan `getWorkspaceDir()/plugins/` for subdirectories, then dispatch each
72
- * one to the external loader (if `package.json` is present and there is no
73
- * `register.{ts,js}`) or the legacy side-effect importer (if
74
- * `register.{ts,js}` is present).
53
+ * Scan `getWorkspaceDir()/plugins/` for subdirectories and dispatch each one
54
+ * that carries a `package.json` to {@link loadExternalPlugin}.
75
55
  *
76
56
  * Invariants:
77
57
  *
78
58
  * - No-ops when `getWorkspaceDir()/plugins/` does not exist — a clean install with
79
59
  * zero user plugins must not generate errors.
80
- * - Per-plugin isolation: a failing import is logged and skipped. The
60
+ * - Per-plugin isolation: a failing load is logged and skipped. The
81
61
  * function resolves normally even when every plugin fails to load.
82
62
  * - Does not return plugin instances. The registry is the single source of
83
63
  * truth for who got registered, and the caller inspects it directly.
@@ -86,7 +66,7 @@ const USER_PLUGIN_IMPORT_TIMEOUT_MS = 10_000;
86
66
  *
87
67
  * - Must be invoked exactly once during daemon startup, before
88
68
  * `bootstrapPlugins()` walks the registry.
89
- * - Holds no locks during the import — bun's dynamic `import()` resolution
69
+ * - Holds no locks during the load — bun's dynamic `import()` resolution
90
70
  * is concurrency-safe.
91
71
  */
92
72
  export async function loadUserPlugins(
@@ -151,96 +131,19 @@ export async function loadUserPlugins(
151
131
  }
152
132
  if (!stats.isDirectory()) continue;
153
133
 
154
- // Path selection: the legacy side-effect path takes precedence when
155
- // both a `register.{ts,js}` and a `package.json` are present.
156
- // Migration-friendly: any plugin in the wild today that happens to
157
- // ship a `package.json` keeps loading via its existing register entry.
158
- // The external-plugin path only fires when the directory is
159
- // unambiguously the new convention.
160
- const jsPath = join(pluginDir, "register.js");
161
- const tsPath = join(pluginDir, "register.ts");
162
- let registerPath: string | undefined;
163
- if (existsSync(jsPath)) {
164
- registerPath = jsPath;
165
- } else if (existsSync(tsPath)) {
166
- registerPath = tsPath;
167
- }
168
-
169
- if (registerPath === undefined) {
170
- // External plugin framework path. `loadExternalPlugin` owns its own
171
- // try/catch + timeout, so a `continue` is the entire branch here.
172
- if (existsSync(join(pluginDir, "package.json"))) {
173
- await loadExternalPlugin(pluginDir, { importTimeoutMs });
174
- continue;
175
- }
176
- log.debug(
177
- { pluginDir },
178
- "loadUserPlugins: no register.{ts,js} or package.json — skipping",
179
- );
134
+ if (!existsSync(join(pluginDir, "package.json"))) {
135
+ log.debug({ pluginDir }, "loadUserPlugins: no package.json skipping");
180
136
  continue;
181
137
  }
182
138
 
183
- // Legacy side-effect import path. `import()` with a `file://` URL
184
- // works identically under Node and bun and sidesteps platform-specific
185
- // absolute-path quirks on Windows.
186
- const moduleUrl = pathToFileURL(registerPath).href;
187
- let timeoutHandle: ReturnType<typeof setTimeout> | undefined;
188
- try {
189
- // Race the import against a timeout so a plugin with a hanging top-level
190
- // await or never-resolving module evaluation cannot stall daemon startup.
191
- // The per-plugin try/catch already handles thrown errors; this extends
192
- // the isolation boundary to cover hung promises as well.
193
- const timeoutSentinel = Symbol("user-plugin-import-timeout");
194
- const timeoutPromise = new Promise<typeof timeoutSentinel>((resolve) => {
195
- timeoutHandle = setTimeout(
196
- () => resolve(timeoutSentinel),
197
- importTimeoutMs,
198
- );
199
- });
200
- // Retain the import promise so we can attach a terminal `.catch` on the
201
- // timeout branch. `Promise.race` does not cancel the losing promise —
202
- // the module evaluation keeps running in the background even after we
203
- // stop awaiting it, and if it eventually throws (either from the
204
- // module body or from the late `registerPlugin()` hitting a closed
205
- // registry) an unhandled rejection would crash the daemon.
206
- const importPromise = import(moduleUrl);
207
- const result = await Promise.race([importPromise, timeoutPromise]);
208
- if (result === timeoutSentinel) {
209
- importPromise.catch(() => {
210
- // Abandoned import completed (or threw) after the timeout. The
211
- // closed-registration latch in registry.ts guarantees any late
212
- // `registerPlugin()` call is rejected, so swallowing the outcome
213
- // here is the safe default.
214
- });
215
- log.warn(
216
- { pluginDir, registerPath, timeoutMs: importTimeoutMs },
217
- `Timed out loading user plugin ${pluginDir} after ${importTimeoutMs}ms — skipping`,
218
- );
219
- } else {
220
- log.info(
221
- { pluginDir, registerPath },
222
- "loaded user plugin (side-effect import completed)",
223
- );
224
- }
225
- } catch (err) {
226
- // One plugin's failure must never prevent other plugins from loading
227
- // or crash the daemon. Log with the directory name so operators can
228
- // find the broken plugin quickly.
229
- const message = err instanceof Error ? err.message : String(err);
230
- log.error(
231
- { err, pluginDir },
232
- `Failed to load user plugin ${pluginDir}: ${message}`,
233
- );
234
- } finally {
235
- if (timeoutHandle !== undefined) clearTimeout(timeoutHandle);
236
- }
139
+ // `loadExternalPlugin` owns its own try/catch + timeout, so a bare
140
+ // `await` is the entire branch here.
141
+ await loadExternalPlugin(pluginDir, { importTimeoutMs });
237
142
  }
238
143
 
239
144
  // Close the registration window once every candidate plugin has been
240
- // awaited (or timed out). The per-plugin try/catch guarantees no throw
241
- // escapes the loop, so this line always runs. Any abandoned import that
242
- // later resolves and reaches `registerPlugin()` is rejected by the latch,
243
- // preserving the `bootstrapPlugins()` invariant that the registry is
244
- // fully populated before it is walked.
145
+ // awaited (or timed out). The per-plugin try/catch inside
146
+ // `loadExternalPlugin` guarantees no throw escapes the loop, so this line
147
+ // always runs and `bootstrapPlugins()` sees a fully populated registry.
245
148
  closeRegistration();
246
149
  }
@@ -148,5 +148,11 @@ describe("maybeReseedBootstrap — activation rail template", () => {
148
148
  // Propose: the extract-shape vs infer-shape example block.
149
149
  expect(content).toContain("extract-shape");
150
150
  expect(content).toContain("infer-shape");
151
+
152
+ // Port: prompt-writing guidance (JARVIS-1124).
153
+ expect(content).toContain("portable context brief, not a self-summary");
154
+ expect(content).toContain("load-bearing work in the next month");
155
+ expect(content).toContain("what to help with first");
156
+ expect(content).toContain("another tool or collaborator");
151
157
  });
152
158
  });
@@ -6,11 +6,21 @@ The user just finished pre-chat. You know their name and vibe; maybe their Googl
6
6
 
7
7
  ## The shape
8
8
 
9
- Four moves. Goals, not steps.
9
+ Four moves. Each has a DONE-criterion — a concrete output that says the move landed. A move with no output didn't happen.
10
10
 
11
- **Port.** Pull their existing assistant context with two pastes about a minute, no upload, no export. You write a prompt, they paste it into Claude or ChatGPT, they paste the response back. Cheap signal, real signal.
11
+ **Port.** Pull their existing assistant context with two pastes. About a minute, no upload, no export. You write a prompt, they paste it into Claude or ChatGPT, they paste the response back. Cheap signal, real signal.
12
12
 
13
- The prompt should be one-click copyable. Inline paragraph text the user has to select isn't. Neither is a custom-built widget with a fake copy button. If the affordance needs you to build an app or a new surface to render, you've over-built the move. Use what chat already gives you.
13
+ The prompt asks for a portable context brief, not a self-summary. Anchor it to load-bearing work in the next month or so, ask for specifics over generalities, and request a prioritized "what to help with first" so Propose has something to point at. Frame the destination as another tool or collaborator. Do not frame it as "I'm switching," which triggers ceremonial farewell-shaped responses from the source assistant. Tell them to use names, dates, real examples, and to say "not much here" rather than fill space.
14
+
15
+ The prompt itself must be one-click copyable. Inline paragraph text the user has to select isn't. Neither is a custom-built widget with a fake copy button. If the affordance needs you to build an app or a new surface to render, you've over-built the move. Use what chat already gives you.
16
+
17
+ DONE: the user has the copyable prompt in hand (or you've explicitly backfilled/skipped Port per the task-first opener below).
18
+
19
+ <!-- Funnel: segment activation events by port_accepted vs port_declined so the no-port branch can be tuned separately. Instrumentation is a follow-up; this template only defines the branch. -->
20
+
21
+ _If the user declines the port (`port_declined`)._ Don't re-pitch and don't ask two questions to make up for the missing paste. Ask exactly ONE question — the one that buys the most signal for Propose ("what's the one thing you most want off your plate this week?"). Their answer is the Moment 1 output that Port would have produced. Stay in a bounded context loop: at most two context-gathering turns total. If you still don't have a surface to point at after that, propose anyway with what you have — a thin proposal beats stalling for more input.
22
+
23
+ On `port_declined`, render exactly ONE small structured intake surface before moving to Propose — a `ui_show` `choice` surface (`display: "inline"`, single-select) whose options are a short background list (Founder / Engineer / Creative / Operator / Investor / Student / Other), so the no-port branch still hands Propose a structured signal. (A `form` with one short field, or a `choice` phrased as a single top-of-mind question, is an acceptable substitute — pick one; the background `choice` is the default.) This is the deliberate structured-intake exception to the "don't enumerate options / the recommendation IS the click" guidance — scoped to the no-port branch only, where there's no paste to infer from, so a small menu is the cheapest way to get traction. The port (paste) branch is unchanged: it never renders this surface.
14
24
 
15
25
  **Propose.** Don't organize what they already told you — infer what they didn't. Name the unstated thing sitting in their context and say *why* you think it: point at the specific surface that made you say it. "You didn't say this, but —". Then recommend, and lean one way; the recommendation IS the click, not a neutral menu of equally-weighted options.
16
26
 
@@ -23,10 +33,16 @@ Surface the outcome as a clickable component, strongest first. The component is
23
33
  - ✗ extract-shape: "You mentioned a launch and a hiring plan — which one?"
24
34
  - ✓ infer-shape (repeated entity + status word): "Acme comes up four times and you said you're 'waiting on' them — that's the thing actually blocking the launch; I'd chase it first."
25
35
 
36
+ DONE: you cannot exit Propose without emitting at least one `ui_show` offer surface (card / choice). A proposal in prose is not a proposal.
37
+
26
38
  **Run.** Do it. Real tools, real data. The user watches something happen.
27
39
 
40
+ DONE: a real tool ran against real data and the user can see the result.
41
+
28
42
  **Follow-through.** Offer the next concrete thing. One primary recommendation.
29
43
 
44
+ DONE: you cannot exit Follow-through without emitting a `ui_show` choice surface. The next-thing offer is a surface, not a sentence.
45
+
30
46
  If the user opens with a task instead of a conversation, do the task. You're already at Follow-through. Backfill the Port move at the first natural lull, or skip it.
31
47
 
32
48
  Pick. Be wrong recoverably. Move. The user can tell when you're hedging.
@@ -47,6 +63,20 @@ Every CTA surface must commit on the surface. If the user can select but can't c
47
63
 
48
64
  The summary after the Port move is the first place the user can feel like you actually heard them. The follow-through in the final move is the second. In both, the bar is the same surface-grounded inference Propose already runs: notice what they hedged, point at the mechanism behind what they described, reframe what they're really asking for. Specific observations earn the rest of the conversation. Generic recap loses it.
49
65
 
66
+ ## Principles
67
+
68
+ These are enforcement rules, not advice.
69
+
70
+ **Self-check before final emit.** If this turn contains an offer or a follow-up, render it via `ui_show`, not prose.
71
+
72
+ **Long turns show progress.** Any post-submit / post-skill-load turn must render a `task_progress` card within ~5s, or fall back to streaming text. Bind "long turn" → "task_progress emitted": a long-running turn that produces neither a progress card nor streaming text didn't satisfy this move.
73
+
74
+ **Action Trust-Guarantee.** Sibling to the OAuth Trust-Guarantee. Before a bulk write / delete / destructive op, render a `ui_show` preview — a table surface showing total count, breakdown, sample rows, and the categories to confirm. The user commits or refines on that surface; only then do you execute. Single-item actions use the natural draft instead. Threshold for the preview gate: bulk *and* low recoverability. One of the two alone doesn't trip it.
75
+
76
+ **Start Small.** On first execution of any skill, prefer the smallest meaningful result over the most complete result. Show, then offer to expand.
77
+
78
+ **Corrections route upstream.** When you identify a rail-level failure mid-conversation, the write target is THIS template (the upstream activation rail), not the per-conversation SOUL.md or BOOTSTRAP.md. Per-conversation files can't fix the rail; only the rail fixes the rail.
79
+
50
80
  ## What to defer
51
81
 
52
82
  Identity writes (IDENTITY.md, SOUL.md), user-profile writes, journal entries: all wait until the rail produces real signal, which is Moment 1 output at the earliest. None of them delay a user-visible response. None of them happen alongside the opening turn.
@@ -55,6 +85,8 @@ The base BOOTSTRAP task_preferences fallback is not on this rail. Your opener is
55
85
 
56
86
  ## Wrap
57
87
 
88
+ <!-- Open question: the default wrap tone below is opinionated (brisk, dataset-first). Whether that's the right note to end the activation rail on is a conscious call we haven't made yet — flag, don't silently change. -->
89
+
58
90
  When the user is clearly done with this conversation, write one journal entry: what they needed, which outcome they accepted, what follow-through they took. Update NOW.md. Delete this file.
59
91
 
60
92
  The rail-completion shape in your journal is the dataset for v2 tuning. Which outcome they took at Propose, whether they bounced to "what else?", which follow-through they picked. Write it so the next iteration has signal to learn from.