@vellumai/assistant 0.8.1 → 0.8.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 (506) hide show
  1. package/ARCHITECTURE.md +2 -7
  2. package/Dockerfile +75 -1
  3. package/bun.lock +11 -1
  4. package/docker-entrypoint.sh +5 -0
  5. package/docker-init-apt-root.sh +94 -0
  6. package/docker-kata-apt-env.sh +39 -0
  7. package/docs/plugins.md +88 -47
  8. package/docs/skills.md +9 -7
  9. package/examples/plugins/echo/README.md +27 -27
  10. package/examples/plugins/echo/package.json +3 -0
  11. package/examples/plugins/echo/register.ts +31 -31
  12. package/node_modules/@vellumai/slack-text/src/index.test.ts +114 -14
  13. package/node_modules/@vellumai/slack-text/src/index.ts +82 -18
  14. package/openapi.yaml +325 -3
  15. package/package.json +3 -1
  16. package/scripts/generate-openapi.ts +83 -10
  17. package/scripts/sync-llm-catalog.ts +2 -2
  18. package/scripts/sync-web-search-catalog.ts +47 -25
  19. package/src/__tests__/agent-image-optimize.test.ts +11 -3
  20. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +131 -0
  21. package/src/__tests__/anthropic-provider.test.ts +45 -0
  22. package/src/__tests__/app-builder-tool-scripts.test.ts +9 -3
  23. package/src/__tests__/app-executors.test.ts +220 -4
  24. package/src/__tests__/auto-analysis-end-to-end.test.ts +35 -0
  25. package/src/__tests__/bundled-asset.test.ts +6 -6
  26. package/src/__tests__/channel-availability-routes.test.ts +206 -0
  27. package/src/__tests__/channel-delivery-store.test.ts +289 -1
  28. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -1
  29. package/src/__tests__/clawhub.test.ts +75 -16
  30. package/src/__tests__/compactor-tail-resolution.test.ts +41 -0
  31. package/src/__tests__/config-schema.test.ts +21 -0
  32. package/src/__tests__/config-set-route.test.ts +80 -0
  33. package/src/__tests__/config-sounds-sync.test.ts +97 -0
  34. package/src/__tests__/config-watcher-skill-reseed.test.ts +453 -0
  35. package/src/__tests__/context-search-conversations-source.test.ts +117 -2
  36. package/src/__tests__/context-search-memory-v2-source.test.ts +0 -1
  37. package/src/__tests__/context-search-workspace-source.test.ts +7 -0
  38. package/src/__tests__/context-token-estimator.test.ts +1 -0
  39. package/src/__tests__/conversation-abort-tool-results.test.ts +4 -1
  40. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
  41. package/src/__tests__/conversation-agent-loop-overflow.test.ts +92 -92
  42. package/src/__tests__/conversation-agent-loop.test.ts +2 -0
  43. package/src/__tests__/conversation-error.test.ts +42 -3
  44. package/src/__tests__/conversation-fork-crud.test.ts +82 -0
  45. package/src/__tests__/conversation-inference-profile-route.test.ts +40 -4
  46. package/src/__tests__/conversation-lifecycle.test.ts +173 -0
  47. package/src/__tests__/conversation-message-sync-tags.test.ts +97 -0
  48. package/src/__tests__/conversation-pairing.test.ts +54 -0
  49. package/src/__tests__/conversation-process-callsite.test.ts +4 -1
  50. package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -1
  51. package/src/__tests__/conversation-queue.test.ts +4 -1
  52. package/src/__tests__/conversation-runtime-assembly.test.ts +76 -9
  53. package/src/__tests__/conversation-slash-queue.test.ts +59 -1
  54. package/src/__tests__/conversation-slash-unknown.test.ts +4 -1
  55. package/src/__tests__/conversation-surfaces-table-action.test.ts +360 -0
  56. package/src/__tests__/conversation-sync-tags.test.ts +235 -0
  57. package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
  58. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
  59. package/src/__tests__/credential-security-invariants.test.ts +3 -2
  60. package/src/__tests__/db-slack-external-content-normalization.test.ts +301 -0
  61. package/src/__tests__/delete-managed-skill-tool.test.ts +55 -13
  62. package/src/__tests__/disk-pressure-tools.test.ts +1 -0
  63. package/src/__tests__/dm-backfill.test.ts +121 -10
  64. package/src/__tests__/document-tool-security.test.ts +258 -0
  65. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
  66. package/src/__tests__/edit-propagation.test.ts +33 -0
  67. package/src/__tests__/empty-response-pipeline.test.ts +0 -4
  68. package/src/__tests__/external-plugin-loader.test.ts +60 -36
  69. package/src/__tests__/filing-service.test.ts +140 -0
  70. package/src/__tests__/get-skill-detail-audit.test.ts +0 -4
  71. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +43 -62
  72. package/src/__tests__/helpers/tar-fixtures.ts +39 -0
  73. package/src/__tests__/helpers/wait-for.ts +21 -0
  74. package/src/__tests__/history-repair-pipeline.test.ts +0 -3
  75. package/src/__tests__/history-repair.test.ts +73 -0
  76. package/src/__tests__/host-app-control-proxy.test.ts +266 -10
  77. package/src/__tests__/image-credentials.test.ts +1 -1
  78. package/src/__tests__/inbound-slack-persistence.test.ts +2 -0
  79. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +1 -1
  80. package/src/__tests__/inference-profile-reaper.test.ts +4 -2
  81. package/src/__tests__/inference-profile-session-handler.test.ts +18 -6
  82. package/src/__tests__/inference-profile-session-ipc.test.ts +17 -5
  83. package/src/__tests__/injector-chain.test.ts +10 -8
  84. package/src/__tests__/install-skill-routing.test.ts +155 -37
  85. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +92 -3
  86. package/src/__tests__/list-messages-page-latest.test.ts +55 -0
  87. package/src/__tests__/llm-call-pipeline.test.ts +0 -3
  88. package/src/__tests__/llm-catalog-parity.test.ts +55 -13
  89. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +34 -0
  90. package/src/__tests__/llm-request-log-source-factory.test.ts +29 -53
  91. package/src/__tests__/llm-usage-store.test.ts +114 -0
  92. package/src/__tests__/managed-profile-guard.test.ts +31 -29
  93. package/src/__tests__/managed-skill-lifecycle.test.ts +109 -18
  94. package/src/__tests__/managed-store.test.ts +84 -192
  95. package/src/__tests__/media-generate-image.test.ts +1 -1
  96. package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -2
  97. package/src/__tests__/messages-after-tiebreaker.test.ts +122 -0
  98. package/src/__tests__/oauth-commands-routes.test.ts +168 -16
  99. package/src/__tests__/oauth-provider-profiles.test.ts +9 -0
  100. package/src/__tests__/openai-provider.test.ts +24 -0
  101. package/src/__tests__/openai-responses-cutover-guard.test.ts +17 -9
  102. package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -2
  103. package/src/__tests__/persistence-pipeline.test.ts +0 -2
  104. package/src/__tests__/{managed-proxy-context.test.ts → platform-proxy-context.test.ts} +1 -1
  105. package/src/__tests__/platform.test.ts +2 -0
  106. package/src/__tests__/plugin-api-shim.test.ts +125 -0
  107. package/src/__tests__/plugin-bootstrap.test.ts +10 -36
  108. package/src/__tests__/plugin-external-api.test.ts +68 -0
  109. package/src/__tests__/plugin-registry.test.ts +0 -77
  110. package/src/__tests__/plugin-route-contribution.test.ts +0 -1
  111. package/src/__tests__/plugin-skill-contribution.test.ts +0 -2
  112. package/src/__tests__/plugin-tool-contribution.test.ts +16 -15
  113. package/src/__tests__/plugin-types.test.ts +3 -13
  114. package/src/__tests__/process-message-background-slack.test.ts +8 -1
  115. package/src/__tests__/process-message-display-content.test.ts +421 -0
  116. package/src/__tests__/provider-catalog-visibility.test.ts +142 -0
  117. package/src/__tests__/provider-error-scenarios.test.ts +111 -0
  118. package/src/__tests__/{provider-managed-proxy-integration.test.ts → provider-platform-proxy-integration.test.ts} +8 -8
  119. package/src/__tests__/scaffold-managed-skill-tool.test.ts +65 -13
  120. package/src/__tests__/schedule-routes.test.ts +50 -3
  121. package/src/__tests__/schedule-store.test.ts +94 -0
  122. package/src/__tests__/scheduler-reuse-conversation.test.ts +54 -7
  123. package/src/__tests__/schema-transforms.test.ts +20 -0
  124. package/src/__tests__/search-skills-unified.test.ts +0 -5
  125. package/src/__tests__/server-history-render.test.ts +43 -0
  126. package/src/__tests__/skill-load-feature-flag.test.ts +0 -12
  127. package/src/__tests__/skill-load-tool.test.ts +27 -89
  128. package/src/__tests__/skill-memory.test.ts +23 -3
  129. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -38
  130. package/src/__tests__/skills-files-catalog-fallback.test.ts +0 -3
  131. package/src/__tests__/skills-install-extract.test.ts +49 -38
  132. package/src/__tests__/skills-install-staging.test.ts +159 -0
  133. package/src/__tests__/skills-uninstall.test.ts +9 -41
  134. package/src/__tests__/skills.test.ts +51 -58
  135. package/src/__tests__/slack-channel-config.test.ts +9 -0
  136. package/src/__tests__/subagent-tool-filtering.test.ts +50 -0
  137. package/src/__tests__/system-prompt.test.ts +737 -63
  138. package/src/__tests__/terminal-tools.test.ts +28 -1
  139. package/src/__tests__/thread-backfill.test.ts +557 -27
  140. package/src/__tests__/title-generate-pipeline.test.ts +0 -13
  141. package/src/__tests__/token-estimate-pipeline.test.ts +0 -3
  142. package/src/__tests__/tool-error-pipeline.test.ts +0 -3
  143. package/src/__tests__/tool-execute-pipeline.test.ts +0 -5
  144. package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
  145. package/src/__tests__/tool-executor.test.ts +16 -4
  146. package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -12
  147. package/src/__tests__/turn-events-store.test.ts +256 -0
  148. package/src/__tests__/twilio-routes.test.ts +4 -0
  149. package/src/__tests__/user-plugin-loader.test.ts +0 -7
  150. package/src/__tests__/voice-session-bridge.test.ts +198 -0
  151. package/src/__tests__/web-search-catalog-parity.test.ts +32 -10
  152. package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +115 -3
  153. package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +50 -0
  154. package/src/__tests__/workspace-migration-073-repair-recall-callsite-empty-profile.test.ts +153 -0
  155. package/src/__tests__/workspace-migration-085-memory-v2-bm25-b-reembed-disabled-v2-pages.test.ts +220 -0
  156. package/src/__tests__/workspace-migration-086-revert-stale-gemini-mis-rewrites.test.ts +269 -0
  157. package/src/__tests__/workspace-migration-remove-legacy-skills-index.test.ts +309 -0
  158. package/src/__tests__/workspace-migrations-runner.test.ts +111 -3
  159. package/src/acp/resolve-agent.ts +1 -1
  160. package/src/agent/image-optimize.ts +13 -5
  161. package/src/calls/voice-session-bridge.ts +61 -42
  162. package/src/channels/types.ts +108 -0
  163. package/src/cli/__tests__/unknown-command.test.ts +24 -0
  164. package/src/cli/commands/__tests__/changelog.test.ts +304 -319
  165. package/src/cli/commands/__tests__/schedules.test.ts +491 -0
  166. package/src/cli/commands/changelog.ts +106 -42
  167. package/src/cli/commands/conversations.ts +102 -17
  168. package/src/cli/commands/default-action.ts +10 -53
  169. package/src/cli/commands/notifications.ts +329 -317
  170. package/src/cli/commands/plugins.ts +185 -0
  171. package/src/cli/commands/schedules.ts +391 -0
  172. package/src/cli/commands/telemetry.ts +40 -0
  173. package/src/cli/lib/__tests__/cli-colors.test.ts +48 -0
  174. package/src/cli/lib/__tests__/confirm-prompt.test.ts +159 -0
  175. package/src/cli/lib/__tests__/install-from-github.test.ts +355 -0
  176. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +154 -0
  177. package/src/cli/lib/__tests__/uninstall-plugin.test.ts +124 -0
  178. package/src/cli/lib/__tests__/unknown-command.test.ts +106 -0
  179. package/src/cli/lib/cli-colors.ts +12 -0
  180. package/src/cli/lib/confirm-prompt.ts +79 -0
  181. package/src/cli/lib/install-from-github.ts +304 -0
  182. package/src/cli/lib/list-installed-plugins.ts +137 -0
  183. package/src/cli/lib/uninstall-plugin.ts +82 -0
  184. package/src/cli/lib/unknown-command.ts +111 -0
  185. package/src/cli/program.ts +38 -2
  186. package/src/config/bundled-skills/app-builder/SKILL.md +23 -21
  187. package/src/config/bundled-skills/app-builder/TOOLS.json +7 -0
  188. package/src/config/bundled-skills/computer-use/TOOLS.json +15 -52
  189. package/src/config/bundled-skills/document/SKILL.md +23 -3
  190. package/src/config/bundled-skills/document/TOOLS.json +53 -0
  191. package/src/config/bundled-skills/document/tools/document-delete.ts +12 -0
  192. package/src/config/bundled-skills/document/tools/document-list.ts +12 -0
  193. package/src/config/bundled-skills/document/tools/document-read.ts +12 -0
  194. package/src/config/bundled-skills/skill-management/SKILL.md +2 -2
  195. package/src/config/bundled-skills/skill-management/TOOLS.json +7 -7
  196. package/src/config/bundled-tool-registry.ts +6 -0
  197. package/src/config/feature-flag-registry.json +41 -1
  198. package/src/config/loader.ts +64 -38
  199. package/src/config/schema.ts +7 -10
  200. package/src/config/schemas/__tests__/llm-request-logs.test.ts +36 -0
  201. package/src/config/schemas/channels.ts +8 -0
  202. package/src/config/schemas/compaction.ts +28 -0
  203. package/src/config/schemas/heartbeat.ts +9 -0
  204. package/src/config/schemas/llm-request-logs.ts +31 -7
  205. package/src/config/schemas/llm.ts +3 -0
  206. package/src/config/schemas/memory-retrieval.ts +18 -0
  207. package/src/config/schemas/tools.ts +14 -0
  208. package/src/config/skills.ts +3 -96
  209. package/src/context/compactor.ts +1047 -0
  210. package/src/context/token-estimator.ts +2 -2
  211. package/src/context/window-manager.ts +197 -1520
  212. package/src/credential-execution/managed-catalog.ts +37 -0
  213. package/src/credential-health/credential-health-service.ts +280 -19
  214. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +34 -0
  215. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +138 -0
  216. package/src/daemon/__tests__/conversation-tool-setup.test.ts +74 -0
  217. package/src/daemon/approval-generators.ts +8 -6
  218. package/src/daemon/config-watcher.ts +94 -31
  219. package/src/daemon/conversation-agent-loop.ts +169 -9
  220. package/src/daemon/conversation-error.ts +171 -37
  221. package/src/daemon/conversation-lifecycle.ts +53 -40
  222. package/src/daemon/conversation-messaging.ts +25 -6
  223. package/src/daemon/conversation-process.ts +49 -12
  224. package/src/daemon/conversation-runtime-assembly.ts +16 -1
  225. package/src/daemon/conversation-slash.ts +12 -5
  226. package/src/daemon/conversation-store.ts +11 -4
  227. package/src/daemon/conversation-tool-setup.ts +39 -7
  228. package/src/daemon/conversation.ts +33 -1
  229. package/src/daemon/external-plugins-bootstrap.ts +217 -181
  230. package/src/daemon/first-greeting.ts +22 -2
  231. package/src/daemon/handlers/config-model.ts +6 -5
  232. package/src/daemon/handlers/config-slack-channel.ts +15 -3
  233. package/src/daemon/handlers/shared.ts +14 -5
  234. package/src/daemon/handlers/skills.ts +111 -108
  235. package/src/daemon/history-repair.ts +28 -1
  236. package/src/daemon/host-app-control-proxy.ts +98 -23
  237. package/src/daemon/lifecycle.ts +45 -35
  238. package/src/daemon/meet-host-supervisor.ts +5 -4
  239. package/src/daemon/memory-v2-startup.ts +49 -0
  240. package/src/daemon/message-protocol.ts +1 -0
  241. package/src/daemon/message-types/conversations.ts +25 -0
  242. package/src/daemon/message-types/messages.ts +61 -0
  243. package/src/daemon/message-types/subagents.ts +1 -0
  244. package/src/daemon/message-types/sync.ts +1 -0
  245. package/src/daemon/pkb-reminder-builder.test.ts +1 -1
  246. package/src/daemon/pkb-reminder-builder.ts +1 -1
  247. package/src/daemon/plugin-source-watcher.ts +146 -0
  248. package/src/daemon/process-message.ts +21 -3
  249. package/src/daemon/server.ts +11 -2
  250. package/src/daemon/skill-memory-refresh.ts +29 -0
  251. package/src/documents/document-store.ts +221 -3
  252. package/src/embedded/plugin-api.ts +40 -0
  253. package/src/filing/filing-service.ts +39 -0
  254. package/src/heartbeat/__tests__/heartbeat-service.test.ts +91 -6
  255. package/src/heartbeat/heartbeat-run-store.ts +2 -1
  256. package/src/heartbeat/heartbeat-service.ts +41 -0
  257. package/src/home/__tests__/feed-types.test.ts +40 -0
  258. package/src/home/feed-types.ts +22 -0
  259. package/src/home/post-connect-feed.ts +1 -0
  260. package/src/index.ts +18 -1
  261. package/src/live-voice/__tests__/live-voice-stt.test.ts +57 -0
  262. package/src/mcp/client.ts +20 -4
  263. package/src/media/image-credentials.ts +3 -3
  264. package/src/memory/__tests__/bookmark-crud.test.ts +33 -27
  265. package/src/memory/__tests__/conversation-queries.test.ts +263 -0
  266. package/src/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +113 -0
  267. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +119 -14
  268. package/src/memory/__tests__/message-content.test.ts +35 -0
  269. package/src/memory/bookmark-crud.ts +42 -10
  270. package/src/memory/context-search/sources/conversations.ts +62 -2
  271. package/src/memory/context-search/sources/workspace.ts +4 -0
  272. package/src/memory/conversation-crud.ts +63 -19
  273. package/src/memory/conversation-queries.ts +110 -10
  274. package/src/memory/db-init.ts +6 -0
  275. package/src/memory/delivery-crud.ts +152 -5
  276. package/src/memory/embedding-backend.ts +4 -4
  277. package/src/memory/external-conversation-store.ts +66 -5
  278. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +66 -9
  279. package/src/memory/graph/conversation-graph-memory.ts +31 -15
  280. package/src/memory/graph/tools.ts +3 -3
  281. package/src/memory/indexer.ts +34 -29
  282. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +73 -0
  283. package/src/memory/jobs/embed-concept-page.ts +20 -11
  284. package/src/memory/jobs-worker.ts +6 -1
  285. package/src/memory/llm-request-log-source-clickhouse.ts +17 -10
  286. package/src/memory/llm-request-log-source.ts +19 -52
  287. package/src/memory/llm-usage-store.ts +125 -5
  288. package/src/memory/memory-retrospective-startup-cleanup.ts +72 -5
  289. package/src/memory/message-content.ts +1 -1
  290. package/src/memory/migrations/109-external-conversation-bindings.ts +15 -4
  291. package/src/memory/migrations/229-delete-private-conversations.test.ts +38 -1
  292. package/src/memory/migrations/229-delete-private-conversations.ts +7 -0
  293. package/src/memory/migrations/247-external-conversation-binding-thread-id.ts +78 -0
  294. package/src/memory/migrations/248-create-onboarding-events.ts +21 -0
  295. package/src/memory/migrations/249-normalize-slack-external-content.ts +240 -0
  296. package/src/memory/migrations/index.ts +6 -0
  297. package/src/memory/migrations/registry.ts +8 -0
  298. package/src/memory/onboarding-events-store.ts +106 -0
  299. package/src/memory/schema/bookmarks.ts +0 -2
  300. package/src/memory/schema/calls.ts +1 -0
  301. package/src/memory/schema/inference.ts +1 -3
  302. package/src/memory/schema/infrastructure.ts +12 -0
  303. package/src/memory/turn-events-store.ts +127 -2
  304. package/src/memory/v2/__tests__/activation.test.ts +0 -8
  305. package/src/memory/v2/__tests__/injection.test.ts +98 -8
  306. package/src/memory/v2/__tests__/migration.test.ts +87 -0
  307. package/src/memory/v2/__tests__/page-index.test.ts +83 -0
  308. package/src/memory/v2/__tests__/prompts-router.test.ts +58 -6
  309. package/src/memory/v2/__tests__/qdrant.test.ts +66 -3
  310. package/src/memory/v2/__tests__/router.test.ts +15 -0
  311. package/src/memory/v2/__tests__/skill-store.test.ts +387 -8
  312. package/src/memory/v2/injection.ts +32 -6
  313. package/src/memory/v2/migration.ts +49 -19
  314. package/src/memory/v2/page-index.ts +35 -5
  315. package/src/memory/v2/prompts/router.ts +11 -8
  316. package/src/memory/v2/prompts/sweep.ts +2 -2
  317. package/src/memory/v2/qdrant.ts +135 -7
  318. package/src/memory/v2/router.ts +9 -8
  319. package/src/memory/v2/skill-store.ts +120 -35
  320. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +45 -5
  321. package/src/messaging/providers/slack/__tests__/download.test.ts +231 -0
  322. package/src/messaging/providers/slack/adapter.ts +43 -5
  323. package/src/messaging/providers/slack/client.ts +27 -0
  324. package/src/messaging/providers/slack/deep-link.ts +65 -0
  325. package/src/messaging/providers/slack/download.ts +104 -0
  326. package/src/messaging/providers/slack/message-metadata.test.ts +32 -0
  327. package/src/messaging/providers/slack/message-metadata.ts +27 -0
  328. package/src/messaging/providers/slack/render-transcript.test.ts +134 -0
  329. package/src/messaging/providers/slack/render-transcript.ts +69 -5
  330. package/src/messaging/providers/slack/types.ts +20 -1
  331. package/src/notifications/conversation-pairing.ts +2 -1
  332. package/src/notifications/decision-engine.ts +2 -1
  333. package/src/notifications/emit-signal.ts +20 -1
  334. package/src/notifications/home-feed-side-effect.ts +54 -0
  335. package/src/notifications/signal.ts +3 -1
  336. package/src/oauth/connection-resolver.ts +8 -4
  337. package/src/oauth/platform-connection.ts +6 -2
  338. package/src/oauth/seed-providers.ts +10 -1
  339. package/src/permissions/checker.ts +2 -0
  340. package/src/permissions/ipc-risk-types.ts +1 -0
  341. package/src/permissions/question-prompter.test.ts +416 -0
  342. package/src/permissions/question-prompter.ts +294 -0
  343. package/src/platform/client.test.ts +1 -1
  344. package/src/platform/client.ts +1 -1
  345. package/src/plugin-api/constants.ts +26 -0
  346. package/src/plugin-api/index.ts +34 -1
  347. package/src/plugin-api/types.ts +104 -22
  348. package/src/plugins/defaults/circuit-breaker.ts +0 -5
  349. package/src/plugins/defaults/compaction.ts +0 -4
  350. package/src/plugins/defaults/empty-response.ts +0 -2
  351. package/src/plugins/defaults/history-repair.ts +0 -2
  352. package/src/plugins/defaults/injectors.ts +36 -3
  353. package/src/plugins/defaults/llm-call.ts +0 -2
  354. package/src/plugins/defaults/memory-retrieval.ts +0 -1
  355. package/src/plugins/defaults/overflow-reduce.ts +0 -1
  356. package/src/plugins/defaults/persistence.ts +0 -2
  357. package/src/plugins/defaults/title-generate.ts +0 -5
  358. package/src/plugins/defaults/token-estimate.ts +0 -2
  359. package/src/plugins/defaults/tool-error.ts +0 -7
  360. package/src/plugins/defaults/tool-execute.ts +0 -2
  361. package/src/plugins/defaults/tool-result-truncate.ts +0 -4
  362. package/src/plugins/ensure-plugin-api-shim.ts +96 -0
  363. package/src/plugins/external-api.ts +104 -0
  364. package/src/plugins/external-plugin-loader.ts +105 -32
  365. package/src/plugins/feature-gate.ts +22 -0
  366. package/src/plugins/pipeline.ts +37 -0
  367. package/src/plugins/registry.ts +48 -80
  368. package/src/plugins/types.ts +31 -26
  369. package/src/plugins/user-loader.ts +21 -2
  370. package/src/proactive-artifact/aux-message-injector.ts +11 -0
  371. package/src/proactive-artifact/job.test.ts +37 -5
  372. package/src/prompts/__tests__/system-prompt.test.ts +12 -0
  373. package/src/prompts/__tests__/task-progress-hint-section.test.ts +99 -0
  374. package/src/prompts/normalize-onboarding.ts +27 -0
  375. package/src/prompts/sections.ts +302 -0
  376. package/src/prompts/system-prompt.ts +63 -166
  377. package/src/prompts/templates/BOOTSTRAP.md +17 -1
  378. package/src/prompts/templates/system-sections.ts +173 -0
  379. package/src/providers/__tests__/inference.test.ts +22 -7
  380. package/src/providers/anthropic/client.ts +28 -28
  381. package/src/providers/connection-resolution.ts +7 -0
  382. package/src/providers/inference/adapter-factory.ts +41 -4
  383. package/src/providers/inference/connections.ts +74 -29
  384. package/src/providers/inference/resolve-auth.ts +12 -4
  385. package/src/providers/model-catalog.ts +294 -12
  386. package/src/providers/openai/chat-completions-provider.ts +10 -2
  387. package/src/providers/openrouter/client.ts +7 -0
  388. package/src/providers/{managed-proxy → platform-proxy}/constants.ts +4 -1
  389. package/src/providers/{managed-proxy → platform-proxy}/context.ts +3 -3
  390. package/src/providers/provider-availability.ts +17 -2
  391. package/src/providers/provider-catalog-visibility.ts +36 -0
  392. package/src/providers/registry.ts +22 -14
  393. package/src/providers/retry.ts +47 -1
  394. package/src/runtime/__tests__/agent-wake.test.ts +152 -0
  395. package/src/runtime/agent-wake.ts +42 -14
  396. package/src/runtime/auth/route-policy.ts +8 -1
  397. package/src/runtime/btw-sidechain.ts +2 -0
  398. package/src/runtime/http-types.ts +19 -0
  399. package/src/runtime/migrations/origin-mode.ts +1 -1
  400. package/src/runtime/pending-interactions.ts +1 -0
  401. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +17 -0
  402. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +5 -1
  403. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +107 -20
  404. package/src/runtime/routes/__tests__/question-routes.test.ts +395 -0
  405. package/src/runtime/routes/__tests__/tts-routes.test.ts +64 -1
  406. package/src/runtime/routes/acp-routes-list.test.ts +143 -0
  407. package/src/runtime/routes/acp-routes.ts +5 -3
  408. package/src/runtime/routes/auth-routes.ts +1 -1
  409. package/src/runtime/routes/bookmark-routes.ts +5 -3
  410. package/src/runtime/routes/btw-routes.ts +5 -1
  411. package/src/runtime/routes/channel-availability-routes.ts +121 -0
  412. package/src/runtime/routes/conversation-cli-routes.ts +44 -3
  413. package/src/runtime/routes/conversation-list-routes.ts +3 -20
  414. package/src/runtime/routes/conversation-management-routes.ts +17 -42
  415. package/src/runtime/routes/conversation-query-routes.ts +40 -35
  416. package/src/runtime/routes/conversation-routes.ts +90 -11
  417. package/src/runtime/routes/documents-routes.ts +25 -86
  418. package/src/runtime/routes/group-routes.ts +5 -0
  419. package/src/runtime/routes/inbound-conversation.ts +28 -8
  420. package/src/runtime/routes/inbound-message-handler.ts +236 -41
  421. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +111 -0
  422. package/src/runtime/routes/inbound-stages/background-dispatch.ts +32 -1
  423. package/src/runtime/routes/inbound-stages/edit-intercept.ts +17 -4
  424. package/src/runtime/routes/index.ts +6 -0
  425. package/src/runtime/routes/inference-profile-session-handler.ts +17 -44
  426. package/src/runtime/routes/inference-profile-session-reaper.ts +7 -21
  427. package/src/runtime/routes/inference-provider-connection-routes.ts +65 -21
  428. package/src/runtime/routes/integrations/slack/share.ts +4 -52
  429. package/src/runtime/routes/integrations/slack/token.ts +43 -0
  430. package/src/runtime/routes/integrations/twilio.ts +6 -13
  431. package/src/runtime/routes/notification-routes.ts +1 -1
  432. package/src/runtime/routes/oauth-commands-routes.ts +105 -15
  433. package/src/runtime/routes/oauth-lifecycle-routes.ts +43 -0
  434. package/src/runtime/routes/question-routes.ts +259 -0
  435. package/src/runtime/routes/rename-conversation-routes.ts +2 -33
  436. package/src/runtime/routes/schedule-routes.ts +4 -7
  437. package/src/runtime/routes/subagents-routes.ts +57 -18
  438. package/src/runtime/routes/telemetry-routes.ts +27 -0
  439. package/src/runtime/routes/tts-routes.ts +27 -2
  440. package/src/runtime/routes/workspace-routes.test.ts +43 -0
  441. package/src/runtime/routes/workspace-routes.ts +28 -0
  442. package/src/runtime/services/conversation-serializer.ts +39 -7
  443. package/src/runtime/sync/resource-sync-events.ts +93 -1
  444. package/src/schedule/schedule-store.ts +27 -2
  445. package/src/schedule/scheduler.ts +9 -1
  446. package/src/security/__tests__/untrusted-content.test.ts +86 -0
  447. package/src/security/untrusted-content.ts +93 -8
  448. package/src/skills/catalog-files.ts +1 -1
  449. package/src/skills/catalog-install.ts +233 -116
  450. package/src/skills/clawhub.ts +70 -13
  451. package/src/skills/managed-store.ts +4 -119
  452. package/src/skills/skillssh-registry.ts +27 -48
  453. package/src/subagent/manager.ts +15 -7
  454. package/src/telemetry/types.ts +113 -1
  455. package/src/telemetry/usage-telemetry-reporter.test.ts +312 -5
  456. package/src/telemetry/usage-telemetry-reporter.ts +113 -7
  457. package/src/tools/apps/executors.ts +58 -7
  458. package/src/tools/ask-question/ask-question-tool.test.ts +509 -0
  459. package/src/tools/ask-question/ask-question-tool.ts +304 -0
  460. package/src/tools/browser/browser-execution.ts +15 -11
  461. package/src/tools/computer-use/definitions.ts +3 -3
  462. package/src/tools/credentials/vault.ts +1 -1
  463. package/src/tools/document/document-tool.ts +124 -1
  464. package/src/tools/filesystem/edit.ts +1 -1
  465. package/src/tools/filesystem/list.ts +1 -1
  466. package/src/tools/filesystem/read.ts +1 -1
  467. package/src/tools/filesystem/write.ts +5 -2
  468. package/src/tools/host-filesystem/transfer.ts +1 -1
  469. package/src/tools/host-terminal/host-shell.ts +1 -1
  470. package/src/tools/permission-checker.ts +1 -1
  471. package/src/tools/registry.ts +17 -7
  472. package/src/tools/schedule/create.ts +2 -2
  473. package/src/tools/schema-transforms.ts +7 -2
  474. package/src/tools/side-effects.ts +1 -0
  475. package/src/tools/skills/delete-managed.ts +4 -4
  476. package/src/tools/skills/execute.ts +1 -1
  477. package/src/tools/skills/scaffold-managed.ts +3 -2
  478. package/src/tools/subagent/notify-parent.ts +1 -1
  479. package/src/tools/system/request-permission.ts +2 -2
  480. package/src/tools/terminal/safe-env.ts +60 -1
  481. package/src/tools/tool-manifest.ts +2 -0
  482. package/src/tools/types.ts +72 -21
  483. package/src/tools/ui-surface/definitions.ts +6 -5
  484. package/src/tts/__tests__/provider-adapters.test.ts +76 -2
  485. package/src/tts/providers/elevenlabs-provider.ts +75 -1
  486. package/src/types/onboarding-context.ts +2 -0
  487. package/src/util/errors.ts +17 -0
  488. package/src/util/platform.ts +10 -0
  489. package/src/watcher/__tests__/engine.test.ts +22 -0
  490. package/src/watcher/engine.ts +6 -2
  491. package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +80 -15
  492. package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +35 -22
  493. package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +3 -1
  494. package/src/workspace/migrations/083-system-prompt-prefix-to-file.ts +191 -0
  495. package/src/workspace/migrations/084-remove-legacy-skills-index.ts +276 -0
  496. package/src/workspace/migrations/085-memory-v2-bm25-b-reembed-disabled-v2-pages.ts +137 -0
  497. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +198 -0
  498. package/src/workspace/migrations/registry.ts +8 -0
  499. package/src/workspace/migrations/runner.ts +39 -9
  500. package/src/workspace/migrations/types.ts +4 -0
  501. package/examples/plugins/echo/bun.lock +0 -25
  502. package/src/__tests__/context-window-manager.test.ts +0 -2481
  503. package/src/context/__tests__/compact-prompt.test.ts +0 -63
  504. package/src/context/prompts/compact.md +0 -26
  505. package/src/prompts/__tests__/build-cli-reference-section.test.ts +0 -37
  506. /package/src/__tests__/{secret-routes-managed-proxy.test.ts → secret-routes-platform-proxy.test.ts} +0 -0
@@ -15,7 +15,7 @@ let mockAssistantId = "";
15
15
  // Module mocks
16
16
  // ---------------------------------------------------------------------------
17
17
 
18
- mock.module("../providers/managed-proxy/context.js", () => ({
18
+ mock.module("../providers/platform-proxy/context.js", () => ({
19
19
  resolveManagedProxyContext: async () => mockManagedProxyCtx,
20
20
  }));
21
21
 
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import { getPlatformAssistantId } from "../config/env.js";
9
- import { resolveManagedProxyContext } from "../providers/managed-proxy/context.js";
9
+ import { resolveManagedProxyContext } from "../providers/platform-proxy/context.js";
10
10
  import { credentialKey } from "../security/credential-key.js";
11
11
  import { getSecureKeyAsync } from "../security/secure-keys.js";
12
12
  import { getLogger } from "../util/logger.js";
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Public hook-name constants.
3
+ *
4
+ * Plugin authors reference hooks by name in two places: the keys on
5
+ * `Plugin.hooks` and the daemon's `runHook(name, ctx)` call sites.
6
+ * Centralizing the string literals here keeps the typo surface minimal
7
+ * and lets call sites import a typed constant instead of repeating a
8
+ * free-form string.
9
+ *
10
+ * New hooks land here as additional `HOOKS.*` entries. The runtime
11
+ * `runHook(name, ctx)` accepts any string (so test fixtures and
12
+ * forward-compat hooks can still chain through), but call sites in
13
+ * first-party code should always reach for a `HOOKS.*` constant.
14
+ */
15
+
16
+ export const HOOKS = {
17
+ /** Plugin bootstrap. Fires once when the daemon loads the plugin. */
18
+ INIT: "init",
19
+ /** Plugin teardown. Fires once when the daemon unloads the plugin. */
20
+ SHUTDOWN: "shutdown",
21
+ /** Fires once per user turn, immediately before the agent loop receives `runMessages`. */
22
+ USER_PROMPT_SUBMIT: "user-prompt-submit",
23
+ } as const;
24
+
25
+ /** Union of every hook name declared in {@link HOOKS}. */
26
+ export type HookName = (typeof HOOKS)[keyof typeof HOOKS];
@@ -8,6 +8,39 @@
8
8
  *
9
9
  * Keep this file's surface stable across minor/patch releases. Anything
10
10
  * exported here is part of the public contract.
11
+ *
12
+ * ## Surface today
13
+ *
14
+ * The public package is intentionally **declarative**: a plugin is a
15
+ * directory whose `package.json` is the manifest and whose `hooks/` /
16
+ * `tools/` / `skills/` / `routes/` subdirectories are the contributions.
17
+ * The host introspects the directory at load time and wires it into the
18
+ * runtime — plugin authors never call a runtime registration function.
19
+ *
20
+ * What this module exposes is therefore types-only: the context shapes
21
+ * the host hands to plugin hooks, and the logger shape they include.
22
+ *
23
+ * - {@link PluginInitContext} — passed to `init` hook at bootstrap
24
+ * - {@link PluginShutdownContext} — passed to `shutdown` hook at teardown
25
+ * - {@link UserPromptSubmitContext} — passed to `user-prompt-submit` hook,
26
+ * fired immediately before the agent loop receives a user's prompt
27
+ * - {@link PluginLogger} — pino-compatible logger shape on the contexts
28
+ * - {@link ToolContext} — passed to a plugin tool's `execute` method
29
+ * - {@link ToolExecutionResult} — return shape of a plugin tool's `execute`
30
+ *
31
+ * Pipeline-argument types (`LLMCallArgs`, `MemoryArgs`, etc.) currently
32
+ * live in `assistant/src/plugins/types.ts` and have not yet migrated into
33
+ * this package. A follow-up PR will move them into this surface as the
34
+ * per-pipeline schemas stabilize.
11
35
  */
12
36
 
13
- export type { PluginInitContext, PluginShutdownContext } from "./types.js";
37
+ export type { HookName } from "./constants.js";
38
+ export { HOOKS } from "./constants.js";
39
+ export type {
40
+ PluginInitContext,
41
+ PluginLogger,
42
+ PluginShutdownContext,
43
+ ToolContext,
44
+ ToolExecutionResult,
45
+ UserPromptSubmitContext,
46
+ } from "./types.js";
@@ -1,21 +1,64 @@
1
1
  /**
2
2
  * Public plugin-API types.
3
3
  *
4
- * This module is the source-of-truth for types that plugin authors depend on.
5
- * The rest of the assistant imports from here via relative paths
6
- * (`../plugin-api/types.js`). At publish time, this file's contents are
7
- * bundled into the `@vellumai/plugin-api` npm package; at runtime in the
8
- * assistant binary, the same source is reachable to user plugins via a
9
- * boot-time shim that re-exports from the embedded bundle.
10
- *
11
- * Today this module is intentionally narrow only `PluginInitContext` and
12
- * `PluginShutdownContext`. Additional public types migrate over in
13
- * follow-up PRs as the surface stabilizes.
14
- *
15
- * Internal-only types (pipeline shapes, middleware, manifest validation,
16
- * etc.) stay in `assistant/src/plugins/types.ts` until they're ready to
17
- * become public.
4
+ * This module is the entry point plugin authors land on when they import
5
+ * from `@vellumai/plugin-api`. The shapes here are the canonical public
6
+ * contract anything exported is part of the surface that semver gates.
7
+ *
8
+ * ## Tool-execution types
9
+ *
10
+ * `ToolContext` and `ToolExecutionResult` are re-exports of the narrow,
11
+ * stable bases defined alongside their daemon-internal counterparts in
12
+ * `assistant/src/tools/types.ts`. The daemon-internal `ToolContext` /
13
+ * `ToolExecutionResult` (with CES, trust classification, lifecycle
14
+ * events, sensitive-output bindings, risk metadata, etc.) `extends`
15
+ * the public bases, so the runtime can hand plugins the full value
16
+ * without a manual cast and tsc enforces the structural relationship.
17
+ * Plugin tools see the narrow surface only — they MUST NOT set fields
18
+ * that belong to the daemon-internal extension.
19
+ *
20
+ * ## Hook contexts
21
+ *
22
+ * The init / shutdown hook contexts are owned by this module directly.
23
+ * They have no daemon-internal extension today (the daemon constructs
24
+ * and hands them straight through), so there's nothing to inherit from.
25
+ *
26
+ * ## Compatibility
27
+ *
28
+ * Adding fields to any public shape is non-breaking. Renaming or
29
+ * removing fields is breaking and gated on a major bump of
30
+ * `@vellumai/plugin-api`.
31
+ */
32
+
33
+ import type { Message } from "../providers/types.js";
34
+
35
+ // ─── Tool-execution types (re-exported from daemon source-of-truth) ──────────
36
+
37
+ export type {
38
+ PluginToolContext as ToolContext,
39
+ PluginToolExecutionResult as ToolExecutionResult,
40
+ } from "../tools/types.js";
41
+
42
+ // ─── Logger ──────────────────────────────────────────────────────────────────
43
+
44
+ /**
45
+ * Minimal pino-compatible logger surface handed to plugin hooks. The host
46
+ * supplies a pino child logger bound to `{ plugin: <name> }`; this
47
+ * interface intentionally captures only the two call shapes plugin code
48
+ * needs (structured object + optional message), so the public surface
49
+ * doesn't take a dependency on pino's full type machinery.
50
+ *
51
+ * Each method accepts a structured-fields object followed by an optional
52
+ * message string. Plugin authors that need pino's wider API (`child()`,
53
+ * `level`, etc.) can cast to their own narrower interface in plugin code
54
+ * — but the canonical contract here covers the 99% case.
18
55
  */
56
+ export interface PluginLogger {
57
+ info(obj: Record<string, unknown>, msg?: string): void;
58
+ warn(obj: Record<string, unknown>, msg?: string): void;
59
+ error(obj: Record<string, unknown>, msg?: string): void;
60
+ debug(obj: Record<string, unknown>, msg?: string): void;
61
+ }
19
62
 
20
63
  // ─── Init context ────────────────────────────────────────────────────────────
21
64
 
@@ -29,17 +72,17 @@ export interface PluginInitContext {
29
72
  config: unknown;
30
73
  /** Resolved credential values keyed by the entries of `manifest.requiresCredential`. */
31
74
  credentials: Record<string, string>;
32
- /**
33
- * Pino-compatible child logger bound to `{ plugin: <name> }`. Untyped here
34
- * to avoid pulling pino into the types module.
35
- */
36
- logger: unknown;
75
+ /** Pino-compatible child logger bound to `{ plugin: <name> }`. */
76
+ logger: PluginLogger;
37
77
  /** Absolute path to `<workspaceDir>/plugins-data/<plugin>/` (created by bootstrap). */
38
78
  pluginStorageDir: string;
39
- /** Assistant semver for compatibility checks inside the plugin. */
79
+ /**
80
+ * Assistant semver. Plugins can compare against this for defensive
81
+ * runtime checks — but the canonical compat contract is the host
82
+ * version against the plugin's `peerDependencies["@vellumai/plugin-api"]`
83
+ * semver range, enforced at load time by the external-plugin loader.
84
+ */
40
85
  assistantVersion: string;
41
- /** Capability → version-list map (`ASSISTANT_API_VERSIONS`) for defensive runtime checks. */
42
- apiVersions: Record<string, string[]>;
43
86
  }
44
87
 
45
88
  // ─── Shutdown context ────────────────────────────────────────────────────────
@@ -60,3 +103,42 @@ export interface PluginShutdownContext {
60
103
  /** Assistant semver for compatibility checks inside the plugin. */
61
104
  assistantVersion: string;
62
105
  }
106
+
107
+ // ─── User-prompt-submit hook context ─────────────────────────────────────────
108
+
109
+ /**
110
+ * Context passed to the `user-prompt-submit` hook. Fires once per user
111
+ * turn, after the agent loop has prepared the message list (PKB / NOW /
112
+ * memory-graph injections, history repair, overflow reduction all already
113
+ * applied) and immediately before the messages are handed to the agent
114
+ * loop's tool/LLM iteration.
115
+ *
116
+ * The hook may transform `latestMessages` either by mutating it in place
117
+ * (`push` / `splice` / `length = 0`) or by returning a new context with
118
+ * a fresh `latestMessages` array — see {@link PluginHookFn}'s polymorphic
119
+ * return shape. The daemon threads the final `latestMessages` value into
120
+ * `agentLoop.run()` as the run-messages argument.
121
+ *
122
+ * `originalMessages` is the user's original message list, frozen for the
123
+ * hook. Plugins should treat it as a stable reference point if they need
124
+ * to recover from earlier transformations or compare against the pristine
125
+ * state.
126
+ *
127
+ * Multiple plugins' hooks chain in registration order — each plugin's
128
+ * hook sees the previous plugin's mutations (whether by reassignment or
129
+ * in-place mutation).
130
+ */
131
+ export interface UserPromptSubmitContext {
132
+ /** Conversation ID the user prompt was submitted on. */
133
+ readonly conversationId: string;
134
+ /**
135
+ * The user's original message list, immutable for the hook. Plugins
136
+ * may snapshot or compare against this but MUST NOT mutate it.
137
+ */
138
+ readonly originalMessages: ReadonlyArray<Message>;
139
+ /**
140
+ * The working message list that flows into `agentLoop.run`. Plugins
141
+ * may mutate this in place or replace it by returning a new context.
142
+ */
143
+ latestMessages: Message[];
144
+ }
@@ -55,11 +55,6 @@ export const defaultCircuitBreakerPlugin: Plugin = {
55
55
  manifest: {
56
56
  name: "default-circuit-breaker",
57
57
  version: "1.0.0",
58
- provides: { circuitBreakerApi: "v1" },
59
- requires: {
60
- pluginRuntime: "v1",
61
- circuitBreakerApi: "v1",
62
- },
63
58
  },
64
59
 
65
60
  middleware: {
@@ -112,10 +112,6 @@ export const defaultCompactionPlugin: Plugin = {
112
112
  manifest: {
113
113
  name: DEFAULT_COMPACTION_PLUGIN_NAME,
114
114
  version: "1.0.0",
115
- requires: {
116
- pluginRuntime: "v1",
117
- compactionApi: "v1",
118
- },
119
115
  },
120
116
  middleware: {
121
117
  compaction: defaultCompactionMiddleware,
@@ -95,8 +95,6 @@ export const defaultEmptyResponsePlugin: Plugin = {
95
95
  manifest: {
96
96
  name: "default-empty-response",
97
97
  version: "1.0.0",
98
- provides: { emptyResponseApi: "v1" },
99
- requires: { pluginRuntime: "v1", emptyResponseApi: "v1" },
100
98
  },
101
99
  middleware: {
102
100
  emptyResponse: passthrough,
@@ -54,8 +54,6 @@ export const defaultHistoryRepairPlugin: Plugin = {
54
54
  manifest: {
55
55
  name: "default-history-repair",
56
56
  version: "1.0.0",
57
- provides: { historyRepair: "v1" },
58
- requires: { pluginRuntime: "v1", historyRepairApi: "v1" },
59
57
  },
60
58
  middleware: {
61
59
  historyRepair: passthrough,
@@ -19,6 +19,7 @@
19
19
  * | `pkb-reminder` | 35 | after-memory-prefix |
20
20
  * | `memory-v2-static` | 38 | after-memory-prefix |
21
21
  * | `now-md` | 40 | after-memory-prefix |
22
+ * | `active-documents` | 45 | prepend-user-tail |
22
23
  * | `subagent-status` | 50 | append-user-tail |
23
24
  * | `slack-messages` | 60 | replace-run-messages |
24
25
  * | `thread-focus` | 70 | append-user-tail |
@@ -91,6 +92,7 @@ export const DEFAULT_INJECTOR_ORDER = {
91
92
  pkbReminder: 35,
92
93
  memoryV2Static: 38,
93
94
  nowMd: 40,
95
+ activeDocuments: 45,
94
96
  subagentStatus: 50,
95
97
  slackMessages: 60,
96
98
  threadFocus: 70,
@@ -438,6 +440,39 @@ const nowMdInjector: Injector = {
438
440
  },
439
441
  };
440
442
 
443
+ /**
444
+ * `active-documents` injector — order 45, prepend-user-tail.
445
+ *
446
+ * Injects an `<active_documents>` block listing open documents in the
447
+ * conversation so the assistant can target them with `document_update`
448
+ * instead of creating duplicates via `document_create`.
449
+ *
450
+ * Gating:
451
+ * - `mode === "full"`.
452
+ * - `activeDocuments` has at least one entry.
453
+ */
454
+ const activeDocumentsInjector: Injector = {
455
+ name: "active-documents",
456
+ order: DEFAULT_INJECTOR_ORDER.activeDocuments,
457
+ async produce(ctx: TurnContext): Promise<InjectionBlock | null> {
458
+ const inputs = readInjectionInputs(ctx);
459
+ const mode = inputs.mode ?? "full";
460
+ if (mode !== "full") return null;
461
+ const docs = inputs.activeDocuments;
462
+ if (!docs || docs.length === 0) return null;
463
+ const lines = docs.map(
464
+ (d) =>
465
+ `- surface_id: "${d.surfaceId}", title: "${d.title}", words: ${d.wordCount}`,
466
+ );
467
+ const text = `<active_documents>\nThe following documents are open in this conversation. Use document_update with the surface_id to edit them — do NOT call document_create for documents that already exist.\n${lines.join("\n")}\n</active_documents>`;
468
+ return {
469
+ id: "active-documents",
470
+ text,
471
+ placement: "prepend-user-tail",
472
+ };
473
+ },
474
+ };
475
+
441
476
  /**
442
477
  * `subagent-status` injector — order 50, append-user-tail.
443
478
  *
@@ -562,9 +597,6 @@ export const defaultInjectorsPlugin: Plugin = {
562
597
  manifest: {
563
598
  name: "default-injectors",
564
599
  version: "1.0.0",
565
- requires: {
566
- pluginRuntime: "v1",
567
- },
568
600
  },
569
601
  injectors: [
570
602
  diskPressureWarningInjector,
@@ -574,6 +606,7 @@ export const defaultInjectorsPlugin: Plugin = {
574
606
  pkbReminderInjector,
575
607
  memoryV2StaticInjector,
576
608
  nowMdInjector,
609
+ activeDocumentsInjector,
577
610
  subagentStatusInjector,
578
611
  slackMessagesInjector,
579
612
  threadFocusInjector,
@@ -42,8 +42,6 @@ export const defaultLlmCallPlugin: Plugin = {
42
42
  manifest: {
43
43
  name: "default-llm-call",
44
44
  version: "1.0.0",
45
- provides: { llmCall: "v1" },
46
- requires: { pluginRuntime: "v1" },
47
45
  },
48
46
  middleware: {
49
47
  llmCall: async function defaultLlmCall(
@@ -190,7 +190,6 @@ export const defaultMemoryRetrievalPlugin: Plugin = {
190
190
  manifest: {
191
191
  name: "default-memory-retrieval",
192
192
  version: "0.0.1",
193
- requires: { pluginRuntime: "v1", memoryApi: "v1" },
194
193
  },
195
194
  middleware: {
196
195
  memoryRetrieval: defaultMemoryRetrievalMiddleware,
@@ -156,7 +156,6 @@ export const defaultOverflowReducePlugin: Plugin = {
156
156
  manifest: {
157
157
  name: "default-overflow-reduce",
158
158
  version: "1.0.0",
159
- requires: { pluginRuntime: "v1", overflowReduceApi: "v1" },
160
159
  },
161
160
  middleware: {
162
161
  overflowReduce: defaultOverflowReduceMiddleware,
@@ -98,8 +98,6 @@ export const defaultPersistencePlugin: Plugin = {
98
98
  manifest: {
99
99
  name: "default-persistence",
100
100
  version: "1.0.0",
101
- provides: { persistence: "v1" },
102
- requires: { pluginRuntime: "v1" },
103
101
  },
104
102
  middleware: {
105
103
  persistence: passthrough,
@@ -64,11 +64,6 @@ export const defaultTitleGeneratePlugin: Plugin = {
64
64
  manifest: {
65
65
  name: "default-title-generate",
66
66
  version: "1.0.0",
67
- provides: { titleGenerate: "v1" },
68
- requires: {
69
- pluginRuntime: "v1",
70
- titleGenerateApi: "v1",
71
- },
72
67
  },
73
68
  };
74
69
 
@@ -72,8 +72,6 @@ export const defaultTokenEstimatePlugin: Plugin = {
72
72
  manifest: {
73
73
  name: "default-token-estimate",
74
74
  version: "1.0.0",
75
- provides: { tokenEstimate: "v1" },
76
- requires: { pluginRuntime: "v1", tokenEstimateApi: "v1" },
77
75
  },
78
76
  middleware: {
79
77
  tokenEstimate: passthrough,
@@ -90,13 +90,6 @@ export const defaultToolErrorPlugin: Plugin = {
90
90
  manifest: {
91
91
  name: "default-tool-error",
92
92
  version: "1.0.0",
93
- requires: {
94
- pluginRuntime: "v1",
95
- toolErrorApi: "v1",
96
- },
97
- provides: {
98
- toolError: "v1",
99
- },
100
93
  },
101
94
  middleware: {
102
95
  toolError: defaultToolErrorMiddleware,
@@ -58,8 +58,6 @@ export const defaultToolExecutePlugin: Plugin = {
58
58
  manifest: {
59
59
  name: "default-tool-execute",
60
60
  version: "1.0.0",
61
- provides: { toolExecuteApi: "v1" },
62
- requires: { pluginRuntime: "v1", toolExecuteApi: "v1" },
63
61
  },
64
62
  middleware: {
65
63
  toolExecute: defaultToolExecute,
@@ -55,10 +55,6 @@ export const defaultToolResultTruncatePlugin: Plugin = {
55
55
  manifest: {
56
56
  name: "default-tool-result-truncate",
57
57
  version: "1.0.0",
58
- requires: {
59
- pluginRuntime: "v1",
60
- toolResultTruncateApi: "v1",
61
- },
62
58
  },
63
59
  middleware: {
64
60
  toolResultTruncate: passthrough,
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Materializes the workspace-level `@vellumai/plugin-api` shim so that
3
+ * user plugins under `<workspaceDir>/plugins/<name>/` can resolve a
4
+ * standard bare import:
5
+ *
6
+ * import { ... } from "@vellumai/plugin-api";
7
+ *
8
+ * Bun's Node-style resolution walks up from the plugin directory and
9
+ * finds `<workspaceDir>/node_modules/@vellumai/plugin-api/` — a tiny
10
+ * shim package whose `index.js` re-binds the plugin-api namespace that
11
+ * the assistant already loaded into its module graph (and parked on
12
+ * `globalThis` under {@link PLUGIN_API_REGISTRY_KEY}).
13
+ *
14
+ * This avoids duplicating the plugin-api package per plugin while still
15
+ * letting the assistant's compiled binary be the single source of truth
16
+ * for the public API. The runtime mechanism is uniform across:
17
+ * - JIT / Docker: plugin-api loads from source, shim re-binds via globalThis
18
+ * - `bun --compile` (macOS bare-metal): plugin-api ships inside the
19
+ * binary's regular code graph (Bun's bundler resolves
20
+ * `import * as pluginApi from "../plugin-api/index.js"` at compile
21
+ * time, inlining relative imports), shim re-binds via globalThis
22
+ *
23
+ * Idempotent: safe to call repeatedly. The shim's contents are
24
+ * deterministic given the runtime export list — fresh exports (added in
25
+ * later PRs) automatically expand the generated `index.js`.
26
+ *
27
+ * Called from {@link loadUserPlugins} at the top of its body so the
28
+ * ordering constraint (shim exists before any plugin's
29
+ * `import "@vellumai/plugin-api"` is parsed) is enforced by code, not
30
+ * by a docstring in `lifecycle.ts`.
31
+ */
32
+
33
+ import { mkdir, writeFile } from "node:fs/promises";
34
+ import { join } from "node:path";
35
+
36
+ import assistantPkg from "../../package.json" with { type: "json" };
37
+ import {
38
+ PLUGIN_API_EXPORTS,
39
+ PLUGIN_API_REGISTRY_KEY,
40
+ } from "../embedded/plugin-api.js";
41
+ import { getLogger } from "../util/logger.js";
42
+ import { getWorkspaceDir } from "../util/platform.js";
43
+
44
+ const log = getLogger("plugin-api-shim");
45
+
46
+ const PACKAGE_NAME = "@vellumai/plugin-api";
47
+
48
+ /**
49
+ * Build the body of the workspace shim's `index.js`. Exported so the
50
+ * smoke test can assert against the same generator the daemon uses.
51
+ */
52
+ export function buildShimSource(
53
+ exports: readonly string[] = PLUGIN_API_EXPORTS,
54
+ registryKey: symbol = PLUGIN_API_REGISTRY_KEY,
55
+ ): string {
56
+ const description = registryKey.description ?? "";
57
+ const lines = [
58
+ `const api = globalThis[Symbol.for(${JSON.stringify(description)})];`,
59
+ ...exports.map((name) => `export const ${name} = api.${name};`),
60
+ ];
61
+ return `${lines.join("\n")}\n`;
62
+ }
63
+
64
+ export async function ensurePluginApiShim(opts?: {
65
+ /** Override the workspace root. Defaults to `getWorkspaceDir()`. */
66
+ workspaceDir?: string;
67
+ }): Promise<void> {
68
+ const workspaceDir = opts?.workspaceDir ?? getWorkspaceDir();
69
+ const shimDir = join(workspaceDir, "node_modules", PACKAGE_NAME);
70
+
71
+ await mkdir(shimDir, { recursive: true });
72
+
73
+ const indexJs = buildShimSource();
74
+ const packageJson = `${JSON.stringify(
75
+ {
76
+ name: PACKAGE_NAME,
77
+ version: assistantPkg.version,
78
+ type: "module",
79
+ main: "./index.js",
80
+ },
81
+ null,
82
+ 2,
83
+ )}\n`;
84
+
85
+ await writeFile(join(shimDir, "index.js"), indexJs);
86
+ await writeFile(join(shimDir, "package.json"), packageJson);
87
+
88
+ log.info(
89
+ {
90
+ shimDir,
91
+ exports: PLUGIN_API_EXPORTS,
92
+ version: assistantPkg.version,
93
+ },
94
+ "plugin-api shim materialized",
95
+ );
96
+ }
@@ -0,0 +1,104 @@
1
+ /**
2
+ * External plugin runtime — `globalThis.__vellumPluginRuntime` bridge.
3
+ *
4
+ * Workspace-local plugins (`<workspaceDir>/plugins/*`) get dynamic-imported by
5
+ * {@link loadUserPlugins}. They need to call `registerPlugin()` from their
6
+ * module body and they typically also want to read secrets, subscribe to
7
+ * runtime events, etc.
8
+ *
9
+ * Importing those symbols by absolute path
10
+ * (`/abs/path/to/assistant/src/plugins/registry.js`) works when the daemon is
11
+ * running from source — both the daemon and the dynamic-imported plugin
12
+ * resolve the same on-disk file and share module identity. It DOES NOT work
13
+ * when the daemon is a `bun --compile` binary: the daemon's modules are baked
14
+ * into the executable, and any absolute-path import re-loads a fresh disk
15
+ * copy. `registerPlugin()` then writes into a disjoint registry instance and
16
+ * the daemon never sees the plugin.
17
+ *
18
+ * The fix is to expose a single, stable handle on `globalThis` that plugins
19
+ * read at module-load time. The daemon's bundled modules attach themselves
20
+ * here once at startup; plugins consume the same instance regardless of how
21
+ * the daemon was built.
22
+ *
23
+ * Plugins use the bridge like this:
24
+ *
25
+ * const runtime = (globalThis as { __vellumPluginRuntime?: ... })
26
+ * .__vellumPluginRuntime;
27
+ * if (!runtime || runtime.version !== 1) throw new Error("...");
28
+ * const { registerPlugin, assistantEventHub, getSecureKeyAsync } = runtime;
29
+ *
30
+ * Type-only imports (`import type { Plugin } from "..."`) remain free to use
31
+ * absolute paths or workspace-local copies — the TypeScript compiler erases
32
+ * them and they have no module-identity effect at runtime.
33
+ *
34
+ * See `assistant/docs/plugins.md` for the full authoring contract and
35
+ * `assistant/examples/plugins/echo/register.ts` for a worked example.
36
+ */
37
+
38
+ import { assistantEventHub } from "../runtime/assistant-event-hub.js";
39
+ import { getSecureKeyAsync } from "../security/secure-keys.js";
40
+ import { registerPlugin } from "./registry.js";
41
+
42
+ /**
43
+ * The handle plugins read from `globalThis.__vellumPluginRuntime`.
44
+ *
45
+ * `version` is the contract version. Plugins should assert against the
46
+ * version they were authored against and refuse to register if they see a
47
+ * different one — bumping it is a breaking change to the plugin surface.
48
+ *
49
+ * The field set is intentionally small: the most-commonly-needed symbols
50
+ * across both static (module-load-time) and dynamic (init-time) plugin
51
+ * lifecycle. Plugins that need richer runtime state can still receive it
52
+ * through {@link PluginInitContext} during `init()`.
53
+ */
54
+ export interface VellumPluginRuntime {
55
+ readonly version: 1;
56
+ readonly registerPlugin: typeof registerPlugin;
57
+ readonly assistantEventHub: typeof assistantEventHub;
58
+ readonly getSecureKeyAsync: typeof getSecureKeyAsync;
59
+ }
60
+
61
+ /** Stable globalThis key. Don't rename — plugins reference it by string. */
62
+ const RUNTIME_GLOBAL_KEY = "__vellumPluginRuntime" as const;
63
+
64
+ interface GlobalWithRuntime {
65
+ [RUNTIME_GLOBAL_KEY]?: VellumPluginRuntime;
66
+ }
67
+
68
+ /**
69
+ * Install the plugin runtime bridge on `globalThis`. Idempotent — repeat
70
+ * calls are no-ops, so it's safe to invoke from tests that also touch the
71
+ * lifecycle path.
72
+ *
73
+ * Must be called BEFORE {@link loadUserPlugins} runs, otherwise plugins that
74
+ * touch `globalThis.__vellumPluginRuntime` in their module body will throw.
75
+ */
76
+ export function installPluginRuntime(): void {
77
+ const g = globalThis as GlobalWithRuntime;
78
+ if (g[RUNTIME_GLOBAL_KEY]) return;
79
+ g[RUNTIME_GLOBAL_KEY] = {
80
+ version: 1,
81
+ registerPlugin,
82
+ assistantEventHub,
83
+ getSecureKeyAsync,
84
+ };
85
+ }
86
+
87
+ /**
88
+ * Read the installed runtime. Returns `undefined` if {@link installPluginRuntime}
89
+ * hasn't been called yet — plugins should treat this as a fatal error.
90
+ *
91
+ * Exposed mainly for tests and for the rare in-process consumer that wants
92
+ * to read the bridge from the same module graph that installed it.
93
+ */
94
+ export function getPluginRuntime(): VellumPluginRuntime | undefined {
95
+ return (globalThis as GlobalWithRuntime)[RUNTIME_GLOBAL_KEY];
96
+ }
97
+
98
+ /**
99
+ * Tear down the runtime handle. Test-only — production code never uninstalls
100
+ * because the runtime lifetime is the daemon lifetime.
101
+ */
102
+ export function uninstallPluginRuntimeForTests(): void {
103
+ delete (globalThis as GlobalWithRuntime)[RUNTIME_GLOBAL_KEY];
104
+ }