@vellumai/assistant 0.10.2-dev.202606250318.5e7cfb0 → 0.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (430) hide show
  1. package/bun.lock +0 -20
  2. package/docs/workspace-tools.md +33 -42
  3. package/eslint-rules/cli-no-daemon-internals.js +0 -6
  4. package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +0 -31
  5. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +0 -44
  6. package/node_modules/@vellumai/gateway-client/src/index.ts +0 -14
  7. package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +0 -17
  8. package/node_modules/@vellumai/service-contracts/package.json +0 -1
  9. package/node_modules/@vellumai/service-contracts/src/index.ts +0 -1
  10. package/openapi.yaml +0 -155
  11. package/package.json +1 -4
  12. package/scripts/test.sh +15 -36
  13. package/src/__tests__/actor-token-service.test.ts +14 -36
  14. package/src/__tests__/agent-loop-override-profile.test.ts +0 -1
  15. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +0 -2
  16. package/src/__tests__/agent-wake-override-profile.test.ts +0 -2
  17. package/src/__tests__/annotate-activity-metadata.test.ts +0 -2
  18. package/src/__tests__/annotate-risk-options.test.ts +0 -2
  19. package/src/__tests__/approval-cascade.test.ts +0 -2
  20. package/src/__tests__/assistant-attachments.test.ts +0 -42
  21. package/src/__tests__/background-workers-disk-pressure.test.ts +0 -2
  22. package/src/__tests__/btw-routes.test.ts +0 -2
  23. package/src/__tests__/build-persisted-content.test.ts +0 -2
  24. package/src/__tests__/call-controller.test.ts +0 -19
  25. package/src/__tests__/channel-guardian.test.ts +58 -94
  26. package/src/__tests__/channel-reply-delivery.test.ts +0 -2
  27. package/src/__tests__/compaction-events.test.ts +0 -2
  28. package/src/__tests__/compaction.benchmark.test.ts +0 -2
  29. package/src/__tests__/compactor-call-site-logging.test.ts +0 -2
  30. package/src/__tests__/compactor-low-watermark-cut.test.ts +0 -2
  31. package/src/__tests__/compactor-preserved-tail-count.test.ts +0 -2
  32. package/src/__tests__/compactor-summary-call-truncation.test.ts +0 -2
  33. package/src/__tests__/compactor-web-search-strip.test.ts +0 -2
  34. package/src/__tests__/config-loader-backfill.test.ts +10 -123
  35. package/src/__tests__/config-schema.test.ts +0 -1
  36. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +29 -31
  37. package/src/__tests__/contacts-relay-reads.test.ts +15 -13
  38. package/src/__tests__/conversation-abort-tool-results.test.ts +0 -2
  39. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +0 -2
  40. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +0 -2
  41. package/src/__tests__/conversation-agent-loop-overflow.test.ts +0 -2
  42. package/src/__tests__/conversation-agent-loop.test.ts +0 -134
  43. package/src/__tests__/conversation-analysis-routes.test.ts +0 -2
  44. package/src/__tests__/conversation-app-control-lifecycle.test.ts +0 -2
  45. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -2
  46. package/src/__tests__/conversation-history-web-search.test.ts +0 -2
  47. package/src/__tests__/conversation-load-history-repair.test.ts +0 -2
  48. package/src/__tests__/conversation-load-history-stripped.test.ts +0 -2
  49. package/src/__tests__/conversation-pairing.test.ts +0 -2
  50. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +0 -2
  51. package/src/__tests__/conversation-process-callsite.test.ts +0 -2
  52. package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -2
  53. package/src/__tests__/conversation-queue.test.ts +0 -91
  54. package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -14
  55. package/src/__tests__/conversation-routes-slash-commands.test.ts +0 -14
  56. package/src/__tests__/conversation-slash-queue.test.ts +0 -2
  57. package/src/__tests__/conversation-slash-unknown.test.ts +0 -2
  58. package/src/__tests__/conversation-speed-override.test.ts +0 -2
  59. package/src/__tests__/conversation-surfaces-task-progress.test.ts +0 -29
  60. package/src/__tests__/conversation-title-service.test.ts +0 -2
  61. package/src/__tests__/conversation-tool-setup-attribution.test.ts +0 -47
  62. package/src/__tests__/conversation-usage.test.ts +0 -2
  63. package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -2
  64. package/src/__tests__/conversation-workspace-injection.test.ts +0 -2
  65. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -2
  66. package/src/__tests__/credential-security-invariants.test.ts +1 -1
  67. package/src/__tests__/db-migration-rollback.test.ts +171 -205
  68. package/src/__tests__/db-test-helpers.ts +4 -5
  69. package/src/__tests__/deterministic-verification-control-plane.test.ts +2 -4
  70. package/src/__tests__/disk-pressure-guard.test.ts +0 -41
  71. package/src/__tests__/dm-persistence.test.ts +0 -2
  72. package/src/__tests__/emit-signal-routing-intent.test.ts +5 -10
  73. package/src/__tests__/events-dev-bypass-actor.test.ts +1 -7
  74. package/src/__tests__/exploration-drift-hook.test.ts +2 -3
  75. package/src/__tests__/filing-service.test.ts +0 -2
  76. package/src/__tests__/guardian-binding-drift-heal.test.ts +10 -75
  77. package/src/__tests__/guardian-dispatch.test.ts +1 -95
  78. package/src/__tests__/guardian-outbound-http.test.ts +0 -13
  79. package/src/__tests__/heartbeat-disk-pressure.test.ts +0 -2
  80. package/src/__tests__/heartbeat-service.test.ts +0 -2
  81. package/src/__tests__/helpers/channel-test-adapter.ts +7 -1
  82. package/src/__tests__/host-app-control-routes.test.ts +30 -24
  83. package/src/__tests__/host-bash-routes.test.ts +41 -31
  84. package/src/__tests__/host-browser-routes.test.ts +32 -26
  85. package/src/__tests__/host-cu-routes-targeted.test.ts +33 -25
  86. package/src/__tests__/host-file-routes-targeted.test.ts +52 -40
  87. package/src/__tests__/host-transfer-routes-targeted.test.ts +43 -31
  88. package/src/__tests__/http-user-message-parity.test.ts +8 -290
  89. package/src/__tests__/inbound-invite-redemption.test.ts +0 -28
  90. package/src/__tests__/inbound-slack-persistence.test.ts +0 -2
  91. package/src/__tests__/invite-redemption-service.test.ts +0 -198
  92. package/src/__tests__/llm-context-normalization.test.ts +0 -105
  93. package/src/__tests__/llm-request-log-error-payload.test.ts +9 -71
  94. package/src/__tests__/llm-usage-store.test.ts +0 -25
  95. package/src/__tests__/mcp-health-check.test.ts +1 -2
  96. package/src/__tests__/media-stream-server-integration.test.ts +0 -127
  97. package/src/__tests__/memory-retrieval-hook.test.ts +0 -2
  98. package/src/__tests__/messaging-send-tool.test.ts +0 -2
  99. package/src/__tests__/migration-import-from-url.test.ts +2 -2
  100. package/src/__tests__/mtime-cache.test.ts +5 -146
  101. package/src/__tests__/native-web-search.test.ts +0 -2
  102. package/src/__tests__/non-member-access-request.test.ts +17 -189
  103. package/src/__tests__/notification-broadcaster.test.ts +0 -4
  104. package/src/__tests__/notification-decision-recipient-context.test.ts +32 -33
  105. package/src/__tests__/notification-deep-link.test.ts +0 -6
  106. package/src/__tests__/notification-guardian-path.test.ts +0 -19
  107. package/src/__tests__/openai-provider.test.ts +12 -22
  108. package/src/__tests__/openai-responses-provider.test.ts +2 -12
  109. package/src/__tests__/outbound-slack-persistence.test.ts +0 -2
  110. package/src/__tests__/pending-interactions-resolved-event.test.ts +4 -7
  111. package/src/__tests__/persistence-secret-redaction.test.ts +0 -2
  112. package/src/__tests__/plugin-bootstrap.test.ts +73 -3
  113. package/src/__tests__/plugin-route-contribution.test.ts +17 -4
  114. package/src/__tests__/plugin-tool-contribution.test.ts +18 -3
  115. package/src/__tests__/plugin-types.test.ts +2 -0
  116. package/src/__tests__/process-message-background-slack.test.ts +0 -2
  117. package/src/__tests__/process-message-display-content.test.ts +0 -2
  118. package/src/__tests__/provider-error-scenarios.test.ts +4 -5
  119. package/src/__tests__/provider-usage-tracking.test.ts +0 -39
  120. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +0 -2
  121. package/src/__tests__/registry.test.ts +1 -4
  122. package/src/__tests__/relay-server.test.ts +25 -694
  123. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -0
  124. package/src/__tests__/secret-ingress-http.test.ts +0 -14
  125. package/src/__tests__/send-endpoint-busy.test.ts +8 -30
  126. package/src/__tests__/skills.test.ts +0 -44
  127. package/src/__tests__/slack-inbound-verification.test.ts +2 -47
  128. package/src/__tests__/stt-hints.test.ts +13 -44
  129. package/src/__tests__/subagent-detail.test.ts +0 -27
  130. package/src/__tests__/subagent-disposal.test.ts +0 -65
  131. package/src/__tests__/subagent-notify-parent.test.ts +0 -2
  132. package/src/__tests__/subagent-role-registry.test.ts +2 -7
  133. package/src/__tests__/subagent-spawn-tool-fork.test.ts +0 -2
  134. package/src/__tests__/subagent-tools.test.ts +0 -2
  135. package/src/__tests__/suggestion-routes.test.ts +0 -2
  136. package/src/__tests__/title-generate-hook.test.ts +0 -2
  137. package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -2
  138. package/src/__tests__/tool-executor.test.ts +11 -16
  139. package/src/__tests__/tool-preview-lifecycle.test.ts +0 -2
  140. package/src/__tests__/tool-result-metadata-plumbing.test.ts +0 -2
  141. package/src/__tests__/tool-start-timestamp.test.ts +0 -2
  142. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +10 -10
  143. package/src/__tests__/twilio-routes.test.ts +0 -96
  144. package/src/__tests__/ui-file-upload-surface.test.ts +0 -86
  145. package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
  146. package/src/__tests__/voice-invite-redemption.test.ts +0 -33
  147. package/src/__tests__/web-search-backend-failure.test.ts +0 -2
  148. package/src/__tests__/workspace-migration-remove-hooks.test.ts +35 -14
  149. package/src/__tests__/workspace-tool-loader.test.ts +2 -195
  150. package/src/__tests__/workspace-tools-watcher-flag.test.ts +70 -0
  151. package/src/agent/loop.ts +0 -56
  152. package/src/api/index.ts +1 -19
  153. package/src/api/responses/llm-request-log-entry.ts +0 -29
  154. package/src/api/responses/subagent-detail.ts +0 -17
  155. package/src/api/surfaces.ts +3 -39
  156. package/src/approvals/guardian-request-resolvers.ts +11 -1
  157. package/src/calls/__tests__/relay-setup-router.test.ts +4 -262
  158. package/src/calls/call-domain.ts +3 -3
  159. package/src/calls/guardian-dispatch.ts +8 -10
  160. package/src/calls/inbound-trust-reader.ts +1 -17
  161. package/src/calls/media-stream-server.ts +0 -21
  162. package/src/calls/relay-server.ts +50 -167
  163. package/src/calls/relay-setup-router.ts +7 -37
  164. package/src/calls/relay-verification.ts +4 -4
  165. package/src/calls/stt-hints.ts +12 -9
  166. package/src/calls/twilio-routes.ts +4 -14
  167. package/src/channels/types.ts +20 -10
  168. package/src/cli/commands/__tests__/cache.test.ts +1 -8
  169. package/src/cli/commands/cache.ts +181 -194
  170. package/src/cli/commands/db/__tests__/repair.test.ts +5 -6
  171. package/src/cli/commands/db/status.ts +1 -37
  172. package/src/cli/commands/mcp.ts +218 -252
  173. package/src/cli/commands/memory/index.ts +0 -2
  174. package/src/cli/commands/plugins.ts +3 -75
  175. package/src/cli/lib/__tests__/install-from-github.test.ts +0 -102
  176. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +1 -160
  177. package/src/cli/lib/list-installed-plugins.ts +1 -179
  178. package/src/config/__tests__/sync-gated-profiles.test.ts +3 -11
  179. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +17 -27
  180. package/src/config/bundled-skills/contacts/tools/contact-search.ts +3 -13
  181. package/src/config/bundled-skills/subagent/SKILL.md +1 -1
  182. package/src/config/bundled-skills/subagent/TOOLS.json +1 -1
  183. package/src/config/feature-flag-registry.json +13 -5
  184. package/src/config/loader.ts +5 -38
  185. package/src/config/schemas/__tests__/memory-v3.test.ts +0 -1
  186. package/src/config/schemas/memory-lifecycle.ts +0 -12
  187. package/src/config/schemas/memory-v3.ts +0 -7
  188. package/src/config/schemas/memory.ts +0 -4
  189. package/src/config/schemas/timeouts.ts +0 -8
  190. package/src/config/seed-inference-profiles.ts +11 -21
  191. package/src/config/skills.ts +5 -27
  192. package/src/config/sync-gated-profiles.ts +13 -12
  193. package/src/contacts/contacts-write.ts +0 -3
  194. package/src/daemon/assistant-attachments.ts +4 -27
  195. package/src/daemon/conversation-agent-loop.ts +0 -28
  196. package/src/daemon/conversation-process.ts +16 -35
  197. package/src/daemon/conversation-surfaces.ts +38 -111
  198. package/src/daemon/conversation-tool-setup.ts +16 -50
  199. package/src/daemon/conversation.ts +1 -13
  200. package/src/daemon/disk-pressure-guard.ts +2 -12
  201. package/src/daemon/event-loop-watchdog.ts +1 -28
  202. package/src/daemon/external-plugins-bootstrap.ts +34 -4
  203. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -25
  204. package/src/daemon/handlers/config-a2a.ts +14 -6
  205. package/src/daemon/handlers/config-channels.ts +22 -78
  206. package/src/daemon/handlers/conversations.ts +0 -77
  207. package/src/daemon/lifecycle.ts +0 -4
  208. package/src/daemon/mcp-reload-service.ts +0 -10
  209. package/src/daemon/memory-v2-startup.test.ts +0 -72
  210. package/src/daemon/memory-v2-startup.ts +19 -87
  211. package/src/daemon/message-types/conversations.ts +0 -2
  212. package/src/daemon/message-types/surfaces.ts +12 -12
  213. package/src/daemon/server.ts +4 -0
  214. package/src/daemon/shutdown-handlers.ts +0 -20
  215. package/src/daemon/tool-setup-types.ts +0 -9
  216. package/src/daemon/workspace-tools-watcher.ts +328 -0
  217. package/src/ipc/__tests__/clients-list-ipc.test.ts +1 -1
  218. package/src/ipc/assistant-server.ts +2 -2
  219. package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +0 -1
  220. package/src/mcp/client.ts +1 -15
  221. package/src/mcp/mcp-auth-orchestrator.ts +1 -6
  222. package/src/mcp/mcp-oauth-provider.ts +8 -19
  223. package/src/memory/__tests__/memory-retrospective-job.test.ts +0 -8
  224. package/src/memory/conversation-crud.ts +0 -38
  225. package/src/memory/db-connection.ts +3 -22
  226. package/src/memory/db-init.ts +502 -36
  227. package/src/memory/db-singleton.ts +4 -6
  228. package/src/memory/jobs-worker.ts +0 -58
  229. package/src/memory/llm-request-log-store.ts +1 -26
  230. package/src/memory/llm-usage-store.ts +20 -48
  231. package/src/memory/memory-retrospective-job.ts +8 -9
  232. package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +56 -130
  233. package/src/memory/migrations/__tests__/run-migrations.test.ts +2 -2
  234. package/src/memory/migrations/registry.ts +573 -0
  235. package/src/memory/migrations/run-migrations.ts +6 -90
  236. package/src/memory/migrations/validate-migration-state.ts +66 -101
  237. package/src/memory/schema/conversations.ts +0 -9
  238. package/src/memory/schema/infrastructure.ts +0 -20
  239. package/src/memory/v2/__tests__/cli-command-store.test.ts +0 -25
  240. package/src/memory/v2/__tests__/skill-store.test.ts +0 -80
  241. package/src/memory/v2/cli-command-store.ts +38 -75
  242. package/src/memory/v2/prompts/consolidation.ts +82 -13
  243. package/src/memory/v2/prompts/router.ts +93 -21
  244. package/src/memory/v2/skill-store.ts +31 -68
  245. package/src/notifications/__tests__/broadcaster.test.ts +8 -16
  246. package/src/notifications/__tests__/decision-engine.test.ts +9 -78
  247. package/src/notifications/broadcaster.ts +1 -8
  248. package/src/notifications/decision-engine.ts +7 -15
  249. package/src/notifications/destination-resolver.ts +24 -68
  250. package/src/notifications/emit-signal.ts +14 -39
  251. package/src/permissions/question-prompter.test.ts +1 -1
  252. package/src/permissions/question-prompter.ts +4 -7
  253. package/src/plugin-api/index.ts +6 -6
  254. package/src/plugin-api/types.ts +5 -3
  255. package/src/plugin-api/vision-support.test.ts +4 -28
  256. package/src/plugin-api/vision-support.ts +31 -66
  257. package/src/plugins/defaults/advisor/__tests__/consult.test.ts +0 -161
  258. package/src/plugins/defaults/advisor/consult.ts +6 -110
  259. package/src/plugins/defaults/advisor/steering.ts +2 -14
  260. package/src/plugins/defaults/advisor/tools/advisor.ts +5 -32
  261. package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +1 -2
  262. package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +7 -47
  263. package/src/plugins/defaults/image-fallback/hooks/post-tool-use.ts +11 -10
  264. package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +20 -12
  265. package/src/plugins/defaults/image-fallback/src/caption-blocks.ts +11 -42
  266. package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +3 -33
  267. package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +4 -48
  268. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +8 -4
  269. package/src/plugins/defaults/memory-v3-shadow/injector.ts +15 -43
  270. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +2 -11
  271. package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +13 -77
  272. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +11 -12
  273. package/src/plugins/mtime-cache.ts +291 -76
  274. package/src/plugins/pipeline.ts +13 -111
  275. package/src/plugins/types.ts +2 -0
  276. package/src/providers/anthropic/client.ts +0 -5
  277. package/src/providers/call-site-routing.ts +0 -4
  278. package/src/providers/model-catalog.ts +0 -16
  279. package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
  280. package/src/providers/openai/chat-completions-provider.ts +83 -37
  281. package/src/providers/openai/responses-provider.ts +46 -50
  282. package/src/providers/openrouter/client.ts +0 -5
  283. package/src/providers/provider-send-message.ts +0 -4
  284. package/src/providers/ratelimit.ts +0 -4
  285. package/src/providers/retry.ts +0 -4
  286. package/src/providers/types.ts +0 -9
  287. package/src/providers/usage-tracking.ts +0 -4
  288. package/src/runtime/__tests__/trust-verdict-consumer.test.ts +3 -335
  289. package/src/runtime/access-request-helper.ts +39 -19
  290. package/src/runtime/actor-trust-resolver.ts +2 -2
  291. package/src/runtime/assistant-event-hub.ts +1 -1
  292. package/src/runtime/assistant-stream-state.ts +2 -9
  293. package/src/runtime/auth/require-bound-guardian.ts +11 -21
  294. package/src/runtime/channel-verification-service.ts +31 -56
  295. package/src/runtime/confirmation-request-guardian-bridge.ts +3 -3
  296. package/src/runtime/guardian-vellum-migration.ts +7 -66
  297. package/src/runtime/invite-redemption-service.ts +187 -198
  298. package/src/runtime/local-actor-identity.ts +11 -76
  299. package/src/runtime/pending-interactions.ts +1 -11
  300. package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +5 -56
  301. package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
  302. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +0 -187
  303. package/src/runtime/routes/browser-routes.ts +1 -1
  304. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +5 -13
  305. package/src/runtime/routes/channel-verification-routes.ts +3 -3
  306. package/src/runtime/routes/contact-routes.ts +32 -8
  307. package/src/runtime/routes/conversation-cli-routes.ts +5 -4
  308. package/src/runtime/routes/conversation-list-routes.ts +7 -4
  309. package/src/runtime/routes/conversation-query-routes.ts +0 -72
  310. package/src/runtime/routes/conversation-routes.ts +85 -84
  311. package/src/runtime/routes/events-routes.ts +2 -2
  312. package/src/runtime/routes/global-search-routes.ts +1 -3
  313. package/src/runtime/routes/guardian-action-routes.ts +5 -4
  314. package/src/runtime/routes/host-app-control-routes.ts +4 -5
  315. package/src/runtime/routes/host-bash-routes.ts +4 -5
  316. package/src/runtime/routes/host-browser-routes.ts +11 -9
  317. package/src/runtime/routes/host-cu-routes.ts +4 -5
  318. package/src/runtime/routes/host-file-routes.ts +4 -5
  319. package/src/runtime/routes/host-transfer-routes.ts +6 -6
  320. package/src/runtime/routes/http-adapter.ts +1 -1
  321. package/src/runtime/routes/identity-routes.ts +2 -3
  322. package/src/runtime/routes/inbound-message-handler.ts +5 -5
  323. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +5 -97
  324. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +49 -61
  325. package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -16
  326. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +7 -7
  327. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +8 -21
  328. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +3 -14
  329. package/src/runtime/routes/index.ts +0 -2
  330. package/src/runtime/routes/llm-context-normalization.ts +0 -83
  331. package/src/runtime/routes/mcp-auth-routes.ts +19 -171
  332. package/src/runtime/routes/migration-rollback-routes.ts +3 -4
  333. package/src/runtime/routes/migration-routes.ts +1 -4
  334. package/src/runtime/routes/subagents-routes.ts +0 -5
  335. package/src/runtime/routes/surface-action-routes.ts +56 -42
  336. package/src/runtime/services/__tests__/conversation-serializer.test.ts +0 -1
  337. package/src/runtime/services/conversation-serializer.ts +9 -7
  338. package/src/runtime/tool-grant-request-helper.ts +3 -3
  339. package/src/runtime/trust-verdict-consumer.ts +9 -85
  340. package/src/runtime/verification-outbound-actions.ts +18 -18
  341. package/src/signals/user-message.ts +0 -16
  342. package/src/subagent/manager.ts +0 -9
  343. package/src/subagent/types.ts +3 -3
  344. package/src/telemetry/types.ts +1 -34
  345. package/src/telemetry/usage-telemetry-reporter.test.ts +2 -3
  346. package/src/telemetry/usage-telemetry-reporter.ts +3 -87
  347. package/src/tools/ask-question/ask-question-tool.test.ts +0 -29
  348. package/src/tools/ask-question/ask-question-tool.ts +0 -13
  349. package/src/tools/executor.ts +4 -4
  350. package/src/tools/registry.ts +0 -18
  351. package/src/tools/shared/filesystem/path-policy.ts +5 -12
  352. package/src/tools/tool-approval-handler.ts +1 -1
  353. package/src/tools/tool-defaults.ts +2 -9
  354. package/src/tools/tool-manifest.ts +0 -3
  355. package/src/tools/types.ts +2 -17
  356. package/src/tools/workspace-tools/loader.ts +244 -348
  357. package/src/util/errors.ts +1 -26
  358. package/src/util/platform.ts +0 -5
  359. package/src/workflows/library.test.ts +0 -140
  360. package/src/workflows/library.ts +28 -82
  361. package/src/workspace/migrations/017-seed-persona-dirs.ts +34 -3
  362. package/src/workspace/migrations/019-scope-journal-to-guardian.ts +24 -3
  363. package/src/workspace/migrations/048-remove-workspace-hooks.ts +66 -14
  364. package/src/workspace/migrations/registry.ts +0 -2
  365. package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-delivery-contract.test.ts +0 -91
  366. package/node_modules/@vellumai/gateway-client/src/guardian-delivery-contract.ts +0 -48
  367. package/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +0 -28
  368. package/node_modules/@vellumai/service-contracts/src/channels.ts +0 -41
  369. package/src/__tests__/code-search-tool.test.ts +0 -585
  370. package/src/__tests__/guardian-expiry-notifier.test.ts +0 -282
  371. package/src/__tests__/mcp-config-secret-boundary.test.ts +0 -390
  372. package/src/__tests__/plugin-pipeline.test.ts +0 -96
  373. package/src/__tests__/sse-actor-principal-guardian-source.test.ts +0 -102
  374. package/src/__tests__/steer-on-enqueue-question.test.ts +0 -181
  375. package/src/__tests__/workspace-migration-111-prune-seeded-callsite-defaults.test.ts +0 -208
  376. package/src/agent/loop-exclusive-tool.test.ts +0 -150
  377. package/src/api/constants/sse-replay.ts +0 -41
  378. package/src/api/events/conversation-notice.ts +0 -26
  379. package/src/approvals/guardian-channel-delivery.ts +0 -30
  380. package/src/approvals/guardian-expiry-notifier.ts +0 -148
  381. package/src/cli/commands/memory/__tests__/worker.test.ts +0 -302
  382. package/src/cli/commands/memory/worker.ts +0 -175
  383. package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +0 -143
  384. package/src/config/prune-seeded-callsite-defaults.ts +0 -110
  385. package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +0 -129
  386. package/src/contacts/__tests__/guardian-delivery-reader.test.ts +0 -312
  387. package/src/contacts/__tests__/member-write-relay.test.ts +0 -202
  388. package/src/contacts/guardian-delivery-reader.ts +0 -223
  389. package/src/contacts/member-write-relay.ts +0 -189
  390. package/src/daemon/conversation-notices.ts +0 -60
  391. package/src/daemon/handlers/__tests__/config-channels.test.ts +0 -225
  392. package/src/hooks/hook-loader.ts +0 -341
  393. package/src/mcp/mcp-header-store.ts +0 -134
  394. package/src/memory/__tests__/301-create-watchdog-events.test.ts +0 -110
  395. package/src/memory/__tests__/prompt-override.test.ts +0 -192
  396. package/src/memory/__tests__/watchdog-events-store.test.ts +0 -161
  397. package/src/memory/migrations/300-add-processing-started-at.ts +0 -30
  398. package/src/memory/migrations/301-create-watchdog-events.ts +0 -45
  399. package/src/memory/migrations/__tests__/209-strip-thinking-from-consolidated.test.ts +0 -224
  400. package/src/memory/prompt-override.ts +0 -129
  401. package/src/memory/steps.ts +0 -573
  402. package/src/memory/watchdog-events-store.ts +0 -87
  403. package/src/memory/worker-control.ts +0 -118
  404. package/src/memory/worker-process.ts +0 -72
  405. package/src/notifications/__tests__/connected-channels.test.ts +0 -114
  406. package/src/notifications/__tests__/destination-resolver.test.ts +0 -256
  407. package/src/onboarding/checkin-event.test.ts +0 -222
  408. package/src/onboarding/checkin-event.ts +0 -321
  409. package/src/onboarding/schedule-checkin.ts +0 -190
  410. package/src/plugins/defaults/advisor/__tests__/context-pack-gating.test.ts +0 -106
  411. package/src/plugins/defaults/advisor/__tests__/context-pack.test.ts +0 -60
  412. package/src/plugins/defaults/advisor/context-pack.ts +0 -288
  413. package/src/plugins/defaults/memory-v3-shadow/pool-select.test.ts +0 -146
  414. package/src/plugins/surface-import.ts +0 -121
  415. package/src/providers/openai/__tests__/api-error-normalization.test.ts +0 -321
  416. package/src/providers/openai/api-error-normalization.ts +0 -270
  417. package/src/runtime/__tests__/channel-verification-service.test.ts +0 -133
  418. package/src/runtime/__tests__/guardian-vellum-migration.test.ts +0 -181
  419. package/src/runtime/__tests__/is-guardian-bound-for-channel.test.ts +0 -66
  420. package/src/runtime/__tests__/local-principal-trust.test.ts +0 -164
  421. package/src/runtime/anchored-guardian.test.ts +0 -156
  422. package/src/runtime/anchored-guardian.ts +0 -135
  423. package/src/runtime/auth/__tests__/require-bound-guardian.test.ts +0 -99
  424. package/src/runtime/local-principal-trust.ts +0 -52
  425. package/src/runtime/routes/__tests__/contact-routes.test.ts +0 -212
  426. package/src/runtime/routes/__tests__/global-search-routes.test.ts +0 -93
  427. package/src/runtime/routes/onboarding-checkin-routes.ts +0 -86
  428. package/src/tools/filesystem/search.ts +0 -543
  429. package/src/util/telemetry-db-path.ts +0 -24
  430. package/src/workspace/migrations/111-prune-seeded-callsite-defaults.ts +0 -134
@@ -436,108 +436,6 @@ describe("installPlugin — marketplace resolution", () => {
436
436
  expect(meta.contentHash).toMatch(/^v2:[0-9a-f]{64}$/);
437
437
  });
438
438
 
439
- test("installs a plugin rooted at a sub-path, copying only that subtree", async () => {
440
- // GIVEN a marketplace entry whose source pins a directory *within* a repo
441
- // (a monorepo that ships several plugins) rather than the repo root.
442
- const NESTED_SHA = "0f".repeat(20);
443
- const NESTED_MANIFEST = {
444
- name: "vellum-assistant",
445
- plugins: [
446
- {
447
- name: "nested-plugin",
448
- source: {
449
- source: "github",
450
- repo: "example-org/monorepo",
451
- path: "packages/my-plugin",
452
- ref: NESTED_SHA,
453
- },
454
- description: "A plugin that lives in a monorepo sub-directory.",
455
- },
456
- ],
457
- };
458
- const fetch = makeContentsFetch({ tree: {}, manifest: NESTED_MANIFEST });
459
- // The clone carries files both at the repo root and under the pinned
460
- // sub-path; only the sub-path subtree should be materialized.
461
- const runGit = fakeGitRunner({
462
- tree: {
463
- "package.json": '{"name":"monorepo-root"}',
464
- "README.md": "# monorepo root",
465
- "packages/my-plugin/package.json": '{"name":"nested-plugin"}',
466
- "packages/my-plugin/README.md": "# nested plugin",
467
- "packages/my-plugin/hooks/init.ts": "export default async () => {};",
468
- "packages/other-plugin/package.json": '{"name":"other"}',
469
- },
470
- commit: NESTED_SHA,
471
- });
472
-
473
- // WHEN we install by name
474
- const result = await installPlugin(
475
- { name: "nested-plugin", ref: "main" },
476
- { fetch, runGit, workspacePluginsDir: pluginsDir },
477
- );
478
-
479
- // THEN only the sub-path subtree lands, rooted at <pluginsDir>/nested-plugin
480
- const target = join(pluginsDir, "nested-plugin");
481
- expect(result.target).toBe(target);
482
- expect(readFileSync(join(target, "package.json"), "utf-8")).toBe(
483
- '{"name":"nested-plugin"}',
484
- );
485
- expect(existsSync(join(target, "README.md"))).toBe(true);
486
- expect(existsSync(join(target, "hooks", "init.ts"))).toBe(true);
487
- // AND the repo-root and sibling-package files are NOT copied in — the
488
- // install is scoped to the pinned directory.
489
- expect(result.fileCount).toBe(3);
490
- expect(readFileSync(join(target, "package.json"), "utf-8")).not.toContain(
491
- "monorepo-root",
492
- );
493
- expect(existsSync(join(target, "packages"))).toBe(false);
494
-
495
- // AND provenance records the sub-path so an upgrade/diff re-resolves the
496
- // same directory rather than the repo root.
497
- const meta = readInstallMeta(target);
498
- expect(meta?.source.owner).toBe("example-org");
499
- expect(meta?.source.repo).toBe("monorepo");
500
- expect(meta?.source.path).toBe("packages/my-plugin");
501
- expect(meta?.source.ref).toBe(NESTED_SHA);
502
- });
503
-
504
- test("a sub-path that does not exist in the clone surfaces a clean not-found", async () => {
505
- // GIVEN an entry pinning a directory the cloned ref doesn't contain
506
- const MISSING_SHA = "1a".repeat(20);
507
- const MISSING_PATH_MANIFEST = {
508
- name: "vellum-assistant",
509
- plugins: [
510
- {
511
- name: "nested-plugin",
512
- source: {
513
- source: "github",
514
- repo: "example-org/monorepo",
515
- path: "packages/does-not-exist",
516
- ref: MISSING_SHA,
517
- },
518
- },
519
- ],
520
- };
521
- const fetch = makeContentsFetch({
522
- tree: {},
523
- manifest: MISSING_PATH_MANIFEST,
524
- });
525
- const runGit = fakeGitRunner({
526
- tree: { "package.json": '{"name":"monorepo-root"}' },
527
- commit: MISSING_SHA,
528
- });
529
-
530
- // WHEN we install
531
- // THEN the absent sub-path yields a hard not-found and nothing is staged
532
- await expect(
533
- installPlugin(
534
- { name: "nested-plugin", ref: "main" },
535
- { fetch, runGit, workspacePluginsDir: pluginsDir },
536
- ),
537
- ).rejects.toBeInstanceOf(PluginNotFoundError);
538
- expect(readdirSync(pluginsDir)).toEqual([]);
539
- });
540
-
541
439
  test("refuses to install when the checked-out commit differs from the pinned SHA", async () => {
542
440
  // GIVEN a clone whose resolved HEAD does not match the manifest's pinned
543
441
  // commit SHA — i.e. the upstream object served something unexpected
@@ -17,7 +17,7 @@ import { tmpdir } from "node:os";
17
17
  import { join } from "node:path";
18
18
  import { afterEach, beforeEach, describe, expect, test } from "bun:test";
19
19
 
20
- import { listAllPlugins, listInstalledPlugins } from "../list-installed-plugins.js";
20
+ import { listInstalledPlugins } from "../list-installed-plugins.js";
21
21
 
22
22
  let pluginsDir: string;
23
23
 
@@ -152,162 +152,3 @@ describe("listInstalledPlugins", () => {
152
152
  expect(result.map((p) => p.name)).toEqual(["valid"]);
153
153
  });
154
154
  });
155
-
156
- describe("listAllPlugins", () => {
157
- test("includes default plugins with source=default", () => {
158
- const result = listAllPlugins({ workspacePluginsDir: pluginsDir });
159
- const defaults = result.filter((p) => p.source === "default");
160
- // All 15 default plugins should be present.
161
- expect(defaults.length).toBe(15);
162
- // Names should all start with "default-".
163
- expect(defaults.every((p) => p.name.startsWith("default-"))).toBe(true);
164
- // None should be disabled by default in a fresh temp dir.
165
- expect(defaults.every((p) => !p.disabled)).toBe(true);
166
- });
167
-
168
- test("includes user plugins with source=user", () => {
169
- mkdirSync(join(pluginsDir, "my-plugin"));
170
- writeFileSync(
171
- join(pluginsDir, "my-plugin", "package.json"),
172
- JSON.stringify({ name: "my-plugin", version: "1.0.0" }),
173
- );
174
-
175
- const result = listAllPlugins({ workspacePluginsDir: pluginsDir });
176
- const user = result.filter((p) => p.source === "user");
177
- expect(user).toHaveLength(1);
178
- expect(user[0]!.name).toBe("my-plugin");
179
- expect(user[0]!.disabled).toBe(false);
180
- });
181
-
182
- test("user plugins appear before default plugins", () => {
183
- mkdirSync(join(pluginsDir, "zzz-user"));
184
- writeFileSync(
185
- join(pluginsDir, "zzz-user", "package.json"),
186
- JSON.stringify({ name: "zzz-user", version: "1.0.0" }),
187
- );
188
-
189
- const result = listAllPlugins({ workspacePluginsDir: pluginsDir });
190
- const firstDefaultIdx = result.findIndex((p) => p.source === "default");
191
- const lastUserIdx = result
192
- .map((p, i) => (p.source === "user" ? i : -1))
193
- .filter((i) => i >= 0)
194
- .pop();
195
-
196
- expect(lastUserIdx).toBeDefined();
197
- expect(firstDefaultIdx).toBeGreaterThan(lastUserIdx!);
198
- });
199
-
200
- test("detects disabled state for user plugins", () => {
201
- mkdirSync(join(pluginsDir, "my-plugin"));
202
- writeFileSync(
203
- join(pluginsDir, "my-plugin", "package.json"),
204
- JSON.stringify({ name: "my-plugin", version: "1.0.0" }),
205
- );
206
- writeFileSync(join(pluginsDir, "my-plugin", ".disabled"), "");
207
-
208
- const result = listAllPlugins({ workspacePluginsDir: pluginsDir });
209
- const entry = result.find((p) => p.name === "my-plugin");
210
- expect(entry).toBeDefined();
211
- expect(entry!.disabled).toBe(true);
212
- });
213
-
214
- test("detects disabled state for default plugins via stub directory", () => {
215
- mkdirSync(join(pluginsDir, "default-advisor"), { recursive: true });
216
- writeFileSync(join(pluginsDir, "default-advisor", ".disabled"), "");
217
-
218
- const result = listAllPlugins({ workspacePluginsDir: pluginsDir });
219
- const advisor = result.find((p) => p.name === "default-advisor");
220
- expect(advisor).toBeDefined();
221
- expect(advisor!.disabled).toBe(true);
222
- });
223
-
224
- test("default stub directory is excluded from user listing", () => {
225
- mkdirSync(join(pluginsDir, "default-advisor"), { recursive: true });
226
- writeFileSync(join(pluginsDir, "default-advisor", ".disabled"), "");
227
-
228
- const result = listAllPlugins({ workspacePluginsDir: pluginsDir });
229
- // Should appear exactly once, as a default entry (not a user entry).
230
- const advisorEntries = result.filter((p) => p.name === "default-advisor");
231
- expect(advisorEntries).toHaveLength(1);
232
- expect(advisorEntries[0]!.source).toBe("default");
233
- });
234
-
235
- test("sort order: enabled user, disabled user, enabled default, disabled default", () => {
236
- // User plugins
237
- mkdirSync(join(pluginsDir, "aaa-enabled"));
238
- writeFileSync(
239
- join(pluginsDir, "aaa-enabled", "package.json"),
240
- JSON.stringify({ name: "aaa-enabled", version: "1.0.0" }),
241
- );
242
- mkdirSync(join(pluginsDir, "bbb-disabled"));
243
- writeFileSync(
244
- join(pluginsDir, "bbb-disabled", "package.json"),
245
- JSON.stringify({ name: "bbb-disabled", version: "1.0.0" }),
246
- );
247
- writeFileSync(join(pluginsDir, "bbb-disabled", ".disabled"), "");
248
-
249
- // Disable one default plugin
250
- mkdirSync(join(pluginsDir, "default-advisor"), { recursive: true });
251
- writeFileSync(join(pluginsDir, "default-advisor", ".disabled"), "");
252
-
253
- const result = listAllPlugins({ workspacePluginsDir: pluginsDir });
254
-
255
- const enabledUserIdx = result.findIndex(
256
- (p) => p.source === "user" && !p.disabled,
257
- );
258
- const disabledUserIdx = result.findIndex(
259
- (p) => p.source === "user" && p.disabled,
260
- );
261
- const enabledDefaultIdx = result.findIndex(
262
- (p) => p.source === "default" && !p.disabled,
263
- );
264
- const disabledDefaultIdx = result.findIndex(
265
- (p) => p.source === "default" && p.disabled,
266
- );
267
-
268
- // All groups present.
269
- expect(enabledUserIdx).toBeGreaterThanOrEqual(0);
270
- expect(disabledUserIdx).toBeGreaterThan(enabledUserIdx);
271
- expect(enabledDefaultIdx).toBeGreaterThan(disabledUserIdx);
272
- expect(disabledDefaultIdx).toBeGreaterThan(enabledDefaultIdx);
273
- });
274
-
275
- test("user plugins sorted by install date within each group", () => {
276
- // Create two user plugins with different install dates.
277
- // First plugin (older).
278
- mkdirSync(join(pluginsDir, "older-plugin"));
279
- writeFileSync(
280
- join(pluginsDir, "older-plugin", "package.json"),
281
- JSON.stringify({ name: "older-plugin", version: "1.0.0" }),
282
- );
283
- writeFileSync(
284
- join(pluginsDir, "older-plugin", "install-meta.json"),
285
- JSON.stringify({ installedAt: "2025-01-01T00:00:00.000Z" }),
286
- );
287
-
288
- // Second plugin (newer).
289
- mkdirSync(join(pluginsDir, "newer-plugin"));
290
- writeFileSync(
291
- join(pluginsDir, "newer-plugin", "package.json"),
292
- JSON.stringify({ name: "newer-plugin", version: "1.0.0" }),
293
- );
294
- writeFileSync(
295
- join(pluginsDir, "newer-plugin", "install-meta.json"),
296
- JSON.stringify({ installedAt: "2025-06-01T00:00:00.000Z" }),
297
- );
298
-
299
- const result = listAllPlugins({ workspacePluginsDir: pluginsDir });
300
- const userPlugins = result.filter((p) => p.source === "user");
301
- expect(userPlugins).toHaveLength(2);
302
- // Older plugin should come first (install date ascending).
303
- expect(userPlugins[0]!.name).toBe("older-plugin");
304
- expect(userPlugins[1]!.name).toBe("newer-plugin");
305
- });
306
-
307
- test("default plugins have version from their manifest", () => {
308
- const result = listAllPlugins({ workspacePluginsDir: pluginsDir });
309
- const advisor = result.find((p) => p.name === "default-advisor");
310
- expect(advisor).toBeDefined();
311
- expect(advisor!.packageJson?.version).toBeTruthy();
312
- });
313
- });
@@ -13,25 +13,10 @@
13
13
  */
14
14
 
15
15
  import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
16
- import { dirname, join } from "node:path";
16
+ import { join } from "node:path";
17
17
 
18
18
  import { getWorkspacePluginsDir } from "../../util/platform.js";
19
19
 
20
- /**
21
- * Directory containing first-party default plugin packages. Each subdirectory
22
- * has a `package.json` with `name` (prefixed `default-`) and `version`.
23
- * Read from the filesystem at call time to avoid pulling hook/tool
24
- * implementations into the CLI process (which would create circular
25
- * dependencies in test environments).
26
- */
27
- const DEFAULT_PLUGINS_DIR = join(
28
- dirname(new URL(import.meta.url).pathname),
29
- "..",
30
- "..",
31
- "plugins",
32
- "defaults",
33
- );
34
-
35
20
  /** Minimal manifest fields surfaced to the CLI. */
36
21
  export interface PluginPackageMetadata {
37
22
  readonly name?: string;
@@ -55,20 +40,6 @@ export interface InstalledPluginInfo {
55
40
  readonly issues: readonly string[];
56
41
  }
57
42
 
58
- /** Where the plugin comes from. */
59
- export type PluginSource = "user" | "default";
60
-
61
- /**
62
- * Extended plugin entry that includes source (`user` vs `default`) and
63
- * disabled status. Used by {@link listAllPlugins}.
64
- */
65
- export interface AllPluginInfo extends InstalledPluginInfo {
66
- /** Whether this is a user-installed or first-party default plugin. */
67
- readonly source: PluginSource;
68
- /** Whether the plugin is disabled via a `.disabled` sentinel file. */
69
- readonly disabled: boolean;
70
- }
71
-
72
43
  /** Options accepted by {@link listInstalledPlugins}. */
73
44
  export interface ListInstalledPluginsOptions {
74
45
  /** Override the workspace plugins directory. Falls back to {@link getWorkspacePluginsDir}. */
@@ -175,152 +146,3 @@ function readPluginEntry(
175
146
 
176
147
  return { name, target, packageJson, issues };
177
148
  }
178
-
179
- /**
180
- * List all plugins — both user-installed (from `<workspace>/plugins/`) and
181
- * first-party defaults (from the source tree). Each entry is annotated with
182
- * its `source` (`"user"` or `"default"`) and `disabled` status (whether a
183
- * `.disabled` sentinel file exists in the plugin's workspace directory).
184
- *
185
- * For user plugins, the `.disabled` file lives in the plugin's own install
186
- * directory. For default plugins, it lives in a stub directory at
187
- * `<workspace>/plugins/<manifest-name>/` (created by `plugins disable`).
188
- *
189
- * Stub directories created by `plugins disable <default-name>` are excluded
190
- * from the user listing so a disabled default plugin appears only once (as a
191
- * default entry, not a duplicate user entry with "missing package.json").
192
- *
193
- * Sort order:
194
- * 1. Enabled user plugins (by install date, oldest first — matches
195
- * hook/tool resolution order)
196
- * 2. Disabled user plugins (by install date)
197
- * 3. Enabled default plugins (by repo array order — matches registration
198
- * order which fixes hook-chain order)
199
- * 4. Disabled default plugins (by repo array order)
200
- */
201
- export function listAllPlugins(
202
- opts: ListInstalledPluginsOptions = {},
203
- ): AllPluginInfo[] {
204
- const pluginsDir = opts.workspacePluginsDir ?? getWorkspacePluginsDir();
205
-
206
- // ── User plugins ───────────────────────────────────────────────────────
207
- // Filter out default-plugin stub directories (created by `plugins disable
208
- // default-<name>`) so they don't show up as duplicate user entries.
209
- const defaultNames = new Set(
210
- readDefaultPluginManifests().map((m) => m.name),
211
- );
212
- const userPlugins: AllPluginInfo[] = listInstalledPlugins(opts)
213
- .filter((entry) => !defaultNames.has(entry.name))
214
- .map((entry) => ({
215
- ...entry,
216
- source: "user" as const,
217
- disabled: existsSync(join(entry.target, ".disabled")),
218
- }));
219
-
220
- // ── Default plugins ────────────────────────────────────────────────────
221
- // Default plugins live in the source tree at src/plugins/defaults/<name>/.
222
- // Read each package.json from the filesystem to get name+version without
223
- // importing hook/tool implementations (which would create circular
224
- // dependencies in test environments). The .disabled sentinel lives in a
225
- // stub directory at <workspace>/plugins/<manifest-name>/.
226
- // readDefaultPluginManifests returns in repo array (registration) order.
227
- const defaultPlugins: AllPluginInfo[] = readDefaultPluginManifests().map(
228
- (manifest) => {
229
- const target = join(pluginsDir, manifest.name);
230
- const disabled = existsSync(join(target, ".disabled"));
231
- return {
232
- name: manifest.name,
233
- target,
234
- packageJson: {
235
- name: manifest.name,
236
- version: manifest.version,
237
- },
238
- issues: [],
239
- source: "default" as const,
240
- disabled,
241
- };
242
- },
243
- );
244
-
245
- // Sort: enabled user (install date), disabled user (install date),
246
- // enabled default (repo order), disabled default (repo order).
247
- const enabledUser = userPlugins.filter((p) => !p.disabled);
248
- const disabledUser = userPlugins.filter((p) => p.disabled);
249
- const enabledDefault = defaultPlugins.filter((p) => !p.disabled);
250
- const disabledDefault = defaultPlugins.filter((p) => p.disabled);
251
-
252
- enabledUser.sort((a, b) => getPluginInstallDate(a) - getPluginInstallDate(b));
253
- disabledUser.sort(
254
- (a, b) => getPluginInstallDate(a) - getPluginInstallDate(b),
255
- );
256
- // enabledDefault and disabledDefault keep repo array order (no sort).
257
-
258
- return [...enabledUser, ...disabledUser, ...enabledDefault, ...disabledDefault];
259
- }
260
-
261
- interface DefaultPluginManifest {
262
- readonly name: string;
263
- readonly version?: string;
264
- }
265
-
266
- /**
267
- * Read first-party default plugin manifests from the filesystem. Each
268
- * subdirectory under {@link DEFAULT_PLUGINS_DIR} that has a `package.json`
269
- * with a `name` field is included. This avoids importing `defaults/index.ts`
270
- * (which would pull in hook/tool implementations and create circular
271
- * dependencies in test environments).
272
- */
273
- function readDefaultPluginManifests(): readonly DefaultPluginManifest[] {
274
- if (!existsSync(DEFAULT_PLUGINS_DIR)) return [];
275
-
276
- const entries = readdirSync(DEFAULT_PLUGINS_DIR, { withFileTypes: true })
277
- .filter((e) => e.isDirectory())
278
- .map((e) => e.name)
279
- .sort();
280
-
281
- const manifests: DefaultPluginManifest[] = [];
282
- for (const name of entries) {
283
- const pkgJsonPath = join(DEFAULT_PLUGINS_DIR, name, "package.json");
284
- if (!existsSync(pkgJsonPath)) continue;
285
- try {
286
- const raw = readFileSync(pkgJsonPath, "utf8");
287
- const parsed = JSON.parse(raw) as Record<string, unknown>;
288
- if (typeof parsed.name === "string") {
289
- manifests.push({
290
- name: parsed.name,
291
- version:
292
- typeof parsed.version === "string" ? parsed.version : undefined,
293
- });
294
- }
295
- } catch {
296
- // Skip malformed entries — lenient like listInstalledPlugins.
297
- }
298
- }
299
- return manifests;
300
- }
301
-
302
- /**
303
- * Resolve the install date for a user plugin directory, in epoch ms.
304
- * Reads `install-meta.json`'s `installedAt` field first, falling back to
305
- * the directory's birthtime. Mirrors the logic in mtime-cache's
306
- * `getInstallDate` so the sort order matches hook/tool resolution order.
307
- */
308
- function getPluginInstallDate(plugin: AllPluginInfo): number {
309
- const metaPath = join(plugin.target, "install-meta.json");
310
- try {
311
- if (existsSync(metaPath)) {
312
- const raw = JSON.parse(readFileSync(metaPath, "utf8")) as Record<string, unknown>;
313
- if (typeof raw.installedAt === "string") {
314
- const ms = Date.parse(raw.installedAt);
315
- if (Number.isFinite(ms)) return ms;
316
- }
317
- }
318
- } catch {
319
- // Fall through to birthtime.
320
- }
321
- try {
322
- return statSync(plugin.target).birthtimeMs;
323
- } catch {
324
- return 0;
325
- }
326
- }
@@ -109,13 +109,10 @@ describe("reconcileFlagGatedProfiles", () => {
109
109
 
110
110
  const raw = readConfig();
111
111
  const osBeta = raw.llm.profiles["os-beta"]!;
112
- expect(osBeta.model).toBe("MiniMaxAI/MiniMax-M3");
113
- expect(osBeta.provider_connection).toBe("together-managed");
114
- expect(osBeta.provider).toBe("together");
112
+ expect(osBeta.model).toBe("accounts/fireworks/models/glm-5p2");
113
+ expect(osBeta.provider_connection).toBe("fireworks-managed");
115
114
  expect(osBeta.source).toBe("managed");
116
115
  expect(osBeta.label).toBe("OS Beta");
117
- expect(osBeta.effort).toBe("low");
118
- expect(osBeta.topP).toBe(0.95);
119
116
 
120
117
  const order = raw.llm.profileOrder;
121
118
  expect(order.indexOf("os-beta")).toBe(order.indexOf("balanced") + 1);
@@ -131,7 +128,6 @@ describe("reconcileFlagGatedProfiles", () => {
131
128
  expect(osBeta.status).toBe("disabled");
132
129
  expect(osBeta.label).toBe("OS Beta (Managed)");
133
130
  expect(osBeta.source).toBe("managed");
134
- expect(osBeta.effort).toBe("low");
135
131
  });
136
132
 
137
133
  test("flag on is idempotent across repeated runs", () => {
@@ -154,7 +150,6 @@ describe("reconcileFlagGatedProfiles", () => {
154
150
  raw.llm.profiles["os-beta"]!.label = "My OS Beta";
155
151
  raw.llm.profiles["os-beta"]!.status = "disabled";
156
152
  raw.llm.profiles["os-beta"]!.advisorEnabled = true;
157
- raw.llm.profiles["os-beta"]!.topP = 0.8;
158
153
  writeConfig(raw);
159
154
  invalidateConfigCache();
160
155
 
@@ -164,10 +159,7 @@ describe("reconcileFlagGatedProfiles", () => {
164
159
  expect(after.label).toBe("My OS Beta");
165
160
  expect(after.status).toBe("disabled");
166
161
  expect(after.advisorEnabled).toBe(true);
167
- expect(after.topP).toBe(0.8);
168
- expect(after.model).toBe("MiniMaxAI/MiniMax-M3");
169
- expect(after.provider_connection).toBe("together-managed");
170
- expect(after.effort).toBe("low");
162
+ expect(after.model).toBe("accounts/fireworks/models/glm-5p2");
171
163
  });
172
164
 
173
165
  test("flag off removes a managed os-beta and applies fallbacks", () => {
@@ -1,5 +1,4 @@
1
- import type { ContactRead } from "@vellumai/gateway-client/gateway-ipc-contracts";
2
-
1
+ import type { ContactWithChannels } from "../../../../contacts/types.js";
3
2
  import { cliIpcCall } from "../../../../ipc/cli-client.js";
4
3
  import { resolveGuardianName } from "../../../../prompts/user-reference.js";
5
4
  import type {
@@ -7,12 +6,6 @@ import type {
7
6
  ToolExecutionResult,
8
7
  } from "../../../../tools/types.js";
9
8
 
10
- function guardianAwareName(contact: Pick<ContactRead, "role" | "displayName">) {
11
- return contact.role === "guardian"
12
- ? resolveGuardianName(contact.displayName)
13
- : contact.displayName;
14
- }
15
-
16
9
  export async function executeContactMerge(
17
10
  input: Record<string, unknown>,
18
11
  _context: ToolContext,
@@ -29,10 +22,10 @@ export async function executeContactMerge(
29
22
 
30
23
  // Validate both contacts exist before merging
31
24
  const [keepRes, mergeRes] = await Promise.all([
32
- cliIpcCall<{ contact: ContactRead }>("getContact", {
25
+ cliIpcCall<{ contact: ContactWithChannels }>("getContact", {
33
26
  pathParams: { id: keepId },
34
27
  }),
35
- cliIpcCall<{ contact: ContactRead }>("getContact", {
28
+ cliIpcCall<{ contact: ContactWithChannels }>("getContact", {
36
29
  pathParams: { id: mergeId },
37
30
  }),
38
31
  ]);
@@ -49,7 +42,7 @@ export async function executeContactMerge(
49
42
 
50
43
  const mergeResult = await cliIpcCall<{
51
44
  ok: boolean;
52
- contact: ContactRead;
45
+ contact: ContactWithChannels;
53
46
  }>("merge_contacts", {
54
47
  body: { keepId, mergeId },
55
48
  });
@@ -58,22 +51,19 @@ export async function executeContactMerge(
58
51
  return { content: `Error: ${mergeResult.error}`, isError: true };
59
52
  }
60
53
 
61
- const mergedId = mergeResult.result!.contact.id;
62
-
63
- // Re-read the surviving contact through the gateway-relayed read so role and
64
- // interactionCount come from the gateway ContactRead.
65
- const mergedRes = await cliIpcCall<{ contact: ContactRead }>("getContact", {
66
- pathParams: { id: mergedId },
67
- });
68
-
69
- if (!mergedRes.ok) {
70
- return { content: `Error: ${mergedRes.error}`, isError: true };
71
- }
72
-
73
- const merged = mergedRes.result!.contact;
74
- const displayName = guardianAwareName(merged);
75
- const keepName = guardianAwareName(keepContact);
76
- const mergeName = guardianAwareName(mergeContact);
54
+ const merged = mergeResult.result!.contact;
55
+ const displayName =
56
+ merged.role === "guardian"
57
+ ? resolveGuardianName(merged.displayName)
58
+ : merged.displayName;
59
+ const keepName =
60
+ keepContact.role === "guardian"
61
+ ? resolveGuardianName(keepContact.displayName)
62
+ : keepContact.displayName;
63
+ const mergeName =
64
+ mergeContact.role === "guardian"
65
+ ? resolveGuardianName(mergeContact.displayName)
66
+ : mergeContact.displayName;
77
67
 
78
68
  const channelList = merged.channels
79
69
  .map(
@@ -1,5 +1,4 @@
1
- import type { ContactRead } from "@vellumai/gateway-client/gateway-ipc-contracts";
2
-
1
+ import type { ContactWithChannels } from "../../../../contacts/types.js";
3
2
  import { cliIpcCall } from "../../../../ipc/cli-client.js";
4
3
  import { resolveGuardianName } from "../../../../prompts/user-reference.js";
5
4
  import type {
@@ -7,16 +6,7 @@ import type {
7
6
  ToolExecutionResult,
8
7
  } from "../../../../tools/types.js";
9
8
 
10
- // The search route may carry an optional per-channel `externalChatId` not modeled
11
- // on the gateway `ContactRead` channel contract.
12
- type SearchChannel = ContactRead["channels"][number] & {
13
- externalChatId?: string | null;
14
- };
15
- type SearchContact = Omit<ContactRead, "channels"> & {
16
- channels: SearchChannel[];
17
- };
18
-
19
- function formatContactSummary(c: SearchContact): string {
9
+ function formatContactSummary(c: ContactWithChannels): string {
20
10
  const displayName =
21
11
  c.role === "guardian" ? resolveGuardianName(c.displayName) : c.displayName;
22
12
  const parts = [`- **${displayName}** (ID: ${c.id})`];
@@ -55,7 +45,7 @@ export async function executeContactSearch(
55
45
  };
56
46
  }
57
47
 
58
- const res = await cliIpcCall<SearchContact[]>("search_contacts", {
48
+ const res = await cliIpcCall<ContactWithChannels[]>("search_contacts", {
59
49
  body: { query, channelAddress, channelType, limit },
60
50
  });
61
51
 
@@ -39,7 +39,7 @@ Each subagent is spawned with a role that determines its tool access. Choose the
39
39
  | `researcher` | `web_search`, `web_fetch`, `file_read`, `file_list`, `recall`, `notify_parent` | Information gathering, web research, codebase exploration, reading documentation |
40
40
  | `coder` | `bash`, `file_read`, `file_write`, `file_edit`, `web_search`, `recall`, `notify_parent` | Code changes, file editing, running commands, build/test tasks |
41
41
  | `planner` | `file_read`, `file_list`, `web_search`, `web_fetch`, `recall`, `notify_parent` | Analysis, planning, synthesizing information, reviewing approaches |
42
- | `investigator` | `code_search`, `file_read`, `file_list`, `web_search`, `web_fetch`, `recall`, `notify_parent` | Root-cause analysis: debugging, log forensics, tracing behavior across many files. Read-only search/read tools only (no shell): use `code_search` to grep file contents across directories, `file_list` to enumerate paths, `file_read` to read whole files and logs; returns a compact root-cause report |
42
+ | `investigator` | `bash`, `file_read`, `file_list`, `web_search`, `web_fetch`, `recall`, `notify_parent` | Root-cause analysis: debugging, log forensics, tracing behavior across many files. Shell access is for read-only investigation (grep/find/reading logs); returns a compact root-cause report |
43
43
 
44
44
  All specialized roles (`researcher`, `coder`, `planner`) include `notify_parent` for mid-run communication with the parent.
45
45
 
@@ -38,7 +38,7 @@
38
38
  "planner",
39
39
  "investigator"
40
40
  ],
41
- "description": "Agent specialization that controls tool access. 'researcher': read-only (web, files, memory). 'coder': file and bash access. 'planner': read-only analysis. 'investigator': root-cause analysis — debugging, log forensics, tracing behavior across many files; uses read-only search/read tools (code_search, file_read, file_list) with no shell access and returns a compact root-cause report. 'general': full access (default). Ignored when fork: true (forks always use general)."
41
+ "description": "Agent specialization that controls tool access. 'researcher': read-only (web, files, memory). 'coder': file and bash access. 'planner': read-only analysis. 'investigator': root-cause analysis — debugging, log forensics, tracing behavior across many files; has bash for read-only investigation (grep/find/log inspection) and returns a compact root-cause report. 'general': full access (default). Ignored when fork: true (forks always use general)."
42
42
  },
43
43
  "inference_profile": {
44
44
  "type": "string",