@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
@@ -1827,109 +1827,4 @@ describe("normalizeLlmContextPayloads", () => {
1827
1827
  },
1828
1828
  ]);
1829
1829
  });
1830
-
1831
- describe("provider error response payloads", () => {
1832
- test("extracts a structured error from a rejected call's response payload", () => {
1833
- const normalized = normalizeLlmContextPayloads({
1834
- createdAt: 1_742_400_000_000,
1835
- requestPayload: {
1836
- model: "accounts/fireworks/models/glm-5p2",
1837
- messages: [{ role: "user", content: "hello" }],
1838
- },
1839
- responsePayload: {
1840
- error: {
1841
- name: "ProviderError",
1842
- message:
1843
- "This model doesn't support image input. Remove the image or switch to a vision-capable model.",
1844
- code: "PROVIDER_ERROR",
1845
- provider: "fireworks",
1846
- statusCode: 400,
1847
- },
1848
- },
1849
- });
1850
-
1851
- expect(normalized.error).toEqual({
1852
- name: "ProviderError",
1853
- message:
1854
- "This model doesn't support image input. Remove the image or switch to a vision-capable model.",
1855
- code: "PROVIDER_ERROR",
1856
- provider: "fireworks",
1857
- statusCode: 400,
1858
- });
1859
- // No response sections are produced for an error payload.
1860
- expect(normalized.responseSections).toBeUndefined();
1861
- });
1862
-
1863
- test("preserves a normalized request alongside the error", () => {
1864
- const normalized = normalizeLlmContextPayloads({
1865
- createdAt: 1_742_400_000_000,
1866
- requestPayload: {
1867
- model: "gpt-4.1",
1868
- tool_choice: "auto",
1869
- messages: [{ role: "user", content: "hi" }],
1870
- },
1871
- responsePayload: { error: { message: "boom" } },
1872
- });
1873
-
1874
- expect(normalized.error).toEqual({ message: "boom" });
1875
- // The request side still normalizes so the Prompt tab keeps working.
1876
- expect(normalized.requestSections?.length).toBeGreaterThan(0);
1877
- expect(normalized.summary?.provider).toBe("openai");
1878
- });
1879
-
1880
- test("carries statusCode 0 and retryAfterMs through", () => {
1881
- const normalized = normalizeLlmContextPayloads({
1882
- createdAt: 1_742_400_000_000,
1883
- requestPayload: null,
1884
- responsePayload: {
1885
- error: {
1886
- name: "ProviderError",
1887
- message: "rate limited",
1888
- provider: "anthropic",
1889
- statusCode: 0,
1890
- retryAfterMs: 1500,
1891
- },
1892
- },
1893
- });
1894
-
1895
- expect(normalized.error).toEqual({
1896
- name: "ProviderError",
1897
- message: "rate limited",
1898
- provider: "anthropic",
1899
- statusCode: 0,
1900
- retryAfterMs: 1500,
1901
- });
1902
- });
1903
-
1904
- test("does not treat a successful response with no error as failed", () => {
1905
- const normalized = normalizeLlmContextPayloads({
1906
- createdAt: 1_742_400_000_000,
1907
- requestPayload: {
1908
- model: "gpt-4.1",
1909
- messages: [{ role: "user", content: "hi" }],
1910
- },
1911
- responsePayload: {
1912
- model: "gpt-4.1",
1913
- choices: [
1914
- {
1915
- finish_reason: "stop",
1916
- message: { role: "assistant", content: "hello" },
1917
- },
1918
- ],
1919
- },
1920
- });
1921
-
1922
- expect(normalized.error).toBeUndefined();
1923
- });
1924
-
1925
- test("ignores an empty error object with no identifying fields", () => {
1926
- const normalized = normalizeLlmContextPayloads({
1927
- createdAt: 1_742_400_000_000,
1928
- requestPayload: null,
1929
- responsePayload: { error: {} },
1930
- });
1931
-
1932
- expect(normalized.error).toBeUndefined();
1933
- });
1934
- });
1935
1830
  });
@@ -25,15 +25,18 @@
25
25
  import { describe, expect, test } from "bun:test";
26
26
 
27
27
  import { buildProviderErrorResponsePayload } from "../memory/llm-request-log-store.js";
28
- import { AssistantError, ErrorCode, ProviderError } from "../util/errors.js";
28
+ import {
29
+ AssistantError,
30
+ ErrorCode,
31
+ ProviderError,
32
+ } from "../util/errors.js";
29
33
 
30
- function persisted(err: Error): {
31
- error: Record<string, unknown>;
32
- rawResponse?: unknown;
33
- } {
34
+ function persisted(err: Error): { error: Record<string, unknown> } {
34
35
  // Round-trip through JSON to assert on the actual stored shape, not the
35
36
  // in-memory object reference.
36
- return JSON.parse(JSON.stringify(buildProviderErrorResponsePayload(err)));
37
+ return JSON.parse(
38
+ JSON.stringify(buildProviderErrorResponsePayload(err)),
39
+ );
37
40
  }
38
41
 
39
42
  describe("buildProviderErrorResponsePayload", () => {
@@ -57,34 +60,6 @@ describe("buildProviderErrorResponsePayload", () => {
57
60
  });
58
61
  });
59
62
 
60
- test("ProviderError serializes upstream provider error metadata when present", () => {
61
- const err = new ProviderError(
62
- "OpenAI API error (401): Invalid API key provided",
63
- "openai",
64
- 401,
65
- {
66
- apiErrorCode: "invalid_api_key",
67
- apiErrorType: "invalid_request_error",
68
- apiErrorParam: "api_key",
69
- requestId: "req_abc123",
70
- },
71
- );
72
- const got = persisted(err);
73
- expect(got).toEqual({
74
- error: {
75
- name: "ProviderError",
76
- message: "OpenAI API error (401): Invalid API key provided",
77
- code: ErrorCode.PROVIDER_ERROR,
78
- provider: "openai",
79
- statusCode: 401,
80
- apiErrorCode: "invalid_api_key",
81
- apiErrorType: "invalid_request_error",
82
- apiErrorParam: "api_key",
83
- requestId: "req_abc123",
84
- },
85
- });
86
- });
87
-
88
63
  test("ProviderError without optional metadata omits statusCode + retryAfterMs", () => {
89
64
  const err = new ProviderError(
90
65
  "Gemini API error: surprise internal state",
@@ -152,43 +127,6 @@ describe("buildProviderErrorResponsePayload", () => {
152
127
  });
153
128
  });
154
129
 
155
- test("captured JSON rawBody is attached as a parsed rawResponse sibling", () => {
156
- // So the inspector's Raw tab can render the actual upstream provider JSON
157
- // (like a successful row) instead of only the extracted error fields.
158
- const err = new ProviderError(
159
- "Together AI API error (400): Model 'MiniMax-M3' is not supported.",
160
- "together",
161
- 400,
162
- {
163
- apiErrorCode: "model_not_supported",
164
- rawBody: JSON.stringify({
165
- detail: "Model 'MiniMax-M3' is not supported.",
166
- }),
167
- },
168
- );
169
- const got = persisted(err);
170
- expect(got.error.apiErrorCode).toBe("model_not_supported");
171
- expect(got.rawResponse).toEqual({
172
- detail: "Model 'MiniMax-M3' is not supported.",
173
- });
174
- });
175
-
176
- test("non-JSON rawBody (HTML/text error page) is kept verbatim as a string", () => {
177
- const err = new ProviderError("Bad gateway", "openai", 400, {
178
- rawBody: "<html><body>upstream timeout</body></html>",
179
- });
180
- const got = persisted(err);
181
- expect(got.rawResponse).toBe("<html><body>upstream timeout</body></html>");
182
- });
183
-
184
- test("no captured rawBody omits the rawResponse sibling entirely", () => {
185
- const err = new ProviderError("rate limited", "anthropic", 429, {
186
- retryAfterMs: 1500,
187
- });
188
- const got = persisted(err);
189
- expect("rawResponse" in got).toBe(false);
190
- });
191
-
192
130
  test("ProviderError with statusCode 0 is still recorded (not coerced to undefined)", () => {
193
131
  // Defensive: `if (err.statusCode !== undefined)` correctly admits 0.
194
132
  // A raw `if (err.statusCode)` would drop it, so the test guards against
@@ -779,31 +779,6 @@ describe("getUsageDayBuckets", () => {
779
779
  expect(buckets[0].totalEstimatedCostUsd).toBeCloseTo(0.05);
780
780
  expect(buckets[0].eventCount).toBe(2);
781
781
  });
782
-
783
- test("collapses many events within a sub-bucket span without losing totals", () => {
784
- // The read path pre-aggregates events into 15-minute UTC buckets in SQL
785
- // before local-time bucketing. Many events inside one such window must
786
- // still sum exactly, and events split across the 15-minute boundary but
787
- // within the same local day must land in the same day bucket.
788
- const windowStart = utcMs(2025, 3, 1, 10); // 10:00:00 UTC
789
- for (let i = 0; i < 50; i++) {
790
- // Spread across ~16 minutes so the events straddle a 15-minute boundary.
791
- insertEventAt(windowStart + i * 20_000, {
792
- inputTokens: 2,
793
- outputTokens: 1,
794
- });
795
- }
796
-
797
- const buckets = getUsageDayBuckets({
798
- from: utcMs(2025, 3, 1),
799
- to: utcMs(2025, 3, 2),
800
- });
801
- expect(buckets).toHaveLength(1);
802
- expect(buckets[0].date).toBe("2025-03-01");
803
- expect(buckets[0].totalInputTokens).toBe(100);
804
- expect(buckets[0].totalOutputTokens).toBe(50);
805
- expect(buckets[0].eventCount).toBe(50);
806
- });
807
782
  });
808
783
 
809
784
  describe("getUsageDayBuckets — timezone-aware", () => {
@@ -58,8 +58,7 @@ mock.module("../mcp/mcp-auth-state.js", () => ({
58
58
  }));
59
59
 
60
60
  mock.module("../mcp/mcp-oauth-provider.js", () => ({
61
- hasMcpOAuthTokens: async () => false,
62
- deleteMcpOAuthCredentials: async () => ({ ok: true, failedKeys: [] }),
61
+ deleteMcpOAuthCredentials: async () => {},
63
62
  }));
64
63
 
65
64
  const { ROUTES } = await import("../runtime/routes/mcp-auth-routes.js");
@@ -176,22 +176,6 @@ mock.module("../calls/channel-admission-reader.js", () => ({
176
176
  getChannelAdmissionPolicy: mockGetChannelAdmissionPolicy,
177
177
  }));
178
178
 
179
- // Mock the inbound trust reader. handleStart awaits this and threads the
180
- // verdict into routeSetup so the media-stream transport enforces the same
181
- // gateway ACL as ConversationRelay. Tests override mockInboundVerdict.
182
- let mockInboundVerdict: unknown = null;
183
- const mockGetInboundTrustVerdict = jest.fn(
184
- async (_args?: Record<string, unknown>) => mockInboundVerdict,
185
- );
186
- mock.module("../calls/inbound-trust-reader.js", () => ({
187
- getInboundTrustVerdict: mockGetInboundTrustVerdict,
188
- getPhoneCallerVerdict: (otherPartyNumber: string | undefined) =>
189
- mockGetInboundTrustVerdict({
190
- channelType: "phone",
191
- actorExternalId: otherPartyNumber || undefined,
192
- }),
193
- }));
194
-
195
179
  // Mock the actor trust resolver (used by handleStart to derive trust context)
196
180
  mock.module("../runtime/actor-trust-resolver.js", () => ({
197
181
  toTrustContext: jest.fn(() => ({
@@ -372,8 +356,6 @@ beforeEach(() => {
372
356
  mockGetChannelAdmissionPolicy.mockClear();
373
357
  mockAdmissionPolicy = null;
374
358
  mockAdmissionGate = null;
375
- mockGetInboundTrustVerdict.mockClear();
376
- mockInboundVerdict = null;
377
359
  // Reset routeSetup to default normal_call
378
360
  mockRouteSetupResult = {
379
361
  outcome: { action: "normal_call" as const, isInbound: true },
@@ -1553,113 +1535,4 @@ describe("media-stream setup outcome scenarios", () => {
1553
1535
  expect(speakSystemPrompt).not.toHaveBeenCalled();
1554
1536
  });
1555
1537
  });
1556
-
1557
- // ── Gateway trust verdict ──────────────────────────────────────────
1558
- // handleStart fetches getInboundTrustVerdict for the inbound caller and
1559
- // threads it into routeSetup, so the media-stream transport enforces the
1560
- // same gateway ACL as ConversationRelay. routeSetup itself decides
1561
- // verdict-vs-local; these tests assert the verdict is fetched and passed.
1562
-
1563
- describe("gateway trust verdict", () => {
1564
- test("fetches the inbound caller's verdict and threads it into routeSetup", async () => {
1565
- mockInboundVerdict = {
1566
- channelType: "phone",
1567
- actorExternalId: "+14155550000",
1568
- contactId: "contact-1",
1569
- channelId: "channel-1",
1570
- status: "verified",
1571
- policy: "allow",
1572
- resolutionFailed: false,
1573
- };
1574
-
1575
- const mockWs = createMockWs();
1576
- mockSessions.set("call-verdict-thread-1", {
1577
- id: "call-verdict-thread-1",
1578
- conversationId: "conv-verdict-thread-1",
1579
- status: "initiated",
1580
- task: null,
1581
- startedAt: null,
1582
- fromNumber: "+14155550000",
1583
- toNumber: "+15550001111",
1584
- });
1585
-
1586
- const session = new MediaStreamCallSession(
1587
- mockWs.ws,
1588
- "call-verdict-thread-1",
1589
- );
1590
- session.handleMessage(makeStartMessage());
1591
- await session.whenSetupSettled();
1592
-
1593
- // Verdict fetched for the inbound caller (from number) on the phone channel.
1594
- expect(mockGetInboundTrustVerdict).toHaveBeenCalledWith({
1595
- channelType: "phone",
1596
- actorExternalId: "+14155550000",
1597
- });
1598
- // Verdict threaded into routeSetup.
1599
- expect(routeSetup).toHaveBeenCalledWith(
1600
- expect.objectContaining({ verdict: mockInboundVerdict }),
1601
- );
1602
- });
1603
-
1604
- test("a blocked/denied member verdict is enforced (deny) on the media-stream transport", async () => {
1605
- // The real router returns `deny` for a member verdict whose ACL is
1606
- // blocked/revoked/deny; the mock reflects that outcome here.
1607
- mockInboundVerdict = {
1608
- channelType: "phone",
1609
- actorExternalId: "+14155550000",
1610
- contactId: "contact-1",
1611
- channelId: "channel-1",
1612
- status: "blocked",
1613
- policy: "deny",
1614
- resolutionFailed: false,
1615
- };
1616
- mockRouteSetupResult = {
1617
- outcome: {
1618
- action: "deny",
1619
- message:
1620
- "This number is not authorized to reach the assistant right now.",
1621
- logReason: "Inbound voice ACL: member blocked",
1622
- },
1623
- resolved: {
1624
- assistantId: "self",
1625
- isInbound: true,
1626
- otherPartyNumber: "+14155550000",
1627
- actorTrust: { trustClass: "unknown", memberRecord: null },
1628
- },
1629
- };
1630
-
1631
- const mockWs = createMockWs();
1632
- mockSessions.set("call-verdict-deny-1", {
1633
- id: "call-verdict-deny-1",
1634
- conversationId: "conv-verdict-deny-1",
1635
- status: "initiated",
1636
- task: null,
1637
- startedAt: null,
1638
- fromNumber: "+14155550000",
1639
- toNumber: "+15550001111",
1640
- });
1641
-
1642
- const session = new MediaStreamCallSession(
1643
- mockWs.ws,
1644
- "call-verdict-deny-1",
1645
- );
1646
- session.handleMessage(makeStartMessage());
1647
- await session.whenSetupSettled();
1648
-
1649
- // Verdict was passed into routeSetup, which denied the caller.
1650
- expect(routeSetup).toHaveBeenCalledWith(
1651
- expect.objectContaining({ verdict: mockInboundVerdict }),
1652
- );
1653
- expect(speakSystemPrompt).toHaveBeenCalledWith(
1654
- expect.anything(),
1655
- "This number is not authorized to reach the assistant right now.",
1656
- );
1657
- expect(updateCallSession).toHaveBeenCalledWith(
1658
- "call-verdict-deny-1",
1659
- expect.objectContaining({ status: "failed" }),
1660
- );
1661
- expect(registerCallController).not.toHaveBeenCalled();
1662
- expect(mockStartInitialGreeting).not.toHaveBeenCalled();
1663
- });
1664
- });
1665
1538
  });
@@ -19,8 +19,6 @@ import { beforeEach, describe, expect, mock, test } from "bun:test";
19
19
  // bindings resolve through the mocks.
20
20
  const updateMessageMetadataMock = mock((_id: string, _updates: unknown) => {});
21
21
  mock.module("../memory/conversation-crud.js", () => ({
22
- setConversationProcessingStartedAt: () => {},
23
- isConversationProcessing: () => false,
24
22
  updateMessageMetadata: updateMessageMetadataMock,
25
23
  }));
26
24
 
@@ -79,8 +79,6 @@ const getBindingByChannelChatMock = mock(
79
79
  );
80
80
 
81
81
  mock.module("../memory/conversation-crud.js", () => ({
82
- setConversationProcessingStartedAt: () => {},
83
- isConversationProcessing: () => false,
84
82
  addMessage: addMessageMock,
85
83
  getConversation: getConversationMock,
86
84
  reserveMessage: mock(async () => ({ id: "msg-reserve" })),
@@ -421,8 +421,8 @@ describe("handleMigrationImport — JSON {url} body", () => {
421
421
  describe("handleMigrationImport — no-swap path omits newer-migration warning", () => {
422
422
  test("credentials-only bundle does not inherit live-DB migration warnings", async () => {
423
423
  // Seed the live workspace DB with a step:* checkpoint that's NOT
424
- // in the known step list. validateMigrationState treats this as a
425
- // "newer version" and would otherwise push a warning into the report. With
424
+ // in the registry. validateMigrationState treats this as a "newer
425
+ // version" and would otherwise push a warning into the report. With
426
426
  // the gate in appendNewerMigrationWarningsIfAny the warning must be
427
427
  // suppressed when the import didn't modify the workspace.
428
428
  const dbDir = join(testWorkspaceRoot, "data", "db");
@@ -7,7 +7,7 @@
7
7
  * cache miss (changed mtime → re-import), plugin deletion (eviction),
8
8
  * and hook collection across multiple plugins.
9
9
  */
10
- import { mkdirSync, rmSync, utimesSync, writeFileSync } from "node:fs";
10
+ import { mkdirSync, rmSync, utimesSync,writeFileSync } from "node:fs";
11
11
  import { tmpdir } from "node:os";
12
12
  import { join } from "node:path";
13
13
  import {
@@ -19,8 +19,8 @@ import {
19
19
  test,
20
20
  } from "bun:test";
21
21
 
22
- import { _inspectHookCacheForTests } from "../hooks/hook-loader.js";
23
22
  import {
23
+ _inspectHookCacheForTests,
24
24
  _inspectToolCacheForTests,
25
25
  getCachedUserTools,
26
26
  getUserHooksFor,
@@ -62,15 +62,7 @@ function writeHook(dir: string, hookName: string, body: string): void {
62
62
  function writeInstallMeta(dir: string, installedAt: string): void {
63
63
  writeFileSync(
64
64
  join(dir, "install-meta.json"),
65
- JSON.stringify(
66
- {
67
- name: "test",
68
- installedAt,
69
- source: { kind: "github", owner: "test", repo: "test", ref: "main" },
70
- },
71
- null,
72
- 2,
73
- ),
65
+ JSON.stringify({ name: "test", installedAt, source: { kind: "github", owner: "test", repo: "test", ref: "main" } }, null, 2),
74
66
  );
75
67
  }
76
68
 
@@ -80,20 +72,6 @@ function writeTool(dir: string, toolName: string, body: string): void {
80
72
  writeFileSync(join(toolsDir, `${toolName}.ts`), body);
81
73
  }
82
74
 
83
- /** The standalone workspace hooks directory (`<workspace>/hooks/`). */
84
- const WORKSPACE_HOOKS_DIR = join(ROOT, "hooks");
85
-
86
- function ensureWorkspaceHooksDir(): void {
87
- rmSync(WORKSPACE_HOOKS_DIR, { recursive: true, force: true });
88
- mkdirSync(WORKSPACE_HOOKS_DIR, { recursive: true });
89
- }
90
-
91
- /** Write a standalone hook file directly under `<workspace>/hooks/`. */
92
- function writeWorkspaceHook(hookName: string, body: string): void {
93
- mkdirSync(WORKSPACE_HOOKS_DIR, { recursive: true });
94
- writeFileSync(join(WORKSPACE_HOOKS_DIR, `${hookName}.ts`), body);
95
- }
96
-
97
75
  /**
98
76
  * Bump a file's mtime forward by ~2 seconds so the mtime cache detects a
99
77
  * change. Using utimesSync avoids race conditions with filesystem mtime
@@ -119,7 +97,6 @@ beforeAll(() => {
119
97
 
120
98
  beforeEach(() => {
121
99
  ensurePluginsDir();
122
- ensureWorkspaceHooksDir();
123
100
  resetPluginCacheForTests();
124
101
  });
125
102
 
@@ -361,9 +338,7 @@ describe("plugin mtime cache (per-surface)", () => {
361
338
  expect(hooks).toHaveLength(2);
362
339
 
363
340
  // beta was installed earlier (Jan 1) so it should come first.
364
- const results = hooks.map((fn) =>
365
- (fn as unknown as () => { tag: string })(),
366
- );
341
+ const results = hooks.map((fn) => (fn as unknown as () => { tag: string })());
367
342
  expect(results[0]!.tag).toBe("beta");
368
343
  expect(results[1]!.tag).toBe("alpha");
369
344
  });
@@ -393,124 +368,8 @@ describe("plugin mtime cache (per-surface)", () => {
393
368
  const hooks = await getUserHooksFor("user-prompt-submit");
394
369
  expect(hooks).toHaveLength(2);
395
370
 
396
- const results = hooks.map((fn) =>
397
- (fn as unknown as () => { tag: string })(),
398
- );
371
+ const results = hooks.map((fn) => (fn as unknown as () => { tag: string })());
399
372
  expect(results[0]!.tag).toBe("dated");
400
373
  expect(results[1]!.tag).toBe("undated");
401
374
  });
402
375
  });
403
-
404
- describe("workspace hooks (<workspace>/hooks/)", () => {
405
- test("getUserHooksFor loads a standalone workspace hook", async () => {
406
- writeWorkspaceHook(
407
- "user-prompt-submit",
408
- `export default () => ({ ws: 1 });`,
409
- );
410
-
411
- await populateCacheAtBoot();
412
-
413
- const hooks = await getUserHooksFor("user-prompt-submit");
414
- expect(hooks).toHaveLength(1);
415
- });
416
-
417
- test("workspace hooks load even when no plugins directory exists", async () => {
418
- rmSync(PLUGINS_DIR, { recursive: true, force: true });
419
- writeWorkspaceHook("post-tool-use", `export default () => ({ ws: 1 });`);
420
-
421
- await populateCacheAtBoot();
422
-
423
- const hooks = await getUserHooksFor("post-tool-use");
424
- expect(hooks).toHaveLength(1);
425
- expect(getCachedUserTools()).toHaveLength(0);
426
- });
427
-
428
- // NB: each test below uses a distinct hook event name so the workspace
429
- // hook file path is unique. Bun caches dynamic import() by URL and does not
430
- // bust on content change, so reusing `<workspace>/hooks/<name>.ts` across
431
- // tests would return a stale module (the existing plugin tests dodge this
432
- // by using a fresh plugin directory per test).
433
- test("plugin hooks run before the workspace hook for the same event", async () => {
434
- const dir = freshPluginDir("ordering-plugin");
435
- writePackageJson(dir, { ...SIMPLE_PKG, name: "ordering-plugin" });
436
- writeHook(
437
- dir,
438
- "pre-model-call",
439
- `export default () => ({ tag: "plugin" });`,
440
- );
441
- writeWorkspaceHook(
442
- "pre-model-call",
443
- `export default () => ({ tag: "workspace" });`,
444
- );
445
-
446
- await populateCacheAtBoot();
447
-
448
- const hooks = await getUserHooksFor("pre-model-call");
449
- expect(hooks).toHaveLength(2);
450
- const results = hooks.map((fn) =>
451
- (fn as unknown as () => { tag: string })(),
452
- );
453
- expect(results[0]!.tag).toBe("plugin");
454
- expect(results[1]!.tag).toBe("workspace");
455
- });
456
-
457
- test("editing a workspace hook file triggers re-import", async () => {
458
- const hookFile = join(WORKSPACE_HOOKS_DIR, "post-model-call.ts");
459
- writeWorkspaceHook("post-model-call", `export default () => ({ v: 1 });`);
460
-
461
- await populateCacheAtBoot();
462
-
463
- const before = _inspectHookCacheForTests().find((c) =>
464
- c.key.startsWith("__workspace__/"),
465
- );
466
- expect(before).toBeDefined();
467
-
468
- touchFile(hookFile);
469
- await getUserHooksFor("post-model-call");
470
-
471
- const after = _inspectHookCacheForTests().find((c) =>
472
- c.key.startsWith("__workspace__/"),
473
- );
474
- expect(after?.sourceMtime).not.toBe(before?.sourceMtime);
475
- });
476
-
477
- test("deleting a workspace hook file evicts it on next read", async () => {
478
- const hookFile = join(WORKSPACE_HOOKS_DIR, "stop.ts");
479
- writeWorkspaceHook("stop", `export default () => ({ v: 1 });`);
480
-
481
- await populateCacheAtBoot();
482
- expect(await getUserHooksFor("stop")).toHaveLength(1);
483
-
484
- rmSync(hookFile, { force: true });
485
-
486
- const hooks = await getUserHooksFor("stop");
487
- expect(hooks).toHaveLength(0);
488
- });
489
-
490
- test("a newly added workspace hook is picked up without restart", async () => {
491
- await populateCacheAtBoot();
492
- expect(await getUserHooksFor("post-compact")).toHaveLength(0);
493
-
494
- writeWorkspaceHook("post-compact", `export default () => ({ v: 1 });`);
495
-
496
- expect(await getUserHooksFor("post-compact")).toHaveLength(1);
497
- });
498
-
499
- test("a workspace init hook runs once at boot", async () => {
500
- // The init hook writes a sentinel file so we can observe it ran exactly
501
- // once during populateCacheAtBoot.
502
- const sentinel = join(ROOT, "ws-init-ran.txt");
503
- rmSync(sentinel, { force: true });
504
- writeWorkspaceHook(
505
- "init",
506
- `import { appendFileSync } from "node:fs";
507
- export default () => { appendFileSync(${JSON.stringify(sentinel)}, "x"); };`,
508
- );
509
-
510
- await populateCacheAtBoot();
511
-
512
- const { readFileSync: rf, existsSync: ex } = await import("node:fs");
513
- expect(ex(sentinel)).toBe(true);
514
- expect(rf(sentinel, "utf8")).toBe("x");
515
- });
516
- });
@@ -95,8 +95,6 @@ mock.module("../config/loader.js", () => ({
95
95
  }));
96
96
 
97
97
  mock.module("../memory/conversation-crud.js", () => ({
98
- setConversationProcessingStartedAt: () => {},
99
- isConversationProcessing: () => false,
100
98
  addMessage: () => ({ id: "mock-msg-id" }),
101
99
  getMessageById: () => null,
102
100
  updateMessageContent: () => {},