@vellumai/assistant 0.10.1 → 0.10.2-dev.202606241651.2d2b40d

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 (367) hide show
  1. package/docs/workspace-tools.md +42 -33
  2. package/eslint-rules/cli-no-daemon-internals.js +6 -0
  3. package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-delivery-contract.test.ts +91 -0
  4. package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +31 -0
  5. package/node_modules/@vellumai/gateway-client/src/guardian-delivery-contract.ts +48 -0
  6. package/node_modules/@vellumai/gateway-client/src/index.ts +14 -0
  7. package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +17 -0
  8. package/openapi.yaml +74 -1
  9. package/package.json +1 -1
  10. package/scripts/test.sh +36 -15
  11. package/src/__tests__/actor-token-service.test.ts +36 -14
  12. package/src/__tests__/agent-loop-override-profile.test.ts +1 -0
  13. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +2 -0
  14. package/src/__tests__/agent-wake-override-profile.test.ts +2 -0
  15. package/src/__tests__/annotate-activity-metadata.test.ts +2 -0
  16. package/src/__tests__/annotate-risk-options.test.ts +2 -0
  17. package/src/__tests__/approval-cascade.test.ts +2 -0
  18. package/src/__tests__/background-workers-disk-pressure.test.ts +2 -0
  19. package/src/__tests__/btw-routes.test.ts +2 -0
  20. package/src/__tests__/build-persisted-content.test.ts +2 -0
  21. package/src/__tests__/call-controller.test.ts +19 -0
  22. package/src/__tests__/channel-guardian.test.ts +94 -58
  23. package/src/__tests__/channel-reply-delivery.test.ts +2 -0
  24. package/src/__tests__/compaction-events.test.ts +2 -0
  25. package/src/__tests__/compaction.benchmark.test.ts +2 -0
  26. package/src/__tests__/compactor-call-site-logging.test.ts +2 -0
  27. package/src/__tests__/compactor-low-watermark-cut.test.ts +2 -0
  28. package/src/__tests__/compactor-preserved-tail-count.test.ts +2 -0
  29. package/src/__tests__/compactor-summary-call-truncation.test.ts +2 -0
  30. package/src/__tests__/compactor-web-search-strip.test.ts +2 -0
  31. package/src/__tests__/computer-use-tools.test.ts +13 -0
  32. package/src/__tests__/config-loader-backfill.test.ts +5 -1
  33. package/src/__tests__/config-schema.test.ts +1 -0
  34. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +31 -29
  35. package/src/__tests__/contacts-relay-reads.test.ts +13 -15
  36. package/src/__tests__/conversation-abort-tool-results.test.ts +2 -0
  37. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +2 -0
  38. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
  39. package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -0
  40. package/src/__tests__/conversation-agent-loop.test.ts +7 -0
  41. package/src/__tests__/conversation-analysis-routes.test.ts +2 -0
  42. package/src/__tests__/conversation-app-control-lifecycle.test.ts +2 -0
  43. package/src/__tests__/conversation-confirmation-signals.test.ts +2 -0
  44. package/src/__tests__/conversation-history-web-search.test.ts +2 -0
  45. package/src/__tests__/conversation-load-history-repair.test.ts +2 -0
  46. package/src/__tests__/conversation-load-history-stripped.test.ts +2 -0
  47. package/src/__tests__/conversation-pairing.test.ts +2 -0
  48. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +2 -0
  49. package/src/__tests__/conversation-process-callsite.test.ts +2 -0
  50. package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -0
  51. package/src/__tests__/conversation-queue.test.ts +91 -0
  52. package/src/__tests__/conversation-routes-guardian-reply.test.ts +14 -0
  53. package/src/__tests__/conversation-routes-slash-commands.test.ts +14 -0
  54. package/src/__tests__/conversation-slash-queue.test.ts +2 -0
  55. package/src/__tests__/conversation-slash-unknown.test.ts +2 -0
  56. package/src/__tests__/conversation-speed-override.test.ts +2 -0
  57. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +65 -0
  58. package/src/__tests__/conversation-title-service.test.ts +2 -0
  59. package/src/__tests__/conversation-tool-setup-attribution.test.ts +47 -0
  60. package/src/__tests__/conversation-usage.test.ts +2 -0
  61. package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -0
  62. package/src/__tests__/conversation-workspace-injection.test.ts +2 -0
  63. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +2 -0
  64. package/src/__tests__/credential-security-invariants.test.ts +0 -1
  65. package/src/__tests__/db-migration-rollback.test.ts +205 -171
  66. package/src/__tests__/db-test-helpers.ts +5 -4
  67. package/src/__tests__/deterministic-verification-control-plane.test.ts +4 -2
  68. package/src/__tests__/disk-pressure-guard.test.ts +41 -0
  69. package/src/__tests__/dm-persistence.test.ts +2 -0
  70. package/src/__tests__/emit-signal-routing-intent.test.ts +10 -5
  71. package/src/__tests__/events-dev-bypass-actor.test.ts +7 -1
  72. package/src/__tests__/filing-service.test.ts +2 -0
  73. package/src/__tests__/guardian-binding-drift-heal.test.ts +75 -10
  74. package/src/__tests__/guardian-dispatch.test.ts +95 -1
  75. package/src/__tests__/guardian-outbound-http.test.ts +13 -0
  76. package/src/__tests__/heartbeat-disk-pressure.test.ts +2 -0
  77. package/src/__tests__/heartbeat-service.test.ts +2 -0
  78. package/src/__tests__/helpers/channel-test-adapter.ts +1 -7
  79. package/src/__tests__/host-app-control-routes.test.ts +24 -30
  80. package/src/__tests__/host-bash-routes.test.ts +31 -41
  81. package/src/__tests__/host-browser-routes.test.ts +26 -32
  82. package/src/__tests__/host-cu-proxy.test.ts +299 -0
  83. package/src/__tests__/host-cu-routes-targeted.test.ts +25 -33
  84. package/src/__tests__/host-file-routes-targeted.test.ts +40 -52
  85. package/src/__tests__/host-transfer-routes-targeted.test.ts +31 -43
  86. package/src/__tests__/http-user-message-parity.test.ts +167 -8
  87. package/src/__tests__/inbound-slack-persistence.test.ts +2 -0
  88. package/src/__tests__/invite-redemption-service.test.ts +43 -0
  89. package/src/__tests__/llm-context-normalization.test.ts +105 -0
  90. package/src/__tests__/llm-usage-store.test.ts +25 -0
  91. package/src/__tests__/media-stream-server-integration.test.ts +127 -0
  92. package/src/__tests__/memory-retrieval-hook.test.ts +2 -0
  93. package/src/__tests__/messaging-send-tool.test.ts +2 -0
  94. package/src/__tests__/migration-import-from-url.test.ts +2 -2
  95. package/src/__tests__/native-web-search.test.ts +2 -0
  96. package/src/__tests__/non-member-access-request.test.ts +189 -17
  97. package/src/__tests__/notification-broadcaster.test.ts +4 -0
  98. package/src/__tests__/notification-decision-recipient-context.test.ts +33 -32
  99. package/src/__tests__/notification-deep-link.test.ts +6 -0
  100. package/src/__tests__/notification-guardian-path.test.ts +19 -0
  101. package/src/__tests__/outbound-slack-persistence.test.ts +2 -0
  102. package/src/__tests__/pending-interactions-resolved-event.test.ts +7 -4
  103. package/src/__tests__/persistence-secret-redaction.test.ts +2 -0
  104. package/src/__tests__/plugin-bootstrap.test.ts +3 -73
  105. package/src/__tests__/plugin-route-contribution.test.ts +4 -17
  106. package/src/__tests__/plugin-tool-contribution.test.ts +3 -18
  107. package/src/__tests__/plugin-types.test.ts +0 -2
  108. package/src/__tests__/process-message-background-slack.test.ts +2 -0
  109. package/src/__tests__/process-message-display-content.test.ts +2 -0
  110. package/src/__tests__/provider-usage-tracking.test.ts +39 -0
  111. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +2 -0
  112. package/src/__tests__/registry.test.ts +3 -0
  113. package/src/__tests__/relay-server.test.ts +694 -25
  114. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
  115. package/src/__tests__/secret-ingress-http.test.ts +14 -0
  116. package/src/__tests__/send-endpoint-busy.test.ts +30 -8
  117. package/src/__tests__/skills.test.ts +44 -0
  118. package/src/__tests__/slack-inbound-verification.test.ts +47 -2
  119. package/src/__tests__/sse-actor-principal-guardian-source.test.ts +102 -0
  120. package/src/__tests__/steer-on-enqueue-question.test.ts +181 -0
  121. package/src/__tests__/stt-hints.test.ts +44 -13
  122. package/src/__tests__/subagent-detail.test.ts +27 -0
  123. package/src/__tests__/subagent-disposal.test.ts +65 -0
  124. package/src/__tests__/subagent-notify-parent.test.ts +2 -0
  125. package/src/__tests__/subagent-spawn-tool-fork.test.ts +2 -0
  126. package/src/__tests__/subagent-tools.test.ts +2 -0
  127. package/src/__tests__/suggestion-routes.test.ts +2 -0
  128. package/src/__tests__/title-generate-hook.test.ts +2 -0
  129. package/src/__tests__/tool-executor-lifecycle-events.test.ts +2 -0
  130. package/src/__tests__/tool-executor.test.ts +16 -11
  131. package/src/__tests__/tool-preview-lifecycle.test.ts +2 -0
  132. package/src/__tests__/tool-result-metadata-plumbing.test.ts +2 -0
  133. package/src/__tests__/tool-start-timestamp.test.ts +2 -0
  134. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +10 -10
  135. package/src/__tests__/twilio-routes.test.ts +96 -0
  136. package/src/__tests__/verification-control-plane-policy.test.ts +2 -0
  137. package/src/__tests__/web-search-backend-failure.test.ts +2 -0
  138. package/src/__tests__/workspace-tool-loader.test.ts +195 -2
  139. package/src/agent/loop-exclusive-tool.test.ts +150 -0
  140. package/src/agent/loop.ts +56 -0
  141. package/src/api/constants/sse-replay.ts +41 -0
  142. package/src/api/index.ts +6 -0
  143. package/src/api/responses/llm-request-log-entry.ts +25 -0
  144. package/src/api/responses/subagent-detail.ts +17 -0
  145. package/src/calls/__tests__/relay-setup-router.test.ts +262 -4
  146. package/src/calls/call-domain.ts +3 -3
  147. package/src/calls/guardian-dispatch.ts +10 -8
  148. package/src/calls/inbound-trust-reader.ts +17 -1
  149. package/src/calls/media-stream-server.ts +21 -0
  150. package/src/calls/relay-server.ts +167 -50
  151. package/src/calls/relay-setup-router.ts +37 -7
  152. package/src/calls/relay-verification.ts +4 -4
  153. package/src/calls/stt-hints.ts +9 -12
  154. package/src/calls/twilio-routes.ts +14 -4
  155. package/src/cli/commands/__tests__/cache.test.ts +8 -1
  156. package/src/cli/commands/cache.ts +194 -181
  157. package/src/cli/commands/db/__tests__/repair.test.ts +6 -5
  158. package/src/cli/commands/db/status.ts +37 -1
  159. package/src/cli/commands/mcp.ts +252 -218
  160. package/src/cli/commands/memory/__tests__/worker.test.ts +302 -0
  161. package/src/cli/commands/memory/index.ts +2 -0
  162. package/src/cli/commands/memory/worker.ts +175 -0
  163. package/src/cli/commands/plugins.ts +75 -3
  164. package/src/cli/lib/__tests__/install-from-github.test.ts +102 -0
  165. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +160 -1
  166. package/src/cli/lib/list-installed-plugins.ts +179 -1
  167. package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +143 -0
  168. package/src/config/bundled-skills/computer-use/TOOLS.json +6 -1
  169. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +27 -17
  170. package/src/config/bundled-skills/contacts/tools/contact-search.ts +13 -3
  171. package/src/config/feature-flag-registry.json +0 -8
  172. package/src/config/loader.ts +36 -5
  173. package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
  174. package/src/config/schemas/memory-lifecycle.ts +12 -0
  175. package/src/config/schemas/memory-v3.ts +7 -0
  176. package/src/config/schemas/memory.ts +4 -0
  177. package/src/config/schemas/timeouts.ts +8 -0
  178. package/src/config/seed-inference-profiles.ts +14 -5
  179. package/src/config/skills.ts +27 -5
  180. package/src/contacts/__tests__/guardian-delivery-reader.test.ts +312 -0
  181. package/src/contacts/contacts-write.ts +3 -0
  182. package/src/contacts/guardian-delivery-reader.ts +223 -0
  183. package/src/daemon/conversation-agent-loop.ts +9 -0
  184. package/src/daemon/conversation-process.ts +39 -17
  185. package/src/daemon/conversation-surfaces.ts +8 -0
  186. package/src/daemon/conversation-tool-setup.ts +49 -16
  187. package/src/daemon/conversation.ts +21 -2
  188. package/src/daemon/disk-pressure-guard.ts +12 -2
  189. package/src/daemon/event-loop-watchdog.ts +28 -1
  190. package/src/daemon/external-plugins-bootstrap.ts +4 -34
  191. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +25 -0
  192. package/src/daemon/handlers/__tests__/config-channels.test.ts +225 -0
  193. package/src/daemon/handlers/config-a2a.ts +6 -14
  194. package/src/daemon/handlers/config-channels.ts +78 -22
  195. package/src/daemon/handlers/conversations.ts +77 -0
  196. package/src/daemon/host-cu-proxy.ts +102 -11
  197. package/src/daemon/lifecycle.ts +4 -0
  198. package/src/daemon/memory-v2-startup.test.ts +72 -0
  199. package/src/daemon/memory-v2-startup.ts +87 -19
  200. package/src/daemon/server.ts +0 -4
  201. package/src/daemon/shutdown-handlers.ts +20 -0
  202. package/src/daemon/tool-setup-types.ts +9 -0
  203. package/src/ipc/__tests__/clients-list-ipc.test.ts +1 -1
  204. package/src/ipc/assistant-server.ts +2 -2
  205. package/src/memory/__tests__/301-create-watchdog-events.test.ts +110 -0
  206. package/src/memory/__tests__/memory-retrospective-job.test.ts +8 -0
  207. package/src/memory/__tests__/prompt-override.test.ts +192 -0
  208. package/src/memory/__tests__/watchdog-events-store.test.ts +161 -0
  209. package/src/memory/conversation-crud.ts +38 -0
  210. package/src/memory/db-connection.ts +22 -3
  211. package/src/memory/db-init.ts +36 -502
  212. package/src/memory/db-singleton.ts +6 -4
  213. package/src/memory/jobs-worker.ts +58 -0
  214. package/src/memory/llm-usage-store.ts +48 -20
  215. package/src/memory/memory-retrospective-job.ts +9 -8
  216. package/src/memory/migrations/014-backfill-inbox-thread-state.ts +13 -3
  217. package/src/memory/migrations/136-drop-assistant-id-columns.ts +52 -27
  218. package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +130 -56
  219. package/src/memory/migrations/300-add-processing-started-at.ts +30 -0
  220. package/src/memory/migrations/301-create-watchdog-events.ts +45 -0
  221. package/src/memory/migrations/__tests__/014-backfill-inbox-thread-state.test.ts +108 -0
  222. package/src/memory/migrations/__tests__/136-drop-assistant-id-columns.test.ts +82 -0
  223. package/src/memory/migrations/__tests__/209-strip-thinking-from-consolidated.test.ts +224 -0
  224. package/src/memory/migrations/__tests__/run-migrations.test.ts +2 -2
  225. package/src/memory/migrations/run-migrations.ts +90 -6
  226. package/src/memory/migrations/schema-introspection.ts +14 -0
  227. package/src/memory/migrations/validate-migration-state.ts +101 -66
  228. package/src/memory/prompt-override.ts +129 -0
  229. package/src/memory/schema/conversations.ts +9 -0
  230. package/src/memory/schema/infrastructure.ts +20 -0
  231. package/src/memory/steps.ts +573 -0
  232. package/src/memory/v2/__tests__/cli-command-store.test.ts +25 -0
  233. package/src/memory/v2/__tests__/skill-store.test.ts +80 -0
  234. package/src/memory/v2/cli-command-store.ts +75 -38
  235. package/src/memory/v2/prompts/consolidation.ts +13 -82
  236. package/src/memory/v2/prompts/router.ts +21 -93
  237. package/src/memory/v2/skill-store.ts +68 -31
  238. package/src/memory/watchdog-events-store.ts +87 -0
  239. package/src/memory/worker-control.ts +118 -0
  240. package/src/memory/worker-process.ts +72 -0
  241. package/src/notifications/__tests__/broadcaster.test.ts +16 -8
  242. package/src/notifications/__tests__/connected-channels.test.ts +114 -0
  243. package/src/notifications/__tests__/decision-engine.test.ts +78 -9
  244. package/src/notifications/__tests__/destination-resolver.test.ts +256 -0
  245. package/src/notifications/broadcaster.ts +8 -1
  246. package/src/notifications/decision-engine.ts +15 -7
  247. package/src/notifications/destination-resolver.ts +68 -24
  248. package/src/notifications/emit-signal.ts +39 -14
  249. package/src/onboarding/checkin-event.test.ts +220 -0
  250. package/src/onboarding/checkin-event.ts +321 -0
  251. package/src/onboarding/schedule-checkin.ts +190 -0
  252. package/src/permissions/question-prompter.test.ts +1 -1
  253. package/src/permissions/question-prompter.ts +7 -4
  254. package/src/plugin-api/index.ts +6 -6
  255. package/src/plugin-api/types.ts +3 -5
  256. package/src/plugin-api/vision-support.test.ts +28 -4
  257. package/src/plugin-api/vision-support.ts +66 -31
  258. package/src/plugins/defaults/advisor/__tests__/consult.test.ts +161 -0
  259. package/src/plugins/defaults/advisor/__tests__/context-pack-gating.test.ts +106 -0
  260. package/src/plugins/defaults/advisor/__tests__/context-pack.test.ts +60 -0
  261. package/src/plugins/defaults/advisor/consult.ts +110 -6
  262. package/src/plugins/defaults/advisor/context-pack.ts +288 -0
  263. package/src/plugins/defaults/advisor/steering.ts +14 -2
  264. package/src/plugins/defaults/advisor/tools/advisor.ts +32 -5
  265. package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +47 -7
  266. package/src/plugins/defaults/image-fallback/hooks/post-tool-use.ts +10 -11
  267. package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +12 -20
  268. package/src/plugins/defaults/image-fallback/src/caption-blocks.ts +42 -11
  269. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +11 -2
  270. package/src/plugins/defaults/memory-v3-shadow/pool-select.test.ts +146 -0
  271. package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +29 -1
  272. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +8 -1
  273. package/src/plugins/mtime-cache.ts +7 -2
  274. package/src/plugins/types.ts +0 -2
  275. package/src/providers/anthropic/client.ts +5 -0
  276. package/src/providers/call-site-routing.ts +4 -0
  277. package/src/providers/model-catalog.ts +16 -0
  278. package/src/providers/openai/responses-provider.ts +5 -0
  279. package/src/providers/openrouter/client.ts +5 -0
  280. package/src/providers/provider-send-message.ts +4 -0
  281. package/src/providers/ratelimit.ts +4 -0
  282. package/src/providers/retry.ts +4 -0
  283. package/src/providers/types.ts +9 -0
  284. package/src/providers/usage-tracking.ts +4 -0
  285. package/src/runtime/__tests__/channel-verification-service.test.ts +133 -0
  286. package/src/runtime/__tests__/guardian-vellum-migration.test.ts +181 -0
  287. package/src/runtime/__tests__/is-guardian-bound-for-channel.test.ts +66 -0
  288. package/src/runtime/__tests__/local-principal-trust.test.ts +164 -0
  289. package/src/runtime/__tests__/trust-verdict-consumer.test.ts +335 -3
  290. package/src/runtime/access-request-helper.ts +19 -39
  291. package/src/runtime/actor-trust-resolver.ts +2 -2
  292. package/src/runtime/anchored-guardian.test.ts +156 -0
  293. package/src/runtime/anchored-guardian.ts +135 -0
  294. package/src/runtime/assistant-event-hub.ts +1 -1
  295. package/src/runtime/assistant-stream-state.ts +9 -2
  296. package/src/runtime/auth/__tests__/require-bound-guardian.test.ts +99 -0
  297. package/src/runtime/auth/require-bound-guardian.ts +21 -11
  298. package/src/runtime/channel-verification-service.ts +56 -31
  299. package/src/runtime/confirmation-request-guardian-bridge.ts +3 -3
  300. package/src/runtime/guardian-vellum-migration.ts +66 -7
  301. package/src/runtime/invite-redemption-service.ts +50 -18
  302. package/src/runtime/local-actor-identity.ts +76 -11
  303. package/src/runtime/local-principal-trust.ts +52 -0
  304. package/src/runtime/pending-interactions.ts +11 -1
  305. package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +56 -5
  306. package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
  307. package/src/runtime/routes/__tests__/contact-routes.test.ts +212 -0
  308. package/src/runtime/routes/__tests__/global-search-routes.test.ts +93 -0
  309. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +215 -1
  310. package/src/runtime/routes/browser-routes.ts +1 -1
  311. package/src/runtime/routes/channel-verification-routes.ts +3 -3
  312. package/src/runtime/routes/contact-routes.ts +8 -32
  313. package/src/runtime/routes/conversation-cli-routes.ts +4 -5
  314. package/src/runtime/routes/conversation-list-routes.ts +4 -7
  315. package/src/runtime/routes/conversation-routes.ts +74 -81
  316. package/src/runtime/routes/events-routes.ts +2 -2
  317. package/src/runtime/routes/global-search-routes.ts +3 -1
  318. package/src/runtime/routes/guardian-action-routes.ts +4 -5
  319. package/src/runtime/routes/host-app-control-routes.ts +5 -4
  320. package/src/runtime/routes/host-bash-routes.ts +5 -4
  321. package/src/runtime/routes/host-browser-routes.ts +9 -11
  322. package/src/runtime/routes/host-cu-routes.ts +5 -4
  323. package/src/runtime/routes/host-file-routes.ts +5 -4
  324. package/src/runtime/routes/host-transfer-routes.ts +6 -6
  325. package/src/runtime/routes/http-adapter.ts +1 -1
  326. package/src/runtime/routes/identity-routes.ts +3 -2
  327. package/src/runtime/routes/inbound-message-handler.ts +5 -5
  328. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +97 -5
  329. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +61 -49
  330. package/src/runtime/routes/inbound-stages/background-dispatch.ts +16 -4
  331. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +7 -7
  332. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +21 -8
  333. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +14 -3
  334. package/src/runtime/routes/index.ts +2 -0
  335. package/src/runtime/routes/llm-context-normalization.ts +71 -0
  336. package/src/runtime/routes/mcp-auth-routes.ts +38 -15
  337. package/src/runtime/routes/migration-rollback-routes.ts +4 -3
  338. package/src/runtime/routes/migration-routes.ts +4 -1
  339. package/src/runtime/routes/onboarding-checkin-routes.ts +86 -0
  340. package/src/runtime/routes/subagents-routes.ts +5 -0
  341. package/src/runtime/routes/surface-action-routes.ts +51 -55
  342. package/src/runtime/services/__tests__/conversation-serializer.test.ts +1 -0
  343. package/src/runtime/services/conversation-serializer.ts +7 -9
  344. package/src/runtime/tool-grant-request-helper.ts +3 -3
  345. package/src/runtime/trust-verdict-consumer.ts +85 -9
  346. package/src/runtime/verification-outbound-actions.ts +18 -18
  347. package/src/signals/user-message.ts +16 -0
  348. package/src/subagent/manager.ts +9 -0
  349. package/src/telemetry/types.ts +34 -1
  350. package/src/telemetry/usage-telemetry-reporter.test.ts +3 -2
  351. package/src/telemetry/usage-telemetry-reporter.ts +87 -3
  352. package/src/tools/ask-question/ask-question-tool.test.ts +29 -0
  353. package/src/tools/ask-question/ask-question-tool.ts +13 -0
  354. package/src/tools/computer-use/definitions.ts +8 -2
  355. package/src/tools/executor.ts +4 -4
  356. package/src/tools/registry.ts +18 -0
  357. package/src/tools/tool-approval-handler.ts +1 -1
  358. package/src/tools/tool-defaults.ts +9 -2
  359. package/src/tools/types.ts +17 -2
  360. package/src/tools/workspace-tools/loader.ts +348 -244
  361. package/src/util/platform.ts +5 -0
  362. package/src/util/telemetry-db-path.ts +24 -0
  363. package/src/workspace/migrations/017-seed-persona-dirs.ts +3 -34
  364. package/src/workspace/migrations/019-scope-journal-to-guardian.ts +3 -24
  365. package/src/__tests__/workspace-tools-watcher-flag.test.ts +0 -70
  366. package/src/daemon/workspace-tools-watcher.ts +0 -328
  367. package/src/memory/migrations/registry.ts +0 -573
@@ -3,17 +3,25 @@ import { getLogger } from "../../util/logger.js";
3
3
  import { getDbPath } from "../../util/platform.js";
4
4
  import { type DrizzleDb, getSqliteFrom } from "../db-connection.js";
5
5
  import {
6
- MIGRATION_REGISTRY,
7
- type MigrationValidationResult,
8
- } from "./registry.js";
9
- import {
6
+ getStepName,
7
+ type MigrationStep,
8
+ normalizeStep,
10
9
  STEP_CHECKPOINT_PREFIX,
11
10
  } from "./run-migrations.js";
12
11
 
13
12
  const log = getLogger("memory-db");
14
13
 
14
+ export interface MigrationValidationResult {
15
+ /** Keys of migrations whose checkpoint has value 'started' — started but never completed. */
16
+ crashed: string[];
17
+ /** Pairs where a completed migration's declared prerequisite is missing from checkpoints. */
18
+ dependencyViolations: Array<{ migration: string; missingDependency: string }>;
19
+ /** Checkpoint keys present in the database but absent from the known step names — likely from a newer version. */
20
+ unknownCheckpoints: string[];
21
+ }
22
+
15
23
  /**
16
- * Validate the applied migration state against the registry at startup.
24
+ * Validate the applied migration state against the known step list at startup.
17
25
  *
18
26
  * Logs a prominent error when a migration started but never completed (crash
19
27
  * detected) — startup continues so the migration can be retried.
@@ -25,9 +33,15 @@ const log = getLogger("memory-db");
25
33
  *
26
34
  * Call this AFTER all DDL and migration functions have run so that the final
27
35
  * state is inspected.
36
+ *
37
+ * @param database The Drizzle database instance.
38
+ * @param steps The full ordered migration step array (same one passed to
39
+ * `runMigrationSteps`). Used to determine known step names for unknown-checkpoint
40
+ * detection and to check `dependsOn` declarations.
28
41
  */
29
42
  export function validateMigrationState(
30
43
  database: DrizzleDb,
44
+ steps: MigrationStep[],
31
45
  ): MigrationValidationResult {
32
46
  const raw = getSqliteFrom(database);
33
47
 
@@ -64,8 +78,6 @@ export function validateMigrationState(
64
78
  }
65
79
 
66
80
  // Build a set of completed step names from `step:*` checkpoints with value '1'.
67
- // The step runner writes these — `migration_*` registry keys are no longer
68
- // written by migration functions (Phase 2 removed withCrashRecovery).
69
81
  const completedStepNames = new Set(
70
82
  rows
71
83
  .filter(
@@ -75,32 +87,24 @@ export function validateMigrationState(
75
87
  .map((r) => r.key.slice(STEP_CHECKPOINT_PREFIX.length)),
76
88
  );
77
89
 
78
- // Map registry entries to their step names to determine which migrations
79
- // are completed. Multiple registry entries can share the same step name
80
- // (e.g., 162's two entries both map to migrateGuardianTimestampsEpochMs).
81
- const completed = new Set<string>();
82
- for (const entry of MIGRATION_REGISTRY) {
83
- if (completedStepNames.has(entry.stepName)) {
84
- completed.add(entry.key);
85
- }
86
- }
87
-
90
+ // Check dependency ordering for object-form steps that declare dependsOn.
91
+ // A step is "completed" if its name appears in the completedStepNames set.
88
92
  const dependencyViolations: Array<{
89
93
  migration: string;
90
94
  missingDependency: string;
91
95
  }> = [];
92
96
 
93
- // Validate dependency ordering.
94
- for (const entry of MIGRATION_REGISTRY) {
95
- if (!entry.dependsOn || entry.dependsOn.length === 0) continue;
96
- // Only check entries that have been completed — unapplied or in-progress
97
+ for (const step of steps) {
98
+ const obj = normalizeStep(step);
99
+ if (!obj.dependsOn || obj.dependsOn.length === 0) continue;
100
+ // Only check steps that have been completed — unapplied or in-progress
97
101
  // migrations have not had a chance to violate their prerequisites yet.
98
- if (!completed.has(entry.key)) continue;
102
+ if (!completedStepNames.has(obj.name)) continue;
99
103
 
100
- for (const dep of entry.dependsOn) {
101
- if (!completed.has(dep)) {
104
+ for (const dep of obj.dependsOn) {
105
+ if (!completedStepNames.has(dep)) {
102
106
  dependencyViolations.push({
103
- migration: entry.key,
107
+ migration: obj.name,
104
108
  missingDependency: dep,
105
109
  });
106
110
  }
@@ -121,10 +125,11 @@ export function validateMigrationState(
121
125
  }
122
126
 
123
127
  // Detect step checkpoints that exist in the database but have no
124
- // corresponding registry entry — these are from a newer version of the daemon.
125
- const registryStepNames = new Set(MIGRATION_REGISTRY.map((e) => e.stepName));
128
+ // corresponding entry in the known step list — these are from a newer
129
+ // version of the daemon.
130
+ const knownStepNames = new Set(steps.map((s) => getStepName(s)));
126
131
  const unknownCheckpoints = [...completedStepNames].filter(
127
- (name) => !registryStepNames.has(name),
132
+ (name) => !knownStepNames.has(name),
128
133
  );
129
134
 
130
135
  if (unknownCheckpoints.length > 0) {
@@ -140,23 +145,26 @@ export function validateMigrationState(
140
145
  /**
141
146
  * Roll back all completed memory (database) migrations with version > targetVersion.
142
147
  *
143
- * Iterates eligible migrations in reverse version order. For each:
144
- * 1. Marks the checkpoint as `"rolling_back"` for crash recovery.
148
+ * Iterates eligible migration steps in reverse version order. For each
149
+ * rollback entry on a completed step:
150
+ * 1. Marks the step checkpoint as `"rolling_back"` for crash recovery.
145
151
  * 2. Calls `entry.down(database)` — each down() manages its own transactions.
146
- * (`down` is required on `MigrationRegistryEntry` at the type level.)
147
- * 3. Deletes the checkpoint from `memory_checkpoints`.
152
+ * 3. Deletes the step checkpoint from `memory_checkpoints`.
153
+ *
154
+ * A single step may carry multiple rollback entries (e.g. migration 162 has
155
+ * two). All entries with version > target are rolled back in reverse version
156
+ * order. The step checkpoint is only deleted after the last rollback entry
157
+ * for that step completes.
148
158
  *
149
159
  * **Usage**: Pass the target version number you want to roll back *to*. All
150
- * migrations with a higher version number that have been applied will be
151
- * reversed. For example, `rollbackMemoryMigration(db, 5)` rolls back all
152
- * applied migrations with version > 5.
160
+ * rollback entries with a higher version number on completed steps will be
161
+ * reversed. For example, `rollbackMemoryMigration(db, 5, steps)` rolls back
162
+ * all rollback entries with version > 5.
153
163
  *
154
- * **Checkpoint state**: Each rolled-back migration's checkpoint is deleted
155
- * from `memory_checkpoints`. If the process crashes mid-rollback, the
156
- * `"rolling_back"` marker is detected and cleared by
157
- * `recoverCrashedMigrations` on the next startup. The forward-step checkpoints
158
- * recorded by the migration runner (the `step:` namespace) for the rolled-back
159
- * entries are also discarded so a later upgrade re-applies them.
164
+ * **Checkpoint state**: Each rolled-back step's `step:*` checkpoint is deleted
165
+ * from `memory_checkpoints` after its down() functions succeed. If the process
166
+ * crashes mid-rollback, the `"rolling_back"` marker is detected and cleared by
167
+ * `recoverCrashedMigrations` on the next startup.
160
168
  *
161
169
  * **Warning — data loss**: Some down() migrations may not fully restore the
162
170
  * original state (e.g., DROP TABLE migrations recreate the table but cannot
@@ -168,13 +176,15 @@ export function validateMigrationState(
168
176
  * query failures, or data corruption.
169
177
  *
170
178
  * @param database The Drizzle database instance.
171
- * @param targetVersion Roll back to this version (exclusive — all migrations
172
- * with version > targetVersion are reversed).
173
- * @returns The list of rolled-back migration keys.
179
+ * @param targetVersion Roll back to this version (exclusive — all rollback
180
+ * entries with version > targetVersion are reversed).
181
+ * @param steps The full ordered migration step array.
182
+ * @returns The list of rolled-back step names.
174
183
  */
175
184
  export function rollbackMemoryMigration(
176
185
  database: DrizzleDb,
177
186
  targetVersion: number,
187
+ steps: MigrationStep[],
178
188
  ): string[] {
179
189
  const raw = getSqliteFrom(database);
180
190
 
@@ -198,41 +208,66 @@ export function rollbackMemoryMigration(
198
208
  .map((r) => r.key.slice(STEP_CHECKPOINT_PREFIX.length)),
199
209
  );
200
210
 
201
- // Find registry entries with version > targetVersion whose step is completed.
202
- // Deduplicate by stepName multiple registry entries can share the same step
203
- // (e.g., 162's two entries), and we only need to clear the step checkpoint once.
204
- const toRollback = MIGRATION_REGISTRY.filter(
205
- (entry) =>
206
- entry.version > targetVersion &&
207
- completedStepNames.has(entry.stepName),
208
- ).sort((a, b) => b.version - a.version); // reverse version order
211
+ // Collect all rollback entries with version > targetVersion on completed steps.
212
+ // Each entry references its parent step name so we can clear the checkpoint
213
+ // after all rollback entries for that step have been executed.
214
+ interface RollbackItem {
215
+ stepName: string;
216
+ version: number;
217
+ description: string;
218
+ down: (db: DrizzleDb) => void;
219
+ }
220
+
221
+ const toRollback: RollbackItem[] = [];
222
+ for (const step of steps) {
223
+ const obj = normalizeStep(step);
224
+ if (!obj.rollback) continue;
225
+ if (!completedStepNames.has(obj.name)) continue;
209
226
 
227
+ for (const entry of obj.rollback) {
228
+ if (entry.version > targetVersion) {
229
+ toRollback.push({
230
+ stepName: obj.name,
231
+ version: entry.version,
232
+ description: entry.description,
233
+ down: entry.down,
234
+ });
235
+ }
236
+ }
237
+ }
238
+
239
+ // Sort in reverse version order — children (higher version) before parents.
240
+ toRollback.sort((a, b) => b.version - a.version);
241
+
242
+ // Group by stepName so we only delete the checkpoint after all rollback
243
+ // entries for that step have been executed.
244
+ const stepNamesToRollback = new Set(toRollback.map((r) => r.stepName));
210
245
  const rolledBack: string[] = [];
211
246
 
212
- for (const entry of toRollback) {
213
- const stepKey = `${STEP_CHECKPOINT_PREFIX}${entry.stepName}`;
247
+ for (const item of toRollback) {
248
+ const stepKey = `${STEP_CHECKPOINT_PREFIX}${item.stepName}`;
214
249
 
215
- // Mark as rolling_back for crash recovery — if the process crashes here,
216
- // recoverCrashedMigrations will clear this checkpoint on next startup.
250
+ // Mark as rolling_back for crash recovery.
217
251
  raw
218
252
  .query(
219
253
  `INSERT OR REPLACE INTO memory_checkpoints (key, value, updated_at) VALUES (?, 'rolling_back', ?)`,
220
254
  )
221
255
  .run(stepKey, Date.now());
222
256
 
223
- // Execute the down migration — let it manage its own transaction lifecycle.
224
- // Many down() functions call BEGIN/COMMIT internally or use PRAGMA statements
225
- // that are no-ops inside a transaction.
226
- entry.down(database);
227
-
228
- // Delete the step checkpoint after down() succeeds.
229
- raw.query(`DELETE FROM memory_checkpoints WHERE key = ?`).run(stepKey);
257
+ // Execute the down migration.
258
+ item.down(database);
230
259
 
231
260
  log.info(
232
- { key: entry.key, version: entry.version },
233
- `Rolled back migration "${entry.key}" (version ${entry.version})`,
261
+ { step: item.stepName, version: item.version, description: item.description },
262
+ `Rolled back migration "${item.stepName}" (version ${item.version})`,
234
263
  );
235
- rolledBack.push(entry.key);
264
+ }
265
+
266
+ // After all down() calls succeed, delete checkpoints for the rolled-back steps.
267
+ for (const stepName of stepNamesToRollback) {
268
+ const stepKey = `${STEP_CHECKPOINT_PREFIX}${stepName}`;
269
+ raw.query(`DELETE FROM memory_checkpoints WHERE key = ?`).run(stepKey);
270
+ rolledBack.push(stepName);
236
271
  }
237
272
 
238
273
  return rolledBack;
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Shared loader for file-based prompt overrides.
3
+ *
4
+ * The memory router, consolidation, and v3 selector prompts each ship a bundled
5
+ * default that operators may replace by pointing a config field at a file. The
6
+ * load-with-fallback semantics are identical across all three, so they live
7
+ * here: path resolution, the size guard, and the permissive fallback that keeps
8
+ * retrieval/consolidation working when an override is missing or malformed.
9
+ *
10
+ * The caller owns the bundled default and any placeholder substitution — this
11
+ * module only decides whether a usable override file exists and returns its raw
12
+ * contents, or `null` to mean "fall back to the bundled prompt."
13
+ */
14
+
15
+ import { lstatSync, readFileSync } from "node:fs";
16
+ import { homedir } from "node:os";
17
+ import { isAbsolute, join } from "node:path";
18
+
19
+ /**
20
+ * Minimal logger surface the loader needs. Structurally compatible with
21
+ * `pino.Logger`, so callers pass their module logger directly and the warnings
22
+ * keep that logger's namespace; tests pass a lightweight recorder.
23
+ */
24
+ export interface PromptOverrideLogger {
25
+ warn(obj: object, msg: string): void;
26
+ }
27
+
28
+ /**
29
+ * Hard upper bound on an override file. The bundled prompts are kilobytes; 1 MiB
30
+ * is generous headroom for a hand-edit while preventing a `settings.write`
31
+ * principal from pointing the field at a giant file (or an unsizeable stream
32
+ * `lstat` can't cap on its own) and slurping it into memory on every call.
33
+ */
34
+ export const MAX_PROMPT_OVERRIDE_BYTES = 1 * 1024 * 1024;
35
+
36
+ /**
37
+ * Resolve a configured override path to an absolute path: a leading `~/` expands
38
+ * to the home directory, an absolute path is used as-is, and a relative path
39
+ * resolves under `workspaceDir`.
40
+ */
41
+ export function resolveOverridePath(
42
+ overridePath: string,
43
+ workspaceDir: string,
44
+ ): string {
45
+ if (overridePath.startsWith("~/")) {
46
+ return join(homedir(), overridePath.slice(2));
47
+ }
48
+ if (isAbsolute(overridePath)) return overridePath;
49
+ return join(workspaceDir, overridePath);
50
+ }
51
+
52
+ /**
53
+ * Load a prompt-override file, returning its raw contents when the override is
54
+ * present and usable, or `null` (after logging a warning describing why) when
55
+ * the caller should fall back to its bundled prompt. A nullish `overridePath`
56
+ * (`null` or `undefined`) returns `null` without touching the filesystem.
57
+ *
58
+ * Fallback is intentionally total — an absent override, a missing, non-regular,
59
+ * oversized, unreadable, or empty/whitespace-only file all degrade to `null`.
60
+ * Memory retrieval and consolidation must never break because of a bad
61
+ * override, so `undefined` (an unset config field) is treated as "no override"
62
+ * rather than crashing on path resolution.
63
+ *
64
+ * `label` names the prompt in the warning messages (e.g. `"router prompt"`).
65
+ */
66
+ export function loadPromptOverride(opts: {
67
+ overridePath: string | null | undefined;
68
+ workspaceDir: string;
69
+ log: PromptOverrideLogger;
70
+ label: string;
71
+ }): string | null {
72
+ const { overridePath, workspaceDir, log, label } = opts;
73
+ if (overridePath == null) return null;
74
+
75
+ const resolvedPath = resolveOverridePath(overridePath, workspaceDir);
76
+ let contents: string;
77
+ try {
78
+ const stat = lstatSync(resolvedPath);
79
+ if (!stat.isFile()) {
80
+ log.warn(
81
+ {
82
+ configuredPath: overridePath,
83
+ resolvedPath,
84
+ reason: "not_regular_file",
85
+ fallback: "bundled",
86
+ },
87
+ `${label} override is not a regular file; using bundled prompt`,
88
+ );
89
+ return null;
90
+ }
91
+ if (stat.size > MAX_PROMPT_OVERRIDE_BYTES) {
92
+ log.warn(
93
+ {
94
+ configuredPath: overridePath,
95
+ resolvedPath,
96
+ size: stat.size,
97
+ limit: MAX_PROMPT_OVERRIDE_BYTES,
98
+ reason: "oversized_override",
99
+ fallback: "bundled",
100
+ },
101
+ `${label} override exceeds size limit; using bundled prompt`,
102
+ );
103
+ return null;
104
+ }
105
+ contents = readFileSync(resolvedPath, "utf-8");
106
+ } catch (err) {
107
+ const code = (err as NodeJS.ErrnoException).code;
108
+ log.warn(
109
+ { configuredPath: overridePath, resolvedPath, code, fallback: "bundled" },
110
+ `${label} override unreadable; using bundled prompt`,
111
+ );
112
+ return null;
113
+ }
114
+
115
+ if (contents.trim().length === 0) {
116
+ log.warn(
117
+ {
118
+ configuredPath: overridePath,
119
+ resolvedPath,
120
+ reason: "empty_override",
121
+ fallback: "bundled",
122
+ },
123
+ `${label} override is empty; using bundled prompt`,
124
+ );
125
+ return null;
126
+ }
127
+
128
+ return contents;
129
+ }
@@ -52,6 +52,15 @@ export const conversations = sqliteTable(
52
52
  inferenceProfileSessionId: text("inference_profile_session_id"),
53
53
  inferenceProfileExpiresAt: integer("inference_profile_expires_at"),
54
54
  lastNotifiedInferenceProfile: text("last_notified_inference_profile"),
55
+ /**
56
+ * Epoch-ms timestamp set when the agent loop starts a turn for this
57
+ * conversation, cleared (NULL) when the turn ends. NULL means not
58
+ * processing. This is the cross-process source of truth for processing
59
+ * state — the in-memory `Conversation._processing` flag is the hot-path
60
+ * read for resident conversations, but CLI-side and other out-of-process
61
+ * callers read this column directly.
62
+ */
63
+ processingStartedAt: integer("processing_started_at"),
55
64
  },
56
65
  (table) => [
57
66
  index("idx_conversations_updated_at").on(table.updatedAt),
@@ -337,6 +337,26 @@ export const skillLoadedEvents = sqliteTable(
337
337
  ],
338
338
  );
339
339
 
340
+ // One row per `watchdog` telemetry event, emitted when a daemon watchdog
341
+ // check fires (event-loop block, stream-idle stall, restart, ...) — see
342
+ // watchdog-events-store.ts for the data contract. Flushed by the usage
343
+ // telemetry reporter. `value` is a REAL (BQ FLOAT) so the daemon need not
344
+ // distinguish int vs float; the platform serializer coerces ints to float.
345
+ // `detail` is a JSON bag stored as text and forwarded verbatim.
346
+ export const watchdogEvents = sqliteTable(
347
+ "watchdog_events",
348
+ {
349
+ id: text("id").primaryKey(),
350
+ createdAt: integer("created_at").notNull(),
351
+ checkName: text("check_name").notNull(),
352
+ value: real("value"),
353
+ detail: text("detail"),
354
+ },
355
+ (table) => [
356
+ index("idx_watchdog_events_created_at_id").on(table.createdAt, table.id),
357
+ ],
358
+ );
359
+
340
360
  export const traceEvents = sqliteTable(
341
361
  "trace_events",
342
362
  {