@vellumai/assistant 0.8.1 → 0.8.3

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 (630) hide show
  1. package/ARCHITECTURE.md +13 -19
  2. package/Dockerfile +75 -1
  3. package/bun.lock +11 -1
  4. package/docker-entrypoint.sh +17 -0
  5. package/docker-init-apt-root.sh +167 -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 +642 -5
  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-loop-exit-reason.test.ts +272 -0
  21. package/src/__tests__/agent-loop-provider-error-recording.test.ts +195 -0
  22. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +131 -0
  23. package/src/__tests__/anthropic-provider.test.ts +45 -0
  24. package/src/__tests__/app-builder-tool-scripts.test.ts +9 -3
  25. package/src/__tests__/app-executors.test.ts +220 -4
  26. package/src/__tests__/auto-analysis-end-to-end.test.ts +35 -0
  27. package/src/__tests__/bundled-asset.test.ts +6 -6
  28. package/src/__tests__/channel-availability-routes.test.ts +206 -0
  29. package/src/__tests__/channel-delivery-store.test.ts +289 -1
  30. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -1
  31. package/src/__tests__/clawhub.test.ts +75 -16
  32. package/src/__tests__/compactor-tail-resolution.test.ts +147 -0
  33. package/src/__tests__/config-get-vision-flag.test.ts +136 -0
  34. package/src/__tests__/config-loader-backfill.test.ts +115 -18
  35. package/src/__tests__/config-schema.test.ts +21 -0
  36. package/src/__tests__/config-set-route.test.ts +80 -0
  37. package/src/__tests__/config-sounds-sync.test.ts +97 -0
  38. package/src/__tests__/config-watcher-skill-reseed.test.ts +453 -0
  39. package/src/__tests__/context-search-conversations-source.test.ts +117 -2
  40. package/src/__tests__/context-search-memory-v2-source.test.ts +0 -1
  41. package/src/__tests__/context-search-workspace-source.test.ts +7 -0
  42. package/src/__tests__/context-token-estimator.test.ts +31 -65
  43. package/src/__tests__/conversation-abort-tool-results.test.ts +4 -1
  44. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
  45. package/src/__tests__/conversation-agent-loop-overflow.test.ts +92 -92
  46. package/src/__tests__/conversation-agent-loop.test.ts +59 -1
  47. package/src/__tests__/conversation-error.test.ts +42 -3
  48. package/src/__tests__/conversation-fork-crud.test.ts +82 -0
  49. package/src/__tests__/conversation-inference-profile-route.test.ts +40 -4
  50. package/src/__tests__/conversation-lifecycle.test.ts +173 -0
  51. package/src/__tests__/conversation-media-retry.test.ts +19 -8
  52. package/src/__tests__/conversation-message-sync-tags.test.ts +97 -0
  53. package/src/__tests__/conversation-pairing.test.ts +54 -0
  54. package/src/__tests__/conversation-process-callsite.test.ts +4 -1
  55. package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -1
  56. package/src/__tests__/conversation-queue.test.ts +4 -1
  57. package/src/__tests__/conversation-runtime-assembly.test.ts +102 -13
  58. package/src/__tests__/conversation-slash-queue.test.ts +59 -1
  59. package/src/__tests__/conversation-slash-unknown.test.ts +4 -1
  60. package/src/__tests__/conversation-surfaces-table-action.test.ts +360 -0
  61. package/src/__tests__/conversation-sync-tags.test.ts +235 -0
  62. package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
  63. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
  64. package/src/__tests__/credential-security-invariants.test.ts +3 -2
  65. package/src/__tests__/date-context.test.ts +45 -0
  66. package/src/__tests__/db-slack-external-content-normalization.test.ts +301 -0
  67. package/src/__tests__/delete-managed-skill-tool.test.ts +55 -13
  68. package/src/__tests__/disk-pressure-tools.test.ts +1 -0
  69. package/src/__tests__/dm-backfill.test.ts +121 -10
  70. package/src/__tests__/document-tool-security.test.ts +258 -0
  71. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
  72. package/src/__tests__/edit-propagation.test.ts +33 -0
  73. package/src/__tests__/empty-response-pipeline.test.ts +0 -4
  74. package/src/__tests__/external-plugin-loader.test.ts +151 -55
  75. package/src/__tests__/filing-service.test.ts +140 -0
  76. package/src/__tests__/get-skill-detail-audit.test.ts +0 -4
  77. package/src/__tests__/guardian-action-no-hardcoded-copy.test.ts +0 -1
  78. package/src/__tests__/guardian-dispatch.test.ts +1 -0
  79. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +43 -62
  80. package/src/__tests__/heartbeat-service.test.ts +24 -164
  81. package/src/__tests__/helpers/channel-test-adapter.ts +0 -2
  82. package/src/__tests__/helpers/tar-fixtures.ts +39 -0
  83. package/src/__tests__/helpers/wait-for.ts +21 -0
  84. package/src/__tests__/history-repair-pipeline.test.ts +0 -3
  85. package/src/__tests__/history-repair.test.ts +73 -0
  86. package/src/__tests__/host-app-control-proxy.test.ts +507 -10
  87. package/src/__tests__/host-proxy-preactivation.test.ts +200 -13
  88. package/src/__tests__/image-credentials.test.ts +1 -1
  89. package/src/__tests__/inbound-slack-persistence.test.ts +2 -0
  90. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +1 -1
  91. package/src/__tests__/inference-profile-reaper.test.ts +4 -2
  92. package/src/__tests__/inference-profile-session-handler.test.ts +18 -6
  93. package/src/__tests__/inference-profile-session-ipc.test.ts +17 -5
  94. package/src/__tests__/injector-background-turn.test.ts +153 -0
  95. package/src/__tests__/injector-chain.test.ts +15 -8
  96. package/src/__tests__/install-skill-routing.test.ts +155 -37
  97. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +99 -3
  98. package/src/__tests__/list-messages-page-latest.test.ts +55 -0
  99. package/src/__tests__/llm-call-pipeline.test.ts +0 -3
  100. package/src/__tests__/llm-callsite-catalog.test.ts +25 -0
  101. package/src/__tests__/llm-catalog-parity.test.ts +58 -13
  102. package/src/__tests__/llm-request-log-agent-loop-exit-reason.test.ts +116 -0
  103. package/src/__tests__/llm-request-log-error-payload.test.ts +138 -0
  104. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +36 -0
  105. package/src/__tests__/llm-request-log-source-factory.test.ts +29 -53
  106. package/src/__tests__/llm-resolver.test.ts +255 -2
  107. package/src/__tests__/llm-usage-store.test.ts +114 -0
  108. package/src/__tests__/managed-profile-guard.test.ts +41 -29
  109. package/src/__tests__/managed-skill-lifecycle.test.ts +109 -18
  110. package/src/__tests__/managed-store.test.ts +84 -192
  111. package/src/__tests__/media-generate-image.test.ts +1 -1
  112. package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -2
  113. package/src/__tests__/messages-after-tiebreaker.test.ts +122 -0
  114. package/src/__tests__/notification-decision-fallback.test.ts +0 -91
  115. package/src/__tests__/notification-decision-strategy.test.ts +14 -31
  116. package/src/__tests__/notification-deep-link.test.ts +15 -0
  117. package/src/__tests__/notification-guardian-path.test.ts +1 -2
  118. package/src/__tests__/notification-platform-adapter.test.ts +5 -4
  119. package/src/__tests__/notification-telegram-adapter.test.ts +1 -0
  120. package/src/__tests__/notification-vellum-adapter.test.ts +113 -0
  121. package/src/__tests__/oauth-commands-routes.test.ts +168 -16
  122. package/src/__tests__/oauth-provider-profiles.test.ts +9 -0
  123. package/src/__tests__/openai-provider.test.ts +242 -3
  124. package/src/__tests__/openai-responses-cutover-guard.test.ts +17 -9
  125. package/src/__tests__/openrouter-provider-only.test.ts +51 -3
  126. package/src/__tests__/openrouter-token-estimation.test.ts +34 -25
  127. package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -2
  128. package/src/__tests__/persistence-pipeline.test.ts +0 -2
  129. package/src/__tests__/{managed-proxy-context.test.ts → platform-proxy-context.test.ts} +7 -2
  130. package/src/__tests__/platform.test.ts +2 -0
  131. package/src/__tests__/plugin-api-shim.test.ts +125 -0
  132. package/src/__tests__/plugin-bootstrap.test.ts +10 -36
  133. package/src/__tests__/plugin-external-api.test.ts +68 -0
  134. package/src/__tests__/plugin-registry.test.ts +0 -77
  135. package/src/__tests__/plugin-route-contribution.test.ts +0 -1
  136. package/src/__tests__/plugin-skill-contribution.test.ts +0 -2
  137. package/src/__tests__/plugin-tool-contribution.test.ts +16 -15
  138. package/src/__tests__/plugin-types.test.ts +3 -13
  139. package/src/__tests__/process-message-background-slack.test.ts +8 -1
  140. package/src/__tests__/process-message-display-content.test.ts +421 -0
  141. package/src/__tests__/provider-catalog-visibility.test.ts +158 -0
  142. package/src/__tests__/provider-error-scenarios.test.ts +111 -0
  143. package/src/__tests__/{provider-managed-proxy-integration.test.ts → provider-platform-proxy-integration.test.ts} +33 -31
  144. package/src/__tests__/scaffold-managed-skill-tool.test.ts +65 -13
  145. package/src/__tests__/schedule-routes.test.ts +50 -3
  146. package/src/__tests__/schedule-store.test.ts +94 -0
  147. package/src/__tests__/scheduler-reuse-conversation.test.ts +54 -7
  148. package/src/__tests__/schema-transforms.test.ts +20 -0
  149. package/src/__tests__/search-skills-unified.test.ts +0 -5
  150. package/src/__tests__/{secret-routes-managed-proxy.test.ts → secret-routes-platform-proxy.test.ts} +1 -1
  151. package/src/__tests__/server-history-render.test.ts +43 -0
  152. package/src/__tests__/skill-load-feature-flag.test.ts +0 -12
  153. package/src/__tests__/skill-load-tool.test.ts +27 -89
  154. package/src/__tests__/skill-memory.test.ts +23 -3
  155. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -38
  156. package/src/__tests__/skills-files-catalog-fallback.test.ts +0 -3
  157. package/src/__tests__/skills-install-extract.test.ts +49 -38
  158. package/src/__tests__/skills-install-staging.test.ts +159 -0
  159. package/src/__tests__/skills-uninstall.test.ts +9 -41
  160. package/src/__tests__/skills.test.ts +51 -58
  161. package/src/__tests__/slack-channel-config.test.ts +9 -0
  162. package/src/__tests__/subagent-tool-filtering.test.ts +50 -0
  163. package/src/__tests__/system-prompt.test.ts +670 -63
  164. package/src/__tests__/terminal-tools.test.ts +28 -1
  165. package/src/__tests__/thread-backfill.test.ts +557 -27
  166. package/src/__tests__/title-generate-pipeline.test.ts +0 -13
  167. package/src/__tests__/token-estimate-pipeline.test.ts +0 -3
  168. package/src/__tests__/tool-error-pipeline.test.ts +0 -3
  169. package/src/__tests__/tool-execute-pipeline.test.ts +0 -5
  170. package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
  171. package/src/__tests__/tool-executor.test.ts +16 -4
  172. package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -12
  173. package/src/__tests__/turn-events-store.test.ts +256 -0
  174. package/src/__tests__/twilio-routes.test.ts +4 -0
  175. package/src/__tests__/user-plugin-loader.test.ts +0 -7
  176. package/src/__tests__/voice-session-bridge.test.ts +198 -0
  177. package/src/__tests__/web-search-catalog-parity.test.ts +32 -10
  178. package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +115 -3
  179. package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +50 -0
  180. package/src/__tests__/workspace-migration-073-repair-recall-callsite-empty-profile.test.ts +153 -0
  181. package/src/__tests__/workspace-migration-085-memory-v2-bm25-b-reembed-disabled-v2-pages.test.ts +220 -0
  182. package/src/__tests__/workspace-migration-086-revert-stale-gemini-mis-rewrites.test.ts +269 -0
  183. package/src/__tests__/workspace-migration-087-memory-router-balanced-profile.test.ts +228 -0
  184. package/src/__tests__/workspace-migration-remove-legacy-skills-index.test.ts +309 -0
  185. package/src/__tests__/workspace-migrations-runner.test.ts +111 -3
  186. package/src/a2a/__tests__/agent-card.test.ts +98 -0
  187. package/src/a2a/__tests__/e2e-a2a-channel.test.ts +597 -0
  188. package/src/a2a/__tests__/protocol-helpers.test.ts +113 -0
  189. package/src/a2a/__tests__/task-store.test.ts +246 -0
  190. package/src/a2a/agent-card.ts +58 -0
  191. package/src/a2a/feature-gate.ts +8 -0
  192. package/src/a2a/protocol-constants.ts +21 -0
  193. package/src/a2a/protocol-errors.ts +50 -0
  194. package/src/a2a/protocol-types.ts +162 -0
  195. package/src/a2a/task-store.ts +168 -0
  196. package/src/acp/resolve-agent.ts +1 -1
  197. package/src/agent/image-optimize.ts +13 -5
  198. package/src/agent/loop.ts +167 -18
  199. package/src/calls/voice-session-bridge.ts +61 -42
  200. package/src/channels/config.ts +9 -0
  201. package/src/channels/types.ts +122 -0
  202. package/src/cli/__tests__/unknown-command.test.ts +24 -0
  203. package/src/cli/commands/__tests__/changelog.test.ts +304 -319
  204. package/src/cli/{__tests__ → commands/__tests__}/notifications.test.ts +201 -28
  205. package/src/cli/commands/__tests__/schedules.test.ts +960 -0
  206. package/src/cli/commands/changelog.ts +106 -42
  207. package/src/cli/commands/conversations.ts +102 -17
  208. package/src/cli/commands/default-action.ts +10 -53
  209. package/src/cli/commands/notifications.ts +388 -346
  210. package/src/cli/commands/plugins.ts +252 -0
  211. package/src/cli/commands/schedules.ts +683 -0
  212. package/src/cli/commands/telemetry.ts +40 -0
  213. package/src/cli/lib/__tests__/cli-colors.test.ts +48 -0
  214. package/src/cli/lib/__tests__/confirm-prompt.test.ts +159 -0
  215. package/src/cli/lib/__tests__/install-from-github.test.ts +355 -0
  216. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +154 -0
  217. package/src/cli/lib/__tests__/search-plugins.test.ts +261 -0
  218. package/src/cli/lib/__tests__/uninstall-plugin.test.ts +124 -0
  219. package/src/cli/lib/__tests__/unknown-command.test.ts +106 -0
  220. package/src/cli/lib/cli-colors.ts +12 -0
  221. package/src/cli/lib/confirm-prompt.ts +79 -0
  222. package/src/cli/lib/install-from-github.ts +303 -0
  223. package/src/cli/lib/list-installed-plugins.ts +137 -0
  224. package/src/cli/lib/search-plugins.ts +163 -0
  225. package/src/cli/lib/uninstall-plugin.ts +82 -0
  226. package/src/cli/lib/unknown-command.ts +111 -0
  227. package/src/cli/program.ts +52 -2
  228. package/src/config/assistant-feature-flags.ts +24 -54
  229. package/src/config/bundled-skills/app-builder/SKILL.md +140 -22
  230. package/src/config/bundled-skills/app-builder/TOOLS.json +7 -0
  231. package/src/config/bundled-skills/computer-use/TOOLS.json +15 -52
  232. package/src/config/bundled-skills/document/SKILL.md +23 -3
  233. package/src/config/bundled-skills/document/TOOLS.json +53 -0
  234. package/src/config/bundled-skills/document/tools/document-delete.ts +12 -0
  235. package/src/config/bundled-skills/document/tools/document-list.ts +12 -0
  236. package/src/config/bundled-skills/document/tools/document-read.ts +12 -0
  237. package/src/config/bundled-skills/phone-calls/SKILL.md +1 -1
  238. package/src/config/bundled-skills/skill-management/SKILL.md +2 -2
  239. package/src/config/bundled-skills/skill-management/TOOLS.json +7 -7
  240. package/src/config/bundled-tool-registry.ts +6 -0
  241. package/src/config/call-site-defaults.ts +105 -0
  242. package/src/config/feature-flag-registry.json +41 -9
  243. package/src/config/llm-resolver.ts +52 -1
  244. package/src/config/loader.ts +64 -38
  245. package/src/config/schema.ts +9 -10
  246. package/src/config/schemas/__tests__/llm-request-logs.test.ts +36 -0
  247. package/src/config/schemas/__tests__/memory-v2.test.ts +3 -3
  248. package/src/config/schemas/channels.ts +17 -0
  249. package/src/config/schemas/compaction.ts +28 -0
  250. package/src/config/schemas/conversations.ts +10 -0
  251. package/src/config/schemas/heartbeat.ts +23 -0
  252. package/src/config/schemas/llm-request-logs.ts +31 -7
  253. package/src/config/schemas/llm.ts +1 -0
  254. package/src/config/schemas/memory-retrieval.ts +18 -0
  255. package/src/config/schemas/memory-retrospective.ts +1 -1
  256. package/src/config/schemas/memory-v2.ts +4 -4
  257. package/src/config/schemas/memory.ts +3 -1
  258. package/src/config/schemas/tools.ts +14 -0
  259. package/src/config/seed-inference-profiles.ts +99 -29
  260. package/src/config/skills.ts +3 -96
  261. package/src/context/compactor.ts +1107 -0
  262. package/src/context/token-estimator.ts +34 -36
  263. package/src/context/window-manager.ts +197 -1520
  264. package/src/credential-execution/managed-catalog.ts +37 -0
  265. package/src/credential-health/credential-health-service.ts +280 -19
  266. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +33 -18
  267. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +138 -0
  268. package/src/daemon/__tests__/conversation-tool-setup.test.ts +74 -0
  269. package/src/daemon/approval-generators.ts +8 -6
  270. package/src/daemon/config-watcher.ts +94 -31
  271. package/src/daemon/conversation-agent-loop-handlers.ts +78 -0
  272. package/src/daemon/conversation-agent-loop.ts +198 -11
  273. package/src/daemon/conversation-error.ts +171 -37
  274. package/src/daemon/conversation-lifecycle.ts +53 -40
  275. package/src/daemon/conversation-messaging.ts +25 -6
  276. package/src/daemon/conversation-process.ts +49 -12
  277. package/src/daemon/conversation-runtime-assembly.ts +25 -1
  278. package/src/daemon/conversation-slash.ts +12 -5
  279. package/src/daemon/conversation-store.ts +11 -4
  280. package/src/daemon/conversation-tool-setup.ts +39 -7
  281. package/src/daemon/conversation.ts +33 -8
  282. package/src/daemon/date-context.ts +40 -0
  283. package/src/daemon/external-plugins-bootstrap.ts +217 -181
  284. package/src/daemon/first-greeting.ts +22 -2
  285. package/src/daemon/guardian-action-generators.ts +1 -125
  286. package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +248 -0
  287. package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +154 -0
  288. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +133 -0
  289. package/src/daemon/handlers/__tests__/config-a2a.test.ts +95 -0
  290. package/src/daemon/handlers/config-a2a.ts +289 -0
  291. package/src/daemon/handlers/config-model.ts +6 -5
  292. package/src/daemon/handlers/config-slack-channel.ts +15 -3
  293. package/src/daemon/handlers/conversations.ts +1 -0
  294. package/src/daemon/handlers/shared.ts +14 -5
  295. package/src/daemon/handlers/skills.ts +111 -108
  296. package/src/daemon/history-repair.ts +28 -1
  297. package/src/daemon/host-app-control-proxy.ts +153 -27
  298. package/src/daemon/host-proxy-preactivation.ts +85 -18
  299. package/src/daemon/lifecycle.ts +89 -91
  300. package/src/daemon/meet-host-supervisor.ts +5 -4
  301. package/src/daemon/memory-v2-startup.ts +85 -0
  302. package/src/daemon/message-protocol.ts +1 -0
  303. package/src/daemon/message-types/conversations.ts +25 -0
  304. package/src/daemon/message-types/messages.ts +61 -0
  305. package/src/daemon/message-types/notifications.ts +21 -0
  306. package/src/daemon/message-types/subagents.ts +1 -0
  307. package/src/daemon/message-types/sync.ts +1 -0
  308. package/src/daemon/pkb-reminder-builder.test.ts +11 -54
  309. package/src/daemon/pkb-reminder-builder.ts +5 -20
  310. package/src/daemon/plugin-source-watcher.ts +146 -0
  311. package/src/daemon/process-message.ts +24 -3
  312. package/src/daemon/server.ts +11 -2
  313. package/src/daemon/skill-memory-refresh.ts +33 -0
  314. package/src/daemon/wake-target-adapter.ts +2 -0
  315. package/src/documents/document-store.ts +221 -3
  316. package/src/embedded/plugin-api.ts +40 -0
  317. package/src/export/__tests__/transcript-formatter.test.ts +121 -0
  318. package/src/export/transcript-formatter.ts +54 -20
  319. package/src/filing/filing-service.ts +39 -0
  320. package/src/heartbeat/__tests__/heartbeat-service.test.ts +135 -6
  321. package/src/heartbeat/heartbeat-run-store.ts +2 -1
  322. package/src/heartbeat/heartbeat-service.ts +73 -189
  323. package/src/home/__tests__/feed-types.test.ts +80 -0
  324. package/src/home/feed-types.ts +36 -2
  325. package/src/home/post-connect-feed.ts +1 -0
  326. package/src/index.ts +18 -1
  327. package/src/ipc/cli-client.ts +147 -45
  328. package/src/live-voice/__tests__/live-voice-stt.test.ts +57 -0
  329. package/src/mcp/client.ts +20 -4
  330. package/src/media/image-credentials.ts +3 -3
  331. package/src/memory/__tests__/bookmark-crud.test.ts +33 -27
  332. package/src/memory/__tests__/conversation-queries.test.ts +483 -0
  333. package/src/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +113 -0
  334. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +2 -50
  335. package/src/memory/__tests__/memory-retrospective-job.test.ts +87 -4
  336. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +119 -14
  337. package/src/memory/__tests__/message-content.test.ts +35 -0
  338. package/src/memory/bookmark-crud.ts +42 -10
  339. package/src/memory/context-search/sources/conversations.ts +62 -2
  340. package/src/memory/context-search/sources/workspace.ts +4 -0
  341. package/src/memory/conversation-crud.ts +63 -19
  342. package/src/memory/conversation-queries.ts +197 -11
  343. package/src/memory/conversation-title-service.ts +26 -4
  344. package/src/memory/db-init.ts +12 -0
  345. package/src/memory/delivery-crud.ts +152 -5
  346. package/src/memory/embedding-backend.ts +4 -4
  347. package/src/memory/external-conversation-store.ts +66 -5
  348. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +150 -12
  349. package/src/memory/graph/conversation-graph-memory.ts +49 -21
  350. package/src/memory/graph/tools.ts +9 -40
  351. package/src/memory/indexer.ts +34 -29
  352. package/src/memory/invite-store.ts +53 -0
  353. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +73 -0
  354. package/src/memory/jobs/embed-concept-page.ts +20 -11
  355. package/src/memory/jobs-worker.ts +6 -1
  356. package/src/memory/llm-request-log-source-clickhouse.ts +24 -12
  357. package/src/memory/llm-request-log-source.ts +19 -52
  358. package/src/memory/llm-request-log-store.ts +92 -1
  359. package/src/memory/llm-usage-store.ts +125 -5
  360. package/src/memory/memory-retrospective-enqueue.ts +1 -20
  361. package/src/memory/memory-retrospective-job.ts +33 -6
  362. package/src/memory/memory-retrospective-startup-cleanup.ts +72 -5
  363. package/src/memory/message-content.ts +1 -1
  364. package/src/memory/migrations/109-external-conversation-bindings.ts +15 -4
  365. package/src/memory/migrations/229-delete-private-conversations.test.ts +38 -1
  366. package/src/memory/migrations/229-delete-private-conversations.ts +7 -0
  367. package/src/memory/migrations/247-external-conversation-binding-thread-id.ts +78 -0
  368. package/src/memory/migrations/248-create-onboarding-events.ts +21 -0
  369. package/src/memory/migrations/249-normalize-slack-external-content.ts +240 -0
  370. package/src/memory/migrations/250-provider-connection-base-url-and-models.ts +28 -0
  371. package/src/memory/migrations/251-a2a-tasks.ts +49 -0
  372. package/src/memory/migrations/252-llm-request-log-agent-loop-exit-reason.ts +32 -0
  373. package/src/memory/migrations/index.ts +9 -0
  374. package/src/memory/migrations/registry.ts +16 -0
  375. package/src/memory/onboarding-events-store.ts +106 -0
  376. package/src/memory/schema/a2a.ts +15 -0
  377. package/src/memory/schema/bookmarks.ts +0 -2
  378. package/src/memory/schema/calls.ts +1 -0
  379. package/src/memory/schema/index.ts +1 -0
  380. package/src/memory/schema/inference.ts +3 -3
  381. package/src/memory/schema/infrastructure.ts +13 -0
  382. package/src/memory/turn-events-store.ts +127 -2
  383. package/src/memory/v2/__tests__/activation-store.test.ts +25 -23
  384. package/src/memory/v2/__tests__/activation.test.ts +0 -8
  385. package/src/memory/v2/__tests__/cli-command-store.test.ts +404 -0
  386. package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +25 -4
  387. package/src/memory/v2/__tests__/injection.test.ts +288 -11
  388. package/src/memory/v2/__tests__/migration.test.ts +87 -0
  389. package/src/memory/v2/__tests__/page-index.test.ts +83 -0
  390. package/src/memory/v2/__tests__/prompts-router.test.ts +58 -6
  391. package/src/memory/v2/__tests__/qdrant.test.ts +66 -3
  392. package/src/memory/v2/__tests__/router.test.ts +15 -0
  393. package/src/memory/v2/__tests__/skill-store.test.ts +387 -8
  394. package/src/memory/v2/__tests__/static-context.test.ts +12 -1
  395. package/src/memory/v2/activation-store.ts +14 -16
  396. package/src/memory/v2/cli-command-content.ts +19 -0
  397. package/src/memory/v2/cli-command-store.ts +304 -0
  398. package/src/memory/v2/frontmatter-sweep.ts +7 -1
  399. package/src/memory/v2/injection.ts +81 -26
  400. package/src/memory/v2/migration.ts +49 -19
  401. package/src/memory/v2/page-index.ts +63 -8
  402. package/src/memory/v2/prompts/router.ts +11 -8
  403. package/src/memory/v2/prompts/sweep.ts +2 -2
  404. package/src/memory/v2/qdrant.ts +135 -7
  405. package/src/memory/v2/router.ts +9 -8
  406. package/src/memory/v2/skill-store.ts +120 -35
  407. package/src/memory/v2/static-context.ts +4 -4
  408. package/src/memory/v2/types.ts +23 -0
  409. package/src/messaging/providers/a2a/__tests__/deliver.test.ts +274 -0
  410. package/src/messaging/providers/a2a/deliver.ts +156 -0
  411. package/src/messaging/providers/gmail/client.ts +9 -2
  412. package/src/messaging/providers/index.ts +11 -2
  413. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +45 -5
  414. package/src/messaging/providers/slack/__tests__/download.test.ts +231 -0
  415. package/src/messaging/providers/slack/adapter.ts +43 -5
  416. package/src/messaging/providers/slack/client.ts +27 -0
  417. package/src/messaging/providers/slack/deep-link.ts +65 -0
  418. package/src/messaging/providers/slack/download.ts +104 -0
  419. package/src/messaging/providers/slack/message-metadata.test.ts +32 -0
  420. package/src/messaging/providers/slack/message-metadata.ts +27 -0
  421. package/src/messaging/providers/slack/render-transcript.test.ts +134 -0
  422. package/src/messaging/providers/slack/render-transcript.ts +69 -5
  423. package/src/messaging/providers/slack/types.ts +20 -1
  424. package/src/notifications/__tests__/broadcaster.test.ts +203 -0
  425. package/src/notifications/__tests__/decision-engine.test.ts +283 -0
  426. package/src/notifications/__tests__/deterministic-checks.test.ts +286 -0
  427. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +1 -0
  428. package/src/notifications/__tests__/home-feed-side-effect.test.ts +430 -7
  429. package/src/notifications/adapters/macos.ts +12 -2
  430. package/src/notifications/broadcaster.ts +29 -4
  431. package/src/notifications/conversation-pairing.ts +2 -1
  432. package/src/notifications/copy-composer.ts +17 -64
  433. package/src/notifications/decision-engine.ts +113 -45
  434. package/src/notifications/deterministic-checks.ts +96 -0
  435. package/src/notifications/emit-signal.ts +21 -1
  436. package/src/notifications/home-feed-side-effect.ts +138 -5
  437. package/src/notifications/signal.ts +3 -5
  438. package/src/notifications/types.ts +8 -0
  439. package/src/oauth/connection-resolver.ts +8 -4
  440. package/src/oauth/platform-connection.test.ts +43 -3
  441. package/src/oauth/platform-connection.ts +19 -6
  442. package/src/oauth/seed-providers.ts +10 -1
  443. package/src/permissions/checker.ts +2 -0
  444. package/src/permissions/ipc-risk-types.ts +1 -0
  445. package/src/permissions/question-prompter.test.ts +416 -0
  446. package/src/permissions/question-prompter.ts +294 -0
  447. package/src/platform/client.test.ts +1 -1
  448. package/src/platform/client.ts +1 -1
  449. package/src/plugin-api/constants.ts +26 -0
  450. package/src/plugin-api/index.ts +34 -1
  451. package/src/plugin-api/types.ts +104 -22
  452. package/src/plugins/defaults/circuit-breaker.ts +0 -5
  453. package/src/plugins/defaults/compaction.ts +0 -4
  454. package/src/plugins/defaults/empty-response.ts +0 -2
  455. package/src/plugins/defaults/history-repair.ts +0 -2
  456. package/src/plugins/defaults/injectors.ts +74 -22
  457. package/src/plugins/defaults/llm-call.ts +0 -2
  458. package/src/plugins/defaults/memory-retrieval.ts +0 -1
  459. package/src/plugins/defaults/overflow-reduce.ts +0 -1
  460. package/src/plugins/defaults/persistence.ts +0 -2
  461. package/src/plugins/defaults/title-generate.ts +0 -5
  462. package/src/plugins/defaults/token-estimate.ts +0 -2
  463. package/src/plugins/defaults/tool-error.ts +0 -7
  464. package/src/plugins/defaults/tool-execute.ts +0 -2
  465. package/src/plugins/defaults/tool-result-truncate.ts +0 -4
  466. package/src/plugins/ensure-plugin-api-shim.ts +96 -0
  467. package/src/plugins/external-api.ts +104 -0
  468. package/src/plugins/external-plugin-loader.ts +187 -42
  469. package/src/plugins/feature-gate.ts +22 -0
  470. package/src/plugins/pipeline.ts +37 -0
  471. package/src/plugins/registry.ts +48 -80
  472. package/src/plugins/types.ts +40 -26
  473. package/src/plugins/user-loader.ts +21 -2
  474. package/src/proactive-artifact/aux-message-injector.ts +11 -0
  475. package/src/proactive-artifact/job.test.ts +37 -5
  476. package/src/prompts/__tests__/system-prompt.test.ts +10 -43
  477. package/src/prompts/__tests__/task-progress-hint-section.test.ts +95 -0
  478. package/src/prompts/normalize-onboarding.ts +27 -0
  479. package/src/prompts/sections.ts +302 -0
  480. package/src/prompts/system-prompt.ts +63 -174
  481. package/src/prompts/templates/BOOTSTRAP.md +17 -1
  482. package/src/prompts/templates/system-sections.ts +164 -0
  483. package/src/providers/__tests__/inference.test.ts +24 -7
  484. package/src/providers/anthropic/client.ts +28 -28
  485. package/src/providers/call-site-routing.ts +24 -6
  486. package/src/providers/connection-resolution.ts +68 -11
  487. package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +74 -0
  488. package/src/providers/inference/__tests__/connections-openai-compatible.test.ts +175 -0
  489. package/src/providers/inference/__tests__/connections-status-label.test.ts +15 -0
  490. package/src/providers/inference/adapter-factory.ts +32 -6
  491. package/src/providers/inference/auth.ts +12 -0
  492. package/src/providers/inference/backfill.ts +14 -1
  493. package/src/providers/inference/connections.ts +159 -34
  494. package/src/providers/inference/resolve-auth.ts +14 -4
  495. package/src/providers/model-catalog.ts +249 -12
  496. package/src/providers/model-intents.ts +3 -3
  497. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +235 -0
  498. package/src/providers/openai/chat-completions-provider.ts +169 -8
  499. package/src/providers/openrouter/client.ts +49 -4
  500. package/src/providers/{managed-proxy → platform-proxy}/constants.ts +4 -2
  501. package/src/providers/{managed-proxy → platform-proxy}/context.ts +3 -3
  502. package/src/providers/provider-availability.ts +17 -2
  503. package/src/providers/provider-catalog-visibility.ts +38 -0
  504. package/src/providers/provider-send-message.ts +27 -12
  505. package/src/providers/registry.ts +52 -15
  506. package/src/providers/retry.ts +47 -1
  507. package/src/runtime/__tests__/agent-wake.test.ts +152 -0
  508. package/src/runtime/agent-wake.ts +103 -15
  509. package/src/runtime/auth/route-policy.ts +21 -1
  510. package/src/runtime/btw-sidechain.ts +2 -0
  511. package/src/runtime/http-server.ts +7 -16
  512. package/src/runtime/http-types.ts +19 -47
  513. package/src/runtime/migrations/origin-mode.ts +1 -1
  514. package/src/runtime/pending-interactions.ts +1 -0
  515. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +17 -0
  516. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +258 -0
  517. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +5 -1
  518. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +172 -23
  519. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +275 -44
  520. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +12 -0
  521. package/src/runtime/routes/__tests__/question-routes.test.ts +395 -0
  522. package/src/runtime/routes/__tests__/tts-routes.test.ts +64 -1
  523. package/src/runtime/routes/acp-routes-list.test.ts +143 -0
  524. package/src/runtime/routes/acp-routes.ts +5 -3
  525. package/src/runtime/routes/auth-routes.ts +1 -1
  526. package/src/runtime/routes/bookmark-routes.ts +5 -3
  527. package/src/runtime/routes/btw-routes.ts +5 -1
  528. package/src/runtime/routes/channel-availability-routes.ts +126 -0
  529. package/src/runtime/routes/consolidation-routes.ts +100 -0
  530. package/src/runtime/routes/conversation-cli-routes.ts +44 -3
  531. package/src/runtime/routes/conversation-list-routes.ts +3 -20
  532. package/src/runtime/routes/conversation-management-routes.ts +17 -42
  533. package/src/runtime/routes/conversation-query-routes.ts +99 -35
  534. package/src/runtime/routes/conversation-routes.ts +97 -11
  535. package/src/runtime/routes/documents-routes.ts +25 -86
  536. package/src/runtime/routes/group-routes.ts +5 -0
  537. package/src/runtime/routes/inbound-conversation.ts +28 -8
  538. package/src/runtime/routes/inbound-message-handler.ts +236 -41
  539. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +111 -0
  540. package/src/runtime/routes/inbound-stages/background-dispatch.ts +32 -1
  541. package/src/runtime/routes/inbound-stages/edit-intercept.ts +17 -4
  542. package/src/runtime/routes/index.ts +8 -0
  543. package/src/runtime/routes/inference-profile-session-handler.ts +17 -44
  544. package/src/runtime/routes/inference-profile-session-reaper.ts +7 -21
  545. package/src/runtime/routes/inference-provider-connection-routes.ts +199 -22
  546. package/src/runtime/routes/integrations/a2a.ts +235 -0
  547. package/src/runtime/routes/integrations/slack/share.ts +4 -52
  548. package/src/runtime/routes/integrations/slack/token.ts +43 -0
  549. package/src/runtime/routes/integrations/twilio.ts +6 -13
  550. package/src/runtime/routes/llm-call-sites-routes.ts +11 -1
  551. package/src/runtime/routes/notification-routes.ts +1 -1
  552. package/src/runtime/routes/oauth-commands-routes.ts +105 -15
  553. package/src/runtime/routes/oauth-lifecycle-routes.ts +43 -0
  554. package/src/runtime/routes/question-routes.ts +259 -0
  555. package/src/runtime/routes/rename-conversation-routes.ts +2 -33
  556. package/src/runtime/routes/schedule-routes.ts +4 -7
  557. package/src/runtime/routes/subagents-routes.ts +98 -18
  558. package/src/runtime/routes/telemetry-routes.ts +27 -0
  559. package/src/runtime/routes/tts-routes.ts +27 -2
  560. package/src/runtime/routes/workspace-routes.test.ts +43 -0
  561. package/src/runtime/routes/workspace-routes.ts +28 -0
  562. package/src/runtime/services/conversation-serializer.ts +39 -7
  563. package/src/runtime/sync/resource-sync-events.ts +93 -1
  564. package/src/schedule/schedule-store.ts +27 -2
  565. package/src/schedule/scheduler.ts +9 -1
  566. package/src/security/__tests__/untrusted-content.test.ts +86 -0
  567. package/src/security/untrusted-content.ts +93 -8
  568. package/src/skills/catalog-files.ts +1 -1
  569. package/src/skills/catalog-install.ts +233 -116
  570. package/src/skills/clawhub.ts +70 -13
  571. package/src/skills/managed-store.ts +4 -119
  572. package/src/skills/skillssh-registry.ts +27 -48
  573. package/src/subagent/manager.ts +17 -7
  574. package/src/telemetry/types.ts +113 -1
  575. package/src/telemetry/usage-telemetry-reporter.test.ts +312 -5
  576. package/src/telemetry/usage-telemetry-reporter.ts +113 -7
  577. package/src/tools/apps/executors.ts +58 -7
  578. package/src/tools/ask-question/ask-question-tool.test.ts +509 -0
  579. package/src/tools/ask-question/ask-question-tool.ts +304 -0
  580. package/src/tools/browser/browser-execution.ts +15 -11
  581. package/src/tools/computer-use/definitions.ts +3 -3
  582. package/src/tools/credentials/vault.ts +1 -1
  583. package/src/tools/document/document-tool.ts +124 -1
  584. package/src/tools/filesystem/edit.ts +1 -1
  585. package/src/tools/filesystem/list.ts +1 -1
  586. package/src/tools/filesystem/read.ts +1 -1
  587. package/src/tools/filesystem/write.ts +5 -2
  588. package/src/tools/host-filesystem/transfer.ts +1 -1
  589. package/src/tools/host-terminal/host-shell.ts +1 -1
  590. package/src/tools/memory/register.ts +1 -9
  591. package/src/tools/permission-checker.ts +1 -1
  592. package/src/tools/registry.ts +17 -7
  593. package/src/tools/schedule/create.ts +2 -2
  594. package/src/tools/schema-transforms.ts +7 -2
  595. package/src/tools/side-effects.ts +1 -0
  596. package/src/tools/skills/delete-managed.ts +4 -4
  597. package/src/tools/skills/execute.ts +1 -1
  598. package/src/tools/skills/scaffold-managed.ts +3 -2
  599. package/src/tools/subagent/notify-parent.ts +1 -1
  600. package/src/tools/system/request-permission.ts +2 -2
  601. package/src/tools/terminal/safe-env.ts +60 -1
  602. package/src/tools/tool-manifest.ts +2 -0
  603. package/src/tools/types.ts +107 -21
  604. package/src/tools/ui-surface/definitions.ts +6 -5
  605. package/src/tts/__tests__/provider-adapters.test.ts +76 -2
  606. package/src/tts/providers/elevenlabs-provider.ts +75 -1
  607. package/src/types/onboarding-context.ts +2 -0
  608. package/src/util/errors.ts +17 -0
  609. package/src/util/platform.ts +10 -0
  610. package/src/watcher/__tests__/engine.test.ts +22 -0
  611. package/src/watcher/engine.ts +6 -2
  612. package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +80 -15
  613. package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +35 -22
  614. package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +3 -1
  615. package/src/workspace/migrations/083-system-prompt-prefix-to-file.ts +191 -0
  616. package/src/workspace/migrations/084-remove-legacy-skills-index.ts +276 -0
  617. package/src/workspace/migrations/085-memory-v2-bm25-b-reembed-disabled-v2-pages.ts +137 -0
  618. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +198 -0
  619. package/src/workspace/migrations/087-memory-router-balanced-profile.ts +91 -0
  620. package/src/workspace/migrations/registry.ts +10 -0
  621. package/src/workspace/migrations/runner.ts +39 -9
  622. package/src/workspace/migrations/types.ts +4 -0
  623. package/examples/plugins/echo/bun.lock +0 -25
  624. package/src/__tests__/context-window-manager.test.ts +0 -2481
  625. package/src/__tests__/guardian-action-conversation-turn.test.ts +0 -441
  626. package/src/context/__tests__/compact-prompt.test.ts +0 -63
  627. package/src/context/prompts/compact.md +0 -26
  628. package/src/memory/graph/__tests__/remember-description.test.ts +0 -55
  629. package/src/prompts/__tests__/build-cli-reference-section.test.ts +0 -37
  630. package/src/runtime/guardian-action-conversation-turn.ts +0 -99
@@ -42,7 +42,11 @@ import type {
42
42
  ToolDefinition,
43
43
  } from "../providers/types.js";
44
44
  import type { SkillRoute } from "../runtime/skill-route-registry.js";
45
- import type { Tool, ToolContext, ToolExecutionResult } from "../tools/types.js";
45
+ import type {
46
+ LoadedPluginTool,
47
+ ToolContext,
48
+ ToolExecutionResult,
49
+ } from "../tools/types.js";
46
50
  import { AssistantError, ErrorCode } from "../util/errors.js";
47
51
 
48
52
  // ─── Manifest ────────────────────────────────────────────────────────────────
@@ -60,22 +64,13 @@ import { AssistantError, ErrorCode } from "../util/errors.js";
60
64
  export interface PluginManifest {
61
65
  /** Unique plugin identifier (kebab-case). Duplicate names fail registration. */
62
66
  name: string;
63
- /** Plugin version (semver). Informational — the registry compares
64
- * capability versions via `requires`, not this field. */
65
- version: string;
66
67
  /**
67
- * Capabilities this plugin exposes to other plugins.
68
- *
69
- * **Reserved for future cross-plugin composition not currently consumed
70
- * by any runtime code.** The field is declared so future cross-plugin work
71
- * can land without a manifest version bump, but today nothing reads it and
72
- * plugins must not depend on it for capability discovery. See
73
- * `assistant/docs/plugins.md` (Cross-plugin communication) for the
74
- * rationale.
68
+ * Plugin version (semver). Informational. Host-compat negotiation lives
69
+ * in the plugin's `package.json` `peerDependencies["@vellumai/plugin-api"]`
70
+ * range checked by the external-plugin loader against the assistant's
71
+ * own version at load time.
75
72
  */
76
- provides?: Record<string, string>;
77
- /** Capabilities this plugin needs from the assistant runtime. */
78
- requires: Record<string, string>;
73
+ version: string;
79
74
  /** Credential keys the plugin needs resolved before `init()` runs. */
80
75
  requiresCredential?: string[];
81
76
  /**
@@ -844,6 +839,24 @@ export interface TurnInjectionInputs {
844
839
  * knows no human is present to answer clarification questions.
845
840
  */
846
841
  readonly isNonInteractive?: boolean;
842
+ /**
843
+ * True when the active conversation's type is "background" or "scheduled"
844
+ * (see `isBackgroundConversationType`). Read by the `background-turn`
845
+ * injector to wrap the tail user message with a contextual reminder when
846
+ * the turn is also non-interactive.
847
+ */
848
+ readonly isBackgroundConversation?: boolean;
849
+ /**
850
+ * Active documents open in this conversation — surfaced by the
851
+ * `active-documents` injector so the assistant can target existing docs
852
+ * with `document_update` instead of creating duplicates.
853
+ */
854
+ readonly activeDocuments?: ReadonlyArray<{
855
+ surfaceId: string;
856
+ title: string;
857
+ wordCount: number;
858
+ updatedAt: number;
859
+ }> | null;
847
860
  }
848
861
 
849
862
  export interface DiskPressureInjectionContext {
@@ -995,15 +1008,18 @@ export interface Injector {
995
1008
  // catalog-discoverable skills today.
996
1009
 
997
1010
  /**
998
- * Tool registration contributed by a plugin. Uses the canonical {@link Tool}
999
- * interface from the tool registry the bootstrap stamps `origin: "plugin"`
1000
- * and `ownerPluginId: <plugin.name>` before handing the batch to
1001
- * `registerPluginTools`, which keeps plugin ref-counts and conflict detection
1002
- * in a namespace disjoint from real skills. Plugin authors supply the
1003
- * functional fields (`name`, `description`, `getDefinition`, `execute`, etc.)
1004
- * and leave the ownership metadata to the bootstrap to set authoritatively.
1011
+ * Tool registration contributed by a plugin. Uses the narrow
1012
+ * {@link LoadedPluginTool} shape. External plugin authors declare the
1013
+ * nameless `PluginTool` file shape; the loader derives `name` from the
1014
+ * `tools/<name>.ts` basename before storing it on `plugin.tools`. Authors
1015
+ * also leave category / ownership metadata to the bootstrap, which stamps
1016
+ * `category: "plugin"`, `origin: "plugin"`, and
1017
+ * `ownerPluginId: <plugin.name>` before handing the batch to
1018
+ * `registerPluginTools`. The registration boundary synthesizes
1019
+ * `getDefinition()` from `{name, description, input_schema}` so the canonical
1020
+ * {@link Tool} interface used by the internal registry stays unchanged.
1005
1021
  */
1006
- export type PluginToolRegistration = Tool;
1022
+ export type PluginToolRegistration = LoadedPluginTool;
1007
1023
  /**
1008
1024
  * HTTP route registration contributed by a plugin. Plugins express routes as
1009
1025
  * {@link SkillRoute} values — the same shape the skill-route registry
@@ -1075,9 +1091,7 @@ export interface PluginSkillRegistration {
1075
1091
  * Unknown keys are populated by the loader for forward compatibility
1076
1092
  * but are not invoked by today's runtime.
1077
1093
  */
1078
- export type PluginHookFn<TCtx = unknown> = (
1079
- ctx: TCtx,
1080
- ) => Promise<TCtx | void>;
1094
+ export type PluginHookFn<TCtx = unknown> = (ctx: TCtx) => Promise<TCtx | void>;
1081
1095
 
1082
1096
  /**
1083
1097
  * Map of lifecycle hooks contributed by a plugin. Keys match file
@@ -49,7 +49,8 @@ import { join } from "node:path";
49
49
  import { pathToFileURL } from "node:url";
50
50
 
51
51
  import { getLogger } from "../util/logger.js";
52
- import { getWorkspaceDir } from "../util/platform.js";
52
+ import { getWorkspacePluginsDir } from "../util/platform.js";
53
+ import { ensurePluginApiShim } from "./ensure-plugin-api-shim.js";
53
54
  import { loadExternalPlugin } from "./external-plugin-loader.js";
54
55
  import { closeRegistration } from "./registry.js";
55
56
 
@@ -93,7 +94,25 @@ export async function loadUserPlugins(
93
94
  ): Promise<void> {
94
95
  const importTimeoutMs = options.importTimeoutMs ?? USER_PLUGIN_IMPORT_TIMEOUT_MS;
95
96
 
96
- const pluginsDir = join(getWorkspaceDir(), "plugins");
97
+ // Materialize the workspace-level `@vellumai/plugin-api` shim *before*
98
+ // we dynamic-import any user plugins. The shim file must exist on disk
99
+ // before the first plugin's `import "@vellumai/plugin-api"` is parsed.
100
+ //
101
+ // Wrapped in try/catch because per `AGENTS.md` the daemon must never
102
+ // block startup. A shim-write failure (ENOSPC, read-only workspace,
103
+ // perms) is logged and we continue — plugins that try to import the
104
+ // public specifier will fail individually inside the per-plugin import
105
+ // loop below, which is already isolated.
106
+ try {
107
+ await ensurePluginApiShim();
108
+ } catch (err) {
109
+ log.warn(
110
+ { err },
111
+ "loadUserPlugins: plugin-api shim materialization failed — continuing with degraded plugin support",
112
+ );
113
+ }
114
+
115
+ const pluginsDir = getWorkspacePluginsDir();
97
116
 
98
117
  if (!existsSync(pluginsDir)) {
99
118
  // The clean-install case. Closing the registration window keeps the
@@ -8,6 +8,10 @@
8
8
 
9
9
  import { createAssistantMessage } from "../agent/message-types.js";
10
10
  import { findConversation } from "../daemon/conversation-store.js";
11
+ import {
12
+ conversationMessagesSyncTag,
13
+ SYNC_TAGS,
14
+ } from "../daemon/message-types/sync.js";
11
15
  import { addMessage } from "../memory/conversation-crud.js";
12
16
  import type { BroadcastFn } from "../notifications/adapters/macos.js";
13
17
  import { getLogger } from "../util/logger.js";
@@ -71,4 +75,11 @@ export async function injectAuxAssistantMessage(params: {
71
75
  type: "conversation_list_invalidated",
72
76
  reason: "reordered",
73
77
  });
78
+ params.broadcastMessage({
79
+ type: "sync_changed",
80
+ tags: [
81
+ SYNC_TAGS.conversationsList,
82
+ conversationMessagesSyncTag(params.conversationId),
83
+ ],
84
+ });
74
85
  }
@@ -1,5 +1,10 @@
1
1
  import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
2
2
 
3
+ import {
4
+ conversationMessagesSyncTag,
5
+ SYNC_TAGS,
6
+ } from "../daemon/message-types/sync.js";
7
+
3
8
  // ── Mock state ──────────────────────────────────────────────────────────
4
9
 
5
10
  // Provider mock
@@ -691,7 +696,7 @@ describe("runProactiveArtifactJob", () => {
691
696
  });
692
697
 
693
698
  describe("injectAuxAssistantMessage", () => {
694
- test("idle conversation: persists with skipIndexing, pushes to getMessages(), broadcasts delta + complete(aux) + list_invalidated", async () => {
699
+ test("idle conversation: persists with skipIndexing, pushes to getMessages(), broadcasts delta + complete(aux) + list sync", async () => {
695
700
  const messages: unknown[] = [];
696
701
  mockConversations.set("conv-inject-1", {
697
702
  processing: false,
@@ -714,7 +719,7 @@ describe("injectAuxAssistantMessage", () => {
714
719
  // Pushed to in-memory messages
715
720
  expect(messages).toHaveLength(1);
716
721
 
717
- // Broadcasts: delta, complete(aux), list_invalidated
722
+ // Broadcasts: delta, complete(aux), list invalidation + sync tag
718
723
  const deltaMsg = broadcastCalls.find(
719
724
  (c) => c.type === "assistant_text_delta",
720
725
  );
@@ -734,6 +739,15 @@ describe("injectAuxAssistantMessage", () => {
734
739
  );
735
740
  expect(listMsg).toBeDefined();
736
741
  expect(listMsg!.reason).toBe("reordered");
742
+
743
+ const syncMsg = broadcastCalls.find((c) => c.type === "sync_changed");
744
+ expect(syncMsg).toEqual({
745
+ type: "sync_changed",
746
+ tags: [
747
+ SYNC_TAGS.conversationsList,
748
+ conversationMessagesSyncTag("conv-inject-1"),
749
+ ],
750
+ });
737
751
  });
738
752
 
739
753
  test("processing → idle: waits for processing to become false before persisting", async () => {
@@ -824,13 +838,22 @@ describe("injectAuxAssistantMessage", () => {
824
838
  broadcastCalls.filter((c) => c.type === "message_complete"),
825
839
  ).toHaveLength(0);
826
840
 
827
- // But list_invalidated IS sent (always sent regardless of processing state)
841
+ // But list invalidation + sync tag ARE sent regardless of processing state.
828
842
  expect(
829
843
  broadcastCalls.filter((c) => c.type === "conversation_list_invalidated"),
830
844
  ).toHaveLength(1);
845
+ expect(broadcastCalls.filter((c) => c.type === "sync_changed")).toEqual([
846
+ {
847
+ type: "sync_changed",
848
+ tags: [
849
+ SYNC_TAGS.conversationsList,
850
+ conversationMessagesSyncTag("conv-inject-3"),
851
+ ],
852
+ },
853
+ ]);
831
854
  });
832
855
 
833
- test("inactive/unloaded conversation: persists + list_invalidated only", async () => {
856
+ test("inactive/unloaded conversation: persists + list sync only", async () => {
834
857
  // No conversation in the store
835
858
  await injectAuxAssistantMessage({
836
859
  conversationId: "conv-inject-4",
@@ -850,10 +873,19 @@ describe("injectAuxAssistantMessage", () => {
850
873
  broadcastCalls.filter((c) => c.type === "message_complete"),
851
874
  ).toHaveLength(0);
852
875
 
853
- // But list_invalidated IS sent
876
+ // But list invalidation + sync tag ARE sent
854
877
  expect(
855
878
  broadcastCalls.filter((c) => c.type === "conversation_list_invalidated"),
856
879
  ).toHaveLength(1);
880
+ expect(broadcastCalls.filter((c) => c.type === "sync_changed")).toEqual([
881
+ {
882
+ type: "sync_changed",
883
+ tags: [
884
+ SYNC_TAGS.conversationsList,
885
+ conversationMessagesSyncTag("conv-inject-4"),
886
+ ],
887
+ },
888
+ ]);
857
889
  });
858
890
  });
859
891
 
@@ -1,10 +1,9 @@
1
1
  /**
2
- * Tests for the Background Conversation gating in buildSystemPrompt.
3
- *
4
- * The Background Conversation guidance is gated on
5
- * `options.isBackgroundConversation === true`. Interactive (default)
6
- * conversations must pay zero token cost — the section must be entirely
7
- * absent unless the flag is explicitly true.
2
+ * Smoke tests for buildSystemPrompt covers tool-routing-guidance
3
+ * exclusions and other call-shape invariants. Background-conversation
4
+ * guidance is no longer rendered into the system prompt; see
5
+ * `__tests__/injector-background-turn.test.ts` for the per-turn
6
+ * user-message injection that replaced it.
8
7
  */
9
8
 
10
9
  import { mkdirSync } from "node:fs";
@@ -58,48 +57,16 @@ mock.module("../../config/loader.js", () => ({
58
57
  setNestedValue: () => {},
59
58
  }));
60
59
 
61
- const { buildSystemPrompt, SYSTEM_PROMPT_CACHE_BOUNDARY } =
62
- await import("../system-prompt.js");
60
+ const { buildSystemPrompt } = await import("../system-prompt.js");
63
61
 
64
- describe("buildSystemPrompt — Background Conversation gating", () => {
62
+ describe("buildSystemPrompt — tool routing guidance", () => {
65
63
  beforeEach(() => {
66
64
  mkdirSync(TEST_DIR, { recursive: true });
67
65
  });
68
66
 
69
- test("isBackgroundConversation: true appends the Background Conversation section", () => {
70
- const result = buildSystemPrompt({ isBackgroundConversation: true });
71
- expect(result).toContain("## Background Conversation");
72
- expect(result).toContain("`notifications` skill");
73
- expect(result).toContain("assistant notifications send");
74
- });
75
-
76
- test("isBackgroundConversation: false — section is omitted", () => {
77
- const result = buildSystemPrompt({ isBackgroundConversation: false });
78
- expect(result).not.toContain("## Background Conversation");
79
- });
80
-
81
- test("options undefined — section is omitted (interactive default)", () => {
82
- const result = buildSystemPrompt(undefined);
83
- expect(result).not.toContain("## Background Conversation");
84
- });
85
-
86
- test("options provided without the flag — section is omitted", () => {
67
+ test("does not include ask_question routing guidance", () => {
87
68
  const result = buildSystemPrompt({});
88
- expect(result).not.toContain("## Background Conversation");
89
- });
90
-
91
- test("section lives in the static (cached) block, not the dynamic suffix", () => {
92
- // The section is deterministic for a given conversationType, so it
93
- // belongs in staticParts to share the cache block with other
94
- // call-time-stable instructions.
95
- const result = buildSystemPrompt({ isBackgroundConversation: true });
96
- const boundaryIdx = result.indexOf(SYSTEM_PROMPT_CACHE_BOUNDARY);
97
- expect(boundaryIdx).toBeGreaterThan(-1);
98
- const staticBlock = result.slice(0, boundaryIdx);
99
- const dynamicBlock = result.slice(
100
- boundaryIdx + SYSTEM_PROMPT_CACHE_BOUNDARY.length,
101
- );
102
- expect(staticBlock).toContain("## Background Conversation");
103
- expect(dynamicBlock).not.toContain("## Background Conversation");
69
+ expect(result).not.toContain("## Clarifying questions");
70
+ expect(result).not.toContain("ask_question");
104
71
  });
105
72
  });
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Tests for the task_progress hint in the 01-parallel-tool-calls workspace
3
+ * system prompt section.
4
+ *
5
+ * Verifies that the task_progress guidance renders unconditionally in the
6
+ * system prompt — no `enabled` frontmatter gating, no options dependency.
7
+ */
8
+
9
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
10
+
11
+ const noopLogger: Record<string, unknown> = new Proxy(
12
+ {} as Record<string, unknown>,
13
+ {
14
+ get: (_target, prop) => (prop === "child" ? () => noopLogger : () => {}),
15
+ },
16
+ );
17
+
18
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
19
+ const realLogger = require("../../util/logger.js");
20
+ mock.module("../../util/logger.js", () => ({
21
+ ...realLogger,
22
+ getLogger: () => noopLogger,
23
+ getCliLogger: () => noopLogger,
24
+ truncateForLog: (v: string) => v,
25
+ initLogger: () => {},
26
+ pruneOldLogFiles: () => 0,
27
+ }));
28
+
29
+ const mockLoadedConfig: Record<string, unknown> = {};
30
+
31
+ mock.module("../../config/loader.js", () => ({
32
+ getConfig: () => ({
33
+ ui: {},
34
+ services: {
35
+ inference: {
36
+ mode: "your-own",
37
+ provider: "anthropic",
38
+ model: "claude-opus-4-6",
39
+ },
40
+ "image-generation": {
41
+ mode: "your-own",
42
+ provider: "gemini",
43
+ model: "gemini-3.1-flash-image-preview",
44
+ },
45
+ "web-search": { mode: "your-own", provider: "inference-provider-native" },
46
+ },
47
+ }),
48
+ loadConfig: () => mockLoadedConfig,
49
+ loadRawConfig: () => ({}),
50
+ saveConfig: () => {},
51
+ saveRawConfig: () => {},
52
+ invalidateConfigCache: () => {},
53
+ getNestedValue: () => undefined,
54
+ setNestedValue: () => {},
55
+ }));
56
+
57
+ const { buildSystemPrompt, ensurePromptFiles, SYSTEM_PROMPT_CACHE_BOUNDARY } =
58
+ await import("../system-prompt.js");
59
+
60
+ describe("task_progress hint in parallel-tool-calls section", () => {
61
+ beforeEach(() => {
62
+ ensurePromptFiles();
63
+ });
64
+
65
+ test("buildSystemPrompt() includes task_progress guidance", () => {
66
+ const result = buildSystemPrompt();
67
+ expect(result).toContain("task_progress");
68
+ expect(result).toContain("No exceptions");
69
+ });
70
+
71
+ test("renders unconditionally — no options required", () => {
72
+ const result = buildSystemPrompt(undefined);
73
+ expect(result).toContain("task_progress");
74
+ });
75
+
76
+ test("renders regardless of options passed", () => {
77
+ const withClientFlag = buildSystemPrompt({ hasNoClient: true });
78
+ const withoutClientFlag = buildSystemPrompt({ hasNoClient: false });
79
+ const withExcludePrefix = buildSystemPrompt({
80
+ excludeCustomPrefix: true,
81
+ });
82
+
83
+ expect(withClientFlag).toContain("task_progress");
84
+ expect(withoutClientFlag).toContain("task_progress");
85
+ expect(withExcludePrefix).toContain("task_progress");
86
+ });
87
+
88
+ test("hint lives in the static (cached) block before SYSTEM_PROMPT_CACHE_BOUNDARY", () => {
89
+ const result = buildSystemPrompt();
90
+ const boundaryIdx = result.indexOf(SYSTEM_PROMPT_CACHE_BOUNDARY);
91
+ expect(boundaryIdx).toBeGreaterThan(-1);
92
+ const staticBlock = result.slice(0, boundaryIdx);
93
+ expect(staticBlock).toContain("task_progress");
94
+ });
95
+ });
@@ -62,6 +62,29 @@ export interface NormalizedOnboarding {
62
62
  dailyTools: string[];
63
63
  tone?: string;
64
64
  assistantName?: string;
65
+ googleConnected?: boolean;
66
+ googleServices?: string[];
67
+ }
68
+
69
+ const SCOPE_SERVICE_MAP: Record<string, string> = {
70
+ "gmail.readonly": "Gmail",
71
+ "gmail.modify": "Gmail",
72
+ "gmail.send": "Gmail",
73
+ "gmail.settings.basic": "Gmail",
74
+ "calendar.readonly": "Calendar",
75
+ "calendar.events": "Calendar",
76
+ drive: "Drive",
77
+ };
78
+
79
+ export function deriveGoogleServices(scopes?: string[]): string[] {
80
+ if (!scopes?.length) return ["Gmail", "Calendar", "Drive"];
81
+ const services = new Set<string>();
82
+ for (const scope of scopes) {
83
+ const suffix = scope.replace("https://www.googleapis.com/auth/", "");
84
+ const service = SCOPE_SERVICE_MAP[suffix];
85
+ if (service) services.add(service);
86
+ }
87
+ return services.size > 0 ? [...services] : ["Gmail", "Calendar", "Drive"];
65
88
  }
66
89
 
67
90
  /**
@@ -76,5 +99,9 @@ export function normalizeOnboardingContext(
76
99
  dailyTools: normalizeTools(ctx.tools),
77
100
  tone: ctx.tone,
78
101
  assistantName: ctx.assistantName,
102
+ googleConnected: ctx.googleConnected,
103
+ googleServices: ctx.googleConnected
104
+ ? deriveGoogleServices(ctx.googleScopes)
105
+ : undefined,
79
106
  };
80
107
  }