@vellumai/assistant 0.8.10 → 0.8.11-staging.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (400) hide show
  1. package/bun.lock +62 -1
  2. package/docs/workspace-tools.md +196 -0
  3. package/examples/plugins/echo/README.md +3 -3
  4. package/knip.json +1 -0
  5. package/openapi.yaml +460 -128
  6. package/package.json +2 -1
  7. package/scripts/build-plugin-api.ts +299 -0
  8. package/src/__tests__/agent-loop-callsite-precedence.test.ts +7 -0
  9. package/src/__tests__/agent-loop-compaction-events.test.ts +197 -0
  10. package/src/__tests__/agent-loop-exit-reason.test.ts +93 -96
  11. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +2 -0
  12. package/src/__tests__/agent-loop-output-hooks.test.ts +274 -1
  13. package/src/__tests__/agent-loop-override-profile.test.ts +3 -0
  14. package/src/__tests__/agent-loop-provider-error-recording.test.ts +4 -0
  15. package/src/__tests__/agent-loop-thinking.test.ts +4 -0
  16. package/src/__tests__/agent-loop.test.ts +578 -5
  17. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +0 -1
  18. package/src/__tests__/approval-cascade.test.ts +1 -0
  19. package/src/__tests__/background-workers-disk-pressure.test.ts +0 -2
  20. package/src/__tests__/btw-routes.test.ts +0 -1
  21. package/src/__tests__/build-persisted-content.test.ts +75 -1
  22. package/src/__tests__/catalog-install-normalize.test.ts +141 -0
  23. package/src/__tests__/ces-startup-timeout.test.ts +60 -0
  24. package/src/__tests__/compaction-events.test.ts +1 -0
  25. package/src/__tests__/config-managed-gemini-defaults.test.ts +2 -46
  26. package/src/__tests__/context-overflow-reducer.test.ts +264 -124
  27. package/src/__tests__/context-window-manager-overflow-rung.test.ts +351 -0
  28. package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
  29. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +13 -5
  30. package/src/__tests__/conversation-agent-loop-overflow.test.ts +284 -455
  31. package/src/__tests__/conversation-agent-loop.test.ts +131 -551
  32. package/src/__tests__/conversation-app-control-instantiation.test.ts +13 -0
  33. package/src/__tests__/conversation-confirmation-signals.test.ts +1 -0
  34. package/src/__tests__/conversation-fork-crud.test.ts +259 -0
  35. package/src/__tests__/conversation-history-web-search.test.ts +1 -1
  36. package/src/__tests__/conversation-lifecycle.test.ts +257 -1
  37. package/src/__tests__/conversation-process-callsite.test.ts +1 -0
  38. package/src/__tests__/conversation-provider-retry-repair.test.ts +38 -377
  39. package/src/__tests__/conversation-queue.test.ts +1 -39
  40. package/src/__tests__/conversation-runtime-assembly.test.ts +119 -8
  41. package/src/__tests__/conversation-skill-tools.test.ts +491 -5
  42. package/src/__tests__/conversation-slash-queue.test.ts +1 -1
  43. package/src/__tests__/conversation-slash-unknown.test.ts +1 -0
  44. package/src/__tests__/conversation-speed-override.test.ts +1 -0
  45. package/src/__tests__/conversation-store.test.ts +74 -0
  46. package/src/__tests__/conversation-surfaces-app-control.test.ts +4 -1
  47. package/src/__tests__/conversation-tool-setup-attribution.test.ts +323 -0
  48. package/src/__tests__/conversation-tool-setup-tools-disabled.test.ts +34 -0
  49. package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -0
  50. package/src/__tests__/conversation-workspace-injection.test.ts +1 -1
  51. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -0
  52. package/src/__tests__/corrected-target.test.ts +93 -0
  53. package/src/__tests__/credential-execution-feature-gates.test.ts +3 -5
  54. package/src/__tests__/credential-execution-tools.test.ts +23 -11
  55. package/src/__tests__/credential-security-invariants.test.ts +6 -1
  56. package/src/__tests__/db-schedule-syntax-migration.test.ts +80 -0
  57. package/src/__tests__/device-id.test.ts +70 -1
  58. package/src/__tests__/embedding-managed-proxy-selection.test.ts +6 -40
  59. package/src/__tests__/empty-response-hook.test.ts +242 -66
  60. package/src/__tests__/external-plugin-loader.test.ts +0 -31
  61. package/src/__tests__/get-skill-detail-audit.test.ts +43 -1
  62. package/src/__tests__/guardian-routing-invariants.test.ts +91 -0
  63. package/src/__tests__/history-repair-hook.test.ts +228 -3
  64. package/src/__tests__/host-app-control-proxy.test.ts +45 -0
  65. package/src/__tests__/host-browser-proxy.test.ts +254 -9
  66. package/src/__tests__/identity-routes.test.ts +1 -0
  67. package/src/__tests__/image-recovery-hook.test.ts +387 -0
  68. package/src/__tests__/injector-chain.test.ts +5 -4
  69. package/src/__tests__/injector-v3-suppression.test.ts +373 -47
  70. package/src/__tests__/intent-routing.test.ts +7 -0
  71. package/src/__tests__/memory-retrieval-hook.test.ts +117 -15
  72. package/src/__tests__/notification-decision-strategy.test.ts +3 -3
  73. package/src/__tests__/oauth-store.test.ts +0 -85
  74. package/src/__tests__/{context-overflow-policy.test.ts → overflow-policy.test.ts} +1 -1
  75. package/src/__tests__/parallel-tool.benchmark.test.ts +4 -0
  76. package/src/__tests__/persist-unsendable-image-downscale.test.ts +29 -9
  77. package/src/__tests__/persist-unsendable-image.test.ts +4 -4
  78. package/src/__tests__/persistence-secret-redaction.test.ts +78 -0
  79. package/src/__tests__/plugin-bootstrap.test.ts +82 -73
  80. package/src/__tests__/plugin-tool-contribution.test.ts +7 -4
  81. package/src/__tests__/plugin-types.test.ts +0 -8
  82. package/src/__tests__/provider-catalog-visibility.test.ts +1 -9
  83. package/src/__tests__/prune-old-conversations-job.test.ts +99 -0
  84. package/src/__tests__/registry.test.ts +240 -1
  85. package/src/__tests__/require-fresh-approval.test.ts +3 -0
  86. package/src/__tests__/schedule-routes.test.ts +116 -1
  87. package/src/__tests__/schedule-store.test.ts +28 -0
  88. package/src/__tests__/schedule-tools.test.ts +94 -1
  89. package/src/__tests__/server-history-render.test.ts +39 -0
  90. package/src/__tests__/skill-projection-feature-flag.test.ts +13 -0
  91. package/src/__tests__/skill-projection.benchmark.test.ts +25 -7
  92. package/src/__tests__/skills.test.ts +202 -0
  93. package/src/__tests__/slim-skill-category.test.ts +195 -0
  94. package/src/__tests__/strip-memory-injections.test.ts +33 -39
  95. package/src/__tests__/test-support/tool-invocation-seed.ts +79 -0
  96. package/src/__tests__/title-generate-hook.test.ts +9 -7
  97. package/src/__tests__/tool-audit-listener.test.ts +264 -1
  98. package/src/__tests__/tool-error-hook.test.ts +4 -3
  99. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -0
  100. package/src/__tests__/tool-executor-lifecycle-events.test.ts +273 -0
  101. package/src/__tests__/tool-result-truncate-hook.test.ts +1 -0
  102. package/src/__tests__/tool-start-timestamp.test.ts +218 -0
  103. package/src/__tests__/tools-get-route.test.ts +202 -0
  104. package/src/__tests__/workspace-tool-loader.test.ts +319 -0
  105. package/src/__tests__/workspace-tools-watcher-flag.test.ts +70 -0
  106. package/src/agent/loop.ts +569 -319
  107. package/src/api/events/tool-result.ts +9 -0
  108. package/src/api/events/tool-use-start.ts +7 -0
  109. package/src/api/index.ts +10 -0
  110. package/src/api/responses/conversation-message.ts +135 -27
  111. package/src/api/responses/memory-v3-selection-log.ts +4 -4
  112. package/src/approvals/guardian-request-resolvers.ts +26 -0
  113. package/src/browser-session/backends/host-bridge.ts +29 -0
  114. package/src/browser-session/index.ts +1 -0
  115. package/src/browser-session/types.ts +5 -1
  116. package/src/cli/commands/__tests__/schedules.test.ts +62 -4
  117. package/src/cli/commands/__tests__/skills.test.ts +53 -0
  118. package/src/cli/commands/channel-verification-sessions.ts +6 -6
  119. package/src/cli/commands/inference-providers.ts +0 -8
  120. package/src/cli/commands/plugins.ts +2 -2
  121. package/src/cli/commands/schedules.ts +27 -4
  122. package/src/cli/commands/skills.ts +187 -146
  123. package/src/cli/commands/tools.ts +106 -0
  124. package/src/cli/lib/__tests__/install-from-github.test.ts +256 -328
  125. package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +6 -2
  126. package/src/cli/lib/__tests__/plugin-details.test.ts +10 -16
  127. package/src/cli/lib/__tests__/plugin-marketplace.test.ts +2 -2
  128. package/src/cli/lib/__tests__/search-plugins.test.ts +145 -240
  129. package/src/cli/lib/install-from-github.ts +187 -117
  130. package/src/cli/lib/plugin-catalog-cache.ts +9 -9
  131. package/src/cli/lib/plugin-details.ts +38 -68
  132. package/src/cli/lib/plugin-marketplace.ts +42 -14
  133. package/src/cli/lib/search-plugins.ts +29 -129
  134. package/src/cli/program.ts +2 -0
  135. package/src/config/bundled-skills/acp/SKILL.md +1 -0
  136. package/src/config/bundled-skills/app-builder/SKILL.md +1 -0
  137. package/src/config/bundled-skills/app-control/SKILL.md +1 -0
  138. package/src/config/bundled-skills/computer-use/SKILL.md +1 -0
  139. package/src/config/bundled-skills/contacts/SKILL.md +1 -0
  140. package/src/config/bundled-skills/document-editor/SKILL.md +1 -0
  141. package/src/config/bundled-skills/followups/SKILL.md +1 -0
  142. package/src/config/bundled-skills/image-studio/SKILL.md +1 -0
  143. package/src/config/bundled-skills/media-processing/SKILL.md +1 -0
  144. package/src/config/bundled-skills/messaging/SKILL.md +1 -0
  145. package/src/config/bundled-skills/phone-calls/SKILL.md +1 -0
  146. package/src/config/bundled-skills/playbooks/SKILL.md +1 -0
  147. package/src/config/bundled-skills/schedule/SKILL.md +1 -0
  148. package/src/config/bundled-skills/schedule/TOOLS.json +11 -3
  149. package/src/config/bundled-skills/sequences/SKILL.md +1 -0
  150. package/src/config/bundled-skills/settings/SKILL.md +1 -0
  151. package/src/config/bundled-skills/skill-management/SKILL.md +101 -1
  152. package/src/config/bundled-skills/subagent/SKILL.md +1 -0
  153. package/src/config/bundled-skills/transcribe/SKILL.md +1 -0
  154. package/src/config/env-registry.ts +23 -0
  155. package/src/config/feature-flag-registry.json +17 -81
  156. package/src/config/loader.ts +5 -22
  157. package/src/config/schema.ts +2 -0
  158. package/src/config/schemas/__tests__/compaction-logs.test.ts +56 -0
  159. package/src/config/schemas/__tests__/memory-v2.test.ts +0 -1
  160. package/src/config/schemas/__tests__/memory-v3.test.ts +61 -1
  161. package/src/config/schemas/compaction-logs.ts +79 -0
  162. package/src/config/schemas/memory-v2.ts +0 -8
  163. package/src/config/schemas/memory-v3.ts +104 -33
  164. package/src/config/seed-inference-profiles.ts +1 -1
  165. package/src/config/skills.ts +117 -47
  166. package/src/context/compactor.ts +11 -0
  167. package/src/context/strip-injections.ts +38 -4
  168. package/src/credential-execution/feature-gates.ts +0 -21
  169. package/src/credential-execution/startup-timeout.ts +32 -4
  170. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +18 -0
  171. package/src/daemon/conversation-agent-loop-handlers.ts +140 -91
  172. package/src/daemon/conversation-agent-loop.ts +123 -658
  173. package/src/daemon/conversation-error.ts +6 -33
  174. package/src/daemon/conversation-lifecycle.ts +1 -1
  175. package/src/daemon/conversation-runtime-assembly.ts +183 -22
  176. package/src/daemon/conversation-skill-tools.ts +137 -8
  177. package/src/daemon/conversation-slash.ts +0 -14
  178. package/src/daemon/conversation-store.ts +2 -19
  179. package/src/daemon/conversation-tool-setup.ts +87 -1
  180. package/src/daemon/conversation.ts +119 -50
  181. package/src/daemon/external-plugins-bootstrap.ts +36 -95
  182. package/src/daemon/handlers/config-channels.ts +11 -2
  183. package/src/daemon/handlers/shared.ts +9 -1
  184. package/src/daemon/handlers/skills.ts +10 -4
  185. package/src/daemon/host-app-control-proxy.ts +72 -57
  186. package/src/daemon/host-browser-proxy.ts +117 -22
  187. package/src/daemon/lifecycle.ts +34 -5
  188. package/src/daemon/message-protocol.ts +0 -7
  189. package/src/daemon/message-types/schedules.ts +1 -0
  190. package/src/daemon/message-types/skills.ts +17 -0
  191. package/src/daemon/providers-setup.ts +3 -0
  192. package/src/daemon/server.ts +3 -3
  193. package/src/daemon/tool-setup-types.ts +9 -3
  194. package/src/daemon/trust-context.ts +23 -0
  195. package/src/daemon/workspace-tools-watcher.ts +324 -0
  196. package/src/events/tool-audit-listener.ts +78 -16
  197. package/src/events/tool-metrics-listener.ts +2 -5
  198. package/src/memory/__tests__/compaction-log-writer-clickhouse.test.ts +227 -0
  199. package/src/memory/__tests__/conversation-queries.test.ts +176 -0
  200. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +20 -32
  201. package/src/memory/compaction-log-writer-clickhouse.ts +418 -0
  202. package/src/memory/conversation-crud.ts +134 -3
  203. package/src/memory/conversation-queries.ts +64 -7
  204. package/src/memory/db-init.ts +14 -0
  205. package/src/memory/embedding-backend.test.ts +130 -1
  206. package/src/memory/embedding-backend.ts +79 -106
  207. package/src/memory/embedding-gemini.ts +5 -0
  208. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +12 -0
  209. package/src/memory/graph/__tests__/handle-remember-v2.test.ts +19 -0
  210. package/src/memory/graph/conversation-graph-memory.ts +36 -25
  211. package/src/memory/graph/tool-handlers.ts +3 -0
  212. package/src/memory/job-handlers/cleanup.ts +3 -1
  213. package/src/memory/jobs-store.ts +0 -28
  214. package/src/memory/jobs-worker.ts +10 -22
  215. package/src/memory/memory-marker.ts +29 -0
  216. package/src/memory/memory-retrospective-startup-cleanup.ts +1 -1
  217. package/src/memory/migrations/268-add-memory-v3-selections.ts +6 -0
  218. package/src/memory/migrations/270-schedule-description.ts +36 -0
  219. package/src/memory/migrations/275-tool-invocations-add-skill-id.test.ts +81 -0
  220. package/src/memory/migrations/275-tool-invocations-add-skill-id.ts +20 -0
  221. package/src/memory/migrations/276-tool-invocations-created-at-id-index.test.ts +68 -0
  222. package/src/memory/migrations/276-tool-invocations-created-at-id-index.ts +20 -0
  223. package/src/memory/migrations/277-add-memory-v3-ever-injected.ts +29 -0
  224. package/src/memory/migrations/278-tool-invocations-telemetry-columns.test.ts +96 -0
  225. package/src/memory/migrations/278-tool-invocations-telemetry-columns.ts +39 -0
  226. package/src/memory/migrations/279-create-skill-loaded-events.test.ts +84 -0
  227. package/src/memory/migrations/279-create-skill-loaded-events.ts +26 -0
  228. package/src/memory/migrations/280-conversations-surfaced-at.test.ts +88 -0
  229. package/src/memory/migrations/280-conversations-surfaced-at.ts +24 -0
  230. package/src/memory/migrations/index.ts +10 -0
  231. package/src/memory/migrations/registry.ts +8 -0
  232. package/src/memory/schema/conversations.ts +16 -0
  233. package/src/memory/schema/infrastructure.ts +26 -0
  234. package/src/memory/skill-loaded-events-store.test.ts +160 -0
  235. package/src/memory/skill-loaded-events-store.ts +95 -0
  236. package/src/memory/tool-executed-events-store.test.ts +219 -0
  237. package/src/memory/tool-executed-events-store.ts +102 -0
  238. package/src/memory/tool-usage-store.ts +15 -3
  239. package/src/memory/v2/__tests__/consolidation-job.test.ts +117 -12
  240. package/src/memory/v2/__tests__/consolidation-prompt-flag-gating-guard.test.ts +189 -0
  241. package/src/memory/v2/__tests__/injected-block-slugs.test.ts +90 -0
  242. package/src/memory/v2/__tests__/page-store.test.ts +33 -0
  243. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +88 -15
  244. package/src/memory/v2/activation-store.ts +50 -1
  245. package/src/memory/v2/consolidation-job.ts +113 -29
  246. package/src/memory/v2/injected-block-slugs.ts +79 -0
  247. package/src/memory/v2/injection.ts +6 -1
  248. package/src/memory/v2/prompts/consolidation.ts +414 -13
  249. package/src/memory/v2/router.ts +2 -28
  250. package/src/memory/v2/static-context.ts +1 -1
  251. package/src/memory/v2/types.ts +16 -0
  252. package/src/notifications/__tests__/copy-composer.test.ts +244 -0
  253. package/src/notifications/access-request-copy.ts +298 -0
  254. package/src/notifications/adapters/slack.ts +3 -3
  255. package/src/notifications/adapters/telegram.ts +2 -1
  256. package/src/notifications/copy-composer.ts +49 -267
  257. package/src/notifications/decision-engine.ts +16 -35
  258. package/src/notifications/home-feed-side-effect.ts +1 -6
  259. package/src/oauth/oauth-store.ts +0 -9
  260. package/src/permissions/checker.test.ts +83 -1
  261. package/src/permissions/checker.ts +25 -2
  262. package/src/permissions/gateway-threshold-reader.test.ts +182 -0
  263. package/src/permissions/gateway-threshold-reader.ts +80 -0
  264. package/src/platform/client.ts +1 -3
  265. package/src/platform/feature-gate.ts +3 -12
  266. package/src/plugin-api/constants.ts +4 -2
  267. package/src/plugin-api/index.ts +63 -11
  268. package/src/plugin-api/types.ts +236 -71
  269. package/src/plugins/defaults/compaction/compact.ts +66 -2
  270. package/src/plugins/defaults/compaction/context-overflow-reducer.ts +240 -32
  271. package/src/plugins/defaults/compaction/corrected-target.ts +53 -0
  272. package/src/{daemon/context-overflow-policy.ts → plugins/defaults/compaction/overflow-policy.ts} +1 -1
  273. package/src/plugins/defaults/compaction/window-manager.ts +303 -1
  274. package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +173 -0
  275. package/src/plugins/defaults/empty-response/hooks/stop.ts +11 -115
  276. package/src/plugins/defaults/empty-response/nudge-state-store.ts +46 -0
  277. package/src/plugins/defaults/history-repair/hooks/post-model-call.ts +50 -0
  278. package/src/plugins/defaults/history-repair/hooks/stop.ts +22 -0
  279. package/src/plugins/defaults/history-repair/repair-state-store.ts +51 -0
  280. package/src/plugins/defaults/history-repair/terminal.ts +39 -2
  281. package/src/plugins/defaults/image-recovery/detect.ts +25 -0
  282. package/src/plugins/defaults/image-recovery/hooks/post-model-call.ts +73 -0
  283. package/src/plugins/defaults/image-recovery/hooks/stop.ts +22 -0
  284. package/src/plugins/defaults/image-recovery/image-recovery-state-store.ts +48 -0
  285. package/src/plugins/defaults/image-recovery/package.json +14 -0
  286. package/src/{daemon/persist-unsendable-image.ts → plugins/defaults/image-recovery/recover.ts} +67 -14
  287. package/src/plugins/defaults/index.ts +71 -5
  288. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +76 -112
  289. package/src/plugins/defaults/memory-retrieval/hooks/{user-prompt-submit-temp.ts → user-prompt-submit.ts} +83 -74
  290. package/src/plugins/defaults/memory-retrieval/injector-chain.ts +14 -8
  291. package/src/plugins/defaults/memory-retrieval/injectors.ts +2 -18
  292. package/src/plugins/defaults/memory-retrieval/package.json +14 -0
  293. package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +1157 -0
  294. package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +683 -0
  295. package/src/plugins/defaults/memory-v3-shadow/__tests__/live-integration.test.ts +161 -140
  296. package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +160 -0
  297. package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +335 -316
  298. package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +145 -53
  299. package/src/plugins/defaults/memory-v3-shadow/__tests__/render-injection.test.ts +38 -1
  300. package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +18 -8
  301. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +112 -71
  302. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +192 -51
  303. package/src/plugins/defaults/memory-v3-shadow/__tests__/types.test.ts +4 -16
  304. package/src/plugins/defaults/memory-v3-shadow/card.test.ts +173 -0
  305. package/src/plugins/defaults/memory-v3-shadow/card.ts +116 -0
  306. package/src/plugins/defaults/memory-v3-shadow/core-set.test.ts +104 -0
  307. package/src/plugins/defaults/memory-v3-shadow/core-set.ts +59 -0
  308. package/src/plugins/defaults/memory-v3-shadow/ever-injected-store.test.ts +305 -0
  309. package/src/plugins/defaults/memory-v3-shadow/ever-injected-store.ts +278 -0
  310. package/src/plugins/defaults/memory-v3-shadow/hot-set.test.ts +138 -0
  311. package/src/plugins/defaults/memory-v3-shadow/hot-set.ts +85 -0
  312. package/src/plugins/defaults/memory-v3-shadow/injector.ts +331 -24
  313. package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +119 -13
  314. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +169 -114
  315. package/src/plugins/defaults/memory-v3-shadow/page-content.ts +47 -16
  316. package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +144 -66
  317. package/src/plugins/defaults/memory-v3-shadow/prune.test.ts +758 -0
  318. package/src/plugins/defaults/memory-v3-shadow/prune.ts +471 -0
  319. package/src/plugins/defaults/memory-v3-shadow/render-injection.ts +68 -16
  320. package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +19 -12
  321. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +96 -43
  322. package/src/plugins/defaults/memory-v3-shadow/types.ts +34 -17
  323. package/src/plugins/defaults/title-generate/hooks/stop.ts +9 -11
  324. package/src/plugins/pipeline.ts +8 -5
  325. package/src/plugins/types.ts +5 -51
  326. package/src/providers/cache-control.ts +26 -0
  327. package/src/providers/inference/__tests__/base-url-route-validation.test.ts +1 -2
  328. package/src/providers/model-catalog.ts +13 -1
  329. package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +147 -0
  330. package/src/providers/openai/chat-completions-provider.ts +46 -0
  331. package/src/providers/openai/responses-provider.ts +45 -0
  332. package/src/providers/registry.ts +0 -8
  333. package/src/runtime/__tests__/agent-wake.test.ts +0 -1
  334. package/src/runtime/agent-wake.ts +13 -0
  335. package/src/runtime/routes/__tests__/acp-routes.test.ts +151 -0
  336. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +12 -50
  337. package/src/runtime/routes/__tests__/conversation-surface-routes.test.ts +322 -0
  338. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +0 -62
  339. package/src/runtime/routes/__tests__/plugins-routes.test.ts +31 -11
  340. package/src/runtime/routes/acp-routes.test.ts +106 -0
  341. package/src/runtime/routes/acp-routes.ts +248 -2
  342. package/src/runtime/routes/browser-tabs-routes.ts +1 -1
  343. package/src/runtime/routes/channel-verification-routes.ts +14 -5
  344. package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +0 -14
  345. package/src/runtime/routes/consolidation-routes.ts +6 -82
  346. package/src/runtime/routes/conversation-list-routes.ts +6 -0
  347. package/src/runtime/routes/conversation-management-routes.ts +71 -0
  348. package/src/runtime/routes/identity-routes.ts +8 -0
  349. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +33 -34
  350. package/src/runtime/routes/inference-provider-connection-routes.ts +0 -45
  351. package/src/runtime/routes/plugins-routes.ts +34 -45
  352. package/src/runtime/routes/schedule-routes.ts +43 -5
  353. package/src/runtime/routes/settings-routes.ts +140 -15
  354. package/src/runtime/routes/skills-routes.ts +18 -6
  355. package/src/runtime/services/__tests__/conversation-serializer.test.ts +140 -0
  356. package/src/runtime/services/conversation-serializer.ts +38 -1
  357. package/src/runtime/verification-outbound-actions.ts +147 -2
  358. package/src/runtime/verification-templates.ts +29 -3
  359. package/src/schedule/schedule-store.ts +19 -0
  360. package/src/skills/catalog-install.ts +77 -13
  361. package/src/tasks/task-scheduler.ts +1 -0
  362. package/src/telemetry/types.ts +66 -1
  363. package/src/telemetry/usage-telemetry-reporter.test.ts +542 -13
  364. package/src/telemetry/usage-telemetry-reporter.ts +213 -20
  365. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +49 -2
  366. package/src/tools/browser/__tests__/browser-status.test.ts +29 -5
  367. package/src/tools/browser/browser-execution.ts +27 -9
  368. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +380 -4
  369. package/src/tools/browser/cdp-client/__tests__/host-bridge-cdp-client.test.ts +107 -0
  370. package/src/tools/browser/cdp-client/__tests__/types.test.ts +6 -1
  371. package/src/tools/browser/cdp-client/factory.ts +217 -17
  372. package/src/tools/browser/cdp-client/host-bridge-cdp-client.ts +67 -0
  373. package/src/tools/browser/cdp-client/types.ts +22 -2
  374. package/src/tools/credential-execution/make-authenticated-request.ts +2 -1
  375. package/src/tools/credential-execution/manage-secure-command-tool.ts +169 -164
  376. package/src/tools/credential-execution/run-authenticated-command.ts +2 -1
  377. package/src/tools/executor.ts +39 -7
  378. package/src/tools/registry.ts +387 -5
  379. package/src/tools/schedule/create.ts +16 -0
  380. package/src/tools/schedule/list.ts +12 -4
  381. package/src/tools/schedule/update.ts +12 -0
  382. package/src/tools/skills/load.ts +11 -6
  383. package/src/tools/terminal/safe-env.ts +2 -0
  384. package/src/tools/types.ts +65 -9
  385. package/src/tools/workspace-tools/loader.ts +673 -0
  386. package/src/usage/attribution.ts +28 -0
  387. package/src/util/device-id.ts +17 -3
  388. package/src/util/platform.ts +16 -0
  389. package/tsconfig.plugin-api.json +13 -0
  390. package/src/__tests__/plugin-external-api.test.ts +0 -68
  391. package/src/__tests__/plugin-skill-contribution.test.ts +0 -355
  392. package/src/daemon/message-types/browser.ts +0 -10
  393. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +0 -187
  394. package/src/plugins/defaults/memory-v3-shadow/__tests__/fixtures/eval-turns.json +0 -36
  395. package/src/plugins/defaults/memory-v3-shadow/__tests__/fixtures/live-turns.json +0 -37
  396. package/src/plugins/defaults/memory-v3-shadow/__tests__/working-set-eviction.test.ts +0 -106
  397. package/src/plugins/defaults/memory-v3-shadow/__tests__/working-set-skeleton.test.ts +0 -44
  398. package/src/plugins/defaults/memory-v3-shadow/working-set.ts +0 -91
  399. package/src/plugins/external-api.ts +0 -114
  400. package/src/plugins/plugin-skill-contributions.ts +0 -292
@@ -0,0 +1,319 @@
1
+ /**
2
+ * Tests for the workspace tool loader (workspace-tools/loader.ts).
3
+ *
4
+ * Each test gets its own per-pid+timestamp+counter tempdir so ESM import
5
+ * caching cannot bleed between cases — bun caches dynamic-imported modules
6
+ * by absolute URL, so two tests cannot reuse the same `<name>.ts` path and
7
+ * still see fresh module evaluation.
8
+ *
9
+ * `VELLUM_WORKSPACE_DIR` is rewritten before each test so
10
+ * `getWorkspaceToolsDir()` walks the isolated tree.
11
+ *
12
+ * Covers:
13
+ * - Loading a well-formed workspace tool from `<name>.ts` adds a net-new entry.
14
+ * - Loading a workspace tool whose name matches a core tool overrides it
15
+ * and stashes the original.
16
+ * - `<name>.js` wins over `<name>.ts` (compiled-binary semantics) and the
17
+ * ignored extension is logged at warn.
18
+ * - `<name>.json` loads as a declarative spec — execute defaults to an
19
+ * error result since JSON has no function type.
20
+ * - `<name>.removed` strips a same-named core tool from the registry
21
+ * without substituting a replacement; restoring the file restores the
22
+ * core tool on next scan.
23
+ * - A file whose import throws is logged + skipped without crashing.
24
+ * - A missing `<workspaceDir>/tools/` directory is a no-op.
25
+ * - A filename stem that fails `isProviderSafeToolName` is logged at error
26
+ * and skipped (no silent provider-safe rewrite — operator must rename).
27
+ * - Multiple workspace tools register in a single batch.
28
+ */
29
+ import { mkdirSync, rmSync, writeFileSync } from "node:fs";
30
+ import { tmpdir } from "node:os";
31
+ import { join } from "node:path";
32
+ import { afterAll, beforeEach, describe, expect, test } from "bun:test";
33
+
34
+ import { RiskLevel } from "../permissions/types.js";
35
+ import {
36
+ __clearRegistryForTesting,
37
+ getCoreToolOverride,
38
+ getStrippedCoreToolNames,
39
+ getTool,
40
+ getToolOwner,
41
+ getWorkspaceToolNames,
42
+ registerTool,
43
+ } from "../tools/registry.js";
44
+ import type { Tool, ToolContext, ToolExecutionResult } from "../tools/types.js";
45
+ import { loadWorkspaceTools } from "../tools/workspace-tools/loader.js";
46
+
47
+ // Per-test counter so each writeTool() call lands in a unique tempdir,
48
+ // defeating bun's per-URL ESM cache between tests. Without this, a
49
+ // second test that writes the same tool name would reuse the first
50
+ // test's already-evaluated module body.
51
+ let testCaseCounter = 0;
52
+ let currentWorkspaceDir: string;
53
+ const TEST_BASE_DIR = join(
54
+ tmpdir(),
55
+ `vellum-workspace-tool-loader-test-${process.pid}-${Date.now()}`,
56
+ );
57
+
58
+ function freshWorkspace(): string {
59
+ testCaseCounter += 1;
60
+ const dir = join(TEST_BASE_DIR, `case-${testCaseCounter}`);
61
+ mkdirSync(dir, { recursive: true });
62
+ process.env.VELLUM_WORKSPACE_DIR = dir;
63
+ currentWorkspaceDir = dir;
64
+ return dir;
65
+ }
66
+
67
+ /**
68
+ * Materialize `<workspaceDir>/tools/<name>.<ext>` with the supplied body.
69
+ * `ext` defaults to `.ts`; pass `.js` or `.json` to exercise the
70
+ * extension precedence and JSON-spec paths.
71
+ *
72
+ * If the body does not include `export default` (for `.ts`/`.js`), the
73
+ * test author is expected to know they're exercising a "missing default
74
+ * export" path — the loader logs an error and skips the entry rather
75
+ * than throwing.
76
+ */
77
+ function writeTool(name: string, body: string, ext = ".ts"): void {
78
+ const toolsDir = join(currentWorkspaceDir, "tools");
79
+ mkdirSync(toolsDir, { recursive: true });
80
+ writeFileSync(join(toolsDir, `${name}${ext}`), body);
81
+ }
82
+
83
+ /** Write a `<name>.removed` sentinel under `<workspaceDir>/tools/`. */
84
+ function writeRemovedSentinel(name: string): void {
85
+ const toolsDir = join(currentWorkspaceDir, "tools");
86
+ mkdirSync(toolsDir, { recursive: true });
87
+ writeFileSync(join(toolsDir, `${name}.removed`), "");
88
+ }
89
+
90
+ function makeFakeCoreTool(name: string): Tool {
91
+ return {
92
+ name,
93
+ description: `Core ${name}`,
94
+ category: "test",
95
+ defaultRiskLevel: RiskLevel.Low,
96
+ executionTarget: "sandbox",
97
+ input_schema: { type: "object", properties: {}, required: [] },
98
+ async execute(
99
+ _input: Record<string, unknown>,
100
+ _context: ToolContext,
101
+ ): Promise<ToolExecutionResult> {
102
+ return { content: "core", isError: false };
103
+ },
104
+ };
105
+ }
106
+
107
+ const WELL_FORMED_BODY = `
108
+ export default {
109
+ description: "from workspace",
110
+ defaultRiskLevel: "low",
111
+ input_schema: {
112
+ type: "object",
113
+ properties: { greeting: { type: "string" } },
114
+ required: [],
115
+ },
116
+ async execute() {
117
+ return { content: "workspace-hello", isError: false };
118
+ },
119
+ };
120
+ `;
121
+
122
+ const JS_BODY = `
123
+ export default {
124
+ description: "from workspace js",
125
+ defaultRiskLevel: "low",
126
+ input_schema: { type: "object", properties: {}, required: [] },
127
+ async execute() {
128
+ return { content: "workspace-js", isError: false };
129
+ },
130
+ };
131
+ `;
132
+
133
+ describe("workspace tool loader", () => {
134
+ beforeEach(() => {
135
+ __clearRegistryForTesting();
136
+ freshWorkspace();
137
+ });
138
+
139
+ afterAll(() => {
140
+ rmSync(TEST_BASE_DIR, { recursive: true, force: true });
141
+ delete process.env.VELLUM_WORKSPACE_DIR;
142
+ });
143
+
144
+ test("registers a net-new tool from <workspaceDir>/tools/<name>.ts", async () => {
145
+ writeTool("hello_workspace", WELL_FORMED_BODY);
146
+
147
+ await loadWorkspaceTools();
148
+
149
+ const tool = getTool("hello_workspace");
150
+ expect(tool).toBeDefined();
151
+ expect(getToolOwner("hello_workspace")?.kind).toBe("workspace");
152
+ expect(tool?.description).toBe("from workspace");
153
+ expect(getWorkspaceToolNames()).toContain("hello_workspace");
154
+ expect(getCoreToolOverride("hello_workspace")).toBeUndefined();
155
+ });
156
+
157
+ test("workspace tool with same name as core tool overrides and stashes the original", async () => {
158
+ const core = makeFakeCoreTool("override_me");
159
+ registerTool(core);
160
+
161
+ writeTool("override_me", WELL_FORMED_BODY);
162
+
163
+ await loadWorkspaceTools();
164
+
165
+ const live = getTool("override_me");
166
+ expect(live).toBeDefined();
167
+ expect(getToolOwner("override_me")?.kind).toBe("workspace");
168
+ expect(live?.description).toBe("from workspace");
169
+ expect(getCoreToolOverride("override_me")).toEqual(core);
170
+ });
171
+
172
+ test(".js wins over .ts for the same stem (compiled-binary semantics)", async () => {
173
+ writeTool("dual_ext", WELL_FORMED_BODY, ".ts");
174
+ writeTool("dual_ext", JS_BODY, ".js");
175
+
176
+ await loadWorkspaceTools();
177
+
178
+ const tool = getTool("dual_ext");
179
+ expect(tool).toBeDefined();
180
+ // JS wins — body said "from workspace js"
181
+ expect(tool?.description).toBe("from workspace js");
182
+ });
183
+
184
+ test(".json declarative spec loads with default error executor", async () => {
185
+ writeTool(
186
+ "data_only",
187
+ JSON.stringify({
188
+ description: "json spec",
189
+ defaultRiskLevel: "low",
190
+ input_schema: { type: "object", properties: {}, required: [] },
191
+ }),
192
+ ".json",
193
+ );
194
+
195
+ await loadWorkspaceTools();
196
+
197
+ const tool = getTool("data_only");
198
+ expect(tool).toBeDefined();
199
+ expect(getToolOwner("data_only")?.kind).toBe("workspace");
200
+ expect(tool?.description).toBe("json spec");
201
+ // JSON specs always pick up the default error executor — calling
202
+ // it returns isError=true with a "no execute implementation" message.
203
+ const result = await tool!.execute(
204
+ {},
205
+ {} as unknown as Parameters<Tool["execute"]>[1],
206
+ );
207
+ expect(result.isError).toBe(true);
208
+ });
209
+
210
+ test(".removed sentinel strips a core tool from the registry", async () => {
211
+ const core = makeFakeCoreTool("strip_me");
212
+ registerTool(core);
213
+ expect(getTool("strip_me")).toBeDefined();
214
+
215
+ writeRemovedSentinel("strip_me");
216
+
217
+ await loadWorkspaceTools();
218
+
219
+ expect(getTool("strip_me")).toBeUndefined();
220
+ expect(getStrippedCoreToolNames()).toContain("strip_me");
221
+ // The stashed core tool is preserved for later restoration.
222
+ expect(getCoreToolOverride("strip_me")).toEqual(core);
223
+ });
224
+
225
+ test(".removed sentinel for a non-existent name is a no-op", async () => {
226
+ writeRemovedSentinel("never_was_a_tool");
227
+
228
+ await loadWorkspaceTools();
229
+
230
+ expect(getTool("never_was_a_tool")).toBeUndefined();
231
+ expect(getStrippedCoreToolNames()).not.toContain("never_was_a_tool");
232
+ });
233
+
234
+ test("per-tool isolation: one bad tool does not block the rest", async () => {
235
+ writeTool(
236
+ "broken_at_import",
237
+ `
238
+ throw new Error("boom at import time");
239
+ `,
240
+ );
241
+ writeTool("good_one", WELL_FORMED_BODY);
242
+
243
+ await loadWorkspaceTools();
244
+
245
+ expect(getTool("broken_at_import")).toBeUndefined();
246
+ expect(getTool("good_one")).toBeDefined();
247
+ expect(getToolOwner("good_one")?.kind).toBe("workspace");
248
+ });
249
+
250
+ test("missing default export logs + skips without crashing", async () => {
251
+ writeTool(
252
+ "no_default",
253
+ `
254
+ export const named = { description: "wrong shape" };
255
+ `,
256
+ );
257
+
258
+ await loadWorkspaceTools();
259
+
260
+ expect(getTool("no_default")).toBeUndefined();
261
+ });
262
+
263
+ test("non-object default export logs + skips without crashing", async () => {
264
+ writeTool(
265
+ "wrong_type",
266
+ `
267
+ export default 42;
268
+ `,
269
+ );
270
+
271
+ await loadWorkspaceTools();
272
+
273
+ expect(getTool("wrong_type")).toBeUndefined();
274
+ });
275
+
276
+ test("no <workspaceDir>/tools/ directory is a no-op", async () => {
277
+ // `freshWorkspace()` does not create a tools/ dir — the loader must
278
+ // complete without throwing and register nothing.
279
+ await loadWorkspaceTools();
280
+
281
+ expect(getWorkspaceToolNames()).toEqual([]);
282
+ });
283
+
284
+ test("filename stems that fail provider-safe validation are skipped", async () => {
285
+ // Provider-safe names match /^[a-zA-Z0-9_-]{1,64}$/. A stem with a
286
+ // space embeds an LLM-provider-incompatible character. The loader
287
+ // refuses to rewrite the name (which would produce an unfindable
288
+ // hash suffix); the operator must rename the file.
289
+ const toolsDir = join(currentWorkspaceDir, "tools");
290
+ mkdirSync(toolsDir, { recursive: true });
291
+ writeFileSync(join(toolsDir, "has space.ts"), WELL_FORMED_BODY);
292
+
293
+ await loadWorkspaceTools();
294
+
295
+ expect(getWorkspaceToolNames()).toEqual([]);
296
+ });
297
+
298
+ test("dotfile stems (starting with .) are excluded", async () => {
299
+ // `.gitignore`, `.DS_Store`, etc. must not register as tools.
300
+ const toolsDir = join(currentWorkspaceDir, "tools");
301
+ mkdirSync(toolsDir, { recursive: true });
302
+ writeFileSync(join(toolsDir, ".gitignore"), "node_modules");
303
+
304
+ await loadWorkspaceTools();
305
+
306
+ expect(getWorkspaceToolNames()).toEqual([]);
307
+ });
308
+
309
+ test("multiple tools register in a single batch", async () => {
310
+ writeTool("alpha", WELL_FORMED_BODY);
311
+ writeTool("beta", WELL_FORMED_BODY);
312
+ writeTool("gamma", WELL_FORMED_BODY);
313
+
314
+ await loadWorkspaceTools();
315
+
316
+ const names = getWorkspaceToolNames().sort();
317
+ expect(names).toEqual(["alpha", "beta", "gamma"]);
318
+ });
319
+ });
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Tests that the `workspace-tools-watcher` feature flag gates the dynamic
3
+ * hot-reload watcher in `WorkspaceToolsWatcher.start()`.
4
+ *
5
+ * The initial disk scan (`loadWorkspaceTools()`) is unconditional and lives
6
+ * elsewhere; this suite only covers whether the live `fs.watch` loop mounts.
7
+ */
8
+ import { mkdirSync, rmSync } from "node:fs";
9
+ import { tmpdir } from "node:os";
10
+ import { join } from "node:path";
11
+ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
12
+
13
+ import { clearFeatureFlagOverridesCache } from "../config/assistant-feature-flags.js";
14
+ import { WorkspaceToolsWatcher } from "../daemon/workspace-tools-watcher.js";
15
+ import { setOverridesForTesting } from "./feature-flag-test-helpers.js";
16
+
17
+ const FLAG = "workspace-tools-watcher";
18
+ const TEST_BASE_DIR = join(
19
+ tmpdir(),
20
+ `vellum-workspace-tools-watcher-flag-test-${process.pid}-${Date.now()}`,
21
+ );
22
+ let caseCounter = 0;
23
+
24
+ function freshWorkspaceWithToolsDir(): void {
25
+ caseCounter += 1;
26
+ const dir = join(TEST_BASE_DIR, `case-${caseCounter}`);
27
+ mkdirSync(join(dir, "tools"), { recursive: true });
28
+ process.env.VELLUM_WORKSPACE_DIR = dir;
29
+ }
30
+
31
+ beforeEach(() => {
32
+ WorkspaceToolsWatcher.resetForTests();
33
+ clearFeatureFlagOverridesCache();
34
+ freshWorkspaceWithToolsDir();
35
+ });
36
+
37
+ afterEach(() => {
38
+ WorkspaceToolsWatcher.resetForTests();
39
+ clearFeatureFlagOverridesCache();
40
+ delete process.env.VELLUM_WORKSPACE_DIR;
41
+ rmSync(TEST_BASE_DIR, { recursive: true, force: true });
42
+ });
43
+
44
+ describe("WorkspaceToolsWatcher feature-flag gate", () => {
45
+ test("does not mount the watch loop when the flag is off", () => {
46
+ // GIVEN the workspace tools directory exists
47
+ // AND the watcher flag is disabled
48
+ setOverridesForTesting({ [FLAG]: false });
49
+
50
+ // WHEN the watcher starts
51
+ const watcher = WorkspaceToolsWatcher.getInstance();
52
+ watcher.start();
53
+
54
+ // THEN no fs.watch loop is mounted
55
+ expect(watcher.isWatchingForTests()).toBe(false);
56
+ });
57
+
58
+ test("mounts the watch loop when the flag is on", () => {
59
+ // GIVEN the workspace tools directory exists
60
+ // AND the watcher flag is enabled
61
+ setOverridesForTesting({ [FLAG]: true });
62
+
63
+ // WHEN the watcher starts
64
+ const watcher = WorkspaceToolsWatcher.getInstance();
65
+ watcher.start();
66
+
67
+ // THEN a live fs.watch loop is mounted
68
+ expect(watcher.isWatchingForTests()).toBe(true);
69
+ });
70
+ });