@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
@@ -93,7 +93,6 @@ import {
93
93
  memoryV2ConsolidateJob,
94
94
  } from "./v2/consolidation-job.js";
95
95
  import { memoryV2SweepJob } from "./v2/sweep-job.js";
96
- import { spawnMemoryWorkerProcess } from "./worker-control.js";
97
96
 
98
97
  const log = getLogger("memory-jobs-worker");
99
98
 
@@ -162,64 +161,7 @@ export interface MemoryJobsWorker {
162
161
  stop(): void;
163
162
  }
164
163
 
165
- /**
166
- * Start the memory jobs worker using the configured implementation.
167
- *
168
- * `memory.worker.enabled` selects between two implementations:
169
- * - enabled: spawn the worker as a separate OS process (the same path as
170
- * `assistant memory worker start`), keeping long-running jobs off the
171
- * caller's event loop.
172
- * - disabled (default): run the worker in-process on the caller's event
173
- * loop.
174
- *
175
- * The flag is read here so callers don't branch on it themselves. It only
176
- * governs which implementation starts; shutdown stops whichever worker is
177
- * actually running (see daemon/shutdown-handlers.ts), so the handle returned
178
- * for the out-of-process implementation has a no-op `stop()`.
179
- *
180
- * This dispatcher must not be used as the standalone worker process's entry —
181
- * that would recurse and fork-bomb. `worker-process.ts` calls
182
- * {@link startInProcessMemoryJobsWorker} directly.
183
- */
184
164
  export function startMemoryJobsWorker(): MemoryJobsWorker {
185
- if (getConfig().memory.worker?.enabled === true) {
186
- void spawnMemoryWorkerProcess()
187
- .then(({ pid, alreadyRunning }) =>
188
- log.info(
189
- { pid, alreadyRunning },
190
- alreadyRunning
191
- ? "Memory worker process already running — reusing it"
192
- : "Memory worker process started",
193
- ),
194
- )
195
- .catch((err) =>
196
- log.warn(
197
- { err },
198
- "Failed to start memory worker process — memory jobs will not be processed",
199
- ),
200
- );
201
- return {
202
- async runOnce(): Promise<number> {
203
- return 0;
204
- },
205
- // No-op: shutdown always stops the worker process via the live-state
206
- // PID probe in daemon/shutdown-handlers.ts, since it can't know whether
207
- // the process was started here or out of band (e.g. `assistant memory
208
- // worker start`) after boot.
209
- stop(): void {},
210
- };
211
- }
212
-
213
- return startInProcessMemoryJobsWorker();
214
- }
215
-
216
- /**
217
- * Run the memory jobs worker in-process on the caller's event loop: poll for
218
- * claimable jobs with adaptive backoff until {@link MemoryJobsWorker.stop} is
219
- * called. This is the worker loop itself — used directly by the daemon (when
220
- * `memory.worker.enabled` is off) and by the standalone worker process.
221
- */
222
- export function startInProcessMemoryJobsWorker(): MemoryJobsWorker {
223
165
  const recovered = resetRunningJobsToPending();
224
166
  if (recovered > 0) {
225
167
  log.info({ recovered }, "Recovered stale running memory jobs");
@@ -94,21 +94,14 @@ export type CompactionAgentLogRow = LogMetaRow & {
94
94
  * can either stringify it directly (daemon-path `recordRequestLog`) or
95
95
  * store it on a pending-log queue that stringifies later (wake-path
96
96
  * `PendingLog.rawResponse`), without double-encoding.
97
- *
98
- * When the provider captured the verbatim upstream body, it is attached as a
99
- * top-level `rawResponse` sibling so the inspector's Raw tab can show the
100
- * actual provider payload (parsed JSON, or the raw string for non-JSON error
101
- * pages) — matching the success path, where Raw shows the real provider JSON.
102
97
  */
103
98
  export function buildProviderErrorResponsePayload(err: Error): {
104
99
  error: Record<string, unknown>;
105
- rawResponse?: unknown;
106
100
  } {
107
101
  const payload: Record<string, unknown> = {
108
102
  name: err.name,
109
103
  message: err.message,
110
104
  };
111
- let rawResponse: unknown;
112
105
  if (err instanceof ProviderError) {
113
106
  payload.code = err.code;
114
107
  payload.provider = err.provider;
@@ -118,28 +111,10 @@ export function buildProviderErrorResponsePayload(err: Error): {
118
111
  if (err.retryAfterMs !== undefined) {
119
112
  payload.retryAfterMs = err.retryAfterMs;
120
113
  }
121
- if (err.apiErrorCode !== undefined) payload.apiErrorCode = err.apiErrorCode;
122
- if (err.apiErrorType !== undefined) payload.apiErrorType = err.apiErrorType;
123
- if (err.apiErrorParam !== undefined)
124
- payload.apiErrorParam = err.apiErrorParam;
125
- if (err.requestId !== undefined) payload.requestId = err.requestId;
126
- if (err.rawBody !== undefined) rawResponse = parseRawBody(err.rawBody);
127
114
  } else if (err instanceof AssistantError) {
128
115
  payload.code = err.code;
129
116
  }
130
- return rawResponse !== undefined
131
- ? { error: payload, rawResponse }
132
- : { error: payload };
133
- }
134
-
135
- /** Parse a captured upstream body as JSON, falling back to the raw string for
136
- * non-JSON error pages (HTML, plain text) or a truncated/invalid prefix. */
137
- function parseRawBody(rawBody: string): unknown {
138
- try {
139
- return JSON.parse(rawBody);
140
- } catch {
141
- return rawBody;
142
- }
117
+ return { error: payload };
143
118
  }
144
119
 
145
120
  export function recordRequestLog(
@@ -525,32 +525,7 @@ export function getUsageTotals(
525
525
  };
526
526
  }
527
527
 
528
- /**
529
- * Width of the SQL pre-aggregation bucket used by the time-series read paths,
530
- * in milliseconds. The series/daily endpoints bucket events into local-day or
531
- * local-hour buckets in JavaScript (SQLite's `strftime` is UTC-only and can't
532
- * honor an IANA timezone). To avoid materializing one JS object per usage event
533
- * — which on a 90-day window can mean hundreds of thousands of rows on the
534
- * daemon's main thread — we first roll events up in SQL into fixed UTC buckets,
535
- * then feed those far-fewer rows into the same JS bucketing logic.
536
- *
537
- * 15 minutes is the finest quantum every real-world IANA UTC offset divides
538
- * into (whole-hour offsets, plus the :30 and :45 zones like Asia/Kolkata and
539
- * Asia/Kathmandu). Because every local-day and local-hour boundary therefore
540
- * lands on a 15-minute UTC boundary, no pre-aggregation bucket can straddle a
541
- * local bucket boundary — so rolling up to 15-minute UTC buckets and then
542
- * re-bucketing in local time is exactly equal to bucketing each raw event.
543
- * DST fall-back hours stay distinct because their instants fall in different
544
- * 15-minute UTC buckets (and the JS layer disambiguates them by UTC offset).
545
- */
546
- const USAGE_PREAGG_BUCKET_MS = 15 * 60 * 1000;
547
-
548
- /**
549
- * Fetch usage rows for a time range, pre-aggregated into {@link
550
- * USAGE_PREAGG_BUCKET_MS} UTC buckets, for in-memory local-time bucketing. Each
551
- * returned row's `created_at` is its UTC bucket start, which the JS bucketing
552
- * maps to the same local bucket every raw event in that window would map to.
553
- */
528
+ /** Fetch raw events in a time range for in-memory bucketing. */
554
529
  function fetchRawBucketRows(
555
530
  range: UsageTimeRange,
556
531
  filter?: UsageAggregationFilter,
@@ -559,14 +534,13 @@ function fetchRawBucketRows(
559
534
  return rawAll<UsageEventBucketRow>(
560
535
  /*sql*/ `
561
536
  SELECT
562
- (created_at / ${USAGE_PREAGG_BUCKET_MS}) * ${USAGE_PREAGG_BUCKET_MS} AS created_at,
563
- COALESCE(SUM(input_tokens), 0) AS input_tokens,
564
- COALESCE(SUM(output_tokens), 0) AS output_tokens,
565
- SUM(estimated_cost_usd) AS estimated_cost_usd,
566
- SUM(COALESCE(llm_call_count, 1)) AS llm_call_count
537
+ created_at,
538
+ input_tokens,
539
+ output_tokens,
540
+ estimated_cost_usd,
541
+ llm_call_count
567
542
  FROM llm_usage_events
568
543
  WHERE ${where.sql}
569
- GROUP BY (created_at / ${USAGE_PREAGG_BUCKET_MS})
570
544
  ORDER BY created_at ASC
571
545
  `,
572
546
  ...where.params,
@@ -855,18 +829,17 @@ export function getUsageGroupedSeries(
855
829
  WHERE ${where.sql}
856
830
  )
857
831
  SELECT
858
- (schedule_usage.created_at / ${USAGE_PREAGG_BUCKET_MS}) * ${USAGE_PREAGG_BUCKET_MS} AS created_at,
859
- COALESCE(SUM(schedule_usage.input_tokens), 0) AS input_tokens,
860
- COALESCE(SUM(schedule_usage.output_tokens), 0) AS output_tokens,
861
- SUM(schedule_usage.estimated_cost_usd) AS estimated_cost_usd,
862
- SUM(COALESCE(schedule_usage.llm_call_count, 1)) AS llm_call_count,
863
- schedule_usage.group_key AS group_key,
864
- MAX(schedule_group_jobs.name) AS group_label
832
+ schedule_usage.created_at,
833
+ schedule_usage.input_tokens,
834
+ schedule_usage.output_tokens,
835
+ schedule_usage.estimated_cost_usd,
836
+ schedule_usage.llm_call_count,
837
+ schedule_usage.group_key,
838
+ schedule_group_jobs.name AS group_label
865
839
  FROM schedule_usage
866
840
  LEFT JOIN cron_jobs schedule_group_jobs
867
841
  ON schedule_group_jobs.id = schedule_usage.group_key
868
- GROUP BY (schedule_usage.created_at / ${USAGE_PREAGG_BUCKET_MS}), schedule_usage.group_key
869
- ORDER BY created_at ASC
842
+ ORDER BY schedule_usage.created_at ASC
870
843
  `,
871
844
  ...groupKeySubquery.params,
872
845
  ...where.params,
@@ -877,16 +850,15 @@ export function getUsageGroupedSeries(
877
850
  rows = rawAll<UsageGroupedBucketRow>(
878
851
  /*sql*/ `
879
852
  SELECT
880
- (e.created_at / ${USAGE_PREAGG_BUCKET_MS}) * ${USAGE_PREAGG_BUCKET_MS} AS created_at,
881
- COALESCE(SUM(e.input_tokens), 0) AS input_tokens,
882
- COALESCE(SUM(e.output_tokens), 0) AS output_tokens,
883
- SUM(e.estimated_cost_usd) AS estimated_cost_usd,
884
- SUM(COALESCE(e.llm_call_count, 1)) AS llm_call_count,
853
+ e.created_at,
854
+ e.input_tokens,
855
+ e.output_tokens,
856
+ e.estimated_cost_usd,
857
+ e.llm_call_count,
885
858
  e.${column} AS group_key
886
859
  FROM llm_usage_events e
887
860
  WHERE ${where.sql}
888
- GROUP BY (e.created_at / ${USAGE_PREAGG_BUCKET_MS}), e.${column}
889
- ORDER BY created_at ASC
861
+ ORDER BY e.created_at ASC
890
862
  `,
891
863
  ...where.params,
892
864
  );
@@ -44,6 +44,7 @@ import {
44
44
  } from "../channels/types.js";
45
45
  import type { AssistantConfig } from "../config/types.js";
46
46
  import { extractTurnContextTimestamp } from "../context/compactor.js";
47
+ import { findConversation } from "../daemon/conversation-registry.js";
47
48
  import {
48
49
  formatLocalTimestamp,
49
50
  resolveTurnTimezoneContext,
@@ -62,7 +63,6 @@ import {
62
63
  forkConversationForRetrospective,
63
64
  getConversation,
64
65
  getMessagesAfter,
65
- isConversationProcessing,
66
66
  resolveOverrideProfile,
67
67
  } from "./conversation-crud.js";
68
68
  import {
@@ -145,15 +145,14 @@ export async function runForkBasedRetrospective(
145
145
 
146
146
  // Forking mid-turn would capture a half-finished display turn — incremental
147
147
  // checkpoint persistence writes complete tool turns to the DB while the
148
- // agent loop is still running. Check the persisted `processing_started_at`
149
- // column (the cross-process source of truth) instead of the in-memory
150
- // registry, so this guard works even when running in a separate CLI
151
- // process with an empty conversation registry. Bump `lastRunAt` so the
152
- // cooldown gate applies, leave `lastProcessedMessageId` untouched so the
153
- // next interval/message-count trigger re-processes the same messages —
154
- // nothing is lost. Returning (not throwing) keeps the jobs-worker from
148
+ // agent loop is still running. Peek the in-memory registry only (an
149
+ // unloaded conversation is by definition not processing); never load the
150
+ // conversation just to check. Bump `lastRunAt` so the cooldown gate
151
+ // applies, leave `lastProcessedMessageId` untouched so the next
152
+ // interval/message-count trigger re-processes the same messages nothing
153
+ // is lost. Returning (not throwing) keeps the jobs-worker from
155
154
  // retry-with-backoff.
156
- if (isConversationProcessing(sourceConversationId)) {
155
+ if (findConversation(sourceConversationId)?.isProcessing()) {
157
156
  bumpRetrospectiveLastRunAt(sourceConversationId, Date.now());
158
157
  log.info(
159
158
  { sourceConversationId },
@@ -1,86 +1,6 @@
1
- import { getLogger } from "../../util/logger.js";
2
- import { getDbPath } from "../../util/platform.js";
3
- import { runAsyncSqlite } from "../db-async-query.js";
4
1
  import type { DrizzleDb } from "../db-connection.js";
5
2
  import { getSqliteFrom } from "../db-connection.js";
6
3
 
7
- const log = getLogger("db-init");
8
-
9
- /**
10
- * Checkpoint key holding the highest `messages.rowid` already swept by this
11
- * migration. Persisted after every window so an interrupted run resumes from
12
- * where it left off instead of restarting the whole table scan. The value is a
13
- * plain integer string — deliberately not `started`/`rolling_back`, so
14
- * `recoverCrashedMigrations` never mistakes it for a stalled step and clears
15
- * it, and not `step:`-prefixed, so `validateMigrationState` ignores it.
16
- */
17
- const WATERMARK_KEY = "migration_209_strip_thinking_watermark";
18
-
19
- /**
20
- * Number of `rowid` values swept per `runAsyncSqlite` dispatch. Each window is
21
- * one off-thread subprocess transaction, so the size bounds both the WAL growth
22
- * per statement and how long a single write lock is held, while keeping the
23
- * number of subprocess spawns low on a large table.
24
- */
25
- const ROWID_WINDOW = 100_000;
26
-
27
- /** SQL predicate: this `json_each` element is an internal reasoning block. */
28
- const IS_THINKING = `json_extract(value, '$.type') IN ('thinking', 'redacted_thinking')`;
29
-
30
- /**
31
- * SQL predicate: this `json_each` element is kept. `IS NOT` (not `!=`) so a
32
- * block with a NULL/absent `type` is preserved, matching the JS filter the
33
- * original migration used (`b.type !== 'thinking'`).
34
- */
35
- const IS_KEPT = `json_extract(value, '$.type') IS NOT 'thinking' AND json_extract(value, '$.type') IS NOT 'redacted_thinking'`;
36
-
37
- /**
38
- * Build the two set-based UPDATEs that sweep one rowid window `(lo, hi]`.
39
- *
40
- * - Statement A strips thinking/redacted_thinking blocks from rows that retain
41
- * at least one kept block, rebuilding the content array in place. `json(value)`
42
- * re-embeds each surviving element as JSON rather than a quoted string.
43
- * - Statement B replaces all-thinking rows (no kept block survives) with the
44
- * null-byte placeholder sentinel so the message isn't left empty. `char(0)`
45
- * is evaluated inside SQLite, so the literal NUL is produced in the database
46
- * and never written into the SQL piped to the sqlite3 CLI.
47
- *
48
- * Both are gated by a cheap `content LIKE '%thinking%'` substring prefilter
49
- * (covers both `thinking` and `redacted_thinking`) so the expensive `json_each`
50
- * work only runs for rows that could possibly contain a reasoning block. The
51
- * two statements touch disjoint row sets (A requires a kept block, B requires
52
- * none), so their order within the window is immaterial.
53
- */
54
- function windowSql(lo: number, hi: number): string {
55
- const scope = `role = 'assistant'
56
- AND rowid > ${lo} AND rowid <= ${hi}
57
- AND content LIKE '%thinking%'
58
- AND json_valid(content)
59
- AND json_type(content) = 'array'`;
60
-
61
- const stripMixed = /*sql*/ `
62
- UPDATE messages
63
- SET content = (
64
- SELECT json_group_array(json(value))
65
- FROM json_each(messages.content)
66
- WHERE ${IS_KEPT}
67
- )
68
- WHERE ${scope}
69
- AND EXISTS (SELECT 1 FROM json_each(messages.content) WHERE ${IS_THINKING})
70
- AND EXISTS (SELECT 1 FROM json_each(messages.content) WHERE ${IS_KEPT});`;
71
-
72
- const placeholderOnly = /*sql*/ `
73
- UPDATE messages
74
- SET content = json_array(
75
- json_object('type', 'text', 'text', char(0) || '__PLACEHOLDER__[internal blocks omitted]')
76
- )
77
- WHERE ${scope}
78
- AND EXISTS (SELECT 1 FROM json_each(messages.content) WHERE ${IS_THINKING})
79
- AND NOT EXISTS (SELECT 1 FROM json_each(messages.content) WHERE ${IS_KEPT});`;
80
-
81
- return `${stripMixed}\n${placeholderOnly}`;
82
- }
83
-
84
4
  /**
85
5
  * Strip thinking and redacted_thinking blocks from all assistant messages.
86
6
  *
@@ -91,62 +11,68 @@ function windowSql(lo: number, hi: number): string {
91
11
  * provider no longer needs to strip, enabling append-only conversation
92
12
  * history and stable prefix caching.
93
13
  *
94
- * The rewrite runs entirely inside SQLite (via JSON1), dispatched through
95
- * {@link runAsyncSqlite} a rowid window at a time. On a host with the `sqlite3`
96
- * CLI each window executes in a subprocess, leaving the daemon's event loop
97
- * free to answer `/healthz` while a multi-GB table is rewritten — the original
98
- * synchronous in-process loop blocked the loop for minutes and tripped the
99
- * startup probe into a restart loop. Progress is checkpointed per window, so an
100
- * interrupted run resumes instead of rescanning from the start.
101
- *
102
- * Idempotent — safe to re-run. Already-cleaned rows no longer contain a
103
- * thinking block, so the substring prefilter skips them.
14
+ * Idempotent safe to re-run.
104
15
  */
105
- export async function migrateStripThinkingFromConsolidated(
16
+ export function migrateStripThinkingFromConsolidated(
106
17
  database: DrizzleDb,
107
- ): Promise<void> {
18
+ ): void {
108
19
  const raw = getSqliteFrom(database);
109
- const dbPath = getDbPath();
110
-
111
- const maxRow = (
112
- raw.query(`SELECT MAX(rowid) AS m FROM messages`).get() as {
113
- m: number | null;
114
- }
115
- ).m;
116
- if (maxRow == null) return; // empty table — nothing to sweep
117
20
 
118
- const watermarkRow = raw
119
- .query(`SELECT value FROM memory_checkpoints WHERE key = ?`)
120
- .get(WATERMARK_KEY) as { value: string } | undefined;
121
- let lo = watermarkRow ? Number.parseInt(watermarkRow.value, 10) || 0 : 0;
122
-
123
- const setWatermark = raw.query(
124
- `INSERT OR REPLACE INTO memory_checkpoints (key, value, updated_at) VALUES (?, ?, ?)`,
125
- );
126
-
127
- while (lo < maxRow) {
128
- const hi = Math.min(lo + ROWID_WINDOW, maxRow);
21
+ const BATCH_SIZE = 100;
22
+ let lastRowid = 0;
23
+
24
+ for (;;) {
25
+ const rows = raw
26
+ .query(
27
+ `SELECT rowid, id, content FROM messages
28
+ WHERE role = 'assistant'
29
+ AND rowid > ?
30
+ ORDER BY rowid
31
+ LIMIT ?`,
32
+ )
33
+ .all(lastRowid, BATCH_SIZE) as Array<{
34
+ rowid: number;
35
+ id: string;
36
+ content: string;
37
+ }>;
38
+
39
+ if (rows.length === 0) break;
40
+
41
+ for (const row of rows) {
42
+ lastRowid = row.rowid;
43
+
44
+ let blocks: Array<{ type: string }>;
45
+ try {
46
+ const parsed = JSON.parse(row.content);
47
+ if (!Array.isArray(parsed)) continue;
48
+ blocks = parsed;
49
+ } catch {
50
+ continue;
51
+ }
52
+
53
+ const hasThinking = blocks.some(
54
+ (b) => b.type === "thinking" || b.type === "redacted_thinking",
55
+ );
56
+ if (!hasThinking) continue;
129
57
 
130
- const res = await runAsyncSqlite(windowSql(lo, hi), { dbPath });
131
- if (!res.ok) {
132
- // Leave the watermark at the last completed window; throwing reports the
133
- // step failed so the runner retries it (from the watermark) next boot
134
- // rather than checkpointing it as done.
135
- throw new Error(
136
- `strip-thinking window (${lo}, ${hi}] failed: ${res.error}`,
58
+ const stripped = blocks.filter(
59
+ (b) => b.type !== "thinking" && b.type !== "redacted_thinking",
137
60
  );
138
- }
139
61
 
140
- lo = hi;
141
- setWatermark.run(WATERMARK_KEY, String(lo), Date.now());
62
+ // Preserve at least one block so the message isn't empty.
63
+ const finalContent =
64
+ stripped.length > 0
65
+ ? stripped
66
+ : [
67
+ {
68
+ type: "text" as const,
69
+ text: "\x00__PLACEHOLDER__[internal blocks omitted]",
70
+ },
71
+ ];
72
+
73
+ raw
74
+ .query(`UPDATE messages SET content = ? WHERE id = ?`)
75
+ .run(JSON.stringify(finalContent), row.id);
76
+ }
142
77
  }
143
-
144
- // Bound WAL growth left by the windowed rewrites, then drop the watermark so
145
- // a future re-run (e.g. after a rollback) starts clean.
146
- await runAsyncSqlite(`PRAGMA wal_checkpoint(TRUNCATE);`, { dbPath });
147
- raw.query(`DELETE FROM memory_checkpoints WHERE key = ?`).run(WATERMARK_KEY);
148
-
149
- log.info(
150
- "Migration 209: stripped thinking blocks from consolidated messages",
151
- );
152
78
  }
@@ -54,7 +54,7 @@ describe("runMigrationSteps — checkpointing", () => {
54
54
 
55
55
  test("records step completions in the shared memory_checkpoints ledger", async () => {
56
56
  /**
57
- * Step bookkeeping lives in the same memory_checkpoints table the step runner
57
+ * Step bookkeeping lives in the same memory_checkpoints table the registry
58
58
  * uses, under the `step:` namespace — one ledger for all applied state.
59
59
  */
60
60
 
@@ -110,7 +110,7 @@ describe("runMigrationSteps — checkpointing", () => {
110
110
  * before the loop so a migration interrupted mid-flight re-runs this boot.
111
111
  */
112
112
 
113
- // GIVEN a database with a stalled step checkpoint left by a crash
113
+ // GIVEN a database with a stalled registry checkpoint left by a crash
114
114
  const db = createTestDb();
115
115
  const raw = getSqliteFrom(db);
116
116
  raw.run(