@vellumai/assistant 0.10.8 → 0.10.9-dev.202607152225.ec6fdbf

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 (1453) hide show
  1. package/AGENTS.md +4 -0
  2. package/ARCHITECTURE.md +52 -88
  3. package/README.md +14 -35
  4. package/docs/activation-funnel-telemetry.md +20 -18
  5. package/docs/architecture/scheduling.md +0 -86
  6. package/docs/runbook-trusted-contacts.md +19 -19
  7. package/docs/trusted-contact-access.md +70 -69
  8. package/docs/workspace-tools.md +4 -2
  9. package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +62 -360
  10. package/eslint-rules/cli-no-daemon-internals.js +91 -275
  11. package/eslint.config.mjs +4 -4
  12. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +1 -0
  13. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/redacted-credential.test.ts +200 -0
  14. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/redacted-credential.ts +226 -0
  15. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +1 -0
  16. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/redacted-credential.test.ts +200 -0
  17. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/redacted-credential.ts +226 -0
  18. package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-request-contract.test.ts +575 -0
  19. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +20 -0
  20. package/node_modules/@vellumai/gateway-client/src/guardian-request-contract.ts +687 -0
  21. package/node_modules/@vellumai/gateway-client/src/index.ts +82 -0
  22. package/node_modules/@vellumai/service-contracts/package.json +1 -0
  23. package/node_modules/@vellumai/service-contracts/src/__tests__/redacted-credential.test.ts +200 -0
  24. package/node_modules/@vellumai/service-contracts/src/redacted-credential.ts +226 -0
  25. package/openapi.yaml +353 -742
  26. package/package.json +2 -2
  27. package/scripts/build-test-fixtures.ts +3 -2
  28. package/scripts/test.ts +2 -7
  29. package/src/__tests__/activation-early-marking.test.ts +1 -8
  30. package/src/__tests__/actor-token-service.test.ts +0 -7
  31. package/src/__tests__/add-message-preassigned-id.test.ts +1 -1
  32. package/src/__tests__/add-message-skip-indexing.test.ts +164 -0
  33. package/src/__tests__/agent-image-optimize.test.ts +104 -1
  34. package/src/__tests__/agent-loop-callsite-precedence.test.ts +5 -15
  35. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +0 -6
  36. package/src/__tests__/agent-loop-override-profile.test.ts +48 -50
  37. package/src/__tests__/agent-loop-pushes-post-hook-prompt.test.ts +4 -17
  38. package/src/__tests__/agent-loop-set-system-prompt.test.ts +3 -14
  39. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +0 -4
  40. package/src/__tests__/agent-wake-override-profile.test.ts +40 -71
  41. package/src/__tests__/always-loaded-tools-guard.test.ts +4 -7
  42. package/src/__tests__/annotate-activity-metadata.test.ts +4 -31
  43. package/src/__tests__/annotate-risk-options.test.ts +4 -31
  44. package/src/__tests__/anthropic-provider.test.ts +11 -0
  45. package/src/__tests__/app-asset-bytes.test.ts +72 -0
  46. package/src/__tests__/app-builder-tool-scripts.test.ts +0 -1
  47. package/src/__tests__/app-bundler.test.ts +4 -20
  48. package/src/__tests__/app-conversation-ids-backfill.test.ts +1 -8
  49. package/src/__tests__/app-executors.test.ts +2 -49
  50. package/src/__tests__/app-routes-csp.test.ts +126 -157
  51. package/src/__tests__/approval-cascade.test.ts +0 -82
  52. package/src/__tests__/approval-interception-trust-gates.test.ts +0 -7
  53. package/src/__tests__/approval-primitive.test.ts +1 -9
  54. package/src/__tests__/approval-routes-http.test.ts +5 -63
  55. package/src/__tests__/assistant-event-hub-machine-name.test.ts +1 -19
  56. package/src/__tests__/assistant-events-sse-hardening.test.ts +4 -21
  57. package/src/__tests__/attachment-stored-path-annotation.test.ts +1 -19
  58. package/src/__tests__/attachment-upload-trusted-source.test.ts +0 -13
  59. package/src/__tests__/attachments-store-heic-normalize.test.ts +0 -13
  60. package/src/__tests__/attachments-store.test.ts +5 -19
  61. package/src/__tests__/audit-log-rotation.test.ts +1 -9
  62. package/src/__tests__/auth-fallback-events-store.test.ts +43 -59
  63. package/src/__tests__/available-skills.test.ts +7 -15
  64. package/src/__tests__/avatar-e2e.test.ts +0 -19
  65. package/src/__tests__/avatar-generator.test.ts +0 -9
  66. package/src/__tests__/background-shell-bash.test.ts +0 -20
  67. package/src/__tests__/background-shell-host-bash.test.ts +0 -34
  68. package/src/__tests__/background-workers-disk-pressure.test.ts +1 -43
  69. package/src/__tests__/browser-fill-credential.test.ts +0 -7
  70. package/src/__tests__/browser-manager.test.ts +1 -8
  71. package/src/__tests__/browser-skill-endstate.test.ts +1 -5
  72. package/src/__tests__/btw-routes.test.ts +7 -30
  73. package/src/__tests__/build-persisted-content.test.ts +96 -29
  74. package/src/__tests__/bundle-scanner.test.ts +27 -1
  75. package/src/__tests__/call-controller.test.ts +96 -149
  76. package/src/__tests__/call-conversation-messages.test.ts +2 -9
  77. package/src/__tests__/call-domain.test.ts +21 -56
  78. package/src/__tests__/call-pointer-message-composer.test.ts +0 -8
  79. package/src/__tests__/call-pointer-messages.test.ts +1 -8
  80. package/src/__tests__/call-recovery.test.ts +4 -11
  81. package/src/__tests__/call-routes-http.test.ts +12 -47
  82. package/src/__tests__/call-site-routing-provider.test.ts +5 -16
  83. package/src/__tests__/call-start-guardian-guard.test.ts +0 -10
  84. package/src/__tests__/call-state.test.ts +1 -8
  85. package/src/__tests__/call-store.test.ts +4 -11
  86. package/src/__tests__/cancel-resolves-conversation-key.test.ts +0 -32
  87. package/src/__tests__/catalog-cache.test.ts +0 -8
  88. package/src/__tests__/catalog-files.test.ts +0 -8
  89. package/src/__tests__/catalog-install-normalize.test.ts +0 -7
  90. package/src/__tests__/ces-rpc-credential-backend.test.ts +0 -7
  91. package/src/__tests__/channel-approval-routes.test.ts +23 -34
  92. package/src/__tests__/channel-approvals.test.ts +0 -7
  93. package/src/__tests__/channel-delivery-store.test.ts +6 -17
  94. package/src/__tests__/channel-guardian.test.ts +0 -7
  95. package/src/__tests__/channel-inbound-disk-pressure.test.ts +15 -20
  96. package/src/__tests__/channel-readiness-routes.test.ts +41 -67
  97. package/src/__tests__/channel-readiness-service.test.ts +13 -45
  98. package/src/__tests__/channel-readiness-slack-remote.test.ts +5 -22
  99. package/src/__tests__/channel-reply-delivery.test.ts +18 -5
  100. package/src/__tests__/channel-retry-sweep.test.ts +0 -7
  101. package/src/__tests__/chat-credential-redaction.test.ts +1395 -0
  102. package/src/__tests__/chat-reveal-guard-priming.test.ts +791 -0
  103. package/src/__tests__/checker.test.ts +0 -24
  104. package/src/__tests__/clawhub-files.test.ts +0 -8
  105. package/src/__tests__/clawhub.test.ts +0 -7
  106. package/src/__tests__/clear-all-lexical.test.ts +0 -6
  107. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +3 -0
  108. package/src/__tests__/client-os-metadata-persistence.test.ts +0 -5
  109. package/src/__tests__/compaction-events.test.ts +26 -99
  110. package/src/__tests__/compaction-ledger-store.test.ts +1 -7
  111. package/src/__tests__/compaction-summary-head-persisted-count.test.ts +0 -27
  112. package/src/__tests__/compaction-trail-store.test.ts +1 -19
  113. package/src/__tests__/compaction.benchmark.test.ts +2 -6
  114. package/src/__tests__/compactor-call-site-logging.test.ts +0 -21
  115. package/src/__tests__/compactor-fixed-boundary.test.ts +0 -21
  116. package/src/__tests__/compactor-image-manifest-trust.test.ts +1 -10
  117. package/src/__tests__/compactor-low-watermark-cut.test.ts +0 -21
  118. package/src/__tests__/compactor-media-strip.test.ts +0 -21
  119. package/src/__tests__/compactor-preserved-tail-count.test.ts +0 -21
  120. package/src/__tests__/compactor-summary-call-truncation.test.ts +0 -21
  121. package/src/__tests__/compactor-web-search-strip.test.ts +0 -21
  122. package/src/__tests__/config-get-vision-flag.test.ts +24 -53
  123. package/src/__tests__/config-loader-backfill.test.ts +9 -25
  124. package/src/__tests__/config-loader-platform-defaults.test.ts +0 -21
  125. package/src/__tests__/config-schema-cmd.test.ts +10 -11
  126. package/src/__tests__/config-schema.test.ts +221 -275
  127. package/src/__tests__/config-set-route.test.ts +32 -62
  128. package/src/__tests__/config-watcher-cleanup-throttle.test.ts +44 -83
  129. package/src/__tests__/config-watcher-skill-reseed.test.ts +0 -16
  130. package/src/__tests__/config-watcher.test.ts +2 -17
  131. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +57 -63
  132. package/src/__tests__/contact-store-interaction-info.test.ts +1 -8
  133. package/src/__tests__/contact-store-user-file.test.ts +1 -8
  134. package/src/__tests__/contacts-tools.test.ts +21 -26
  135. package/src/__tests__/contacts-write.test.ts +1 -8
  136. package/src/__tests__/context-search-memory-v2-source.test.ts +0 -6
  137. package/src/__tests__/context-window-manager-compact-retry.test.ts +0 -27
  138. package/src/__tests__/context-window-manager-overflow-rung.test.ts +0 -21
  139. package/src/__tests__/conversation-abort-tool-results.test.ts +9 -90
  140. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +5 -41
  141. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +16 -54
  142. package/src/__tests__/conversation-agent-loop-overflow.test.ts +14 -79
  143. package/src/__tests__/conversation-agent-loop.test.ts +213 -136
  144. package/src/__tests__/conversation-app-control-instantiation.test.ts +10 -16
  145. package/src/__tests__/conversation-app-control-lifecycle.test.ts +0 -43
  146. package/src/__tests__/conversation-attachments.test.ts +0 -17
  147. package/src/__tests__/conversation-attention-store.test.ts +1 -9
  148. package/src/__tests__/conversation-attention-telegram.test.ts +0 -8
  149. package/src/__tests__/conversation-clear-safety.test.ts +20 -20
  150. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -82
  151. package/src/__tests__/conversation-crud-enabled-plugins.test.ts +1 -7
  152. package/src/__tests__/conversation-crud-inference-profile.test.ts +1 -7
  153. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +0 -7
  154. package/src/__tests__/conversation-disk-view-integration.test.ts +1 -26
  155. package/src/__tests__/conversation-disk-view.test.ts +1 -26
  156. package/src/__tests__/conversation-enabledplugins-route.test.ts +3 -21
  157. package/src/__tests__/conversation-error.test.ts +21 -7
  158. package/src/__tests__/conversation-fork-crud.test.ts +35 -44
  159. package/src/__tests__/conversation-fork-retrospective.test.ts +9 -24
  160. package/src/__tests__/conversation-fork-route.test.ts +0 -32
  161. package/src/__tests__/conversation-history-web-search.test.ts +20 -17
  162. package/src/__tests__/conversation-inference-profile-list.test.ts +0 -17
  163. package/src/__tests__/conversation-inference-profile-route.test.ts +2 -24
  164. package/src/__tests__/conversation-init.benchmark.test.ts +3 -56
  165. package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -33
  166. package/src/__tests__/conversation-lifecycle.test.ts +63 -103
  167. package/src/__tests__/conversation-list-source.test.ts +0 -18
  168. package/src/__tests__/conversation-load-history-repair.test.ts +39 -91
  169. package/src/__tests__/conversation-load-history-stripped.test.ts +12 -57
  170. package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +10 -20
  171. package/src/__tests__/conversation-message-id-uuidv7.test.ts +1 -18
  172. package/src/__tests__/conversation-pairing.test.ts +0 -7
  173. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +0 -9
  174. package/src/__tests__/conversation-process-callsite.test.ts +15 -97
  175. package/src/__tests__/conversation-provider-retry-repair.test.ts +3 -84
  176. package/src/__tests__/conversation-queue.test.ts +12 -108
  177. package/src/__tests__/conversation-routes-disk-view.test.ts +8 -60
  178. package/src/__tests__/conversation-routes-enabled-plugins.test.ts +5 -63
  179. package/src/__tests__/conversation-routes-guardian-reply.test.ts +13 -22
  180. package/src/__tests__/conversation-routes-hidden-queue.test.ts +5 -64
  181. package/src/__tests__/conversation-routes-slash-commands.test.ts +19 -87
  182. package/src/__tests__/conversation-runtime-assembly.test.ts +34 -37
  183. package/src/__tests__/conversation-seed-composer.test.ts +3 -3
  184. package/src/__tests__/conversation-skill-tools.test.ts +19 -32
  185. package/src/__tests__/conversation-slash-queue.test.ts +3 -90
  186. package/src/__tests__/conversation-slash-unknown.test.ts +0 -87
  187. package/src/__tests__/conversation-speed-override.test.ts +19 -94
  188. package/src/__tests__/conversation-starter-routes.test.ts +0 -7
  189. package/src/__tests__/conversation-store.test.ts +72 -66
  190. package/src/__tests__/conversation-summarize-route.test.ts +0 -11
  191. package/src/__tests__/conversation-summarize-up-to.test.ts +4 -89
  192. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +131 -0
  193. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +36 -36
  194. package/src/__tests__/conversation-surfaces-data-persist.test.ts +4 -2
  195. package/src/__tests__/conversation-title-service.test.ts +0 -7
  196. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +0 -1
  197. package/src/__tests__/conversation-tool-setup-attribution.test.ts +37 -60
  198. package/src/__tests__/conversation-tool-setup-tools-disabled.test.ts +17 -17
  199. package/src/__tests__/conversation-unread-route.test.ts +0 -7
  200. package/src/__tests__/conversation-usage.test.ts +21 -71
  201. package/src/__tests__/conversation-wait-for-idle.test.ts +0 -82
  202. package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -45
  203. package/src/__tests__/conversation-workspace-injection.test.ts +0 -88
  204. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -88
  205. package/src/__tests__/conversations-defer-cli.test.ts +3 -0
  206. package/src/__tests__/conversations-import-system-filter.test.ts +0 -17
  207. package/src/__tests__/credential-broker-browser-fill.test.ts +0 -9
  208. package/src/__tests__/credential-broker-server-use.test.ts +0 -9
  209. package/src/__tests__/credential-health-service.test.ts +14 -31
  210. package/src/__tests__/credential-metadata-store.test.ts +0 -8
  211. package/src/__tests__/credential-prompt-route.test.ts +9 -15
  212. package/src/__tests__/credential-resolve.test.ts +0 -8
  213. package/src/__tests__/credential-routes.test.ts +250 -0
  214. package/src/__tests__/credential-security-invariants.test.ts +4 -8
  215. package/src/__tests__/credential-token-resolver.test.ts +0 -9
  216. package/src/__tests__/cross-provider-web-search.test.ts +12 -18
  217. package/src/__tests__/daemon-assistant-events.test.ts +1 -9
  218. package/src/__tests__/daemon-credential-client.test.ts +0 -7
  219. package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +1 -8
  220. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +1 -7
  221. package/src/__tests__/db-llm-request-log-provider-migration.test.ts +0 -8
  222. package/src/__tests__/db-readiness-http-gate.test.ts +0 -18
  223. package/src/__tests__/db-rename-inference-profile-snake-case-migration.test.ts +1 -7
  224. package/src/__tests__/db-test-helpers.ts +10 -3
  225. package/src/__tests__/delete-managed-skill-tool.test.ts +0 -7
  226. package/src/__tests__/delete-propagation.test.ts +0 -7
  227. package/src/__tests__/deterministic-verification-control-plane.test.ts +0 -7
  228. package/src/__tests__/device-id.test.ts +1 -9
  229. package/src/__tests__/disk-pressure-guard.test.ts +0 -4
  230. package/src/__tests__/disk-pressure-routes.test.ts +0 -4
  231. package/src/__tests__/disk-pressure-tools.test.ts +4 -42
  232. package/src/__tests__/dm-backfill.test.ts +0 -7
  233. package/src/__tests__/dm-persistence.test.ts +0 -5
  234. package/src/__tests__/docker-signing-key-bootstrap.test.ts +1 -8
  235. package/src/__tests__/drain-requeue-on-contention.test.ts +1 -8
  236. package/src/__tests__/dynamic-skill-background-guard.test.ts +0 -43
  237. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +2 -27
  238. package/src/__tests__/edit-propagation.test.ts +1 -8
  239. package/src/__tests__/email-invite-adapter.test.ts +8 -33
  240. package/src/__tests__/embedding-managed-proxy-selection.test.ts +0 -8
  241. package/src/__tests__/emit-event-signal.test.ts +1 -1
  242. package/src/__tests__/emit-signal-routing-intent.test.ts +0 -7
  243. package/src/__tests__/empty-state-greeting-cache.test.ts +9 -9
  244. package/src/__tests__/encrypted-store.test.ts +0 -9
  245. package/src/__tests__/ensure-conversation-exists.test.ts +1 -18
  246. package/src/__tests__/events-client-registration.test.ts +1 -19
  247. package/src/__tests__/events-dev-bypass-actor.test.ts +0 -7
  248. package/src/__tests__/events-tail-route.test.ts +1 -8
  249. package/src/__tests__/file-list-tool.test.ts +22 -15
  250. package/src/__tests__/followup-tools.test.ts +1 -16
  251. package/src/__tests__/gateway-only-enforcement.test.ts +3 -44
  252. package/src/__tests__/get-skill-detail-audit.test.ts +0 -7
  253. package/src/__tests__/google-calendar-watcher.test.ts +175 -0
  254. package/src/__tests__/guardian-action-sweep.test.ts +0 -7
  255. package/src/__tests__/guardian-binding-drift-heal.test.ts +0 -7
  256. package/src/__tests__/guardian-card-withdrawal.test.ts +60 -64
  257. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +172 -135
  258. package/src/__tests__/guardian-dispatch.test.ts +58 -157
  259. package/src/__tests__/guardian-expiry-notifier.test.ts +56 -48
  260. package/src/__tests__/guardian-gateway-sim.ts +626 -0
  261. package/src/__tests__/guardian-outbound-http.test.ts +0 -7
  262. package/src/__tests__/guardian-routing-invariants.test.ts +229 -220
  263. package/src/__tests__/guardian-routing-state.test.ts +2 -9
  264. package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -17
  265. package/src/__tests__/guardian-wait-controller.test.ts +44 -43
  266. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +26 -91
  267. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +18 -103
  268. package/src/__tests__/headless-browser-interactions.test.ts +0 -7
  269. package/src/__tests__/headless-browser-mode.test.ts +0 -9
  270. package/src/__tests__/headless-browser-navigate.test.ts +0 -7
  271. package/src/__tests__/headless-browser-read-tools.test.ts +0 -7
  272. package/src/__tests__/headless-browser-snapshot.test.ts +0 -7
  273. package/src/__tests__/heartbeat-disk-pressure.test.ts +9 -38
  274. package/src/__tests__/heartbeat-service.test.ts +83 -106
  275. package/src/__tests__/helpers/channel-test-adapter.ts +10 -0
  276. package/src/__tests__/helpers/gateway-guardian-requests-store-bridge.ts +155 -0
  277. package/src/__tests__/helpers/set-config.ts +40 -0
  278. package/src/__tests__/host-bash-proxy.test.ts +18 -34
  279. package/src/__tests__/host-browser-proxy.test.ts +15 -20
  280. package/src/__tests__/host-shell-tool.test.ts +2 -34
  281. package/src/__tests__/http-conversation-lineage.test.ts +3 -19
  282. package/src/__tests__/http-user-message-parity.test.ts +3 -95
  283. package/src/__tests__/identity-routes.test.ts +1 -9
  284. package/src/__tests__/image-recovery-hook.test.ts +36 -0
  285. package/src/__tests__/inbound-admitted-introduction-nudge.test.ts +6 -12
  286. package/src/__tests__/inbound-invite-redemption.test.ts +0 -7
  287. package/src/__tests__/inbound-slack-persistence.test.ts +0 -5
  288. package/src/__tests__/inbound-trust-verdict.test.ts +2 -8
  289. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +52 -8
  290. package/src/__tests__/inference-profile-reaper.test.ts +1 -7
  291. package/src/__tests__/inference-profile-session-handler.test.ts +4 -30
  292. package/src/__tests__/inference-profile-session-ipc.test.ts +3 -20
  293. package/src/__tests__/ingress-url-consistency.test.ts +1 -23
  294. package/src/__tests__/injector-background-turn.test.ts +10 -24
  295. package/src/__tests__/injector-chain.test.ts +4 -13
  296. package/src/__tests__/injector-pkb-v2-silenced.test.ts +19 -17
  297. package/src/__tests__/inline-command-runner.test.ts +0 -34
  298. package/src/__tests__/inline-skill-load-permissions.test.ts +1 -30
  299. package/src/__tests__/install-skill-routing.test.ts +7 -6
  300. package/src/__tests__/integration-status.test.ts +25 -17
  301. package/src/__tests__/intent-routing.test.ts +1 -50
  302. package/src/__tests__/internal-telemetry-routes.test.ts +41 -22
  303. package/src/__tests__/interrupted-turn-reconciler.test.ts +1 -8
  304. package/src/__tests__/introduction-card-resolver.test.ts +108 -117
  305. package/src/__tests__/invite-redeemed-ipc.test.ts +0 -7
  306. package/src/__tests__/invite-routes-http.test.ts +12 -23
  307. package/src/__tests__/jobs-store-has-pending-job.test.ts +59 -0
  308. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +1 -14
  309. package/src/__tests__/jobs-store-skill-card-upsert.test.ts +191 -0
  310. package/src/__tests__/jobs-store-upsert-debounced.test.ts +1 -14
  311. package/src/__tests__/lexical-index-dual-write.test.ts +0 -6
  312. package/src/__tests__/list-all-apps.test.ts +200 -0
  313. package/src/__tests__/list-messages-attachments.test.ts +11 -20
  314. package/src/__tests__/list-messages-background-tool-completion.test.ts +6 -18
  315. package/src/__tests__/list-messages-client-message-id.test.ts +4 -16
  316. package/src/__tests__/list-messages-hidden-metadata.test.ts +6 -18
  317. package/src/__tests__/list-messages-page-latest.test.ts +3 -19
  318. package/src/__tests__/list-messages-queued.test.ts +1 -18
  319. package/src/__tests__/list-messages-tool-merge.test.ts +7 -18
  320. package/src/__tests__/llm-context-resolution.test.ts +32 -56
  321. package/src/__tests__/llm-context-route-provider.test.ts +1 -8
  322. package/src/__tests__/llm-request-log-agent-loop-exit-reason.test.ts +1 -19
  323. package/src/__tests__/llm-request-log-call-site.test.ts +1 -19
  324. package/src/__tests__/llm-request-log-clickhouse-routing.test.ts +114 -0
  325. package/src/__tests__/llm-request-log-clickhouse-writer-guards.test.ts +108 -0
  326. package/src/__tests__/llm-request-log-disabled-writes.test.ts +11 -30
  327. package/src/__tests__/llm-request-log-sink-clickhouse.test.ts +205 -0
  328. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +1 -22
  329. package/src/__tests__/llm-request-log-source-factory.test.ts +23 -69
  330. package/src/__tests__/llm-request-log-turn-query.test.ts +1 -19
  331. package/src/__tests__/llm-resolver-override-or-default.test.ts +3 -52
  332. package/src/__tests__/llm-resolver.test.ts +342 -602
  333. package/src/__tests__/llm-schema.test.ts +79 -37
  334. package/src/__tests__/llm-usage-store.test.ts +1 -7
  335. package/src/__tests__/log-export-routes.test.ts +0 -7
  336. package/src/__tests__/log-export-workspace.test.ts +0 -7
  337. package/src/__tests__/managed-profile-guard.test.ts +125 -137
  338. package/src/__tests__/managed-skill-lifecycle.test.ts +6 -50
  339. package/src/__tests__/managed-speech-defaults.test.ts +138 -0
  340. package/src/__tests__/managed-store.test.ts +1 -16
  341. package/src/__tests__/mcp-auth-routes.test.ts +15 -26
  342. package/src/__tests__/mcp-config-secret-boundary.test.ts +49 -91
  343. package/src/__tests__/mcp-health-check.test.ts +14 -20
  344. package/src/__tests__/media-generate-image.test.ts +25 -32
  345. package/src/__tests__/media-stream-output.test.ts +0 -9
  346. package/src/__tests__/media-stream-server-integration.test.ts +19 -27
  347. package/src/__tests__/media-stream-stt-session.test.ts +16 -29
  348. package/src/__tests__/memory-jobs-worker-backoff.test.ts +6 -19
  349. package/src/__tests__/memory-jobs-worker-cleanup-cadence.test.ts +33 -12
  350. package/src/__tests__/memory-jobs-worker-lanes.test.ts +10 -29
  351. package/src/__tests__/memory-recall-log-store.test.ts +1 -19
  352. package/src/__tests__/memory-retrieval-hook.test.ts +0 -3
  353. package/src/__tests__/memory-upsert-concurrency.test.ts +12 -35
  354. package/src/__tests__/memory-v2-static-injector.test.ts +5 -17
  355. package/src/__tests__/messages-after-tiebreaker.test.ts +1 -7
  356. package/src/__tests__/messaging-send-tool.test.ts +67 -7
  357. package/src/__tests__/migration-cross-version-compatibility.test.ts +0 -18
  358. package/src/__tests__/migration-export-http.test.ts +10 -23
  359. package/src/__tests__/migration-export-streaming.test.ts +0 -18
  360. package/src/__tests__/migration-export-to-gcs.test.ts +0 -19
  361. package/src/__tests__/migration-import-commit-http.test.ts +11 -23
  362. package/src/__tests__/migration-import-from-gcs.test.ts +0 -19
  363. package/src/__tests__/migration-import-from-url.test.ts +0 -19
  364. package/src/__tests__/migration-import-preflight-http.test.ts +10 -22
  365. package/src/__tests__/migration-jobs-status.test.ts +8 -23
  366. package/src/__tests__/migration-validate-http.test.ts +2 -19
  367. package/src/__tests__/mtime-cache.test.ts +116 -2
  368. package/src/__tests__/native-web-search.test.ts +0 -21
  369. package/src/__tests__/non-member-access-request.test.ts +102 -93
  370. package/src/__tests__/notification-broadcaster.test.ts +32 -21
  371. package/src/__tests__/notification-candidate-guardian-context.test.ts +36 -34
  372. package/src/__tests__/notification-decision-fallback.test.ts +0 -7
  373. package/src/__tests__/notification-decision-identity.test.ts +0 -7
  374. package/src/__tests__/notification-decision-recipient-context.test.ts +0 -7
  375. package/src/__tests__/notification-deep-link.test.ts +0 -7
  376. package/src/__tests__/notification-guardian-path.test.ts +48 -93
  377. package/src/__tests__/notification-platform-adapter.test.ts +0 -7
  378. package/src/__tests__/notification-routing-intent.test.ts +1 -9
  379. package/src/__tests__/notification-schedule-notify-dedup.test.ts +1 -9
  380. package/src/__tests__/notification-telegram-adapter.test.ts +0 -7
  381. package/src/__tests__/oauth-cli.test.ts +0 -19
  382. package/src/__tests__/oauth-commands-routes.test.ts +28 -43
  383. package/src/__tests__/oauth-connect-orchestrator.test.ts +17 -26
  384. package/src/__tests__/oauth-connect-routes.test.ts +19 -18
  385. package/src/__tests__/oauth-provider-profiles.test.ts +3 -9
  386. package/src/__tests__/oauth-provider-visibility.test.ts +0 -7
  387. package/src/__tests__/oauth-store.test.ts +0 -7
  388. package/src/__tests__/oauth2-gateway-transport.test.ts +41 -43
  389. package/src/__tests__/openai-responses-prompt-cache.test.ts +355 -0
  390. package/src/__tests__/openai-responses-provider.test.ts +98 -9
  391. package/src/__tests__/openrouter-responses-transport.test.ts +170 -0
  392. package/src/__tests__/outbound-slack-persistence.test.ts +13 -46
  393. package/src/__tests__/outlook-email-watcher.test.ts +0 -9
  394. package/src/__tests__/outlook-messaging-provider.test.ts +71 -0
  395. package/src/__tests__/path-policy.test.ts +0 -7
  396. package/src/__tests__/persist-media-references.test.ts +1 -6
  397. package/src/__tests__/persist-unsendable-image-downscale.test.ts +6 -3
  398. package/src/__tests__/persist-unsendable-image.test.ts +39 -7
  399. package/src/__tests__/persistence-secret-redaction.test.ts +7 -28
  400. package/src/__tests__/platform-bash-auto-approve.test.ts +0 -46
  401. package/src/__tests__/platform-callback-registration.test.ts +10 -9
  402. package/src/__tests__/platform-proxy-context.test.ts +0 -8
  403. package/src/__tests__/playbook-execution.test.ts +0 -14
  404. package/src/__tests__/playbook-tools.test.ts +0 -14
  405. package/src/__tests__/plugin-api-model-profiles.test.ts +12 -35
  406. package/src/__tests__/plugin-app-serve-routes.test.ts +315 -0
  407. package/src/__tests__/plugin-import-boundary-guard.test.ts +5 -3
  408. package/src/__tests__/plugin-import-boundary-reverse-guard.test.ts +0 -2
  409. package/src/__tests__/plugin-types.test.ts +0 -7
  410. package/src/__tests__/prechat-onboarding-contract.test.ts +0 -27
  411. package/src/__tests__/pricing.test.ts +45 -0
  412. package/src/__tests__/process-message-background-slack.test.ts +7 -21
  413. package/src/__tests__/process-message-display-content.test.ts +37 -6
  414. package/src/__tests__/processing-flag-persist-failure.test.ts +0 -44
  415. package/src/__tests__/provider-commit-message-generator.test.ts +57 -63
  416. package/src/__tests__/provider-error-scenarios.test.ts +5 -6
  417. package/src/__tests__/provider-platform-proxy-integration.test.ts +21 -57
  418. package/src/__tests__/provider-registry-ollama.test.ts +8 -18
  419. package/src/__tests__/provider-send-message-override-profile.test.ts +28 -39
  420. package/src/__tests__/provider-streaming.benchmark.test.ts +1 -6
  421. package/src/__tests__/provider-usage-tracking.test.ts +13 -35
  422. package/src/__tests__/proxy-approval-callback.test.ts +0 -16
  423. package/src/__tests__/prune-old-conversations-job.test.ts +29 -21
  424. package/src/__tests__/prune-old-tool-invocations-job.test.ts +1 -9
  425. package/src/__tests__/public-ingress-urls.test.ts +1 -24
  426. package/src/__tests__/published-app-updater.test.ts +22 -16
  427. package/src/__tests__/qdrant-collection-migration.test.ts +0 -7
  428. package/src/__tests__/qdrant-manager.test.ts +0 -8
  429. package/src/__tests__/ratelimit.test.ts +1 -8
  430. package/src/__tests__/reaction-persistence.test.ts +18 -24
  431. package/src/__tests__/rebuild-index-graph-nodes.test.ts +0 -14
  432. package/src/__tests__/recording-handler.test.ts +0 -27
  433. package/src/__tests__/request-secret-standalone-channel-gate.test.ts +4 -16
  434. package/src/__tests__/require-fresh-approval.test.ts +0 -45
  435. package/src/__tests__/retry-openrouter-only-normalization.test.ts +24 -36
  436. package/src/__tests__/retry-prompt-cache-key.test.ts +123 -0
  437. package/src/__tests__/retry-thinking-adaptive-only.test.ts +45 -61
  438. package/src/__tests__/retry-thinking-tool-choice.test.ts +60 -80
  439. package/src/__tests__/retry-verbosity-normalization.test.ts +27 -37
  440. package/src/__tests__/reveal-success-registry.test.ts +123 -0
  441. package/src/__tests__/run-conversation-turn-persistence.test.ts +113 -0
  442. package/src/__tests__/{scheduler-worker-standdown.test.ts → run-due-schedules.test.ts} +5 -77
  443. package/src/__tests__/runtime-attachment-metadata.test.ts +5 -18
  444. package/src/__tests__/runtime-events-sse-bilingual.test.ts +1 -19
  445. package/src/__tests__/runtime-events-sse-parity.test.ts +1 -20
  446. package/src/__tests__/runtime-events-sse-reconnect.test.ts +1 -19
  447. package/src/__tests__/runtime-events-sse.test.ts +1 -20
  448. package/src/__tests__/scaffold-managed-skill-tool.test.ts +306 -5
  449. package/src/__tests__/schedule-retry.test.ts +22 -23
  450. package/src/__tests__/schedule-routes-workflow-validation.test.ts +18 -42
  451. package/src/__tests__/schedule-routes.test.ts +2 -150
  452. package/src/__tests__/schedule-store.test.ts +0 -8
  453. package/src/__tests__/schedule-tools.test.ts +1 -16
  454. package/src/__tests__/scheduler-disk-pressure.test.ts +0 -26
  455. package/src/__tests__/scheduler-recurrence.test.ts +43 -76
  456. package/src/__tests__/scheduler-reuse-conversation.test.ts +19 -35
  457. package/src/__tests__/scheduler-wake.test.ts +8 -24
  458. package/src/__tests__/scoped-approval-grants.test.ts +1 -9
  459. package/src/__tests__/scoped-grant-security-matrix.test.ts +1 -9
  460. package/src/__tests__/search-skills-unified.test.ts +0 -6
  461. package/src/__tests__/secret-allowlist.test.ts +1 -8
  462. package/src/__tests__/secret-fixtures.ts +9 -0
  463. package/src/__tests__/secret-ingress-channel.test.ts +4 -32
  464. package/src/__tests__/secret-ingress-cli.test.ts +3 -37
  465. package/src/__tests__/secret-ingress-http.test.ts +15 -78
  466. package/src/__tests__/secret-ingress.test.ts +14 -31
  467. package/src/__tests__/secret-prompt-log-hygiene.test.ts +4 -10
  468. package/src/__tests__/secret-prompter-channel-fallback.test.ts +3 -9
  469. package/src/__tests__/secret-routes-platform-proxy.test.ts +3 -40
  470. package/src/__tests__/secure-keys-managed-failover.test.ts +0 -7
  471. package/src/__tests__/secure-keys.test.ts +0 -9
  472. package/src/__tests__/send-endpoint-busy.test.ts +47 -91
  473. package/src/__tests__/sequence-store.test.ts +0 -9
  474. package/src/__tests__/server-history-render.test.ts +29 -8
  475. package/src/__tests__/set-permission-mode.test.ts +8 -16
  476. package/src/__tests__/settings-routes.test.ts +0 -7
  477. package/src/__tests__/shell-credential-ref.test.ts +0 -18
  478. package/src/__tests__/shell-observability.test.ts +0 -21
  479. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -34
  480. package/src/__tests__/skill-load-feature-flag.test.ts +0 -27
  481. package/src/__tests__/skill-load-inline-command.test.ts +0 -25
  482. package/src/__tests__/skill-load-inline-includes.test.ts +0 -25
  483. package/src/__tests__/skill-load-plugin-scope.test.ts +0 -24
  484. package/src/__tests__/skill-projection-feature-flag.test.ts +14 -33
  485. package/src/__tests__/skill-projection.benchmark.test.ts +14 -19
  486. package/src/__tests__/skill-script-runner-sandbox.test.ts +1 -39
  487. package/src/__tests__/skills-file-content-endpoint.test.ts +0 -7
  488. package/src/__tests__/skills-files-catalog-fallback.test.ts +0 -14
  489. package/src/__tests__/slack-channel-config.test.ts +24 -79
  490. package/src/__tests__/slack-inbound-verification.test.ts +5 -13
  491. package/src/__tests__/{slack-reaction-canonical-approval.test.ts → slack-reaction-guardian-approval.test.ts} +18 -74
  492. package/src/__tests__/slack-share-routes.test.ts +0 -1
  493. package/src/__tests__/slim-skill-category.test.ts +0 -14
  494. package/src/__tests__/stale-approval-dedup.test.ts +0 -7
  495. package/src/__tests__/subagent-call-site-routing.test.ts +72 -111
  496. package/src/__tests__/subagent-detail.test.ts +1 -1
  497. package/src/__tests__/subagent-fork-prompt-role.test.ts +0 -12
  498. package/src/__tests__/subagent-notify-parent.test.ts +4 -6
  499. package/src/__tests__/subagent-spawn-and-await.test.ts +0 -18
  500. package/src/__tests__/subagent-tool-filtering.test.ts +21 -31
  501. package/src/__tests__/subagent-tool-gate-mode.test.ts +6 -32
  502. package/src/__tests__/subagent-tools.test.ts +92 -67
  503. package/src/__tests__/suggestion-routes.test.ts +28 -42
  504. package/src/__tests__/summarize-boundary.test.ts +2 -1
  505. package/src/__tests__/system-prompt-ask-mode.test.ts +0 -25
  506. package/src/__tests__/system-prompt.test.ts +0 -33
  507. package/src/__tests__/task-memory-cleanup.test.ts +18 -192
  508. package/src/__tests__/telegram-bot-username-resolution.test.ts +24 -48
  509. package/src/__tests__/telegram-config.test.ts +0 -8
  510. package/src/__tests__/telemetry-routes.test.ts +100 -0
  511. package/src/__tests__/telephony-credential-preflight.test.ts +7 -11
  512. package/src/__tests__/telephony-tts-guard.test.ts +38 -21
  513. package/src/__tests__/terminal-tools.test.ts +0 -21
  514. package/src/__tests__/thread-backfill.test.ts +0 -7
  515. package/src/__tests__/title-generate-hook.test.ts +11 -10
  516. package/src/__tests__/token-manager.test.ts +0 -9
  517. package/src/__tests__/tool-approval-handler.test.ts +0 -8
  518. package/src/__tests__/tool-execution-abort-cleanup.test.ts +5 -33
  519. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +3 -23
  520. package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -48
  521. package/src/__tests__/tool-executor.test.ts +3 -49
  522. package/src/__tests__/tool-grant-request-escalation.test.ts +51 -153
  523. package/src/__tests__/tool-preview-lifecycle.test.ts +2 -29
  524. package/src/__tests__/tool-profiler.test.ts +72 -1
  525. package/src/__tests__/tool-result-metadata-plumbing.test.ts +0 -29
  526. package/src/__tests__/tool-side-effects-slack-dm.test.ts +0 -1
  527. package/src/__tests__/tool-start-timestamp.test.ts +4 -31
  528. package/src/__tests__/tools-get-route.test.ts +2 -1
  529. package/src/__tests__/trust-context-guards.test.ts +19 -7
  530. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +75 -79
  531. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +14 -18
  532. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -7
  533. package/src/__tests__/trusted-contact-verification.test.ts +1 -9
  534. package/src/__tests__/turn-boundary-resolution.test.ts +1 -19
  535. package/src/__tests__/turn-events-store.test.ts +1 -7
  536. package/src/__tests__/turn-outcome-read.test.ts +1 -7
  537. package/src/__tests__/twilio-config.test.ts +11 -28
  538. package/src/__tests__/twilio-provider.test.ts +2 -13
  539. package/src/__tests__/twilio-routes-twiml.test.ts +1 -8
  540. package/src/__tests__/twilio-routes.test.ts +52 -103
  541. package/src/__tests__/twilio-validation.test.ts +5 -22
  542. package/src/__tests__/ui-file-upload-surface.test.ts +6 -9
  543. package/src/__tests__/usage-attribution.test.ts +25 -56
  544. package/src/__tests__/usage-cache-backfill-migration.test.ts +8 -15
  545. package/src/__tests__/usage-routes.test.ts +1 -8
  546. package/src/__tests__/vbundle-pax-and-symlink.test.ts +0 -18
  547. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +0 -24
  548. package/src/__tests__/vercel-config.test.ts +0 -7
  549. package/src/__tests__/verification-control-plane-policy.test.ts +0 -45
  550. package/src/__tests__/voice-approval-resolver-relay.test.ts +106 -75
  551. package/src/__tests__/voice-config-update.test.ts +114 -21
  552. package/src/__tests__/voice-ingress-preflight.test.ts +16 -15
  553. package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -30
  554. package/src/__tests__/voice-session-bridge-processing-wait.test.ts +1 -17
  555. package/src/__tests__/voice-session-bridge.test.ts +14 -46
  556. package/src/__tests__/web-search-backend-failure.test.ts +0 -21
  557. package/src/__tests__/whatsapp-invite-adapter.test.ts +11 -30
  558. package/src/__tests__/workspace-git-service.test.ts +801 -2
  559. package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +1 -26
  560. package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -26
  561. package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +1 -26
  562. package/src/a2a/__tests__/e2e-a2a-channel.test.ts +1 -9
  563. package/src/a2a/__tests__/task-store.test.ts +0 -9
  564. package/src/acp/__tests__/session-manager-persistence.test.ts +1 -8
  565. package/src/acp/__tests__/session-manager-resume.test.ts +0 -7
  566. package/src/acp/__tests__/session-manager-startup.test.ts +1 -8
  567. package/src/agent/image-optimize.ts +80 -0
  568. package/src/agent/loop.ts +20 -5
  569. package/src/api/events/open-conversation.test.ts +64 -0
  570. package/src/api/events/open-conversation.ts +33 -0
  571. package/src/api/index.ts +6 -0
  572. package/src/approvals/AGENTS.md +1 -1
  573. package/src/approvals/guardian-card-withdrawal.ts +26 -19
  574. package/src/approvals/guardian-decision-primitive.ts +172 -102
  575. package/src/approvals/guardian-expiry-notifier.ts +20 -19
  576. package/src/approvals/guardian-request-resolvers.ts +305 -275
  577. package/src/apps/app-store.ts +320 -15
  578. package/src/background-wake/background-wake-routes.test.ts +2 -3
  579. package/src/background-wake/next-wake.test.ts +23 -20
  580. package/src/background-wake/wake-intent-hooks.test.ts +0 -10
  581. package/src/bundler/app-bundler.ts +34 -48
  582. package/src/bundler/app-compiler.ts +39 -4
  583. package/src/bundler/bundle-scanner.ts +13 -0
  584. package/src/bundler/manifest.ts +1 -1
  585. package/src/calls/__tests__/call-setup-router.test.ts +84 -88
  586. package/src/calls/__tests__/fish-audio-client.test.ts +6 -11
  587. package/src/calls/__tests__/voice-control-protocol.test.ts +47 -0
  588. package/src/calls/__tests__/voice-session-bridge.test.ts +151 -16
  589. package/src/calls/__tests__/voice-triage-escalate.test.ts +128 -0
  590. package/src/calls/access-request-wait.ts +35 -35
  591. package/src/calls/call-controller.ts +48 -45
  592. package/src/calls/call-setup-flow.ts +2 -2
  593. package/src/calls/call-setup-router.ts +1 -24
  594. package/src/calls/guardian-dispatch.ts +47 -30
  595. package/src/calls/guardian-wait-controller.ts +31 -18
  596. package/src/calls/media-turn-detector.ts +11 -1
  597. package/src/calls/telephony-credential-preflight.ts +19 -1
  598. package/src/calls/telephony-tts-capability.ts +18 -1
  599. package/src/calls/voice-control-protocol.ts +12 -0
  600. package/src/calls/voice-session-bridge.ts +110 -15
  601. package/src/calls/voice-triage-escalate.ts +136 -0
  602. package/src/channels/__tests__/gateway-guardian-requests.test.ts +669 -0
  603. package/src/channels/gateway-guardian-requests.ts +410 -0
  604. package/src/channels/types.ts +10 -5
  605. package/src/cli/AGENTS.md +77 -51
  606. package/src/cli/__tests__/cli-command-help-coverage.test.ts +29 -0
  607. package/src/cli/commands/__tests__/conversations-import.test.ts +23 -24
  608. package/src/cli/commands/__tests__/gateway.test.ts +55 -0
  609. package/src/cli/commands/__tests__/inference-models.test.ts +3 -0
  610. package/src/cli/commands/__tests__/inference-profiles.test.ts +3 -0
  611. package/src/cli/commands/__tests__/inference-providers.test.ts +3 -0
  612. package/src/cli/commands/__tests__/inference-send.test.ts +0 -10
  613. package/src/cli/commands/__tests__/inference-session.test.ts +4 -11
  614. package/src/cli/commands/__tests__/ui.test.ts +2 -2
  615. package/src/cli/commands/apps.help.ts +46 -0
  616. package/src/cli/commands/apps.ts +51 -0
  617. package/src/cli/commands/avatar.help.ts +229 -0
  618. package/src/cli/commands/avatar.ts +58 -250
  619. package/src/cli/commands/backup.help.ts +183 -0
  620. package/src/cli/commands/backup.ts +107 -276
  621. package/src/cli/commands/bash.help.ts +38 -0
  622. package/src/cli/commands/bash.ts +51 -75
  623. package/src/cli/commands/browser.help.ts +193 -0
  624. package/src/cli/commands/browser.ts +234 -347
  625. package/src/cli/commands/cache.help.ts +123 -0
  626. package/src/cli/commands/cache.ts +72 -166
  627. package/src/cli/commands/changelog.help.ts +59 -0
  628. package/src/cli/commands/changelog.ts +29 -61
  629. package/src/cli/commands/channel-verification-sessions.help.ts +178 -0
  630. package/src/cli/commands/channel-verification-sessions.ts +71 -226
  631. package/src/cli/commands/channels/index.help.ts +67 -0
  632. package/src/cli/commands/channels/index.ts +55 -105
  633. package/src/cli/commands/clients.help.ts +72 -0
  634. package/src/cli/commands/clients.ts +100 -153
  635. package/src/cli/commands/completions.help.ts +33 -0
  636. package/src/cli/commands/completions.ts +43 -66
  637. package/src/cli/commands/config.help.ts +126 -0
  638. package/src/cli/commands/config.ts +59 -174
  639. package/src/cli/commands/contacts.help.ts +327 -0
  640. package/src/cli/commands/contacts.ts +318 -603
  641. package/src/cli/commands/conversations-defer.ts +141 -202
  642. package/src/cli/commands/conversations-import.ts +80 -113
  643. package/src/cli/commands/conversations.help.ts +364 -0
  644. package/src/cli/commands/conversations.ts +143 -328
  645. package/src/cli/commands/credentials.help.ts +290 -0
  646. package/src/cli/commands/credentials.ts +271 -487
  647. package/src/cli/commands/db/index.help.ts +27 -0
  648. package/src/cli/commands/db/index.ts +7 -3
  649. package/src/cli/commands/db/refresh.ts +131 -0
  650. package/src/cli/commands/db/repair-step-conversation-backfill.ts +19 -9
  651. package/src/cli/commands/db/repair.ts +41 -43
  652. package/src/cli/commands/db/status.ts +79 -83
  653. package/src/cli/commands/domain.help.ts +34 -0
  654. package/src/cli/commands/domain.ts +10 -15
  655. package/src/cli/commands/email.help.ts +176 -0
  656. package/src/cli/commands/email.ts +323 -412
  657. package/src/cli/commands/gateway.help.ts +115 -0
  658. package/src/cli/commands/gateway.ts +105 -123
  659. package/src/cli/commands/image-generation.help.ts +72 -0
  660. package/src/cli/commands/image-generation.ts +13 -62
  661. package/src/cli/commands/inference-callsites.ts +34 -49
  662. package/src/cli/commands/inference-models.ts +6 -21
  663. package/src/cli/commands/inference-profiles.ts +95 -156
  664. package/src/cli/commands/inference-providers-default.ts +27 -42
  665. package/src/cli/commands/inference-providers.ts +25 -87
  666. package/src/cli/commands/inference-session.ts +189 -249
  667. package/src/cli/commands/inference.help.ts +485 -0
  668. package/src/cli/commands/inference.ts +104 -165
  669. package/src/cli/commands/keys.help.ts +46 -0
  670. package/src/cli/commands/keys.ts +37 -71
  671. package/src/cli/commands/mcp.help.ts +167 -0
  672. package/src/cli/commands/mcp.ts +123 -267
  673. package/src/cli/commands/memory/__tests__/memory-items.test.ts +4 -0
  674. package/src/cli/commands/memory/__tests__/memory-v2.test.ts +4 -0
  675. package/src/cli/commands/memory/__tests__/memory-v3.test.ts +4 -0
  676. package/src/cli/commands/memory/__tests__/worker.test.ts +12 -5
  677. package/src/cli/commands/memory/index.help.ts +814 -0
  678. package/src/cli/commands/memory/index.ts +5 -27
  679. package/src/cli/commands/memory/items.ts +257 -404
  680. package/src/cli/commands/memory/memory-retrospective.ts +31 -71
  681. package/src/cli/commands/memory/memory-v2-compare-render.ts +2 -2
  682. package/src/cli/commands/memory/memory-v2.ts +435 -646
  683. package/src/cli/commands/memory/memory-v3.ts +158 -283
  684. package/src/cli/commands/memory/nodes.ts +154 -249
  685. package/src/cli/commands/memory/worker.ts +83 -128
  686. package/src/cli/commands/monitoring.help.ts +57 -0
  687. package/src/cli/commands/monitoring.ts +17 -41
  688. package/src/cli/commands/notifications.help.ts +293 -0
  689. package/src/cli/commands/notifications.ts +420 -657
  690. package/src/cli/commands/oauth/apps.ts +182 -315
  691. package/src/cli/commands/oauth/connect.ts +4 -35
  692. package/src/cli/commands/oauth/disconnect.ts +44 -71
  693. package/src/cli/commands/oauth/index.help.ts +855 -0
  694. package/src/cli/commands/oauth/index.ts +5 -31
  695. package/src/cli/commands/oauth/mode.ts +5 -28
  696. package/src/cli/commands/oauth/ping.ts +44 -66
  697. package/src/cli/commands/oauth/providers.ts +413 -772
  698. package/src/cli/commands/oauth/request.ts +6 -35
  699. package/src/cli/commands/oauth/shared.ts +1 -1
  700. package/src/cli/commands/oauth/status.test.ts +6 -6
  701. package/src/cli/commands/oauth/status.ts +45 -62
  702. package/src/cli/commands/oauth/token.ts +32 -71
  703. package/src/cli/commands/pending.help.ts +26 -0
  704. package/src/cli/commands/pending.ts +77 -78
  705. package/src/cli/commands/platform/__tests__/connect.test.ts +3 -1
  706. package/src/cli/commands/platform/__tests__/disconnect.test.ts +4 -4
  707. package/src/cli/commands/platform/__tests__/status.test.ts +0 -90
  708. package/src/cli/commands/platform/connect.ts +10 -21
  709. package/src/cli/commands/platform/disconnect.ts +11 -26
  710. package/src/cli/commands/platform/index.help.ts +187 -0
  711. package/src/cli/commands/platform/index.ts +22 -169
  712. package/src/cli/commands/plugins.help.ts +247 -0
  713. package/src/cli/commands/plugins.ts +356 -437
  714. package/src/cli/commands/ps.help.ts +26 -0
  715. package/src/cli/commands/ps.ts +5 -17
  716. package/src/cli/commands/routes.help.ts +72 -0
  717. package/src/cli/commands/routes.ts +78 -125
  718. package/src/cli/commands/schedules-worker.ts +70 -138
  719. package/src/cli/commands/schedules.help.ts +514 -0
  720. package/src/cli/commands/schedules.ts +494 -871
  721. package/src/cli/commands/sequence.help.ts +183 -0
  722. package/src/cli/commands/sequence.ts +181 -343
  723. package/src/cli/commands/skills.help.ts +159 -0
  724. package/src/cli/commands/skills.ts +230 -368
  725. package/src/cli/commands/status.help.ts +32 -0
  726. package/src/cli/commands/status.ts +38 -3
  727. package/src/cli/commands/stt.help.ts +52 -0
  728. package/src/cli/commands/stt.ts +9 -47
  729. package/src/cli/commands/telemetry.help.ts +14 -0
  730. package/src/cli/commands/telemetry.ts +19 -17
  731. package/src/cli/commands/tools-run.ts +30 -45
  732. package/src/cli/commands/tools.help.ts +81 -0
  733. package/src/cli/commands/tools.ts +43 -83
  734. package/src/cli/commands/trust.help.ts +43 -0
  735. package/src/cli/commands/trust.ts +82 -109
  736. package/src/cli/commands/tts.help.ts +88 -0
  737. package/src/cli/commands/tts.ts +116 -188
  738. package/src/cli/commands/ui.help.ts +213 -0
  739. package/src/cli/commands/ui.ts +363 -380
  740. package/src/cli/commands/usage.help.ts +147 -0
  741. package/src/cli/commands/usage.ts +87 -206
  742. package/src/cli/commands/watchers.help.ts +211 -0
  743. package/src/cli/commands/watchers.ts +261 -417
  744. package/src/cli/commands/webhooks.help.ts +95 -0
  745. package/src/cli/commands/webhooks.ts +44 -115
  746. package/src/cli/index.help.ts +91 -0
  747. package/src/cli/lib/__tests__/global-json-option.test.ts +97 -0
  748. package/src/cli/lib/__tests__/install-from-github.test.ts +144 -4
  749. package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +96 -132
  750. package/src/cli/lib/__tests__/plugin-catalog-local.test.ts +65 -0
  751. package/src/cli/lib/__tests__/plugin-catalog-platform.test.ts +167 -0
  752. package/src/cli/lib/__tests__/plugin-catalog-resolve.test.ts +197 -0
  753. package/src/cli/lib/__tests__/plugin-details.test.ts +349 -240
  754. package/src/cli/lib/__tests__/plugin-fingerprint.test.ts +31 -0
  755. package/src/cli/lib/__tests__/plugin-icon-file.test.ts +50 -1
  756. package/src/cli/lib/__tests__/plugin-marketplace.test.ts +94 -0
  757. package/src/cli/lib/__tests__/plugins-install-offline.test.ts +147 -0
  758. package/src/cli/lib/__tests__/search-plugins.test.ts +193 -309
  759. package/src/cli/lib/bundled-marketplace.json +439 -0
  760. package/src/cli/lib/cli-command-help.ts +83 -10
  761. package/src/cli/lib/global-json-option.ts +41 -0
  762. package/src/cli/lib/install-from-github.ts +69 -2
  763. package/src/cli/lib/plugin-catalog-cache.ts +22 -50
  764. package/src/cli/lib/plugin-catalog-local.ts +71 -0
  765. package/src/cli/lib/plugin-catalog-platform.ts +117 -0
  766. package/src/cli/lib/plugin-catalog-resolve.ts +72 -0
  767. package/src/cli/lib/plugin-details.ts +100 -34
  768. package/src/cli/lib/plugin-fingerprint.ts +18 -7
  769. package/src/cli/lib/plugin-icon-file.ts +38 -26
  770. package/src/cli/lib/plugin-marketplace.ts +15 -2
  771. package/src/cli/lib/publish-plugin.ts +3 -3
  772. package/src/cli/lib/search-plugins.ts +48 -111
  773. package/src/cli/program.ts +7 -0
  774. package/src/cli.ts +22 -13
  775. package/src/config/__tests__/default-profile-catalog.test.ts +8 -12
  776. package/src/config/__tests__/default-provider.test.ts +0 -21
  777. package/src/config/__tests__/deployment-context-defaults.test.ts +0 -21
  778. package/src/config/__tests__/feature-flag-registry-bundled.test.ts +2 -2
  779. package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +0 -21
  780. package/src/config/__tests__/loader-last-known-good.test.ts +0 -21
  781. package/src/config/__tests__/loader-sparse-array-cleanup.test.ts +0 -21
  782. package/src/config/__tests__/platform-rehydration.test.ts +125 -0
  783. package/src/config/__tests__/profile-materialization.test.ts +1 -88
  784. package/src/config/__tests__/seed-default-provider.test.ts +0 -21
  785. package/src/config/__tests__/sync-gated-profiles.test.ts +0 -21
  786. package/src/config/bundled-skills/app-builder/SKILL.md +24 -1
  787. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +30 -0
  788. package/src/config/bundled-skills/contacts/SKILL.md +1 -1
  789. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +4 -2
  790. package/src/config/bundled-skills/messaging/TOOLS.json +2 -2
  791. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +28 -20
  792. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +7 -7
  793. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +3 -3
  794. package/src/config/bundled-skills/schedule/SKILL.md +0 -1
  795. package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
  796. package/src/config/bundled-skills/settings/TOOLS.json +5 -3
  797. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +84 -10
  798. package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +0 -7
  799. package/src/config/call-site-defaults.ts +3 -3
  800. package/src/config/feature-flag-registry.json +15 -63
  801. package/src/config/llm-resolver.ts +88 -475
  802. package/src/config/managed-speech-defaults.ts +115 -0
  803. package/src/config/platform-rehydration.ts +76 -0
  804. package/src/config/profile-materialization.ts +11 -11
  805. package/src/config/schema.ts +93 -129
  806. package/src/config/schemas/__tests__/live-voice.test.ts +24 -6
  807. package/src/config/schemas/__tests__/stt.test.ts +37 -0
  808. package/src/config/schemas/live-voice.ts +10 -4
  809. package/src/config/schemas/llm.ts +51 -15
  810. package/src/config/schemas/memory-lifecycle.ts +1 -13
  811. package/src/config/schemas/memory-retrospective.ts +8 -0
  812. package/src/config/schemas/memory.ts +0 -4
  813. package/src/config/schemas/stt.ts +33 -6
  814. package/src/config/schemas/tts.ts +53 -6
  815. package/src/config/schemas/workspace-git.ts +8 -0
  816. package/src/contacts/contact-store.ts +3 -58
  817. package/src/contacts/types.ts +1 -1
  818. package/src/conversations/__tests__/message-consolidation.test.ts +6 -5
  819. package/src/conversations/message-consolidation.ts +34 -112
  820. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +64 -7
  821. package/src/daemon/__tests__/conversation-tool-setup-plugin-scope.test.ts +3 -7
  822. package/src/daemon/__tests__/conversation-tool-setup.test.ts +8 -6
  823. package/src/daemon/__tests__/embedding-reconcile.test.ts +0 -11
  824. package/src/daemon/__tests__/inference-profile-notification.test.ts +5 -11
  825. package/src/daemon/__tests__/inflight-message-content.test.ts +219 -0
  826. package/src/daemon/__tests__/native-web-search-metadata.test.ts +5 -27
  827. package/src/daemon/__tests__/route-conversation-post.test.ts +158 -0
  828. package/src/daemon/__tests__/wake-conversation-ops-completion.test.ts +0 -6
  829. package/src/daemon/__tests__/web-search-status-text.test.ts +0 -29
  830. package/src/daemon/app-source-watcher.ts +17 -23
  831. package/src/daemon/chat-credential-redaction.ts +1365 -0
  832. package/src/daemon/conversation-agent-loop-handlers.ts +742 -77
  833. package/src/daemon/conversation-agent-loop.ts +10 -17
  834. package/src/daemon/conversation-error.ts +53 -16
  835. package/src/daemon/conversation-history.ts +6 -12
  836. package/src/daemon/conversation-messaging.ts +13 -1
  837. package/src/daemon/conversation-process.ts +16 -11
  838. package/src/daemon/conversation-runtime-assembly.ts +148 -52
  839. package/src/daemon/conversation-surfaces.ts +217 -100
  840. package/src/daemon/conversation-tool-setup.ts +59 -112
  841. package/src/daemon/conversation-turn-finalize.ts +18 -0
  842. package/src/daemon/conversation.ts +35 -66
  843. package/src/daemon/event-loop-watchdog.test.ts +1 -6
  844. package/src/daemon/external-plugins-bootstrap.ts +20 -74
  845. package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +0 -7
  846. package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +1 -8
  847. package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +1 -8
  848. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +1 -8
  849. package/src/daemon/handlers/__tests__/config-a2a.test.ts +1 -8
  850. package/src/daemon/handlers/conversation-history.ts +6 -4
  851. package/src/daemon/handlers/conversations.ts +19 -9
  852. package/src/daemon/handlers/shared.ts +24 -1
  853. package/src/daemon/inflight-message-content.ts +228 -0
  854. package/src/daemon/lifecycle.ts +21 -31
  855. package/src/daemon/message-protocol.ts +2 -7
  856. package/src/daemon/message-provenance.ts +17 -8
  857. package/src/daemon/message-types/conversations.ts +6 -17
  858. package/src/daemon/message-types/host-ui-snapshot.ts +44 -0
  859. package/src/daemon/message-types/inbox.ts +3 -46
  860. package/src/daemon/orphan-reaper.test.ts +1 -6
  861. package/src/daemon/process-message.ts +9 -0
  862. package/src/daemon/providers-setup.ts +5 -75
  863. package/src/daemon/route-conversation-post.ts +158 -0
  864. package/src/daemon/shutdown-handlers.ts +11 -17
  865. package/src/daemon/sqlite-corruption-watchdog.test.ts +0 -6
  866. package/src/documents/document-comments-store.test.ts +1 -7
  867. package/src/export/__tests__/transcript-formatter.test.ts +8 -8
  868. package/src/export/formatter.ts +8 -17
  869. package/src/export/transcript-formatter.ts +4 -1
  870. package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +0 -9
  871. package/src/heartbeat/__tests__/heartbeat-service.test.ts +29 -57
  872. package/src/home/__tests__/home-content-refresh.test.ts +0 -7
  873. package/src/home/__tests__/suggested-prompts.test.ts +0 -11
  874. package/src/ipc/__tests__/contacts-info-ipc.test.ts +12 -10
  875. package/src/ipc/__tests__/email-ipc.test.ts +90 -0
  876. package/src/ipc/assistant-server.ts +10 -22
  877. package/src/ipc/routes/__tests__/guardian-label-ipc-routes.test.ts +74 -0
  878. package/src/ipc/routes/__tests__/invite-ipc-routes.test.ts +0 -7
  879. package/src/ipc/routes/guardian-label-ipc-routes.ts +42 -0
  880. package/src/live-voice/__tests__/live-voice-archive.test.ts +1 -8
  881. package/src/live-voice/__tests__/live-voice-credential-preflight.test.ts +89 -49
  882. package/src/live-voice/__tests__/live-voice-integration.test.ts +116 -2
  883. package/src/live-voice/__tests__/live-voice-resume-registry.test.ts +58 -0
  884. package/src/live-voice/__tests__/live-voice-resume-turn.test.ts +280 -0
  885. package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +337 -0
  886. package/src/live-voice/__tests__/live-voice-tts.test.ts +0 -4
  887. package/src/live-voice/__tests__/live-voice-vad.test.ts +432 -12
  888. package/src/live-voice/__tests__/protocol.test.ts +122 -0
  889. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -41
  890. package/src/live-voice/live-voice-credential-preflight.ts +27 -3
  891. package/src/live-voice/live-voice-resume-registry.ts +54 -0
  892. package/src/live-voice/live-voice-session.ts +602 -61
  893. package/src/live-voice/protocol.ts +143 -1
  894. package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +3 -7
  895. package/src/messaging/provider-types.ts +9 -0
  896. package/src/messaging/providers/a2a/__tests__/deliver.test.ts +0 -9
  897. package/src/messaging/providers/outlook/adapter.ts +17 -2
  898. package/src/messaging/providers/outlook/client.ts +11 -2
  899. package/src/messaging/providers/outlook/types.ts +9 -0
  900. package/src/messaging/providers/slack/__tests__/download.test.ts +1 -8
  901. package/src/messaging/providers/slack/binding-metadata.test.ts +23 -21
  902. package/src/messaging/providers/slack/send.test.ts +0 -7
  903. package/src/messaging/providers/slack/withdraw.test.ts +0 -6
  904. package/src/messaging/providers/telegram-bot/send.test.ts +0 -7
  905. package/src/monitoring/__tests__/plugin-source-watch.test.ts +40 -1
  906. package/src/monitoring/plugin-source-watch.ts +56 -62
  907. package/src/monitoring/recovery/__tests__/inflight-content.test.ts +166 -0
  908. package/src/monitoring/recovery/inflight-content.ts +260 -0
  909. package/src/monitoring/recovery/run-recovery.ts +72 -0
  910. package/src/monitoring/worker.ts +68 -7
  911. package/src/notifications/AGENTS.md +1 -1
  912. package/src/notifications/README.md +4 -4
  913. package/src/notifications/__tests__/broadcaster.test.ts +4 -17
  914. package/src/notifications/__tests__/connected-channels.test.ts +11 -8
  915. package/src/notifications/__tests__/decision-engine.test.ts +0 -7
  916. package/src/notifications/__tests__/destination-resolver.test.ts +18 -12
  917. package/src/notifications/__tests__/deterministic-checks.test.ts +1 -9
  918. package/src/notifications/adapters/macos.ts +3 -5
  919. package/src/notifications/adapters/platform.ts +1 -1
  920. package/src/notifications/broadcaster.ts +13 -4
  921. package/src/notifications/conversation-candidates.ts +21 -28
  922. package/src/notifications/copy-composer.ts +0 -6
  923. package/src/notifications/decision-engine.ts +1 -1
  924. package/src/notifications/{canonical-delivery-recorder.ts → guardian-delivery-recorder.ts} +47 -33
  925. package/src/notifications/home-feed-side-effect.ts +0 -2
  926. package/src/notifications/signal.ts +0 -4
  927. package/src/oauth/byo-connection.test.ts +0 -9
  928. package/src/oauth/connection-resolver.test.ts +18 -46
  929. package/src/oauth/seed-providers.ts +6 -0
  930. package/src/onboarding/__tests__/onboarding-events-store.test.ts +122 -44
  931. package/src/onboarding/onboarding-events-store.ts +67 -115
  932. package/src/onboarding/onboarding-research-events-store.test.ts +222 -0
  933. package/src/onboarding/onboarding-research-events-store.ts +92 -0
  934. package/src/permissions/checker.test.ts +10 -24
  935. package/src/permissions/confirmation-guardian-request.test.ts +94 -0
  936. package/src/permissions/{confirmation-canonical-request.ts → confirmation-guardian-request.ts} +44 -29
  937. package/src/permissions/gateway-threshold-reader.test.ts +0 -8
  938. package/src/permissions/prompter.ts +6 -4
  939. package/src/permissions/question-prompter.test.ts +7 -14
  940. package/src/persistence/__tests__/bulk-write-gate.test.ts +1 -7
  941. package/src/persistence/__tests__/conversation-queries-search.test.ts +0 -7
  942. package/src/persistence/__tests__/main-db-readonly-probe.ts +80 -0
  943. package/src/persistence/__tests__/main-db-readonly.test.ts +35 -0
  944. package/src/persistence/__tests__/message-content-file.test.ts +161 -52
  945. package/src/persistence/__tests__/raw-query-telemetry.test.ts +74 -0
  946. package/src/persistence/conversation-crud.ts +175 -45
  947. package/src/persistence/conversation-disk-view.ts +32 -15
  948. package/src/persistence/conversation-group-migration.test.ts +1 -8
  949. package/src/persistence/conversation-title-service.ts +59 -22
  950. package/src/persistence/db-connection.ts +46 -1
  951. package/src/persistence/db-singleton.ts +7 -1
  952. package/src/persistence/embeddings/__tests__/messages-lexical-index.test.ts +3 -7
  953. package/src/persistence/embeddings/messages-lexical-index.ts +11 -0
  954. package/src/persistence/job-handlers/__tests__/message-lexical-backfill.test.ts +0 -7
  955. package/src/persistence/job-handlers/__tests__/message-lexical-enqueue.test.ts +0 -6
  956. package/src/persistence/job-handlers/__tests__/message-lexical.test.ts +0 -7
  957. package/src/persistence/job-handlers/cleanup.ts +30 -16
  958. package/src/persistence/job-handlers/message-lexical-backfill.ts +8 -5
  959. package/src/persistence/job-handlers/message-lexical.ts +2 -2
  960. package/src/persistence/jobs-store.ts +123 -17
  961. package/src/persistence/lifecycle-events-store.test.ts +84 -0
  962. package/src/persistence/lifecycle-events-store.ts +27 -52
  963. package/src/persistence/llm-request-log-sink-clickhouse.ts +325 -0
  964. package/src/persistence/llm-request-log-store.ts +185 -106
  965. package/src/persistence/llm-request-log-writer-types.ts +80 -0
  966. package/src/persistence/llm-usage-store.ts +5 -2
  967. package/src/persistence/message-content-file.ts +182 -71
  968. package/src/persistence/message-content.ts +18 -10
  969. package/src/persistence/migrations/305-drop-contact-acl-columns.ts +3 -2
  970. package/src/persistence/migrations/325-create-config-setting-events.ts +40 -0
  971. package/src/persistence/migrations/326-move-injection-events-to-memory-db.ts +104 -0
  972. package/src/persistence/migrations/327-create-flush-checkpoints.ts +86 -0
  973. package/src/persistence/migrations/328-drop-memory-v3-learned-edge-tables.ts +16 -0
  974. package/src/persistence/migrations/329-move-onboarding-events-to-telemetry-db.test.ts +179 -0
  975. package/src/persistence/migrations/329-move-onboarding-events-to-telemetry-db.ts +119 -0
  976. package/src/persistence/migrations/330-move-auth-fallback-events-to-telemetry-db.test.ts +197 -0
  977. package/src/persistence/migrations/330-move-auth-fallback-events-to-telemetry-db.ts +108 -0
  978. package/src/persistence/migrations/331-move-lifecycle-events-to-telemetry-db.test.ts +159 -0
  979. package/src/persistence/migrations/331-move-lifecycle-events-to-telemetry-db.ts +97 -0
  980. package/src/persistence/migrations/332-move-skill-loaded-events-to-telemetry-db.test.ts +219 -0
  981. package/src/persistence/migrations/332-move-skill-loaded-events-to-telemetry-db.ts +128 -0
  982. package/src/persistence/migrations/333-create-telemetry-events-table.test.ts +66 -0
  983. package/src/persistence/migrations/333-create-telemetry-events-table.ts +43 -0
  984. package/src/persistence/migrations/334-backfill-telemetry-events-outbox.test.ts +584 -0
  985. package/src/persistence/migrations/334-backfill-telemetry-events-outbox.ts +386 -0
  986. package/src/persistence/migrations/335-collapse-memory-embed-backlog.test.ts +181 -0
  987. package/src/persistence/migrations/335-collapse-memory-embed-backlog.ts +177 -0
  988. package/src/persistence/migrations/__tests__/327-create-flush-checkpoints.test.ts +124 -0
  989. package/src/persistence/raw-query.ts +27 -1
  990. package/src/persistence/schema/calls.ts +0 -23
  991. package/src/persistence/schema/conversation-starters.ts +31 -0
  992. package/src/persistence/schema/conversations.ts +3 -3
  993. package/src/persistence/schema/guardian.ts +0 -150
  994. package/src/persistence/schema/index.ts +1 -0
  995. package/src/persistence/schema/infrastructure.ts +25 -72
  996. package/src/persistence/schema/memory-core.ts +0 -25
  997. package/src/persistence/schema/memory-injection.ts +3 -1
  998. package/src/persistence/schema/tasks.ts +1 -60
  999. package/src/persistence/steps.ts +22 -0
  1000. package/src/platform/client.test.ts +110 -0
  1001. package/src/platform/client.ts +24 -4
  1002. package/src/platform/consent-cache.test.ts +5 -18
  1003. package/src/platform/consent-cache.ts +8 -6
  1004. package/src/platform/managed-speech.test.ts +218 -0
  1005. package/src/platform/managed-speech.ts +204 -0
  1006. package/src/plugin-api/conversation-turn.ts +250 -0
  1007. package/src/plugin-api/index.ts +21 -0
  1008. package/src/plugin-api/model-profiles.test.ts +29 -28
  1009. package/src/plugin-api/vision-support.test.ts +25 -38
  1010. package/src/plugin-api/vision-support.ts +26 -17
  1011. package/src/plugins/AGENTS.md +8 -0
  1012. package/src/plugins/__tests__/source-fingerprint.test.ts +41 -0
  1013. package/src/plugins/collect-source-versions.ts +77 -0
  1014. package/src/plugins/defaults/image-recovery/detect.ts +32 -10
  1015. package/src/plugins/defaults/image-recovery/hooks/post-model-call.ts +20 -18
  1016. package/src/plugins/defaults/image-recovery/recover.ts +86 -59
  1017. package/src/plugins/defaults/memory/__tests__/activation-session-store.test.ts +1 -8
  1018. package/src/plugins/defaults/memory/__tests__/clear-stale-processing-flags.test.ts +1 -8
  1019. package/src/plugins/defaults/memory/__tests__/conversation-queries.test.ts +1 -8
  1020. package/src/plugins/defaults/memory/__tests__/conversation-row-batch-delete.test.ts +7 -18
  1021. package/src/plugins/defaults/memory/__tests__/db-memory-attach.test.ts +22 -18
  1022. package/src/plugins/defaults/memory/__tests__/embedding-cache.test.ts +0 -6
  1023. package/src/plugins/defaults/memory/__tests__/find-most-recent-retrospective-for.test.ts +1 -8
  1024. package/src/plugins/defaults/memory/__tests__/fork-message-copy.test.ts +7 -18
  1025. package/src/plugins/defaults/memory/__tests__/jobs-store-enqueue-gate.test.ts +29 -39
  1026. package/src/plugins/defaults/memory/__tests__/jobs-worker-memory-disabled.test.ts +11 -26
  1027. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +3 -22
  1028. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-schedule.test.ts +215 -1
  1029. package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +0 -7
  1030. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +114 -16
  1031. package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +180 -0
  1032. package/src/plugins/defaults/memory/__tests__/memory-retrospective-skill-card.test.ts +153 -519
  1033. package/src/plugins/defaults/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +0 -7
  1034. package/src/plugins/defaults/memory/__tests__/memory-retrospective-state.test.ts +6 -17
  1035. package/src/plugins/defaults/memory/__tests__/memory-retrospective-trigger-check.test.ts +0 -7
  1036. package/src/plugins/defaults/memory/__tests__/memory-v2-activation-log-store.test.ts +1 -19
  1037. package/src/plugins/defaults/memory/__tests__/memory-v2-concept-frequency.test.ts +0 -18
  1038. package/src/plugins/defaults/memory/__tests__/shutdown-hook.test.ts +8 -7
  1039. package/src/plugins/defaults/memory/__tests__/table-relocation.test.ts +49 -0
  1040. package/src/{persistence → plugins/defaults/memory}/__tests__/worker-control.test.ts +8 -10
  1041. package/src/plugins/defaults/memory/graph/capability-seed.ts +4 -6
  1042. package/src/plugins/defaults/memory/graph/extraction.ts +5 -1
  1043. package/src/plugins/defaults/memory/graph/graph-search.test.ts +2 -8
  1044. package/src/plugins/defaults/memory/graph/tool-handlers.test.ts +0 -6
  1045. package/src/plugins/defaults/memory/graph/tool-handlers.ts +2 -2
  1046. package/src/plugins/defaults/memory/graph/tools.ts +47 -13
  1047. package/src/plugins/defaults/memory/graph-topology/__tests__/build-memory-graph.test.ts +81 -2
  1048. package/src/plugins/defaults/memory/graph-topology/build-memory-graph.ts +67 -32
  1049. package/src/plugins/defaults/memory/hooks/shutdown.ts +8 -11
  1050. package/src/plugins/defaults/memory/indexer.ts +2 -1
  1051. package/src/plugins/defaults/memory/job-handlers/backfill.ts +8 -5
  1052. package/src/plugins/defaults/memory/job-handlers/embedding.test.ts +0 -7
  1053. package/src/plugins/defaults/memory/job-handlers/embedding.ts +2 -2
  1054. package/src/plugins/defaults/memory/job-handlers/index-maintenance.ts +7 -2
  1055. package/src/plugins/defaults/memory/jobs/__tests__/embed-concept-page.test.ts +73 -8
  1056. package/src/plugins/defaults/memory/jobs/embed-concept-page.ts +5 -3
  1057. package/src/plugins/defaults/memory/jobs/embed-pkb-file.test.ts +0 -13
  1058. package/src/plugins/defaults/memory/jobs-worker.ts +139 -107
  1059. package/src/plugins/defaults/memory/memory-db.ts +27 -0
  1060. package/src/plugins/defaults/memory/memory-retrospective-constants.ts +4 -4
  1061. package/src/plugins/defaults/memory/memory-retrospective-job.ts +56 -180
  1062. package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +216 -0
  1063. package/src/plugins/defaults/memory/memory-retrospective-skill-card.ts +122 -202
  1064. package/src/plugins/defaults/memory/message-media.ts +2 -2
  1065. package/src/plugins/defaults/memory/paths.ts +3 -2
  1066. package/src/plugins/defaults/memory/pkb/pkb-index.test.ts +0 -12
  1067. package/src/plugins/defaults/memory/pkb/pkb-reconcile.test.ts +0 -9
  1068. package/src/plugins/defaults/memory/pkb/pkb-search.test.ts +0 -6
  1069. package/src/plugins/defaults/memory/routes/__tests__/memory-v2-simulate-route.test.ts +15 -92
  1070. package/src/plugins/defaults/memory/routes/__tests__/memory-worker-routes.test.ts +201 -0
  1071. package/src/plugins/defaults/memory/routes/memory-item-routes.test.ts +7 -21
  1072. package/src/plugins/defaults/memory/routes/memory-v2-routes.ts +3 -8
  1073. package/src/plugins/defaults/memory/routes/memory-worker-routes.ts +162 -0
  1074. package/src/plugins/defaults/memory/startup.ts +6 -7
  1075. package/src/plugins/defaults/memory/task-memory-cleanup.ts +11 -22
  1076. package/src/plugins/defaults/memory/tools.test.ts +40 -8
  1077. package/src/plugins/defaults/memory/tools.ts +12 -2
  1078. package/src/plugins/defaults/memory/v2/__tests__/activation.test.ts +0 -19
  1079. package/src/plugins/defaults/memory/v2/__tests__/backfill-jobs.test.ts +63 -40
  1080. package/src/plugins/defaults/memory/v2/__tests__/cli-command-store.test.ts +61 -130
  1081. package/src/plugins/defaults/memory/v2/__tests__/consolidation-job.test.ts +406 -10
  1082. package/src/plugins/defaults/memory/v2/__tests__/harness-compare.test.ts +1 -10
  1083. package/src/plugins/defaults/memory/v2/__tests__/harness-oracle.test.ts +1 -10
  1084. package/src/plugins/defaults/memory/v2/__tests__/harness-replay-input.test.ts +1 -10
  1085. package/src/plugins/defaults/memory/v2/__tests__/injection-events.test.ts +61 -69
  1086. package/src/plugins/defaults/memory/v2/__tests__/injection.test.ts +0 -19
  1087. package/src/plugins/defaults/memory/v2/__tests__/migration.test.ts +11 -10
  1088. package/src/plugins/defaults/memory/v2/__tests__/page-index.test.ts +0 -5
  1089. package/src/plugins/defaults/memory/v2/__tests__/qdrant.test.ts +6 -22
  1090. package/src/plugins/defaults/memory/v2/__tests__/reranker.test.ts +3 -5
  1091. package/src/plugins/defaults/memory/v2/__tests__/router.test.ts +7 -20
  1092. package/src/plugins/defaults/memory/v2/__tests__/sim.test.ts +0 -24
  1093. package/src/plugins/defaults/memory/v2/__tests__/skill-content.test.ts +17 -11
  1094. package/src/plugins/defaults/memory/v2/__tests__/skill-store.test.ts +0 -16
  1095. package/src/plugins/defaults/memory/v2/__tests__/static-context.test.ts +0 -10
  1096. package/src/plugins/defaults/memory/v2/__tests__/sweep-job.test.ts +0 -6
  1097. package/src/plugins/defaults/memory/v2/backfill-jobs.ts +5 -2
  1098. package/src/plugins/defaults/memory/v2/cli-command-content.ts +43 -12
  1099. package/src/plugins/defaults/memory/v2/cli-command-store.ts +34 -50
  1100. package/src/plugins/defaults/memory/v2/consolidation-job.ts +216 -10
  1101. package/src/plugins/defaults/memory/v2/harness/router-retriever.ts +1 -8
  1102. package/src/plugins/defaults/memory/v2/injection-events.ts +16 -14
  1103. package/src/plugins/defaults/memory/v2/injection.ts +1 -2
  1104. package/src/plugins/defaults/memory/v2/memory-v2-startup.test.ts +0 -5
  1105. package/src/plugins/defaults/memory/v2/migration.ts +55 -24
  1106. package/src/plugins/defaults/memory/v2/prompts/consolidation.ts +4 -0
  1107. package/src/plugins/defaults/memory/v2/router.ts +4 -14
  1108. package/src/plugins/defaults/memory/v2/sweep-job.ts +1 -0
  1109. package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +10 -22
  1110. package/src/plugins/defaults/memory/v3/__tests__/dense.test.ts +0 -5
  1111. package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +18 -20
  1112. package/src/plugins/defaults/memory/v3/__tests__/section-dense-store.test.ts +0 -5
  1113. package/src/plugins/defaults/memory/v3/__tests__/selection-log-store.test.ts +5 -9
  1114. package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +51 -31
  1115. package/src/plugins/defaults/memory/v3/prune.test.ts +3 -11
  1116. package/src/{persistence → plugins/defaults/memory}/worker-control.ts +12 -21
  1117. package/src/plugins/defaults/memory/worker.ts +19 -2
  1118. package/src/plugins/mtime-cache.ts +166 -70
  1119. package/src/plugins/plugin-tree-walk.ts +41 -4
  1120. package/src/plugins/source-fingerprint.ts +9 -3
  1121. package/src/plugins/surface-import.ts +28 -0
  1122. package/src/plugins/types.ts +9 -23
  1123. package/src/prompts/__tests__/system-prompt.test.ts +0 -28
  1124. package/src/prompts/__tests__/task-progress-hint-section.test.ts +0 -28
  1125. package/src/providers/__tests__/connection-model-compat.test.ts +6 -19
  1126. package/src/providers/__tests__/count-tokens-forwarding.test.ts +1 -21
  1127. package/src/providers/__tests__/dispatch-connection-routing.test.ts +9 -26
  1128. package/src/providers/__tests__/registry-native-web-search.test.ts +4 -10
  1129. package/src/providers/__tests__/retry-callsite.test.ts +240 -235
  1130. package/src/providers/__tests__/satellite-connection-routing.test.ts +11 -36
  1131. package/src/providers/__tests__/vellum-mismatch-routing.test.ts +0 -5
  1132. package/src/providers/anthropic/client.ts +9 -3
  1133. package/src/providers/call-site-routing.ts +7 -3
  1134. package/src/providers/connection-resolution.ts +9 -11
  1135. package/src/providers/content-block-schema.ts +149 -0
  1136. package/src/providers/inference/__tests__/base-url-route-validation.test.ts +7 -11
  1137. package/src/providers/inference/__tests__/codex-token-refresh.test.ts +1 -15
  1138. package/src/providers/inference/auth.ts +23 -0
  1139. package/src/providers/inference/backfill.ts +25 -9
  1140. package/src/providers/model-catalog.ts +213 -5
  1141. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +54 -0
  1142. package/src/providers/openai/chat-completions-provider.ts +13 -2
  1143. package/src/providers/openai/responses-provider.ts +232 -5
  1144. package/src/providers/openrouter/client.ts +53 -0
  1145. package/src/providers/retry.ts +25 -2
  1146. package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +13 -0
  1147. package/src/providers/speech-to-text/__tests__/resolve.test.ts +211 -74
  1148. package/src/providers/speech-to-text/__tests__/vellum-managed-realtime.test.ts +408 -0
  1149. package/src/providers/speech-to-text/__tests__/vellum-managed.test.ts +121 -0
  1150. package/src/providers/speech-to-text/__tests__/vellum-speech-relay-connection.test.ts +126 -0
  1151. package/src/providers/speech-to-text/deepgram-realtime.ts +167 -37
  1152. package/src/providers/speech-to-text/incremental-batch-stream.ts +413 -0
  1153. package/src/providers/speech-to-text/openai-whisper-stream.ts +16 -363
  1154. package/src/providers/speech-to-text/provider-catalog.ts +26 -1
  1155. package/src/providers/speech-to-text/resolve.ts +74 -13
  1156. package/src/providers/speech-to-text/vellum-managed-realtime.ts +309 -0
  1157. package/src/providers/speech-to-text/vellum-managed.ts +71 -0
  1158. package/src/providers/speech-to-text/vellum-speech-relay-connection.ts +174 -0
  1159. package/src/providers/types.ts +23 -4
  1160. package/src/providers/vellum-model-routing.test.ts +26 -0
  1161. package/src/providers/vellum-model-routing.ts +30 -0
  1162. package/src/runtime/AGENTS.md +1 -1
  1163. package/src/runtime/__tests__/actor-trust-resolver.test.ts +2 -8
  1164. package/src/runtime/__tests__/agent-wake.test.ts +100 -27
  1165. package/src/runtime/__tests__/background-job-runner.test.ts +22 -0
  1166. package/src/runtime/__tests__/guardian-vellum-migration.test.ts +0 -5
  1167. package/src/runtime/__tests__/member-verdict-cache.test.ts +2 -9
  1168. package/src/runtime/__tests__/trust-verdict-consumer.test.ts +22 -5
  1169. package/src/runtime/access-request-helper.ts +84 -60
  1170. package/src/runtime/actor-trust-resolver.ts +2 -2
  1171. package/src/runtime/agent-wake.ts +75 -26
  1172. package/src/runtime/assistant-event-hub.ts +1 -0
  1173. package/src/runtime/auth/__tests__/middleware.test.ts +1 -10
  1174. package/src/runtime/auth/__tests__/route-policy.test.ts +0 -7
  1175. package/src/runtime/auth/__tests__/token-service.test.ts +1 -8
  1176. package/src/runtime/auth/same-actor.ts +2 -1
  1177. package/src/runtime/background-job-runner.ts +22 -0
  1178. package/src/runtime/channel-approval-types.ts +1 -1
  1179. package/src/runtime/channel-reply-delivery.ts +38 -19
  1180. package/src/runtime/confirmation-request-guardian-bridge.ts +45 -39
  1181. package/src/runtime/for-chat-mint-registry.ts +118 -0
  1182. package/src/runtime/guardian-action-service.ts +32 -27
  1183. package/src/runtime/guardian-decision-types.ts +2 -2
  1184. package/src/runtime/guardian-reply-router.ts +80 -98
  1185. package/src/runtime/http-server.ts +61 -41
  1186. package/src/runtime/introduction-policy.ts +2 -2
  1187. package/src/runtime/local-actor-identity.ts +19 -7
  1188. package/src/runtime/pending-interactions.ts +1 -0
  1189. package/src/runtime/reveal-nonce.ts +49 -0
  1190. package/src/runtime/reveal-success-registry.ts +306 -0
  1191. package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -7
  1192. package/src/runtime/routes/__tests__/backup-routes.test.ts +195 -125
  1193. package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +4 -1
  1194. package/src/runtime/routes/__tests__/client-routes.test.ts +0 -7
  1195. package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +1 -19
  1196. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +1 -8
  1197. package/src/runtime/routes/__tests__/contact-routes-merge-relay.test.ts +186 -0
  1198. package/src/runtime/routes/__tests__/contact-routes-update-channel-relay.test.ts +2 -3
  1199. package/src/runtime/routes/__tests__/content-source-routes.test.ts +0 -7
  1200. package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +5 -27
  1201. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +0 -7
  1202. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +12 -30
  1203. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +59 -56
  1204. package/src/runtime/routes/__tests__/conversation-surface-routes.test.ts +0 -7
  1205. package/src/runtime/routes/__tests__/default-provider-routes.test.ts +53 -73
  1206. package/src/runtime/routes/__tests__/gateway-status-routes.test.ts +84 -0
  1207. package/src/runtime/routes/__tests__/inference-callsites-routes.test.ts +2 -10
  1208. package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +58 -90
  1209. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +161 -93
  1210. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +6 -1
  1211. package/src/runtime/routes/__tests__/monitoring-routes.test.ts +0 -8
  1212. package/src/runtime/routes/__tests__/plugins-routes.test.ts +218 -64
  1213. package/src/runtime/routes/__tests__/question-routes.test.ts +2 -4
  1214. package/src/runtime/routes/__tests__/retrospective-routes.test.ts +1 -8
  1215. package/src/runtime/routes/__tests__/sanity-routes.test.ts +0 -7
  1216. package/src/runtime/routes/__tests__/schedule-routes-create.test.ts +2 -1
  1217. package/src/runtime/routes/__tests__/schedule-worker-routes.test.ts +16 -56
  1218. package/src/runtime/routes/__tests__/stt-routes.test.ts +0 -9
  1219. package/src/runtime/routes/__tests__/suggest-trust-rule-routes.test.ts +0 -7
  1220. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +5 -0
  1221. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +354 -1
  1222. package/src/runtime/routes/__tests__/tts-routes.test.ts +0 -11
  1223. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +163 -10
  1224. package/src/runtime/routes/__tests__/user-routes-cli.test.ts +154 -0
  1225. package/src/runtime/routes/__tests__/wake-conversation-routes.test.ts +0 -7
  1226. package/src/runtime/routes/acp-routes.ts +21 -9
  1227. package/src/runtime/routes/app-management-routes.ts +231 -60
  1228. package/src/runtime/routes/app-routes.ts +130 -83
  1229. package/src/runtime/routes/auth-routes.ts +3 -1
  1230. package/src/runtime/routes/background-wake-routes.ts +0 -1
  1231. package/src/runtime/routes/cache-routes.ts +3 -3
  1232. package/src/runtime/routes/call-routes.ts +5 -1
  1233. package/src/runtime/routes/channel-verification-routes.ts +2 -1
  1234. package/src/runtime/routes/contact-prompt-routes.ts +11 -5
  1235. package/src/runtime/routes/contact-routes.ts +34 -42
  1236. package/src/runtime/routes/conversation-attention-routes.ts +1 -1
  1237. package/src/runtime/routes/conversation-cli-routes.ts +1 -1
  1238. package/src/runtime/routes/conversation-query-routes.ts +4 -4
  1239. package/src/runtime/routes/conversation-routes.ts +111 -72
  1240. package/src/runtime/routes/credential-routes.ts +116 -3
  1241. package/src/runtime/routes/email-routes.ts +17 -1
  1242. package/src/runtime/routes/events-routes.ts +1 -0
  1243. package/src/runtime/routes/gateway-status-routes.ts +69 -0
  1244. package/src/runtime/routes/guardian-action-routes.ts +18 -16
  1245. package/src/runtime/routes/guardian-approval-interception.ts +6 -4
  1246. package/src/runtime/routes/guardian-approval-prompt.ts +7 -5
  1247. package/src/runtime/routes/guardian-expiry-sweep.ts +130 -0
  1248. package/src/runtime/routes/inbound-message-handler.ts +9 -33
  1249. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +0 -5
  1250. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +9 -9
  1251. package/src/runtime/routes/inbound-stages/admission-policy.test.ts +24 -6
  1252. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +0 -7
  1253. package/src/runtime/routes/inbound-stages/bootstrap-intercept.test.ts +0 -5
  1254. package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +6 -3
  1255. package/src/runtime/routes/inbound-stages/edit-intercept.ts +5 -1
  1256. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +0 -9
  1257. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +4 -1
  1258. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +3 -12
  1259. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +16 -14
  1260. package/src/runtime/routes/inbound-stages/reaction-intercept.test.ts +8 -2
  1261. package/src/runtime/routes/inbound-stages/reaction-intercept.ts +15 -7
  1262. package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +0 -9
  1263. package/src/runtime/routes/index.ts +5 -5
  1264. package/src/runtime/routes/inference-provider-connection-routes.ts +73 -24
  1265. package/src/runtime/routes/inference-send-routes.ts +1 -1
  1266. package/src/runtime/routes/internal-telemetry-routes.ts +11 -2
  1267. package/src/runtime/routes/oauth-connect-routes.ts +27 -7
  1268. package/src/runtime/routes/platform-routes.ts +4 -14
  1269. package/src/runtime/routes/playground/__tests__/force-compact.test.ts +0 -4
  1270. package/src/runtime/routes/playground/__tests__/guard.test.ts +0 -4
  1271. package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +0 -14
  1272. package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +0 -21
  1273. package/src/runtime/routes/playground/__tests__/seed-conversation.test.ts +0 -4
  1274. package/src/runtime/routes/playground/__tests__/seeded-conversations.test.ts +16 -18
  1275. package/src/runtime/routes/playground/__tests__/state.test.ts +0 -14
  1276. package/src/runtime/routes/playground/seed-conversation.ts +5 -4
  1277. package/src/runtime/routes/playground/seeded-conversations.ts +3 -2
  1278. package/src/runtime/routes/plugins-routes.ts +163 -25
  1279. package/src/runtime/routes/profiler-routes.ts +2 -5
  1280. package/src/runtime/routes/publish-routes.ts +15 -18
  1281. package/src/runtime/routes/question-routes.ts +8 -4
  1282. package/src/runtime/routes/schedule-routes.ts +20 -78
  1283. package/src/runtime/routes/schedule-worker-routes.ts +16 -84
  1284. package/src/runtime/routes/secret-routes.ts +14 -0
  1285. package/src/runtime/routes/settings-routes.ts +21 -25
  1286. package/src/runtime/routes/subagents-routes.ts +17 -18
  1287. package/src/runtime/routes/surface-action-routes.ts +18 -39
  1288. package/src/runtime/routes/surface-content-routes.ts +59 -1
  1289. package/src/runtime/routes/surface-conversation-resolver.ts +148 -4
  1290. package/src/runtime/routes/telemetry-routes.ts +74 -1
  1291. package/src/runtime/routes/tts-routes.ts +9 -5
  1292. package/src/runtime/routes/ui-snapshot-routes.test.ts +219 -0
  1293. package/src/runtime/routes/ui-snapshot-routes.ts +313 -0
  1294. package/src/runtime/routes/user-route-dispatcher.ts +52 -53
  1295. package/src/runtime/routes/user-route-resolution.ts +141 -0
  1296. package/src/runtime/routes/user-routes-cli.ts +56 -35
  1297. package/src/runtime/routes/user-routes.ts +9 -2
  1298. package/src/runtime/routes/vellum-actor-trust.ts +67 -0
  1299. package/src/runtime/services/__tests__/auto-analysis-guard.test.ts +1 -8
  1300. package/src/runtime/tool-grant-request-helper.ts +34 -30
  1301. package/src/runtime/trust-verdict-consumer.ts +4 -6
  1302. package/src/schedule/__tests__/worker-control.test.ts +3 -3
  1303. package/src/schedule/schedule-store.ts +0 -41
  1304. package/src/schedule/scheduler.ts +38 -257
  1305. package/src/schedule/worker-control.ts +11 -21
  1306. package/src/schedule/worker.ts +18 -5
  1307. package/src/security/__tests__/oauth2-device-code.test.ts +12 -60
  1308. package/src/security/__tests__/provider-key-env-fallback.test.ts +0 -10
  1309. package/src/security/auth-fallback-events-store.ts +34 -72
  1310. package/src/security/secret-scanner.ts +26 -1
  1311. package/src/sequence/engine.ts +15 -6
  1312. package/src/services/published-app-updater.ts +6 -11
  1313. package/src/stt/__tests__/daemon-batch-transcriber.test.ts +24 -4
  1314. package/src/stt/daemon-batch-transcriber.ts +33 -2
  1315. package/src/stt/stt-stream-session.ts +17 -11
  1316. package/src/stt/types.ts +2 -1
  1317. package/src/subagent/manager.ts +4 -3
  1318. package/src/telemetry/AGENTS.md +44 -0
  1319. package/src/telemetry/__tests__/config-setting-events-store.test.ts +63 -0
  1320. package/src/telemetry/__tests__/config-setting-snapshot.test.ts +107 -0
  1321. package/src/telemetry/__tests__/flush-checkpoints.test.ts +56 -0
  1322. package/src/telemetry/__tests__/outbox-test-harness.ts +83 -0
  1323. package/src/telemetry/__tests__/telemetry-event-fixtures.ts +258 -0
  1324. package/src/telemetry/__tests__/watchdog-events-store.test.ts +32 -122
  1325. package/src/telemetry/config-setting-events-store.ts +40 -0
  1326. package/src/telemetry/config-setting-snapshot.ts +135 -0
  1327. package/src/telemetry/flush-checkpoints.ts +70 -0
  1328. package/src/telemetry/skill-loaded-events-store.test.ts +54 -113
  1329. package/src/telemetry/skill-loaded-events-store.ts +21 -77
  1330. package/src/telemetry/telemetry-event-sources.test.ts +211 -0
  1331. package/src/telemetry/telemetry-event-sources.ts +582 -0
  1332. package/src/telemetry/telemetry-events-outbox.test.ts +330 -0
  1333. package/src/telemetry/telemetry-events-outbox.ts +204 -0
  1334. package/src/telemetry/telemetry-main-db.ts +48 -0
  1335. package/src/telemetry/telemetry-wire-source.json +4 -0
  1336. package/src/telemetry/telemetry-wire-validation.test.ts +157 -0
  1337. package/src/telemetry/telemetry-wire-validation.ts +125 -0
  1338. package/src/telemetry/telemetry-wire.generated.ts +433 -0
  1339. package/src/telemetry/tool-executed-events-store.test.ts +0 -8
  1340. package/src/telemetry/tool-executed-events-store.ts +2 -2
  1341. package/src/telemetry/turn-trace-store.test.ts +86 -7
  1342. package/src/telemetry/turn-trace-store.ts +29 -1
  1343. package/src/telemetry/types.test.ts +38 -0
  1344. package/src/telemetry/types.ts +302 -87
  1345. package/src/telemetry/usage-telemetry-reporter.test.ts +921 -364
  1346. package/src/telemetry/usage-telemetry-reporter.ts +235 -722
  1347. package/src/telemetry/watchdog-direct-emit.test.ts +0 -5
  1348. package/src/telemetry/watchdog-direct-emit.ts +7 -1
  1349. package/src/telemetry/watchdog-events-store.ts +11 -70
  1350. package/src/tools/acp/spawn.test.ts +0 -7
  1351. package/src/tools/apps/definitions.ts +1 -7
  1352. package/src/tools/apps/executors.ts +11 -36
  1353. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +11 -24
  1354. package/src/tools/browser/__tests__/browser-status.test.ts +47 -33
  1355. package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +1 -11
  1356. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +75 -58
  1357. package/src/tools/browser/cdp-client/__tests__/local-cdp-client.test.ts +0 -10
  1358. package/src/tools/browser/network-recorder.test.ts +0 -11
  1359. package/src/tools/document/document-comment-tool.test.ts +1 -7
  1360. package/src/tools/host-terminal/host-shell.test.ts +0 -32
  1361. package/src/tools/host-terminal/host-shell.ts +6 -2
  1362. package/src/tools/network/__tests__/web-fetch-firecrawl.test.ts +13 -15
  1363. package/src/tools/network/__tests__/web-search-metadata.test.ts +15 -18
  1364. package/src/tools/network/__tests__/web-search.test.ts +39 -50
  1365. package/src/tools/registry.ts +148 -196
  1366. package/src/tools/skills/find-similar-skills.test.ts +0 -7
  1367. package/src/tools/skills/sandbox-runner.ts +5 -2
  1368. package/src/tools/skills/scaffold-managed.ts +105 -12
  1369. package/src/tools/subagent/read.ts +6 -4
  1370. package/src/tools/subagent/spawn.ts +20 -29
  1371. package/src/tools/terminal/safe-env.ts +7 -2
  1372. package/src/tools/terminal/shell.test.ts +4 -8
  1373. package/src/tools/terminal/shell.ts +5 -2
  1374. package/src/tools/tool-approval-handler.ts +39 -23
  1375. package/src/tools/tool-input-summary.ts +2 -1
  1376. package/src/tools/tool-manifest.ts +20 -6
  1377. package/src/tools/tool-profiler.ts +37 -6
  1378. package/src/tools/ui-surface/definitions.ts +1 -7
  1379. package/src/tools/workflows/run-workflow.test.ts +8 -22
  1380. package/src/tts/__tests__/provider-adapters.test.ts +28 -22
  1381. package/src/tts/__tests__/provider-resolution.test.ts +26 -0
  1382. package/src/tts/__tests__/synthesis-stream.test.ts +6 -6
  1383. package/src/tts/__tests__/vellum-provider.test.ts +251 -0
  1384. package/src/tts/provider-catalog.ts +6 -0
  1385. package/src/tts/providers/__tests__/vellum-tts-socket.test.ts +266 -0
  1386. package/src/tts/providers/vellum-provider.ts +220 -0
  1387. package/src/tts/providers/vellum-tts-socket.ts +377 -0
  1388. package/src/tts/synthesize-text.ts +15 -5
  1389. package/src/tts/tts-config-resolver.ts +2 -7
  1390. package/src/tts/types.ts +1 -0
  1391. package/src/usage/attribution.ts +20 -114
  1392. package/src/util/abort-reasons.ts +1 -3
  1393. package/src/util/image-conversion.ts +23 -5
  1394. package/src/util/logger.ts +8 -3
  1395. package/src/{config/bundled-skills/messaging/tools/gmail-mime-helpers.ts → util/mime-type.ts} +4 -1
  1396. package/src/util/platform.ts +0 -60
  1397. package/src/util/pricing.ts +10 -1
  1398. package/src/util/telemetry-db-path.ts +9 -7
  1399. package/src/watcher/__tests__/telemetry.test.ts +41 -11
  1400. package/src/watcher/providers/google-calendar.ts +81 -49
  1401. package/src/watcher/telemetry.ts +22 -5
  1402. package/src/workflows/engine-integration.test.ts +0 -6
  1403. package/src/workflows/engine.test.ts +1 -9
  1404. package/src/workflows/journal-store.test.ts +1 -9
  1405. package/src/workflows/leaf-runner.test.ts +17 -50
  1406. package/src/workflows/library.test.ts +1 -9
  1407. package/src/workflows/run-manager.test.ts +1 -9
  1408. package/src/workspace/git-service.ts +932 -37
  1409. package/src/workspace/provider-commit-message-generator.ts +6 -4
  1410. package/__tests__/permissions/gateway-threshold-reader.test.ts +0 -450
  1411. package/src/__tests__/canonical-guardian-store.test.ts +0 -928
  1412. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +0 -140
  1413. package/src/__tests__/plugin-route-contribution.test.ts +0 -245
  1414. package/src/__tests__/skill-runtime-path.test.ts +0 -63
  1415. package/src/__tests__/task-compiler.test.ts +0 -317
  1416. package/src/__tests__/task-management-tools.test.ts +0 -1128
  1417. package/src/__tests__/task-scheduler.test.ts +0 -786
  1418. package/src/config/schemas/schedules.ts +0 -35
  1419. package/src/contacts/canonical-guardian-store.ts +0 -902
  1420. package/src/daemon/message-types/work-items.ts +0 -243
  1421. package/src/runtime/routes/__tests__/memory-worker-routes.test.ts +0 -306
  1422. package/src/runtime/routes/__tests__/task-routes.test.ts +0 -644
  1423. package/src/runtime/routes/assets/vellum-design-system.css +0 -1959
  1424. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +0 -129
  1425. package/src/runtime/routes/inbound-stages/escalation-intercept.test.ts +0 -158
  1426. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +0 -187
  1427. package/src/runtime/routes/memory-worker-routes.ts +0 -227
  1428. package/src/runtime/routes/task-routes.ts +0 -380
  1429. package/src/runtime/routes/work-items-routes.test.ts +0 -75
  1430. package/src/runtime/routes/work-items-routes.ts +0 -881
  1431. package/src/runtime/skill-route-registry.ts +0 -131
  1432. package/src/tasks/SPEC.md +0 -132
  1433. package/src/tasks/task-compiler.ts +0 -194
  1434. package/src/tasks/task-runner.ts +0 -119
  1435. package/src/tasks/task-scheduler.ts +0 -22
  1436. package/src/tasks/task-store.ts +0 -153
  1437. package/src/tasks/tool-sanitizer.ts +0 -38
  1438. package/src/tools/apps/registry.ts +0 -16
  1439. package/src/tools/system/register.ts +0 -9
  1440. package/src/tools/tasks/task-delete.ts +0 -121
  1441. package/src/tools/tasks/task-list.ts +0 -56
  1442. package/src/tools/tasks/task-run.ts +0 -122
  1443. package/src/tools/tasks/task-save.ts +0 -64
  1444. package/src/tools/tasks/work-item-enqueue.ts +0 -300
  1445. package/src/tools/tasks/work-item-list.ts +0 -65
  1446. package/src/tools/tasks/work-item-remove.ts +0 -94
  1447. package/src/tools/tasks/work-item-run.ts +0 -99
  1448. package/src/tools/tasks/work-item-update.ts +0 -166
  1449. package/src/tools/ui-surface/registry.ts +0 -14
  1450. package/src/work-items/resolve-required-tools.test.ts +0 -37
  1451. package/src/work-items/resolve-required-tools.ts +0 -26
  1452. package/src/work-items/work-item-runner.ts +0 -187
  1453. package/src/work-items/work-item-store.ts +0 -416
@@ -6,6 +6,7 @@
6
6
  * testable while keeping shared mutable state bundled in EventHandlerState.
7
7
  */
8
8
 
9
+ import { SENTINEL_REDACTION_VERSION } from "@vellumai/service-contracts/redacted-credential";
9
10
  import type pino from "pino";
10
11
  import { v4 as uuid } from "uuid";
11
12
 
@@ -15,6 +16,7 @@ import type {
15
16
  TurnChannelContext,
16
17
  TurnInterfaceContext,
17
18
  } from "../channels/types.js";
19
+ import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
18
20
  import { getConfig } from "../config/loader.js";
19
21
  import { recordEstimate } from "../context/estimator-calibration.js";
20
22
  import { stripInjectionsForCompaction } from "../context/strip-injections.js";
@@ -61,7 +63,18 @@ import type {
61
63
  Message,
62
64
  } from "../providers/types.js";
63
65
  import { getCurrentSeq } from "../runtime/assistant-stream-state.js";
64
- import { redactSecrets } from "../security/secret-scanner.js";
66
+ import type { ForChatMint } from "../runtime/for-chat-mint-registry.js";
67
+ import {
68
+ currentForChatMintWatermark,
69
+ forChatMintsSince,
70
+ } from "../runtime/for-chat-mint-registry.js";
71
+ import { conversationRevealNonce } from "../runtime/reveal-nonce.js";
72
+ import {
73
+ closeRevealProofWindow,
74
+ currentRevealSuccessWatermark,
75
+ openRevealProofWindow,
76
+ } from "../runtime/reveal-success-registry.js";
77
+ import { credentialKey } from "../security/credential-key.js";
65
78
  import { extractDomain } from "../tools/network/domain-normalize.js";
66
79
  import {
67
80
  classifyWebSearchFailure,
@@ -81,6 +94,26 @@ import {
81
94
  cleanAssistantContent,
82
95
  drainDirectiveDisplayBuffer,
83
96
  } from "./assistant-attachments.js";
97
+ import type {
98
+ LiveRevealGuardEntry,
99
+ ResolvedRevealCandidate,
100
+ RevealCandidateRef,
101
+ } from "./chat-credential-redaction.js";
102
+ import {
103
+ buildLiveRevealGuardEntries,
104
+ collectRevealRefsFromCommand,
105
+ drainCandidateGuardedChunk,
106
+ drainSentinelGuardedText,
107
+ filterRefsByRevealProof,
108
+ neutralizeAndSwapLiveRevealValues,
109
+ redactCandidateValuesLegacy,
110
+ redactSecretsForChat,
111
+ remintAuthoritiesFromCandidates,
112
+ resolveProvenRevealCandidates,
113
+ resolveRefIdentities,
114
+ resolveRevealCandidates,
115
+ type SentinelRemintAuthority,
116
+ } from "./chat-credential-redaction.js";
84
117
  import type { Conversation } from "./conversation.js";
85
118
  import type { AssistantSurface } from "./conversation-agent-loop.js";
86
119
  import {
@@ -90,6 +123,12 @@ import {
90
123
  } from "./conversation-error.js";
91
124
  import { buildDeferredFinalizeEffect } from "./conversation-turn-finalize.js";
92
125
  import { resolveTurnTimezoneContext } from "./date-context.js";
126
+ import {
127
+ appendInflightSnapshot,
128
+ createInflightContentWriter,
129
+ finalizeInflightContent,
130
+ type InflightContentWriter,
131
+ } from "./inflight-message-content.js";
93
132
  import type {
94
133
  CardSurfaceData,
95
134
  ServerMessage,
@@ -194,6 +233,13 @@ export interface EventHandlerState {
194
233
  * absorbs the reserved row into the error message.
195
234
  */
196
235
  assistantRowAwaitingFinalization: boolean;
236
+ /**
237
+ * Per-row in-flight content writers, keyed by message row id. Created
238
+ * lazily on the first partial flush of a row; removed when the row's
239
+ * finalize seam folds the file inline. Writers still present at
240
+ * turn-finalize (cancelled/aborted turns) are folded there.
241
+ */
242
+ readonly inflightWriters: Map<string, InflightContentWriter>;
197
243
  readonly pendingToolResults: Map<string, PendingToolResult>;
198
244
  /**
199
245
  * Reservation of the grouped `user` tool-result row for the current batch,
@@ -338,6 +384,111 @@ export interface EventHandlerState {
338
384
  * every produced assistant row is indexed.
339
385
  */
340
386
  readonly deferredFinalizeEffects: Array<() => Promise<void>>;
387
+ /**
388
+ * Credential refs parsed from `credentials reveal` invocations in this
389
+ * turn's shell-style tool commands (see `chat-credential-redaction.ts`).
390
+ * Staged per tool_use in {@link pendingRevealRefsByToolUse} and promoted
391
+ * here only when that tool's result arrives successfully; consumed at the
392
+ * persist seams to scope the candidate fetch for redaction-sentinel
393
+ * enrichment. Only ever read when the `chat-credential-reveal` feature
394
+ * flag is on.
395
+ */
396
+ readonly revealCandidateRefs: RevealCandidateRef[];
397
+ /**
398
+ * Reveal refs parsed at `tool_use` time, staged until the reveal route
399
+ * itself proves it executed. `tool_use` is emitted BEFORE tool
400
+ * execution — approval denial, cancellation, or the route's
401
+ * untrusted-shell block can still stop the command — and candidate
402
+ * resolution reads plaintext straight from the store, so resolving at
403
+ * propose time would fetch secrets for a reveal that never ran,
404
+ * side-stepping the reveal route's own policy gates. The enclosing
405
+ * tool's success is not proof either (`reveal … || true`, or an echo of
406
+ * the command text), so each staging captures a reveal-success-registry
407
+ * watermark and `handleToolResult` promotes only the refs whose
408
+ * identity the route actually served after it (see
409
+ * `filterRefsByRevealProof`); the rest are dropped.
410
+ */
411
+ readonly pendingRevealRefsByToolUse: Map<
412
+ string,
413
+ /** `proofWindowToken` arms registry recording for this staging's
414
+ * lifetime (see `openRevealProofWindow`) and is closed at result. */
415
+ { refs: RevealCandidateRef[]; watermark: number; proofWindowToken: number }
416
+ >;
417
+ /**
418
+ * Tool stdout held back from live `tool_output_chunk` emission because
419
+ * it ends in a partial occurrence of a reveal candidate's plaintext
420
+ * (keyed by toolUseId). Re-prepended to the tool's next chunk and
421
+ * flushed, redacted, when its tool_result arrives — nothing can complete
422
+ * the partial after that. Only ever populated while proven reveal
423
+ * candidates exist (see `handleToolOutputChunk`).
424
+ */
425
+ readonly toolOutputGuardBuffers: Map<string, string>;
426
+ /**
427
+ * Live text the sentinel stream guard held back from
428
+ * `assistant_text_delta` emission — a trailing partial `〔redacted:`
429
+ * trigger or reveal-candidate plaintext prefix that a later chunk may
430
+ * complete. Re-prepended to the next delta and flushed
431
+ * (neutralized + candidate-swapped) at message_complete. See
432
+ * `drainSentinelGuardedText`.
433
+ */
434
+ pendingSentinelGuardBuffer: string;
435
+ /**
436
+ * Precomputed live-swap entries for this turn's reveal candidates: when
437
+ * the model echoes a candidate's plaintext, the stream guard replaces it
438
+ * with its enriched sentinel before emission so the secret never reaches
439
+ * the wire. Primed asynchronously when `handleToolResult` confirms a
440
+ * staged reveal invocation actually succeeded — before the model's next
441
+ * text can echo the tool's stdout. Empty when the
442
+ * `chat-credential-reveal` flag is off.
443
+ */
444
+ liveRevealGuardEntries: readonly LiveRevealGuardEntry[];
445
+ /**
446
+ * Re-mint authorities derived from this turn's proven reveal candidates
447
+ * (see `remintAuthoritiesFromCandidates`), primed together with
448
+ * {@link liveRevealGuardEntries} behind the same dispatcher barrier so
449
+ * the live guard can consult them synchronously. Combined at each guard
450
+ * site with the `--for-chat` mints the reveal route recorded this run.
451
+ */
452
+ candidateRemintAuthorities: readonly SentinelRemintAuthority[];
453
+ /**
454
+ * `--for-chat` mint-registry watermark captured when this run's state
455
+ * was created. `turnForChatMints` returns only mints the reveal route
456
+ * recorded after this point — the guard's authority for re-minting a
457
+ * sentinel identity is an actually-executed reveal, never a parse of
458
+ * the requested command (which would let a quoted/commented-out
459
+ * invocation allowlist a forgery).
460
+ */
461
+ readonly forChatMintWatermark: number;
462
+ /**
463
+ * `credentialKey`-formatted identities of every reveal invocation THIS run
464
+ * staged from its own `tool_use` commands (`credentialKey` format). The
465
+ * conversation-scoping leg of re-mint authority: registry mints are
466
+ * global (a mint's request body carries no trustworthy conversation
467
+ * identity — see the registry module doc), so `turnForChatMints` accepts
468
+ * only mints whose identity this run itself requested. Staging parses
469
+ * the command the daemon actually dispatched — trusted context a
470
+ * subprocess env override can never rewrite.
471
+ */
472
+ readonly stagedRevealIdentities: Set<string>;
473
+ /**
474
+ * In-flight priming of {@link liveRevealGuardEntries}. The dispatcher
475
+ * awaits this before processing a `text_delta` (and before the
476
+ * end-of-message guard flush) so a fast reveal echo can never race the
477
+ * guard: without the barrier, a quick tool return plus a slow store read
478
+ * would let `drainSentinelGuardedText` run with an empty entry list and
479
+ * send the plaintext over SSE even though the persisted row redacts it.
480
+ * Cleared once settled — steady-state deltas await nothing.
481
+ */
482
+ liveRevealGuardPriming: Promise<void> | undefined;
483
+ /**
484
+ * Memoized resolution of {@link revealCandidateRefs} so a turn with many
485
+ * persist flushes fetches each candidate's plaintext once. Invalidated by
486
+ * ref-count when a later tool call adds more reveal invocations mid-turn.
487
+ */
488
+ revealCandidateCache?: {
489
+ refCount: number;
490
+ candidates: Promise<ResolvedRevealCandidate[]>;
491
+ };
341
492
  }
342
493
 
343
494
  /** Immutable context shared across event handlers within a single agent loop run. */
@@ -395,6 +546,7 @@ export function createEventHandlerState(): EventHandlerState {
395
546
  persistProviderErrorAsAssistantMessage: false,
396
547
  lastAssistantMessageId: undefined,
397
548
  assistantRowAwaitingFinalization: false,
549
+ inflightWriters: new Map(),
398
550
  pendingToolResults: new Map(),
399
551
  pendingToolResultRowReservation: undefined,
400
552
  persistedToolUseIds: new Set(),
@@ -427,16 +579,211 @@ export function createEventHandlerState(): EventHandlerState {
427
579
  compactionStartMessages: new Map(),
428
580
  latencyCursor: 0,
429
581
  deferredFinalizeEffects: [],
582
+ revealCandidateRefs: [],
583
+ pendingRevealRefsByToolUse: new Map(),
584
+ toolOutputGuardBuffers: new Map(),
585
+ revealCandidateCache: undefined,
586
+ pendingSentinelGuardBuffer: "",
587
+ liveRevealGuardEntries: [],
588
+ candidateRemintAuthorities: [],
589
+ forChatMintWatermark: currentForChatMintWatermark(),
590
+ stagedRevealIdentities: new Set(),
591
+ liveRevealGuardPriming: undefined,
430
592
  };
431
593
  }
432
594
 
595
+ /**
596
+ * Resolve this turn's reveal candidates for chat sentinel redaction.
597
+ *
598
+ * Returns `undefined` when the `chat-credential-reveal` flag is off — the
599
+ * persist seams then use the legacy `<redacted type="…" />` marker for
600
+ * SCANNER matches, byte-identical to today (the candidate-aware
601
+ * exact-match fallback still applies via
602
+ * {@link resolvedRevealCandidatesForState}, which is deliberately not
603
+ * flag-gated: keeping a proven revealed plaintext out of persisted rows
604
+ * is independent of which marker format the client renders). When the
605
+ * flag is on, returns the resolved candidates (possibly empty: sentinel
606
+ * mode with nothing revealable). Resolution is memoized on the ref count
607
+ * so plaintexts are fetched at most once per new batch of reveal
608
+ * invocations.
609
+ */
610
+ async function chatRevealCandidates(
611
+ state: EventHandlerState,
612
+ ): Promise<readonly ResolvedRevealCandidate[] | undefined> {
613
+ if (!isAssistantFeatureFlagEnabled("chat-credential-reveal", getConfig())) {
614
+ return undefined;
615
+ }
616
+ return resolvedRevealCandidatesForState(state);
617
+ }
618
+
619
+ /**
620
+ * Flag-independent candidate resolution for the legacy-marker fallbacks:
621
+ * a route-proven reveal plaintext must be kept out of persisted rows in
622
+ * BOTH modes, so the fallback surfaces (tool results always; assistant
623
+ * text when the sentinel flag is off) resolve candidates here directly.
624
+ * Refs only exist when the reveal route actually served the identity
625
+ * (see `filterRefsByRevealProof`), so with the flag off this performs no
626
+ * store reads until a genuine reveal has already happened. Shares the
627
+ * per-state memoization with {@link chatRevealCandidates}.
628
+ */
629
+ async function resolvedRevealCandidatesForState(
630
+ state: EventHandlerState,
631
+ ): Promise<readonly ResolvedRevealCandidate[]> {
632
+ const refCount = state.revealCandidateRefs.length;
633
+ if (refCount === 0) {
634
+ return [];
635
+ }
636
+ if (
637
+ state.revealCandidateCache === undefined ||
638
+ state.revealCandidateCache.refCount !== refCount
639
+ ) {
640
+ state.revealCandidateCache = {
641
+ refCount,
642
+ candidates: resolveRevealCandidates([...state.revealCandidateRefs]),
643
+ };
644
+ }
645
+ return state.revealCandidateCache.candidates;
646
+ }
647
+
648
+ /**
649
+ * Kick off (or refresh) the live stream guard's swap entries from the
650
+ * memoized candidate resolution. Called from `handleToolResult` once a
651
+ * staged reveal invocation is confirmed successful — never at propose
652
+ * time, since candidate resolution reads plaintext straight from the
653
+ * store and the tool may yet be denied or cancelled. The store read is
654
+ * asynchronous while the dispatcher moves on, so a slow
655
+ * `getSecureKeyAsync` could let the next text deltas reach the guard
656
+ * before entries exist. The pending promise is therefore recorded on
657
+ * state and awaited by the dispatcher at the delta boundary (see
658
+ * `dispatchAgentEvent`), turning the race into a barrier. If resolution
659
+ * fails, the guard stays on its previous entries and the persist seams
660
+ * still redact; the stream guard remains a wire-level layer, persistence
661
+ * the redaction boundary.
662
+ */
663
+ function primeLiveRevealGuard(state: EventHandlerState): void {
664
+ const priming = chatRevealCandidates(state)
665
+ .then((candidates) => {
666
+ if (candidates !== undefined && candidates.length > 0) {
667
+ state.liveRevealGuardEntries = buildLiveRevealGuardEntries(candidates);
668
+ state.candidateRemintAuthorities =
669
+ remintAuthoritiesFromCandidates(candidates);
670
+ }
671
+ })
672
+ .catch((err: unknown) => {
673
+ log.debug(
674
+ { err },
675
+ "live reveal guard priming failed; stream swap stays inactive",
676
+ );
677
+ })
678
+ .finally(() => {
679
+ // Only clear our own registration — a later reveal in the same turn
680
+ // may have replaced the pending promise with a fresh one.
681
+ if (state.liveRevealGuardPriming === priming) {
682
+ state.liveRevealGuardPriming = undefined;
683
+ }
684
+ });
685
+ state.liveRevealGuardPriming = priming;
686
+ }
687
+
688
+ /**
689
+ * Barrier for the live reveal guard: resolves once any in-flight priming
690
+ * has settled. Awaited before text deltas are guarded and before the
691
+ * end-of-message guard flush, so echoed plaintext can never beat the
692
+ * guard entries onto the wire. No-op (no await, no microtask churn) when
693
+ * nothing is being primed.
694
+ */
695
+ async function awaitLiveRevealGuardReady(
696
+ state: EventHandlerState,
697
+ ): Promise<void> {
698
+ // Loop: priming that settles can be superseded by a newer registration
699
+ // (two reveals back-to-back) before this await resumes.
700
+ while (state.liveRevealGuardPriming !== undefined) {
701
+ await state.liveRevealGuardPriming;
702
+ }
703
+ }
704
+
705
+ /**
706
+ * `--for-chat` mints authorized for THIS run: recorded by the reveal route
707
+ * after this run's watermark AND matching an identity this run itself
708
+ * staged from its own `tool_use` commands. Both legs are load-bearing —
709
+ * the registry proves a reveal EXECUTED (a quoted/commented-out invocation
710
+ * never reaches the route), while the staging set scopes authority to the
711
+ * conversation that actually requested it (registry records carry no
712
+ * trustworthy conversation identity, so without this leg one
713
+ * conversation's approved reveal could authorize a concurrent
714
+ * conversation's forged sentinel). Read fresh at each guard site rather
715
+ * than cached: the route records a mint while the reveal tool is still
716
+ * executing, so by the time the model echoes the sentinel back the
717
+ * registry is already current — no priming race like the async candidate
718
+ * fetch has.
719
+ */
720
+ function turnForChatMints(
721
+ state: EventHandlerState,
722
+ deps: EventHandlerDeps,
723
+ ): ForChatMint[] {
724
+ if (state.stagedRevealIdentities.size === 0) {
725
+ return [];
726
+ }
727
+ const nonce = conversationRevealNonce(deps.ctx.conversationId);
728
+ return forChatMintsSince(state.forChatMintWatermark).filter(
729
+ (mint) =>
730
+ mint.nonce === nonce &&
731
+ state.stagedRevealIdentities.has(credentialKey(mint.service, mint.field)),
732
+ );
733
+ }
734
+
735
+ /**
736
+ * Combined re-mint authorities for the LIVE emit sites (synchronous):
737
+ * route-recorded `--for-chat` mints plus the candidate-derived authorities
738
+ * primed behind the dispatcher barrier alongside the swap entries.
739
+ */
740
+ function liveRemintAuthorities(
741
+ state: EventHandlerState,
742
+ deps: EventHandlerDeps,
743
+ ): SentinelRemintAuthority[] {
744
+ return [
745
+ ...turnForChatMints(state, deps),
746
+ ...state.candidateRemintAuthorities,
747
+ ];
748
+ }
749
+
750
+ /**
751
+ * Combined re-mint authorities for the PERSIST sites, deriving the
752
+ * candidate half from the resolved candidate set the call site already
753
+ * fetched — persistence must not depend on whether live priming ran
754
+ * (a flush can outlive the stream), so it never reads the primed state.
755
+ */
756
+ function persistRemintAuthorities(
757
+ state: EventHandlerState,
758
+ deps: EventHandlerDeps,
759
+ candidates: readonly ResolvedRevealCandidate[] | undefined,
760
+ ): SentinelRemintAuthority[] {
761
+ return [
762
+ ...turnForChatMints(state, deps),
763
+ ...(candidates !== undefined && candidates.length > 0
764
+ ? remintAuthoritiesFromCandidates(candidates)
765
+ : []),
766
+ ];
767
+ }
768
+
433
769
  // ── Partial-persistence helpers ──────────────────────────────────────
434
770
 
435
- /** Canonical persisted-content build: clean → append surfaces → redact. */
771
+ /**
772
+ * Canonical persisted-content build: clean → append surfaces → redact.
773
+ *
774
+ * `revealCandidates` (defined only when the sentinel flag is on) selects
775
+ * sentinel-mode redaction; `legacyFallbackCandidates` feeds the
776
+ * flag-independent exact-match fallback in legacy mode, so a route-proven
777
+ * reveal plaintext the scanner cannot classify never persists raw
778
+ * regardless of which marker format is active.
779
+ */
436
780
  export function buildPersistedAssistantContent(
437
781
  rawBlocks: readonly ContentBlock[],
438
782
  surfaces: readonly AssistantSurface[],
439
783
  activityByToolUseId?: ReadonlyMap<string, ToolActivityMetadata>,
784
+ revealCandidates?: readonly ResolvedRevealCandidate[],
785
+ legacyFallbackCandidates: readonly ResolvedRevealCandidate[] = [],
786
+ forChatMints: readonly SentinelRemintAuthority[] = [],
440
787
  ): ContentBlock[] {
441
788
  const { cleanedContent } = cleanAssistantContent(rawBlocks);
442
789
  const cleaned = cleanedContent as ContentBlock[];
@@ -457,7 +804,21 @@ export function buildPersistedAssistantContent(
457
804
  return withSurfaces.map((block) => {
458
805
  if (block.type === "text") {
459
806
  const tb = block as Extract<ContentBlock, { type: "text" }>;
460
- return { ...tb, text: redactSecrets(tb.text) };
807
+ // Sentinel mode (chat-credential-reveal flag on) persists redactions
808
+ // the client can render as chips; legacy mode keeps the marker
809
+ // byte-identical to today. Detection is the same scanner either way.
810
+ // Both modes neutralize forged sentinel-shaped strings first so
811
+ // arbitrary content can never manufacture a reveal chip — only
812
+ // redactor-inserted sentinels survive persistence. The
813
+ // `_redactionVersion` rider (internal, same convention as `_startedAt`)
814
+ // marks the block as neutralization-aware; `renderHistoryContent`
815
+ // neutralizes unmarked (pre-feature) blocks at read so forged sentinels
816
+ // in old history rows can never chip-ify either.
817
+ const text =
818
+ revealCandidates !== undefined
819
+ ? redactSecretsForChat(tb.text, revealCandidates, forChatMints)
820
+ : redactCandidateValuesLegacy(tb.text, legacyFallbackCandidates);
821
+ return { ...tb, text, _redactionVersion: SENTINEL_REDACTION_VERSION };
461
822
  }
462
823
  // Native server tools (Anthropic web_search) resolve mid-stream — their
463
824
  // `server_tool_complete` fires before `message_complete` — so the captured
@@ -570,6 +931,45 @@ function resetPartialPersistAccumulator(state: EventHandlerState): void {
570
931
  state.currentThinkingTimestamps = [];
571
932
  state.lastPersistedContentSeq = undefined;
572
933
  state.pendingPartialFlushPromise = undefined;
934
+ // If a previous LLM call (e.g. a retried/replaced stream) held back
935
+ // sentinel-guarded text via `drainSentinelGuardedText`, the stale
936
+ // bytes would be prepended to the retry's first text_delta, potentially
937
+ // emitting a raw credential prefix if it no longer matches a candidate.
938
+ // Clear alongside the other per-row accumulators so the new LLM call
939
+ // starts from an empty buffer.
940
+ state.pendingSentinelGuardBuffer = "";
941
+ }
942
+
943
+ /**
944
+ * Reserve a message row born in-flight: the writer (and its `{ ref }`) is
945
+ * created first, the reservation persists the ref into the newborn row with
946
+ * `finalized = 0`, and the writer is registered under the resolved row id.
947
+ * When the conversation can't be resolved, the row is reserved as a plain
948
+ * inline placeholder and null is returned — content writes then fall back
949
+ * to direct row writes, which stays correct at the cost of a full-blob
950
+ * UPDATE per flush.
951
+ */
952
+ async function reserveInflightMessageRow(
953
+ state: EventHandlerState,
954
+ conversationId: string,
955
+ role: "assistant" | "user",
956
+ metadata: Record<string, unknown> | undefined,
957
+ ): Promise<{ id: string }> {
958
+ const writer = createInflightContentWriter(conversationId);
959
+ const reserved = await reserveMessage(
960
+ conversationId,
961
+ role,
962
+ metadata,
963
+ writer?.ref,
964
+ );
965
+ if (writer && !state.inflightWriters.has(reserved.id)) {
966
+ writer.messageId = reserved.id;
967
+ state.inflightWriters.set(reserved.id, writer);
968
+ }
969
+ // A pre-existing entry for this id means an id collision (only test
970
+ // doubles reuse row ids — production ids are unique); keep the writer
971
+ // already tracking that id so its delta file is still finalized/cleaned.
972
+ return reserved;
573
973
  }
574
974
 
575
975
  /**
@@ -589,12 +989,20 @@ async function persistLoopMessageContent(
589
989
  contentJson: string,
590
990
  op: string,
591
991
  rlog: pino.Logger,
992
+ metadataUpdates?: Record<string, unknown>,
592
993
  ): Promise<boolean> {
593
994
  try {
594
- await withSqliteRetry(() => updateMessageContent(messageId, contentJson), {
595
- op,
596
- context: { messageId },
597
- });
995
+ // Metadata updates (e.g. the served model at finalize) ride the same
996
+ // write as the content — `updateMessageContent` commits both atomically —
997
+ // so a partial write can't leave them out of sync; the updates
998
+ // shallow-merge onto the channel provenance stamped at reserve.
999
+ await withSqliteRetry(
1000
+ () => updateMessageContent(messageId, contentJson, metadataUpdates),
1001
+ {
1002
+ op,
1003
+ context: { messageId },
1004
+ },
1005
+ );
598
1006
  return true;
599
1007
  } catch (err) {
600
1008
  rlog.error(
@@ -618,23 +1026,33 @@ async function flushAccumulatedContent(
618
1026
  return;
619
1027
  }
620
1028
 
1029
+ const revealCandidates = await chatRevealCandidates(state);
621
1030
  const built = buildPersistedAssistantContent(
622
1031
  state.currentMessageContent,
623
1032
  [],
624
1033
  state.toolActivityMetadata,
1034
+ revealCandidates,
1035
+ await resolvedRevealCandidatesForState(state),
1036
+ persistRemintAuthorities(state, deps, revealCandidates),
625
1037
  );
626
- const contentJson = JSON.stringify(built);
627
1038
  // Pair the seq with the exact content snapshot taken above: deltas that
628
1039
  // arrive while the write is in flight bump `lastPersistedContentSeq`
629
1040
  // again, but they are not part of this write.
630
1041
  const flushedSeq = state.lastPersistedContentSeq;
631
1042
 
632
- const persisted = await persistLoopMessageContent(
633
- messageId,
634
- contentJson,
635
- "partial_flush_assistant_content",
636
- deps.rlog,
637
- );
1043
+ // Partial flushes append to the in-flight delta file — a pure file
1044
+ // write; the row has held the `{ ref }` since it was reserved. Delta
1045
+ // lines are stamped with the flushed event seq so the file correlates
1046
+ // 1:1 with the stream.
1047
+ const writer = state.inflightWriters.get(messageId);
1048
+ const persisted = writer
1049
+ ? appendInflightSnapshot(writer, built, flushedSeq ?? undefined, deps.rlog)
1050
+ : await persistLoopMessageContent(
1051
+ messageId,
1052
+ JSON.stringify(built),
1053
+ "partial_flush_assistant_content",
1054
+ deps.rlog,
1055
+ );
638
1056
  // Record only after the write commits, so the snapshot seq never
639
1057
  // claims content that is not yet durable.
640
1058
  if (persisted && flushedSeq != null) {
@@ -868,7 +1286,8 @@ export async function handleLlmCallStarted(
868
1286
  }
869
1287
 
870
1288
  const metadata = buildAssistantChannelMetadata(state, deps);
871
- const reservedRow = await reserveMessage(
1289
+ const reservedRow = await reserveInflightMessageRow(
1290
+ state,
872
1291
  deps.ctx.conversationId,
873
1292
  "assistant",
874
1293
  metadata,
@@ -908,24 +1327,43 @@ function handleTextDelta(
908
1327
  statusText: "Thinking",
909
1328
  });
910
1329
  }
911
- deps.onEvent({
912
- type: "assistant_text_delta",
913
- text: drained.emitText,
914
- conversationId: deps.ctx.conversationId,
915
- messageId: state.lastAssistantMessageId,
916
- });
1330
+ // Live stream guard: neutralize forged sentinels (a genuine sentinel is
1331
+ // created at persist time, never in raw model output) and swap a reveal
1332
+ // candidate's echoed plaintext for its enriched sentinel so the secret
1333
+ // never flashes in the live transcript or crosses the wire. A trigger or
1334
+ // candidate prefix split across chunks is held back in
1335
+ // `pendingSentinelGuardBuffer` and flushed at message end.
1336
+ const guarded = drainSentinelGuardedText(
1337
+ state.pendingSentinelGuardBuffer + drained.emitText,
1338
+ state.liveRevealGuardEntries,
1339
+ liveRemintAuthorities(state, deps),
1340
+ );
1341
+ state.pendingSentinelGuardBuffer = guarded.bufferedRemainder;
1342
+ if (guarded.emitText.length > 0) {
1343
+ deps.onEvent({
1344
+ type: "assistant_text_delta",
1345
+ text: guarded.emitText,
1346
+ conversationId: deps.ctx.conversationId,
1347
+ messageId: state.lastAssistantMessageId,
1348
+ });
1349
+ // Mirror the RAW consumed bytes (not the emitted swap) into
1350
+ // currentMessageContent: the partial flush re-redacts them through
1351
+ // `redactSecretsForChat`, which derives the same enriched sentinel
1352
+ // from the plaintext — whereas a mirrored, already-swapped sentinel
1353
+ // would be indistinguishable from a forgery there and get
1354
+ // neutralized. Buffered bytes (partial triggers / candidate
1355
+ // prefixes) stay excluded until a later chunk emits them.
1356
+ appendTextToCurrentMessage(state, guarded.consumedRaw);
1357
+ // The hub stamps `seq` synchronously on the delta emitted above, so
1358
+ // `getCurrentSeq()` here is that delta's seq -- the position the
1359
+ // mirrored content now reflects. A partial flush snapshots this to
1360
+ // record how far the durable rows track the live stream.
1361
+ state.lastPersistedContentSeq = getCurrentSeq();
1362
+ schedulePartialFlush(state, deps);
1363
+ }
917
1364
  if (deps.shouldGenerateTitle) {
918
1365
  state.firstAssistantText += drained.emitText;
919
1366
  }
920
- // Mirror the drained delta into state.currentMessageContent so partial
921
- // flushes mid-turn see the same content the user is watching live.
922
- appendTextToCurrentMessage(state, drained.emitText);
923
- // The hub stamps `seq` synchronously on the delta emitted above, so
924
- // `getCurrentSeq()` here is that delta's seq -- the position the
925
- // mirrored content now reflects. A partial flush snapshots this to
926
- // record how far the durable rows track the live stream.
927
- state.lastPersistedContentSeq = getCurrentSeq();
928
- schedulePartialFlush(state, deps);
929
1367
  }
930
1368
  }
931
1369
 
@@ -981,6 +1419,46 @@ export function handleToolUse(
981
1419
  if (event.name === "app_create" || event.name === "app_refresh") {
982
1420
  state.appBuildToolUsedThisRun = true;
983
1421
  }
1422
+ // Record `credentials reveal` invocations so the persist seams can enrich
1423
+ // redaction sentinels with a proven vault identity (chat-credential-reveal).
1424
+ // Tool-name agnostic on purpose: any shell-style tool (bash, host_bash)
1425
+ // carries the command in `input.command`. Pure string parse — no store
1426
+ // access happens here: `tool_use` precedes execution, and the refs are
1427
+ // only STAGED until `handleToolResult` sees the reveal actually succeed
1428
+ // (see `pendingRevealRefsByToolUse` — priming at propose time would read
1429
+ // plaintext for a command that approval/cancellation may still block).
1430
+ const command = (event.input as { command?: unknown } | undefined)?.command;
1431
+ if (typeof command === "string" && command.length > 0) {
1432
+ // Id-form refs resolve to service/field NOW (metadata-only lookup): the
1433
+ // same compound command may remove the credential after revealing it,
1434
+ // and by result time the id would no longer resolve — dropping the
1435
+ // proof for a value the tool already printed.
1436
+ const refs = resolveRefIdentities(collectRevealRefsFromCommand(command));
1437
+ if (refs.length > 0) {
1438
+ state.pendingRevealRefsByToolUse.set(event.id, {
1439
+ refs,
1440
+ // Captured before execution: only reveal-route successes recorded
1441
+ // AFTER this point can prove these refs at result time.
1442
+ watermark: currentRevealSuccessWatermark(),
1443
+ // Arms registry recording for this staging's lifetime — the route
1444
+ // retains plaintext only while some tool's proof is pending.
1445
+ proofWindowToken: openRevealProofWindow(),
1446
+ });
1447
+ // The conversation-scoping leg of `--for-chat` re-mint authority:
1448
+ // record which identities THIS run's own commands named. Retained for
1449
+ // the whole run (unlike the staging entry, which handleToolResult
1450
+ // consumes) — the model echoes the sentinel back only after the tool
1451
+ // completes. Parse-only, so by itself this authorizes nothing; a
1452
+ // registry mint (an executed reveal) must also exist.
1453
+ for (const ref of refs) {
1454
+ if (ref.service !== undefined && ref.field !== undefined) {
1455
+ state.stagedRevealIdentities.add(
1456
+ credentialKey(ref.service, ref.field),
1457
+ );
1458
+ }
1459
+ }
1460
+ }
1461
+ }
984
1462
  const startedAt = Date.now();
985
1463
  state.toolCallTimestamps.set(event.id, { startedAt });
986
1464
  state.currentToolUseId = event.id;
@@ -1121,15 +1599,59 @@ function handleToolOutputChunk(
1121
1599
  subToolIsError: structured.subToolIsError,
1122
1600
  subToolId: structured.subToolId,
1123
1601
  });
1124
- } else {
1125
- deps.onEvent({
1126
- type: "tool_output_chunk",
1127
- chunk: event.chunk,
1128
- conversationId: deps.ctx.conversationId,
1129
- toolUseId: event.toolUseId,
1130
- messageId: state.lastAssistantMessageId,
1131
- });
1602
+ return;
1132
1603
  }
1604
+
1605
+ // Redact revealed plaintext from the LIVE stdout stream. The final
1606
+ // tool_result is redacted at its seam, but these chunks reach the client
1607
+ // first and the web drawer renders them until the result replaces them —
1608
+ // without this guard a `credentials reveal` value flashes raw for the
1609
+ // whole tool run. By the time printed bytes arrive here the route has
1610
+ // already recorded any success (the record precedes the CLI receiving
1611
+ // the plaintext), so proven candidates are available SYNCHRONOUSLY from
1612
+ // the registry — no vault read, and the reveal-free path stays untouched.
1613
+ // Covers both this tool's own staged reveals and values already promoted
1614
+ // by an earlier tool in the turn (a later `echo <value>` streams too). A
1615
+ // trailing partial occurrence is held back for the next chunk; the
1616
+ // tool_result seam flushes the remainder. Structured control frames
1617
+ // above are forwarded untouched — they are parsed subtool events, not
1618
+ // reveal stdout, and rewriting their raw JSON could corrupt them.
1619
+ let chunk = event.chunk;
1620
+ const staged = state.pendingRevealRefsByToolUse.get(event.toolUseId);
1621
+ const guardRefs =
1622
+ staged === undefined
1623
+ ? state.revealCandidateRefs
1624
+ : [
1625
+ ...state.revealCandidateRefs,
1626
+ ...filterRefsByRevealProof(
1627
+ staged.refs,
1628
+ staged.watermark,
1629
+ conversationRevealNonce(deps.ctx.conversationId),
1630
+ ),
1631
+ ];
1632
+ if (guardRefs.length > 0) {
1633
+ const candidates = resolveProvenRevealCandidates(guardRefs);
1634
+ if (candidates.length > 0) {
1635
+ const held = state.toolOutputGuardBuffers.get(event.toolUseId) ?? "";
1636
+ const drained = drainCandidateGuardedChunk(held + chunk, candidates);
1637
+ state.toolOutputGuardBuffers.set(
1638
+ event.toolUseId,
1639
+ drained.bufferedRemainder,
1640
+ );
1641
+ if (drained.emitText.length === 0) {
1642
+ return;
1643
+ }
1644
+ chunk = drained.emitText;
1645
+ }
1646
+ }
1647
+
1648
+ deps.onEvent({
1649
+ type: "tool_output_chunk",
1650
+ chunk,
1651
+ conversationId: deps.ctx.conversationId,
1652
+ toolUseId: event.toolUseId,
1653
+ messageId: state.lastAssistantMessageId,
1654
+ });
1133
1655
  }
1134
1656
 
1135
1657
  export function handleInputJsonDelta(
@@ -1161,17 +1683,30 @@ export function handleInputJsonDelta(
1161
1683
  */
1162
1684
  function buildToolResultBlocks(
1163
1685
  pending: ReadonlyMap<string, PendingToolResult>,
1686
+ revealCandidates: readonly ResolvedRevealCandidate[] = [],
1164
1687
  ) {
1688
+ // Tool results keep the legacy `<redacted type/>` marker (NOT sentinels):
1689
+ // history maps tool_result content to `toolCall.result`, which the tool
1690
+ // detail panel renders via CodeBlock — a path with no markdown/chip
1691
+ // support, where a sentinel would show as an inert glyph string. Convert
1692
+ // here only once that surface can render chips. Forged sentinel-shaped
1693
+ // strings in tool output are still neutralized so they can never reach a
1694
+ // chip-enabled surface via quoting. Proven reveal-candidate plaintexts
1695
+ // the scanner cannot classify (opaque manual tokens in the reveal's own
1696
+ // stdout) get a candidate-aware legacy-marker fallback — the tool detail
1697
+ // panel and history must not retain a value every other surface redacts.
1698
+ const redact = (text: string): string =>
1699
+ redactCandidateValuesLegacy(text, revealCandidates);
1165
1700
  return Array.from(pending.entries()).map(([toolUseId, result]) => ({
1166
1701
  type: "tool_result",
1167
1702
  tool_use_id: toolUseId,
1168
- content: redactSecrets(result.content),
1703
+ content: redact(result.content),
1169
1704
  is_error: result.isError,
1170
1705
  ...(result.contentBlocks
1171
1706
  ? {
1172
1707
  contentBlocks: result.contentBlocks.map((block) =>
1173
1708
  block.type === "text"
1174
- ? { ...block, text: redactSecrets(block.text) }
1709
+ ? { ...block, text: redact(block.text) }
1175
1710
  : block,
1176
1711
  ),
1177
1712
  }
@@ -1212,7 +1747,8 @@ function ensureToolResultRowReserved(
1212
1747
  metadata: Record<string, unknown>,
1213
1748
  ): Promise<string> {
1214
1749
  if (state.pendingToolResultRowReservation === undefined) {
1215
- state.pendingToolResultRowReservation = reserveMessage(
1750
+ state.pendingToolResultRowReservation = reserveInflightMessageRow(
1751
+ state,
1216
1752
  conversationId,
1217
1753
  "user",
1218
1754
  metadata,
@@ -1249,14 +1785,22 @@ async function persistPendingToolResultRow(
1249
1785
  deps.ctx.conversationId,
1250
1786
  buildToolResultMetadata(deps),
1251
1787
  );
1252
- // Serialize the content after the reservation resolves so the last of the
1253
- // concurrent writers reflects the fullest batch.
1254
- const persisted = await persistLoopMessageContent(
1255
- rowId,
1256
- JSON.stringify(buildToolResultBlocks(state.pendingToolResults)),
1257
- "persist_tool_result_row",
1258
- deps.rlog,
1259
- );
1788
+ // Snapshot the batch after the reservation resolves so the last of the
1789
+ // concurrent writers reflects the fullest batch. On-arrival writes go to
1790
+ // the in-flight delta file; the finalize seam folds the row inline.
1791
+ const batchBlocks = buildToolResultBlocks(
1792
+ state.pendingToolResults,
1793
+ await resolvedRevealCandidatesForState(state),
1794
+ ) as ContentBlock[];
1795
+ const writer = state.inflightWriters.get(rowId);
1796
+ const persisted = writer
1797
+ ? appendInflightSnapshot(writer, batchBlocks, seq, deps.rlog)
1798
+ : await persistLoopMessageContent(
1799
+ rowId,
1800
+ JSON.stringify(batchBlocks),
1801
+ "persist_tool_result_row",
1802
+ deps.rlog,
1803
+ );
1260
1804
  if (persisted) {
1261
1805
  recordConversationPersistedSeq(deps.ctx.conversationId, seq);
1262
1806
  }
@@ -1296,7 +1840,10 @@ export async function finalizePendingToolResultRow(
1296
1840
  // for workspace references so the blob stays in the attachment store, out of
1297
1841
  // this row and the lexical index. Runs once, here at finalize (on-arrival
1298
1842
  // writes keep base64 for durability); the send boundary re-inflates the refs.
1299
- const blocks = buildToolResultBlocks(state.pendingToolResults);
1843
+ const blocks = buildToolResultBlocks(
1844
+ state.pendingToolResults,
1845
+ await resolvedRevealCandidatesForState(state),
1846
+ );
1300
1847
  const contentJson = JSON.stringify(
1301
1848
  conv != null
1302
1849
  ? referenceMediaBlocksForPersist(
@@ -1307,12 +1854,18 @@ export async function finalizePendingToolResultRow(
1307
1854
  )
1308
1855
  : blocks,
1309
1856
  );
1310
- await persistLoopMessageContent(
1857
+ const toolRowFinalized = await finalizeInflightContent(
1858
+ state.inflightWriters.get(rowId),
1311
1859
  rowId,
1312
1860
  contentJson,
1313
- "finalize_tool_result_row",
1314
1861
  rlog,
1315
1862
  );
1863
+ // Keep the writer on a failed finalize (e.g. persistent SQLITE_BUSY) so
1864
+ // the turn tail's stranded fold can retry — deleting it would leave the
1865
+ // row `finalized = 0` in a live daemon until crash recovery.
1866
+ if (toolRowFinalized) {
1867
+ state.inflightWriters.delete(rowId);
1868
+ }
1316
1869
  // Sync the row to the JSONL disk view so it stays in lockstep with the DB.
1317
1870
  if (conv != null) {
1318
1871
  syncMessageToDisk(conversationId, rowId, conv.createdAt);
@@ -1379,6 +1932,76 @@ export async function handleToolResult(
1379
1932
  deps: EventHandlerDeps,
1380
1933
  event: Extract<AgentEvent, { type: "tool_result" }>,
1381
1934
  ): Promise<void> {
1935
+ // Promote staged reveal refs now that the tool has finished: a ref is
1936
+ // promoted only if the reveal ROUTE recorded a success for its identity
1937
+ // after the staging watermark — the enclosing tool's exit status proves
1938
+ // nothing (`reveal … || true` succeeds when the route failed; an echo of
1939
+ // the command text never calls the route; conversely, a compound command
1940
+ // can print the secret and then exit non-zero, in which case the model
1941
+ // HAS the plaintext and the guard entry is protective). Only then may
1942
+ // candidate resolution read the plaintext from the store. Synchronous —
1943
+ // the dispatcher awaits `tool_result` before any later `text_delta`, so
1944
+ // the priming promise is registered before the barrier can be consulted.
1945
+ const stagedReveal = state.pendingRevealRefsByToolUse.get(event.toolUseId);
1946
+ if (stagedReveal !== undefined) {
1947
+ state.pendingRevealRefsByToolUse.delete(event.toolUseId);
1948
+ const provenRefs = filterRefsByRevealProof(
1949
+ stagedReveal.refs,
1950
+ stagedReveal.watermark,
1951
+ conversationRevealNonce(deps.ctx.conversationId),
1952
+ );
1953
+ // The proof is consumed (proven values now ride the refs), so this
1954
+ // staging no longer needs the registry to record.
1955
+ closeRevealProofWindow(stagedReveal.proofWindowToken);
1956
+ if (provenRefs.length > 0) {
1957
+ state.revealCandidateRefs.push(...provenRefs);
1958
+ primeLiveRevealGuard(state);
1959
+ }
1960
+ }
1961
+
1962
+ // Redact THIS tool's own stdout before it leaves the daemon. The reveal
1963
+ // command that just proved a candidate printed the plaintext into its own
1964
+ // `event.content`; priming the assistant-text guard only protects a later
1965
+ // echo, not this result. The persist path already redacts via
1966
+ // `buildToolResultBlocks`, but the LIVE `tool_result` SSE below forwards
1967
+ // `event.content` verbatim and the web reducer stores `event.result`
1968
+ // directly — so an opaque/manual value the scanner cannot classify would
1969
+ // flash in the tool card until a history refetch. Apply the same
1970
+ // candidate-aware legacy redaction the persisted tool-result row uses, to
1971
+ // both the buffered content and the emitted result, so wire and storage
1972
+ // agree from the first frame.
1973
+ //
1974
+ // Guard the resolution behind the ref count: candidate resolution is async
1975
+ // (it reads the vault), and awaiting it here would push every side effect
1976
+ // below — the cancellation emit, the pending-result buffering, the
1977
+ // activity/risk metadata capture, `annotatePersistedAssistantMessage`, and
1978
+ // the live `tool_result` emit — onto a later microtask. Callers that drive
1979
+ // this handler synchronously (the dispatcher, and the metadata/preview
1980
+ // tests) rely on those effects landing before the returned promise's first
1981
+ // suspension, so a reveal-free tool result must stay fully synchronous and
1982
+ // pass its content through untouched — exactly as before this guard shipped.
1983
+ // The refs are non-empty only after the reveal route actually served an
1984
+ // identity this turn, which is precisely when redaction must fire.
1985
+ let redactedContent = event.content;
1986
+ // DISCARD (never emit) stdout the live chunk guard held back for this
1987
+ // tool. The buffer was held precisely because it contains or ends in a
1988
+ // PARTIAL occurrence of a candidate's plaintext, and complete-value
1989
+ // redaction cannot mask a partial — flushing it would put up to
1990
+ // value-length-minus-one raw credential bytes on the wire. Nothing is
1991
+ // lost: the redacted `event.content` emitted below carries the full
1992
+ // output and supersedes the streamed view immediately.
1993
+ state.toolOutputGuardBuffers.delete(event.toolUseId);
1994
+ if (state.revealCandidateRefs.length > 0) {
1995
+ const revealCandidatesForResult =
1996
+ await resolvedRevealCandidatesForState(state);
1997
+ if (revealCandidatesForResult.length > 0) {
1998
+ redactedContent = redactCandidateValuesLegacy(
1999
+ event.content,
2000
+ revealCandidatesForResult,
2001
+ );
2002
+ }
2003
+ }
2004
+
1382
2005
  // A synthesized cancellation (the tool never executed) is captured for
1383
2006
  // persistence and forwarded to the client like any result, but skips every
1384
2007
  // side effect that assumes the tool ran. A real result already captured or
@@ -1390,6 +2013,10 @@ export async function handleToolResult(
1390
2013
  ) {
1391
2014
  return;
1392
2015
  }
2016
+ // Buffer the RAW content: every persist path redacts exactly once via
2017
+ // `buildToolResultBlocks`, and buffering already-redacted bytes would
2018
+ // redact twice — a candidate value overlapping the marker's own text
2019
+ // would corrupt the persisted marker on the second pass.
1393
2020
  state.pendingToolResults.set(event.toolUseId, {
1394
2021
  content: event.content,
1395
2022
  isError: event.isError,
@@ -1398,7 +2025,7 @@ export async function handleToolResult(
1398
2025
  deps.onEvent({
1399
2026
  type: "tool_result",
1400
2027
  toolName: "",
1401
- result: event.content,
2028
+ result: redactedContent,
1402
2029
  isError: event.isError,
1403
2030
  conversationId: deps.ctx.conversationId,
1404
2031
  messageId: state.lastAssistantMessageId,
@@ -1432,6 +2059,12 @@ export async function handleToolResult(
1432
2059
  // Perform state mutations before deps.onEvent() so that if onEvent throws
1433
2060
  // (e.g. SSE disconnection) and the error is suppressed by dispatchAgentEvent,
1434
2061
  // critical state like pendingToolResults and currentToolUseId is still updated.
2062
+ // Buffer the RAW content: every persist path redacts exactly once via
2063
+ // `buildToolResultBlocks` (with the fullest candidate set at flush time),
2064
+ // so wire and storage still agree. Buffering the already-redacted bytes
2065
+ // would redact twice — a candidate value that overlaps the marker's own
2066
+ // text (e.g. a manual value `redacted`) would match inside the
2067
+ // first-pass marker and corrupt the persisted row.
1435
2068
  state.pendingToolResults.set(event.toolUseId, {
1436
2069
  content: event.content,
1437
2070
  isError: event.isError,
@@ -1539,10 +2172,12 @@ export async function handleToolResult(
1539
2172
  }
1540
2173
 
1541
2174
  // Send to client last so state is consistent even if onEvent throws.
2175
+ // `result` carries the reveal-redacted stdout (see above) so the live tool
2176
+ // card never shows a revealed plaintext the persisted row hides.
1542
2177
  deps.onEvent({
1543
2178
  type: "tool_result",
1544
2179
  toolName: "",
1545
- result: event.content,
2180
+ result: redactedContent,
1546
2181
  isError: event.isError,
1547
2182
  diff: event.diff,
1548
2183
  status: event.status,
@@ -1604,12 +2239,7 @@ function recordToolStartOnPersistedMessage(
1604
2239
  return;
1605
2240
  }
1606
2241
 
1607
- let content: ContentBlock[];
1608
- try {
1609
- content = JSON.parse(row.content) as ContentBlock[];
1610
- } catch {
1611
- return;
1612
- }
2242
+ const content: ContentBlock[] = row.content;
1613
2243
 
1614
2244
  for (const block of content) {
1615
2245
  if (block.type !== "tool_use") {
@@ -1663,12 +2293,7 @@ function recordToolPreviewStartOnPersistedMessage(
1663
2293
  return;
1664
2294
  }
1665
2295
 
1666
- let content: ContentBlock[];
1667
- try {
1668
- content = JSON.parse(row.content) as ContentBlock[];
1669
- } catch {
1670
- return;
1671
- }
2296
+ const content: ContentBlock[] = row.content;
1672
2297
 
1673
2298
  for (const block of content) {
1674
2299
  if (block.type !== "tool_use") {
@@ -1717,12 +2342,7 @@ function annotatePersistedAssistantMessage(
1717
2342
  return;
1718
2343
  }
1719
2344
 
1720
- let content: ContentBlock[];
1721
- try {
1722
- content = JSON.parse(row.content) as ContentBlock[];
1723
- } catch {
1724
- return;
1725
- }
2345
+ const content: ContentBlock[] = row.content;
1726
2346
 
1727
2347
  let modified = false;
1728
2348
  for (const block of content) {
@@ -1993,18 +2613,42 @@ export async function handleMessageComplete(
1993
2613
  state.pendingPartialFlushPromise = undefined;
1994
2614
  }
1995
2615
 
1996
- // Flush any remaining directive display buffer
1997
- if (state.pendingDirectiveDisplayBuffer.length > 0) {
2616
+ // Flush any remaining directive display buffer, prepending live text the
2617
+ // sentinel guard held back (a split trigger or candidate-prefix tail).
2618
+ // The concatenation is candidate-swapped and gap-neutralized as a whole:
2619
+ // at end-of-message nothing can complete a partial trigger (a completed
2620
+ // one here would be a forged sentinel), and a reveal-candidate plaintext
2621
+ // that completes across the two buffers still swaps to its sentinel.
2622
+ const trailingLiveText =
2623
+ state.pendingSentinelGuardBuffer + state.pendingDirectiveDisplayBuffer;
2624
+ if (trailingLiveText.length > 0) {
2625
+ // Same barrier as the text-delta path: the flush below swaps against
2626
+ // `liveRevealGuardEntries`, so an in-flight priming must settle first.
2627
+ await awaitLiveRevealGuardReady(state);
1998
2628
  deps.onEvent({
1999
2629
  type: "assistant_text_delta",
2000
- text: state.pendingDirectiveDisplayBuffer,
2630
+ text: neutralizeAndSwapLiveRevealValues(
2631
+ trailingLiveText,
2632
+ state.liveRevealGuardEntries,
2633
+ liveRemintAuthorities(state, deps),
2634
+ ),
2001
2635
  conversationId: deps.ctx.conversationId,
2002
2636
  messageId: state.lastAssistantMessageId,
2003
2637
  });
2638
+ // The hub stamps `seq` synchronously on the delta emitted above, so
2639
+ // `getCurrentSeq()` is that delta's position — advance the persisted-seq
2640
+ // mirror exactly like the normal text-delta path. The finalize below
2641
+ // records this value; without the advance it would record the PREVIOUS
2642
+ // emitted chunk's seq, so a `/messages` snapshot could contain this tail
2643
+ // while advertising a seq before the delta that carried it — and a
2644
+ // reconnecting client applying `seq > snapshot.seq` would append the
2645
+ // tail a second time.
2646
+ state.lastPersistedContentSeq = getCurrentSeq();
2004
2647
  if (deps.shouldGenerateTitle) {
2005
2648
  state.firstAssistantText += state.pendingDirectiveDisplayBuffer;
2006
2649
  }
2007
2650
  state.pendingDirectiveDisplayBuffer = "";
2651
+ state.pendingSentinelGuardBuffer = "";
2008
2652
  }
2009
2653
 
2010
2654
  // Finalize the grouped tool-result row. Each result was persisted into this
@@ -2051,11 +2695,15 @@ export async function handleMessageComplete(
2051
2695
  // redacted) via the shared helper. The partial-persist flush uses
2052
2696
  // the same helper with `surfaces=[]` so a mid-turn snapshot lands in
2053
2697
  // the same shape as the finalize.
2698
+ const finalRevealCandidates = await chatRevealCandidates(state);
2054
2699
  const contentForPersistence = stampThinkingTiming(
2055
2700
  buildPersistedAssistantContent(
2056
2701
  event.message.content as ContentBlock[],
2057
2702
  deps.ctx.currentTurnSurfaces,
2058
2703
  state.toolActivityMetadata,
2704
+ finalRevealCandidates,
2705
+ await resolvedRevealCandidatesForState(state),
2706
+ persistRemintAuthorities(state, deps, finalRevealCandidates),
2059
2707
  ),
2060
2708
  state.currentThinkingTimestamps,
2061
2709
  );
@@ -2074,12 +2722,24 @@ export async function handleMessageComplete(
2074
2722
  );
2075
2723
  }
2076
2724
  const contentJson = JSON.stringify(contentForPersistence);
2077
- const persisted = await persistLoopMessageContent(
2725
+ // Stamp the served model carried on the event (`response.model`, the same
2726
+ // value `llm_usage` records) onto the row alongside the content, so turn-trace
2727
+ // assembly can attribute each assistant message to the model that actually
2728
+ // ran it — including per-call reroutes by a `pre-model-call` hook. Absent on
2729
+ // synthesized completions with no provider response; the key is omitted then.
2730
+ const persisted = await finalizeInflightContent(
2731
+ state.inflightWriters.get(assistantMessageId),
2078
2732
  assistantMessageId,
2079
2733
  contentJson,
2080
- "finalize_assistant_message",
2081
2734
  deps.rlog,
2735
+ event.model ? { model: event.model } : undefined,
2082
2736
  );
2737
+ // Keep the writer on a failed finalize (e.g. persistent SQLITE_BUSY) so
2738
+ // the turn tail's stranded fold can retry — deleting it would leave the
2739
+ // row `finalized = 0` in a live daemon until crash recovery.
2740
+ if (persisted) {
2741
+ state.inflightWriters.delete(assistantMessageId);
2742
+ }
2083
2743
  state.assistantRowAwaitingFinalization = false;
2084
2744
  // The assistant row now holds the authoritative content (text + thinking +
2085
2745
  // tool_use blocks from `event.message`), and any drained tool-result rows
@@ -2359,6 +3019,11 @@ export async function dispatchAgentEvent(
2359
3019
  await handleLlmCallStarted(state, deps);
2360
3020
  break;
2361
3021
  case "text_delta":
3022
+ // Reveal-guard barrier: if a `credentials reveal` tool_use just
3023
+ // started priming the live guard, resolve it before this delta is
3024
+ // guarded — otherwise a fast reveal echo could cross SSE with an
3025
+ // empty entry list. Steady state awaits nothing.
3026
+ await awaitLiveRevealGuardReady(state);
2362
3027
  handleTextDelta(state, deps, event);
2363
3028
  break;
2364
3029
  case "thinking_delta":