@vellumai/assistant 0.10.0 → 0.10.1-staging.1

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 (824) hide show
  1. package/ARCHITECTURE.md +36 -37
  2. package/bun.lock +3 -0
  3. package/docs/workflows.md +12 -7
  4. package/eslint-rules/cli-no-daemon-internals.js +6 -0
  5. package/node_modules/@slack/types/LICENSE +23 -0
  6. package/node_modules/@slack/types/README.md +32 -0
  7. package/node_modules/@slack/types/dist/block-kit/block-elements.d.ts +953 -0
  8. package/node_modules/@slack/types/dist/block-kit/block-elements.d.ts.map +1 -0
  9. package/node_modules/@slack/types/dist/block-kit/block-elements.js +4 -0
  10. package/node_modules/@slack/types/dist/block-kit/block-elements.js.map +1 -0
  11. package/node_modules/@slack/types/dist/block-kit/blocks.d.ts +474 -0
  12. package/node_modules/@slack/types/dist/block-kit/blocks.d.ts.map +1 -0
  13. package/node_modules/@slack/types/dist/block-kit/blocks.js +3 -0
  14. package/node_modules/@slack/types/dist/block-kit/blocks.js.map +1 -0
  15. package/node_modules/@slack/types/dist/block-kit/composition-objects.d.ts +237 -0
  16. package/node_modules/@slack/types/dist/block-kit/composition-objects.d.ts.map +1 -0
  17. package/node_modules/@slack/types/dist/block-kit/composition-objects.js +4 -0
  18. package/node_modules/@slack/types/dist/block-kit/composition-objects.js.map +1 -0
  19. package/node_modules/@slack/types/dist/block-kit/extensions.d.ts +88 -0
  20. package/node_modules/@slack/types/dist/block-kit/extensions.d.ts.map +1 -0
  21. package/node_modules/@slack/types/dist/block-kit/extensions.js +3 -0
  22. package/node_modules/@slack/types/dist/block-kit/extensions.js.map +1 -0
  23. package/node_modules/@slack/types/dist/calls.d.ts +26 -0
  24. package/node_modules/@slack/types/dist/calls.d.ts.map +1 -0
  25. package/node_modules/@slack/types/dist/calls.js +6 -0
  26. package/node_modules/@slack/types/dist/calls.js.map +1 -0
  27. package/node_modules/@slack/types/dist/chunk.d.ts +52 -0
  28. package/node_modules/@slack/types/dist/chunk.d.ts.map +1 -0
  29. package/node_modules/@slack/types/dist/chunk.js +3 -0
  30. package/node_modules/@slack/types/dist/chunk.js.map +1 -0
  31. package/node_modules/@slack/types/dist/common/bot-profile.d.ts +12 -0
  32. package/node_modules/@slack/types/dist/common/bot-profile.d.ts.map +1 -0
  33. package/node_modules/@slack/types/dist/common/bot-profile.js +3 -0
  34. package/node_modules/@slack/types/dist/common/bot-profile.js.map +1 -0
  35. package/node_modules/@slack/types/dist/common/status-emoji-display-info.d.ts +6 -0
  36. package/node_modules/@slack/types/dist/common/status-emoji-display-info.d.ts.map +1 -0
  37. package/node_modules/@slack/types/dist/common/status-emoji-display-info.js +3 -0
  38. package/node_modules/@slack/types/dist/common/status-emoji-display-info.js.map +1 -0
  39. package/node_modules/@slack/types/dist/dialog.d.ts +36 -0
  40. package/node_modules/@slack/types/dist/dialog.d.ts.map +1 -0
  41. package/node_modules/@slack/types/dist/dialog.js +3 -0
  42. package/node_modules/@slack/types/dist/dialog.js.map +1 -0
  43. package/node_modules/@slack/types/dist/events/app.d.ts +204 -0
  44. package/node_modules/@slack/types/dist/events/app.d.ts.map +1 -0
  45. package/node_modules/@slack/types/dist/events/app.js +3 -0
  46. package/node_modules/@slack/types/dist/events/app.js.map +1 -0
  47. package/node_modules/@slack/types/dist/events/assistant.d.ts +29 -0
  48. package/node_modules/@slack/types/dist/events/assistant.d.ts.map +1 -0
  49. package/node_modules/@slack/types/dist/events/assistant.js +3 -0
  50. package/node_modules/@slack/types/dist/events/assistant.js.map +1 -0
  51. package/node_modules/@slack/types/dist/events/call.d.ts +8 -0
  52. package/node_modules/@slack/types/dist/events/call.d.ts.map +1 -0
  53. package/node_modules/@slack/types/dist/events/call.js +3 -0
  54. package/node_modules/@slack/types/dist/events/call.js.map +1 -0
  55. package/node_modules/@slack/types/dist/events/channel.d.ts +85 -0
  56. package/node_modules/@slack/types/dist/events/channel.d.ts.map +1 -0
  57. package/node_modules/@slack/types/dist/events/channel.js +3 -0
  58. package/node_modules/@slack/types/dist/events/channel.js.map +1 -0
  59. package/node_modules/@slack/types/dist/events/dnd.d.ts +24 -0
  60. package/node_modules/@slack/types/dist/events/dnd.d.ts.map +1 -0
  61. package/node_modules/@slack/types/dist/events/dnd.js +3 -0
  62. package/node_modules/@slack/types/dist/events/dnd.js.map +1 -0
  63. package/node_modules/@slack/types/dist/events/email.d.ts +6 -0
  64. package/node_modules/@slack/types/dist/events/email.d.ts.map +1 -0
  65. package/node_modules/@slack/types/dist/events/email.js +3 -0
  66. package/node_modules/@slack/types/dist/events/email.js.map +1 -0
  67. package/node_modules/@slack/types/dist/events/emoji.d.ts +11 -0
  68. package/node_modules/@slack/types/dist/events/emoji.d.ts.map +1 -0
  69. package/node_modules/@slack/types/dist/events/emoji.js +3 -0
  70. package/node_modules/@slack/types/dist/events/emoji.js.map +1 -0
  71. package/node_modules/@slack/types/dist/events/entity-details-requested.d.ts +21 -0
  72. package/node_modules/@slack/types/dist/events/entity-details-requested.d.ts.map +1 -0
  73. package/node_modules/@slack/types/dist/events/entity-details-requested.js +3 -0
  74. package/node_modules/@slack/types/dist/events/entity-details-requested.js.map +1 -0
  75. package/node_modules/@slack/types/dist/events/file.d.ts +60 -0
  76. package/node_modules/@slack/types/dist/events/file.d.ts.map +1 -0
  77. package/node_modules/@slack/types/dist/events/file.js +4 -0
  78. package/node_modules/@slack/types/dist/events/file.js.map +1 -0
  79. package/node_modules/@slack/types/dist/events/function.d.ts +33 -0
  80. package/node_modules/@slack/types/dist/events/function.d.ts.map +1 -0
  81. package/node_modules/@slack/types/dist/events/function.js +3 -0
  82. package/node_modules/@slack/types/dist/events/function.js.map +1 -0
  83. package/node_modules/@slack/types/dist/events/grid-migration.d.ts +9 -0
  84. package/node_modules/@slack/types/dist/events/grid-migration.d.ts.map +1 -0
  85. package/node_modules/@slack/types/dist/events/grid-migration.js +3 -0
  86. package/node_modules/@slack/types/dist/events/grid-migration.js.map +1 -0
  87. package/node_modules/@slack/types/dist/events/group.d.ts +55 -0
  88. package/node_modules/@slack/types/dist/events/group.d.ts.map +1 -0
  89. package/node_modules/@slack/types/dist/events/group.js +3 -0
  90. package/node_modules/@slack/types/dist/events/group.js.map +1 -0
  91. package/node_modules/@slack/types/dist/events/im.d.ts +26 -0
  92. package/node_modules/@slack/types/dist/events/im.d.ts.map +1 -0
  93. package/node_modules/@slack/types/dist/events/im.js +3 -0
  94. package/node_modules/@slack/types/dist/events/im.js.map +1 -0
  95. package/node_modules/@slack/types/dist/events/index.d.ts +60 -0
  96. package/node_modules/@slack/types/dist/events/index.d.ts.map +1 -0
  97. package/node_modules/@slack/types/dist/events/index.js +43 -0
  98. package/node_modules/@slack/types/dist/events/index.js.map +1 -0
  99. package/node_modules/@slack/types/dist/events/invite.d.ts +20 -0
  100. package/node_modules/@slack/types/dist/events/invite.d.ts.map +1 -0
  101. package/node_modules/@slack/types/dist/events/invite.js +3 -0
  102. package/node_modules/@slack/types/dist/events/invite.js.map +1 -0
  103. package/node_modules/@slack/types/dist/events/link-shared.d.ts +16 -0
  104. package/node_modules/@slack/types/dist/events/link-shared.d.ts.map +1 -0
  105. package/node_modules/@slack/types/dist/events/link-shared.js +3 -0
  106. package/node_modules/@slack/types/dist/events/link-shared.js.map +1 -0
  107. package/node_modules/@slack/types/dist/events/member.d.ts +19 -0
  108. package/node_modules/@slack/types/dist/events/member.d.ts.map +1 -0
  109. package/node_modules/@slack/types/dist/events/member.js +3 -0
  110. package/node_modules/@slack/types/dist/events/member.js.map +1 -0
  111. package/node_modules/@slack/types/dist/events/message-metadata.d.ts +38 -0
  112. package/node_modules/@slack/types/dist/events/message-metadata.d.ts.map +1 -0
  113. package/node_modules/@slack/types/dist/events/message-metadata.js +3 -0
  114. package/node_modules/@slack/types/dist/events/message-metadata.js.map +1 -0
  115. package/node_modules/@slack/types/dist/events/message.d.ts +306 -0
  116. package/node_modules/@slack/types/dist/events/message.d.ts.map +1 -0
  117. package/node_modules/@slack/types/dist/events/message.js +3 -0
  118. package/node_modules/@slack/types/dist/events/message.js.map +1 -0
  119. package/node_modules/@slack/types/dist/events/pin.d.ts +60 -0
  120. package/node_modules/@slack/types/dist/events/pin.d.ts.map +1 -0
  121. package/node_modules/@slack/types/dist/events/pin.js +3 -0
  122. package/node_modules/@slack/types/dist/events/pin.js.map +1 -0
  123. package/node_modules/@slack/types/dist/events/reaction.d.ts +23 -0
  124. package/node_modules/@slack/types/dist/events/reaction.d.ts.map +1 -0
  125. package/node_modules/@slack/types/dist/events/reaction.js +3 -0
  126. package/node_modules/@slack/types/dist/events/reaction.js.map +1 -0
  127. package/node_modules/@slack/types/dist/events/shared-channel.d.ts +134 -0
  128. package/node_modules/@slack/types/dist/events/shared-channel.d.ts.map +1 -0
  129. package/node_modules/@slack/types/dist/events/shared-channel.js +3 -0
  130. package/node_modules/@slack/types/dist/events/shared-channel.js.map +1 -0
  131. package/node_modules/@slack/types/dist/events/star.d.ts +13 -0
  132. package/node_modules/@slack/types/dist/events/star.d.ts.map +1 -0
  133. package/node_modules/@slack/types/dist/events/star.js +3 -0
  134. package/node_modules/@slack/types/dist/events/star.js.map +1 -0
  135. package/node_modules/@slack/types/dist/events/steps-from-apps.d.ts +82 -0
  136. package/node_modules/@slack/types/dist/events/steps-from-apps.d.ts.map +1 -0
  137. package/node_modules/@slack/types/dist/events/steps-from-apps.js +3 -0
  138. package/node_modules/@slack/types/dist/events/steps-from-apps.js.map +1 -0
  139. package/node_modules/@slack/types/dist/events/subteam.d.ts +66 -0
  140. package/node_modules/@slack/types/dist/events/subteam.d.ts.map +1 -0
  141. package/node_modules/@slack/types/dist/events/subteam.js +3 -0
  142. package/node_modules/@slack/types/dist/events/subteam.js.map +1 -0
  143. package/node_modules/@slack/types/dist/events/team.d.ts +99 -0
  144. package/node_modules/@slack/types/dist/events/team.d.ts.map +1 -0
  145. package/node_modules/@slack/types/dist/events/team.js +3 -0
  146. package/node_modules/@slack/types/dist/events/team.js.map +1 -0
  147. package/node_modules/@slack/types/dist/events/token.d.ts +8 -0
  148. package/node_modules/@slack/types/dist/events/token.d.ts.map +1 -0
  149. package/node_modules/@slack/types/dist/events/token.js +3 -0
  150. package/node_modules/@slack/types/dist/events/token.js.map +1 -0
  151. package/node_modules/@slack/types/dist/events/user.d.ts +313 -0
  152. package/node_modules/@slack/types/dist/events/user.d.ts.map +1 -0
  153. package/node_modules/@slack/types/dist/events/user.js +3 -0
  154. package/node_modules/@slack/types/dist/events/user.js.map +1 -0
  155. package/node_modules/@slack/types/dist/index.d.ts +12 -0
  156. package/node_modules/@slack/types/dist/index.d.ts.map +1 -0
  157. package/node_modules/@slack/types/dist/index.js +28 -0
  158. package/node_modules/@slack/types/dist/index.js.map +1 -0
  159. package/node_modules/@slack/types/dist/message-attachments.d.ts +171 -0
  160. package/node_modules/@slack/types/dist/message-attachments.d.ts.map +1 -0
  161. package/node_modules/@slack/types/dist/message-attachments.js +3 -0
  162. package/node_modules/@slack/types/dist/message-attachments.js.map +1 -0
  163. package/node_modules/@slack/types/dist/message-metadata.d.ts +281 -0
  164. package/node_modules/@slack/types/dist/message-metadata.d.ts.map +1 -0
  165. package/node_modules/@slack/types/dist/message-metadata.js +27 -0
  166. package/node_modules/@slack/types/dist/message-metadata.js.map +1 -0
  167. package/node_modules/@slack/types/dist/views.d.ts +71 -0
  168. package/node_modules/@slack/types/dist/views.d.ts.map +1 -0
  169. package/node_modules/@slack/types/dist/views.js +3 -0
  170. package/node_modules/@slack/types/dist/views.js.map +1 -0
  171. package/node_modules/@slack/types/package.json +47 -0
  172. package/node_modules/@vellumai/gateway-client/bun.lock +3 -0
  173. package/node_modules/@vellumai/gateway-client/package.json +1 -0
  174. package/node_modules/@vellumai/gateway-client/src/__tests__/contact-read-contracts.test.ts +69 -0
  175. package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +65 -0
  176. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +162 -0
  177. package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +8 -0
  178. package/node_modules/@vellumai/gateway-client/src/index.ts +14 -0
  179. package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +4 -2
  180. package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +3 -2
  181. package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +78 -0
  182. package/openapi.yaml +345 -18
  183. package/package.json +2 -1
  184. package/scripts/memory-inspect.ts +24 -14
  185. package/src/__tests__/access-request-seed-content-blocks.test.ts +83 -103
  186. package/src/__tests__/activation-early-marking.test.ts +1 -1
  187. package/src/__tests__/actor-token-service.test.ts +3 -3
  188. package/src/__tests__/agent-loop-callsite-precedence.test.ts +1 -40
  189. package/src/__tests__/agent-loop-compaction-events.test.ts +0 -1
  190. package/src/__tests__/agent-loop-compaction-strip.test.ts +0 -1
  191. package/src/__tests__/agent-loop-exit-reason.test.ts +0 -1
  192. package/src/__tests__/agent-loop-pushes-post-hook-prompt.test.ts +306 -0
  193. package/src/__tests__/agent-loop-regrowth-guard.test.ts +0 -1
  194. package/src/__tests__/agent-loop.test.ts +3 -0
  195. package/src/__tests__/agent-wake-override-profile.test.ts +2 -0
  196. package/src/__tests__/anthropic-provider.test.ts +143 -9
  197. package/src/__tests__/app-builder-skill-instructions.test.ts +47 -5
  198. package/src/__tests__/app-conversation-ids-backfill.test.ts +1 -1
  199. package/src/__tests__/app-source-watcher.test.ts +30 -10
  200. package/src/__tests__/approval-cascade.test.ts +6 -0
  201. package/src/__tests__/approval-interception-trust-gates.test.ts +151 -0
  202. package/src/__tests__/approval-primitive.test.ts +1 -1
  203. package/src/__tests__/approval-routes-http.test.ts +1 -1
  204. package/src/__tests__/assistant-attachments.test.ts +155 -0
  205. package/src/__tests__/assistant-event-hub-machine-name.test.ts +2 -4
  206. package/src/__tests__/assistant-events-sse-hardening.test.ts +1 -1
  207. package/src/__tests__/assistant-events-sse-shed.test.ts +1 -1
  208. package/src/__tests__/attachment-upload-trusted-source.test.ts +13 -8
  209. package/src/__tests__/attachments-store.test.ts +1 -1
  210. package/src/__tests__/audit-log-rotation.test.ts +50 -54
  211. package/src/__tests__/auth-fallback-events-store.test.ts +1 -1
  212. package/src/__tests__/auto-analysis-end-to-end.test.ts +9 -14
  213. package/src/__tests__/background-shell-bash.test.ts +4 -1
  214. package/src/__tests__/background-shell-host-bash.test.ts +17 -3
  215. package/src/__tests__/background-workers-disk-pressure.test.ts +1 -0
  216. package/src/__tests__/call-controller.test.ts +1 -1
  217. package/src/__tests__/call-conversation-messages.test.ts +1 -1
  218. package/src/__tests__/call-domain.test.ts +1 -1
  219. package/src/__tests__/call-pointer-messages.test.ts +3 -4
  220. package/src/__tests__/call-recovery.test.ts +1 -1
  221. package/src/__tests__/call-routes-http.test.ts +1 -1
  222. package/src/__tests__/call-store.test.ts +1 -1
  223. package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
  224. package/src/__tests__/canonical-guardian-store.test.ts +24 -1
  225. package/src/__tests__/channel-approval-routes.test.ts +73 -1119
  226. package/src/__tests__/channel-delivery-store.test.ts +1 -1
  227. package/src/__tests__/channel-guardian.test.ts +265 -641
  228. package/src/__tests__/channel-inbound-disk-pressure.test.ts +1 -2
  229. package/src/__tests__/channel-retry-sweep.test.ts +1 -1
  230. package/src/__tests__/compaction-events.test.ts +6 -0
  231. package/src/__tests__/compaction-trail-store.test.ts +6 -5
  232. package/src/__tests__/compaction.benchmark.test.ts +0 -1
  233. package/src/__tests__/compactor-image-manifest-trust.test.ts +1 -1
  234. package/src/__tests__/config-loader-backfill.test.ts +183 -51
  235. package/src/__tests__/config-schema.test.ts +34 -0
  236. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +1 -2
  237. package/src/__tests__/contact-store-user-file.test.ts +2 -2
  238. package/src/__tests__/contacts-relay-reads.test.ts +409 -0
  239. package/src/__tests__/contacts-tools.test.ts +4 -4
  240. package/src/__tests__/contacts-write.test.ts +1 -2
  241. package/src/__tests__/context-search-conversations-source.test.ts +1 -1
  242. package/src/__tests__/context-window-manager-compact-retry.test.ts +6 -2
  243. package/src/__tests__/context-window-manager-overflow-rung.test.ts +6 -2
  244. package/src/__tests__/conversation-abort-tool-results.test.ts +6 -0
  245. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +3 -0
  246. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +3 -0
  247. package/src/__tests__/conversation-agent-loop-overflow.test.ts +3 -0
  248. package/src/__tests__/conversation-agent-loop.test.ts +3 -0
  249. package/src/__tests__/conversation-attachments.test.ts +2 -5
  250. package/src/__tests__/conversation-attention-store.test.ts +1 -1
  251. package/src/__tests__/conversation-attention-telegram.test.ts +1 -2
  252. package/src/__tests__/conversation-clear-safety.test.ts +1 -1
  253. package/src/__tests__/conversation-confirmation-signals.test.ts +6 -0
  254. package/src/__tests__/conversation-crud-inference-profile.test.ts +1 -1
  255. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +12 -19
  256. package/src/__tests__/conversation-disk-view-integration.test.ts +1 -1
  257. package/src/__tests__/conversation-disk-view.test.ts +1 -1
  258. package/src/__tests__/conversation-fork-crud.test.ts +10 -8
  259. package/src/__tests__/conversation-fork-retrospective.test.ts +250 -0
  260. package/src/__tests__/conversation-fork-route.test.ts +1 -1
  261. package/src/__tests__/conversation-inference-profile-list.test.ts +1 -1
  262. package/src/__tests__/conversation-inference-profile-route.test.ts +1 -1
  263. package/src/__tests__/conversation-init.benchmark.test.ts +1 -1
  264. package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -1
  265. package/src/__tests__/conversation-lifecycle.test.ts +117 -0
  266. package/src/__tests__/conversation-list-source.test.ts +3 -3
  267. package/src/__tests__/conversation-process-callsite.test.ts +6 -14
  268. package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
  269. package/src/__tests__/conversation-queue.test.ts +6 -0
  270. package/src/__tests__/conversation-routes-disk-view.test.ts +1 -1
  271. package/src/__tests__/conversation-runtime-assembly.test.ts +115 -12
  272. package/src/__tests__/conversation-slash-queue.test.ts +6 -0
  273. package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
  274. package/src/__tests__/conversation-speed-override.test.ts +6 -0
  275. package/src/__tests__/conversation-starter-routes.test.ts +5 -5
  276. package/src/__tests__/conversation-store.test.ts +1 -1
  277. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +1 -1
  278. package/src/__tests__/conversation-sync-tags.test.ts +1 -1
  279. package/src/__tests__/conversation-usage.test.ts +1 -1
  280. package/src/__tests__/conversation-wipe.test.ts +9 -8
  281. package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -0
  282. package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
  283. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -0
  284. package/src/__tests__/conversations-import-system-filter.test.ts +1 -1
  285. package/src/__tests__/copy-composer-tc-templates.test.ts +17 -0
  286. package/src/__tests__/credential-security-invariants.test.ts +0 -1
  287. package/src/__tests__/db-acp-history.test.ts +2 -2
  288. package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +5 -7
  289. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +6 -7
  290. package/src/__tests__/db-llm-request-log-provider-migration.test.ts +5 -10
  291. package/src/__tests__/db-migration-rollback.test.ts +129 -39
  292. package/src/__tests__/db-proxy-transaction.test.ts +1 -1
  293. package/src/__tests__/db-schedule-syntax-migration.test.ts +0 -11
  294. package/src/__tests__/db-test-helpers.ts +36 -19
  295. package/src/__tests__/delete-propagation.test.ts +1 -1
  296. package/src/__tests__/deterministic-verification-control-plane.test.ts +26 -8
  297. package/src/__tests__/disk-pressure-tools.test.ts +41 -1
  298. package/src/__tests__/dm-backfill.test.ts +1 -1
  299. package/src/__tests__/drop-capability-card-state-migration.test.ts +0 -8
  300. package/src/__tests__/edit-propagation.test.ts +1 -1
  301. package/src/__tests__/emit-signal-routing-intent.test.ts +83 -0
  302. package/src/__tests__/empty-response-hook.test.ts +42 -0
  303. package/src/__tests__/events-client-registration.test.ts +1 -1
  304. package/src/__tests__/followup-tools.test.ts +1 -1
  305. package/src/__tests__/gemini-count-tokens.test.ts +70 -0
  306. package/src/__tests__/guardian-action-sweep.test.ts +9 -2
  307. package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
  308. package/src/__tests__/guardian-card-withdrawal.test.ts +1 -1
  309. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +1 -1
  310. package/src/__tests__/guardian-dispatch.test.ts +1 -1
  311. package/src/__tests__/guardian-outbound-http.test.ts +7 -12
  312. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +1 -1
  313. package/src/__tests__/guardian-routing-invariants.test.ts +2 -4
  314. package/src/__tests__/guardian-routing-state.test.ts +1 -2
  315. package/src/__tests__/guardian-verification-voice-binding.test.ts +1 -1
  316. package/src/__tests__/headless-browser-mode.test.ts +2 -2
  317. package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -0
  318. package/src/__tests__/heartbeat-service.test.ts +6 -0
  319. package/src/__tests__/helpers/channel-test-adapter.ts +98 -0
  320. package/src/__tests__/http-conversation-lineage.test.ts +1 -1
  321. package/src/__tests__/image-recovery-hook.test.ts +1 -1
  322. package/src/__tests__/inbound-invite-redemption.test.ts +1 -2
  323. package/src/__tests__/inbound-trust-verdict.test.ts +254 -0
  324. package/src/__tests__/inference-profile-reaper.test.ts +1 -1
  325. package/src/__tests__/inference-profile-session-handler.test.ts +1 -1
  326. package/src/__tests__/inference-profile-session-ipc.test.ts +1 -1
  327. package/src/__tests__/injector-chain.test.ts +1 -1
  328. package/src/__tests__/injector-disk-pressure.test.ts +11 -6
  329. package/src/__tests__/internal-telemetry-routes.test.ts +1 -1
  330. package/src/__tests__/invite-redemption-service.test.ts +244 -43
  331. package/src/__tests__/invite-routes-http.test.ts +35 -186
  332. package/src/__tests__/invite-service-ipc.test.ts +287 -0
  333. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +5 -5
  334. package/src/__tests__/jobs-store-upsert-debounced.test.ts +9 -12
  335. package/src/__tests__/list-messages-attachments.test.ts +42 -1
  336. package/src/__tests__/list-messages-client-message-id.test.ts +1 -1
  337. package/src/__tests__/list-messages-hidden-metadata.test.ts +1 -1
  338. package/src/__tests__/list-messages-page-latest.test.ts +1 -1
  339. package/src/__tests__/list-messages-tool-merge.test.ts +1 -1
  340. package/src/__tests__/llm-context-route-provider.test.ts +69 -4
  341. package/src/__tests__/llm-request-log-agent-loop-exit-reason.test.ts +9 -5
  342. package/src/__tests__/llm-request-log-call-site.test.ts +6 -6
  343. package/src/__tests__/llm-request-log-turn-query.test.ts +27 -13
  344. package/src/__tests__/llm-usage-store.test.ts +40 -1
  345. package/src/__tests__/log-export-routes.test.ts +1 -1
  346. package/src/__tests__/log-export-workspace.test.ts +3 -3
  347. package/src/__tests__/memory-jobs-worker-lanes.test.ts +5 -5
  348. package/src/__tests__/memory-recall-log-store.test.ts +1 -1
  349. package/src/__tests__/memory-upsert-concurrency.test.ts +3 -4
  350. package/src/__tests__/messages-after-tiebreaker.test.ts +1 -1
  351. package/src/__tests__/migration-import-from-url.test.ts +2 -2
  352. package/src/__tests__/mtime-cache.test.ts +375 -0
  353. package/src/__tests__/non-member-access-request.test.ts +1 -2
  354. package/src/__tests__/notification-candidate-guardian-context.test.ts +203 -0
  355. package/src/__tests__/notification-guardian-path.test.ts +1 -1
  356. package/src/__tests__/notification-schedule-notify-dedup.test.ts +1 -1
  357. package/src/__tests__/oauth-provider-profiles.test.ts +1 -1
  358. package/src/__tests__/oauth-provider-visibility.test.ts +1 -1
  359. package/src/__tests__/oauth-store.test.ts +1 -1
  360. package/src/__tests__/persist-unsendable-image-downscale.test.ts +1 -1
  361. package/src/__tests__/persist-unsendable-image.test.ts +1 -1
  362. package/src/__tests__/persona-resolver.test.ts +39 -1
  363. package/src/__tests__/platform-bash-auto-approve.test.ts +1 -1
  364. package/src/__tests__/playbook-execution.test.ts +1 -1
  365. package/src/__tests__/playbook-tools.test.ts +1 -1
  366. package/src/__tests__/plugin-api-model-profiles.test.ts +74 -21
  367. package/src/__tests__/plugin-bootstrap.test.ts +78 -0
  368. package/src/__tests__/provider-platform-proxy-integration.test.ts +25 -5
  369. package/src/__tests__/provider-usage-tracking.test.ts +1 -1
  370. package/src/__tests__/prune-old-conversations-job.test.ts +1 -1
  371. package/src/__tests__/reaction-persistence.test.ts +1 -1
  372. package/src/__tests__/relay-server.test.ts +357 -56
  373. package/src/__tests__/runtime-attachment-metadata.test.ts +10 -1
  374. package/src/__tests__/runtime-events-sse-bilingual.test.ts +7 -9
  375. package/src/__tests__/runtime-events-sse-parity.test.ts +1 -1
  376. package/src/__tests__/runtime-events-sse-reconnect.test.ts +1 -1
  377. package/src/__tests__/runtime-events-sse.test.ts +1 -1
  378. package/src/__tests__/schedule-retry.test.ts +1 -1
  379. package/src/__tests__/schedule-routes-workflow-validation.test.ts +1 -1
  380. package/src/__tests__/schedule-routes.test.ts +1 -1
  381. package/src/__tests__/schedule-store.test.ts +1 -1
  382. package/src/__tests__/schedule-tools.test.ts +1 -1
  383. package/src/__tests__/scheduler-disk-pressure.test.ts +1 -1
  384. package/src/__tests__/scheduler-recurrence.test.ts +1 -1
  385. package/src/__tests__/scheduler-reuse-conversation.test.ts +1 -1
  386. package/src/__tests__/scheduler-wake.test.ts +2 -1
  387. package/src/__tests__/scoped-approval-grants.test.ts +1 -1
  388. package/src/__tests__/scoped-grant-security-matrix.test.ts +5 -5
  389. package/src/__tests__/scrub-corrupted-image-attachments.test.ts +0 -8
  390. package/src/__tests__/secret-routes-platform-proxy.test.ts +1 -0
  391. package/src/__tests__/send-endpoint-busy.test.ts +1 -1
  392. package/src/__tests__/sequence-store.test.ts +1 -1
  393. package/src/__tests__/server-history-render.test.ts +40 -1
  394. package/src/__tests__/settings-routes.test.ts +11 -10
  395. package/src/__tests__/skill-load-tool.test.ts +72 -0
  396. package/src/__tests__/slack-inbound-verification.test.ts +1 -3
  397. package/src/__tests__/slack-messaging-token-resolution.test.ts +13 -2
  398. package/src/__tests__/slack-reaction-canonical-approval.test.ts +1 -1
  399. package/src/__tests__/subagent-tool-gate-mode.test.ts +2 -73
  400. package/src/__tests__/subagent-tools.test.ts +1 -31
  401. package/src/__tests__/system-prompt.test.ts +1 -1
  402. package/src/__tests__/system-storage-cleanup-skill.test.ts +56 -0
  403. package/src/__tests__/task-compiler.test.ts +1 -1
  404. package/src/__tests__/task-management-tools.test.ts +1 -1
  405. package/src/__tests__/task-memory-cleanup.test.ts +9 -6
  406. package/src/__tests__/task-scheduler.test.ts +1 -1
  407. package/src/__tests__/thread-backfill.test.ts +1 -1
  408. package/src/__tests__/tool-approval-handler.test.ts +1 -1
  409. package/src/__tests__/tool-approval-seed-content-blocks.test.ts +2 -0
  410. package/src/__tests__/tool-executor.test.ts +32 -1
  411. package/src/__tests__/tool-grant-request-escalation.test.ts +1 -2
  412. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +73 -1
  413. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +34 -34
  414. package/src/__tests__/trusted-contact-multichannel.test.ts +1 -2
  415. package/src/__tests__/trusted-contact-verification.test.ts +1 -1
  416. package/src/__tests__/turn-boundary-resolution.test.ts +3 -3
  417. package/src/__tests__/turn-events-store.test.ts +1 -1
  418. package/src/__tests__/twilio-routes.test.ts +2 -3
  419. package/src/__tests__/usage-cache-backfill-migration.test.ts +20 -10
  420. package/src/__tests__/usage-routes.test.ts +1 -1
  421. package/src/__tests__/user-plugin-loader.test.ts +34 -29
  422. package/src/__tests__/verification-control-plane-policy.test.ts +2 -2
  423. package/src/__tests__/voice-invite-redemption.test.ts +134 -36
  424. package/src/__tests__/voice-scoped-grant-consumer.test.ts +1 -1
  425. package/src/__tests__/voice-session-bridge.test.ts +1 -1
  426. package/src/__tests__/workspace-git-service.test.ts +114 -1
  427. package/src/__tests__/workspace-heartbeat-service.test.ts +45 -0
  428. package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +1 -1
  429. package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -1
  430. package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +88 -18
  431. package/src/__tests__/workspace-migration-108-drop-balanced-economy-profile.test.ts +6 -6
  432. package/src/__tests__/workspace-migration-109-swap-quality-profile-to-glm-5p2.test.ts +281 -0
  433. package/src/__tests__/workspace-migration-110-flip-balanced-profile-to-together.test.ts +167 -0
  434. package/src/__tests__/workspace-migrations-runner.test.ts +55 -0
  435. package/src/a2a/__tests__/e2e-a2a-channel.test.ts +1 -1
  436. package/src/a2a/__tests__/task-store.test.ts +1 -1
  437. package/src/acp/__tests__/session-manager-persistence.test.ts +1 -1
  438. package/src/acp/__tests__/session-manager-resume.test.ts +22 -11
  439. package/src/acp/__tests__/session-manager-startup.test.ts +1 -1
  440. package/src/acp/__tests__/session-manager.test.ts +72 -1
  441. package/src/acp/index.ts +10 -0
  442. package/src/acp/session-manager.ts +35 -0
  443. package/src/agent/loop.ts +45 -27
  444. package/src/api/index.ts +0 -6
  445. package/src/approvals/AGENTS.md +1 -2
  446. package/src/approvals/guardian-decision-primitive.ts +13 -210
  447. package/src/approvals/guardian-request-resolvers.ts +104 -58
  448. package/src/background-wake/wake-intent-hooks.test.ts +1 -1
  449. package/src/calls/__tests__/inbound-trust-reader.test.ts +110 -0
  450. package/src/calls/__tests__/relay-setup-router.test.ts +88 -62
  451. package/src/calls/inbound-trust-reader.ts +40 -0
  452. package/src/calls/relay-server.ts +65 -23
  453. package/src/calls/relay-setup-router.ts +20 -6
  454. package/src/calls/relay-verification.ts +7 -7
  455. package/src/cli/commands/contacts.ts +6 -24
  456. package/src/cli/commands/db/__tests__/repair.test.ts +15 -6
  457. package/src/cli/commands/db/__tests__/status.test.ts +7 -3
  458. package/src/cli/commands/db/status.ts +212 -33
  459. package/src/cli/commands/memory/__tests__/memory-v3.test.ts +6 -1
  460. package/src/cli/commands/memory/index.ts +2 -0
  461. package/src/cli/commands/memory/memory-retrospective.ts +129 -0
  462. package/src/cli/commands/memory/memory-v3.ts +176 -4
  463. package/src/cli/commands/plugins.ts +268 -11
  464. package/src/cli/lib/__tests__/install-from-github.test.ts +40 -0
  465. package/src/cli/lib/__tests__/plugin-pin-history.test.ts +162 -0
  466. package/src/cli/lib/__tests__/toggle-plugin.test.ts +158 -0
  467. package/src/cli/lib/install-from-github.ts +47 -6
  468. package/src/cli/lib/plugin-marketplace.ts +11 -0
  469. package/src/cli/lib/plugin-pin-history.ts +257 -0
  470. package/src/cli/lib/toggle-plugin.ts +146 -0
  471. package/src/config/__tests__/sync-gated-profiles.test.ts +2 -2
  472. package/src/config/bundled-skills/app-builder/SKILL.md +15 -33
  473. package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +3 -8
  474. package/src/config/bundled-skills/app-builder/references/INTERACTION_HOOKS.md +64 -37
  475. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +1 -1
  476. package/src/config/bundled-skills/app-builder/references/WIDGETS.md +14 -72
  477. package/src/config/bundled-skills/app-builder/references/examples/README.md +1 -2
  478. package/src/config/bundled-skills/contacts/SKILL.md +7 -12
  479. package/src/config/bundled-skills/messaging/tools/shared.ts +4 -1
  480. package/src/config/bundled-skills/system-storage-cleanup/SKILL.md +74 -0
  481. package/src/config/bundled-skills/workflows/SKILL.md +4 -3
  482. package/src/config/call-site-defaults.ts +11 -2
  483. package/src/config/feature-flag-registry.json +0 -8
  484. package/src/config/profile-dispatchability.ts +11 -0
  485. package/src/config/schemas/call-site-catalog.ts +7 -0
  486. package/src/config/schemas/llm.ts +2 -0
  487. package/src/config/schemas/memory-lifecycle.ts +5 -3
  488. package/src/config/schemas/timeouts.ts +24 -0
  489. package/src/config/seed-inference-profiles.ts +133 -45
  490. package/src/config/sync-gated-profiles.ts +13 -1
  491. package/src/contacts/contact-store.ts +21 -0
  492. package/src/contacts/member-status.ts +9 -0
  493. package/src/credential-health/credential-health-service.ts +1 -5
  494. package/src/daemon/__tests__/conversation-tool-setup.test.ts +44 -0
  495. package/src/daemon/app-source-watcher.ts +31 -18
  496. package/src/daemon/assistant-attachments.ts +94 -4
  497. package/src/daemon/conversation-agent-loop-handlers.ts +3 -0
  498. package/src/daemon/conversation-agent-loop.ts +9 -36
  499. package/src/daemon/conversation-runtime-assembly.ts +91 -66
  500. package/src/daemon/conversation-tool-setup.ts +20 -63
  501. package/src/daemon/conversation.ts +144 -52
  502. package/src/daemon/event-loop-watchdog.test.ts +85 -0
  503. package/src/daemon/event-loop-watchdog.ts +133 -0
  504. package/src/daemon/external-plugins-bootstrap.ts +26 -80
  505. package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +1 -1
  506. package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +1 -1
  507. package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +1 -1
  508. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +1 -1
  509. package/src/daemon/handlers/__tests__/config-a2a.test.ts +1 -1
  510. package/src/daemon/handlers/config-channels.ts +32 -18
  511. package/src/daemon/handlers/conversations.ts +7 -0
  512. package/src/daemon/handlers/shared.ts +7 -0
  513. package/src/daemon/lifecycle.ts +16 -3
  514. package/src/daemon/message-types/inbox.ts +0 -6
  515. package/src/daemon/message-types/messages.ts +0 -4
  516. package/src/daemon/message-types/surfaces.ts +18 -8
  517. package/src/daemon/server.ts +0 -4
  518. package/src/daemon/tool-setup-types.ts +0 -7
  519. package/src/daemon/trust-context.ts +6 -0
  520. package/src/daemon/wake-conversation-ops.ts +70 -0
  521. package/src/daemon/workspace-tools-watcher.ts +7 -3
  522. package/src/documents/document-comments-store.test.ts +1 -1
  523. package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +1 -1
  524. package/src/heartbeat/__tests__/heartbeat-service.test.ts +6 -0
  525. package/src/heartbeat/heartbeat-service.ts +3 -4
  526. package/src/ipc/__tests__/attachment-ipc.test.ts +1 -1
  527. package/src/ipc/__tests__/browser-ipc.test.ts +73 -2
  528. package/src/ipc/__tests__/watcher-ipc.test.ts +59 -39
  529. package/src/ipc/assistant-server.ts +8 -0
  530. package/src/ipc/gateway-client.ts +2 -1
  531. package/src/ipc/routes/__tests__/invite-ipc-routes.test.ts +58 -0
  532. package/src/ipc/routes/invite-ipc-routes.ts +66 -0
  533. package/src/live-voice/__tests__/live-voice-archive.test.ts +1 -1
  534. package/src/memory/__tests__/activation-session-store.test.ts +1 -1
  535. package/src/memory/__tests__/auto-analysis-guard.test.ts +1 -1
  536. package/src/memory/__tests__/conversation-group-migration.test.ts +1 -1
  537. package/src/memory/__tests__/conversation-queries.test.ts +1 -1
  538. package/src/memory/__tests__/db-async-query.test.ts +1 -1
  539. package/src/memory/__tests__/db-logs-attach.test.ts +110 -0
  540. package/src/memory/__tests__/db-maintenance.test.ts +28 -36
  541. package/src/memory/__tests__/db-memory-attach.test.ts +113 -0
  542. package/src/memory/__tests__/find-analysis-conversation.test.ts +1 -1
  543. package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +1 -1
  544. package/src/memory/__tests__/fork-message-copy.test.ts +232 -0
  545. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +3 -0
  546. package/src/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +5 -5
  547. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +8 -6
  548. package/src/memory/__tests__/memory-retrospective-job.test.ts +30 -37
  549. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +69 -66
  550. package/src/memory/__tests__/memory-retrospective-state.test.ts +1 -1
  551. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +1 -1
  552. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +1 -1
  553. package/src/memory/__tests__/onboarding-events-store.test.ts +1 -1
  554. package/src/memory/__tests__/table-relocation.test.ts +129 -0
  555. package/src/memory/conversation-crud.ts +461 -152
  556. package/src/memory/db-async-query.ts +89 -5
  557. package/src/memory/db-connection.ts +101 -18
  558. package/src/memory/db-init.ts +409 -234
  559. package/src/memory/db-maintenance.ts +43 -38
  560. package/src/memory/db-singleton.ts +45 -19
  561. package/src/memory/fork-message-copy.ts +170 -0
  562. package/src/memory/graph/__tests__/handle-remember-v2.test.ts +92 -0
  563. package/src/memory/graph/bootstrap.test.ts +6 -3
  564. package/src/memory/graph/retriever.test.ts +12 -12
  565. package/src/memory/graph/store.test.ts +15 -25
  566. package/src/memory/graph/store.ts +23 -14
  567. package/src/memory/graph/tool-handlers.ts +34 -5
  568. package/src/memory/graph/tools.ts +5 -2
  569. package/src/memory/indexer.ts +21 -9
  570. package/src/memory/job-handlers/cleanup.ts +10 -3
  571. package/src/memory/job-handlers/embedding.test.ts +4 -4
  572. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +4 -4
  573. package/src/memory/jobs/embed-pkb-file.test.ts +7 -7
  574. package/src/memory/jobs-store.ts +36 -24
  575. package/src/memory/llm-request-log-store.ts +51 -19
  576. package/src/memory/llm-usage-store.ts +31 -1
  577. package/src/memory/memory-retrospective-job.ts +27 -19
  578. package/src/memory/memory-retrospective-startup-cleanup.ts +10 -2
  579. package/src/memory/migrations/{100-core-tables.ts → 000-core-tables.ts} +6 -10
  580. package/src/memory/migrations/104-core-indexes.ts +1 -1
  581. package/src/memory/migrations/126-backfill-guardian-principal-id.ts +189 -196
  582. package/src/memory/migrations/127-guardian-principal-id-not-null.ts +98 -105
  583. package/src/memory/migrations/134-contacts-notes-column.ts +66 -69
  584. package/src/memory/migrations/135-backfill-contact-interaction-stats.ts +19 -22
  585. package/src/memory/migrations/136-drop-assistant-id-columns.ts +227 -230
  586. package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +204 -209
  587. package/src/memory/migrations/141-rename-verification-table.ts +45 -48
  588. package/src/memory/migrations/142-rename-verification-session-id-column.ts +16 -23
  589. package/src/memory/migrations/143-rename-guardian-verification-values.ts +23 -30
  590. package/src/memory/migrations/144-rename-voice-to-phone.ts +133 -136
  591. package/src/memory/migrations/145-drop-accounts-table.ts +4 -7
  592. package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +79 -82
  593. package/src/memory/migrations/148-drop-reminders-table.ts +3 -6
  594. package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +71 -78
  595. package/src/memory/migrations/157-invite-contact-id.ts +73 -76
  596. package/src/memory/migrations/162-guardian-timestamps-epoch-ms.ts +44 -58
  597. package/src/memory/migrations/169-rename-gmail-provider-key-to-google.ts +36 -43
  598. package/src/memory/migrations/174-rename-thread-starters-table.ts +30 -37
  599. package/src/memory/migrations/176-drop-capability-card-state.ts +17 -22
  600. package/src/memory/migrations/177-create-trace-events-table.ts +23 -28
  601. package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +36 -43
  602. package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +14 -21
  603. package/src/memory/migrations/191-backfill-audio-attachment-mime-types.ts +17 -24
  604. package/src/memory/migrations/192-contacts-user-file-column.ts +6 -9
  605. package/src/memory/migrations/193-add-source-type-columns.ts +33 -36
  606. package/src/memory/migrations/194-memory-recall-logs.ts +34 -39
  607. package/src/memory/migrations/196-strip-integration-prefix-from-provider-keys.ts +59 -66
  608. package/src/memory/migrations/199-guardian-request-enrichment-columns.ts +41 -48
  609. package/src/memory/migrations/204-rename-memory-graph-type-values.ts +11 -18
  610. package/src/memory/migrations/206-scrub-corrupted-image-attachments.ts +76 -83
  611. package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +50 -57
  612. package/src/memory/migrations/211-memory-recall-logs-query-context.ts +6 -11
  613. package/src/memory/migrations/212-llm-request-logs-created-at-index.ts +4 -9
  614. package/src/memory/migrations/217-conversation-host-access.ts +13 -18
  615. package/src/memory/migrations/220-normalize-user-file-by-principal.ts +86 -93
  616. package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +41 -48
  617. package/src/memory/migrations/230-acp-session-history.ts +23 -28
  618. package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +58 -62
  619. package/src/memory/migrations/232-activation-state.ts +11 -16
  620. package/src/memory/migrations/233-document-conversations.ts +20 -25
  621. package/src/memory/migrations/234-memory-v2-activation-logs.ts +26 -31
  622. package/src/memory/migrations/235-slack-compaction-watermark.ts +5 -10
  623. package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +6 -11
  624. package/src/memory/migrations/237-heartbeat-runs.ts +22 -27
  625. package/src/memory/migrations/239-trace-events-created-at-index.ts +4 -9
  626. package/src/memory/migrations/242-message-bookmarks.ts +17 -22
  627. package/src/memory/migrations/245-memory-retrospective-state.ts +8 -13
  628. package/src/memory/migrations/249-normalize-slack-external-content.ts +37 -41
  629. package/src/memory/migrations/251-a2a-tasks.ts +27 -32
  630. package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +12 -17
  631. package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +10 -15
  632. package/src/memory/migrations/256-memory-v2-injection-events.ts +70 -74
  633. package/src/memory/migrations/259-conversation-cleaned-at.ts +4 -9
  634. package/src/memory/migrations/260-rename-cleaned-at.ts +11 -16
  635. package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +3 -8
  636. package/src/memory/migrations/262-memory-v3-coactivation.ts +21 -26
  637. package/src/memory/migrations/263-memory-v3-auto-edges.ts +14 -19
  638. package/src/memory/migrations/270-schedule-description.ts +7 -12
  639. package/src/memory/migrations/272-acp-session-history-cwd.ts +8 -13
  640. package/src/memory/migrations/281-memory-retrospective-remembered-log.ts +8 -13
  641. package/src/memory/migrations/297-move-llm-request-logs-to-logs-db.ts +111 -0
  642. package/src/memory/migrations/298-move-memory-jobs-to-memory-db.ts +128 -0
  643. package/src/memory/migrations/299-canonical-guardian-deliveries-conversation-index.ts +19 -0
  644. package/src/memory/migrations/__tests__/297-move-llm-request-logs.test.ts +180 -0
  645. package/src/memory/migrations/__tests__/run-migrations.test.ts +333 -7
  646. package/src/memory/migrations/helpers/relocation.ts +227 -0
  647. package/src/memory/migrations/registry.ts +63 -0
  648. package/src/memory/migrations/run-migrations.ts +187 -16
  649. package/src/memory/migrations/validate-migration-state.ts +50 -145
  650. package/src/memory/raw-query.ts +47 -2
  651. package/src/memory/skill-loaded-events-store.test.ts +1 -1
  652. package/src/memory/task-memory-cleanup.ts +62 -41
  653. package/src/memory/tool-executed-events-store.test.ts +1 -1
  654. package/src/memory/turn-trace-store.test.ts +1 -1
  655. package/src/memory/v2/__tests__/backfill-jobs.test.ts +16 -15
  656. package/src/memory/v2/__tests__/harness-compare.test.ts +1 -1
  657. package/src/memory/v2/__tests__/harness-oracle.test.ts +1 -1
  658. package/src/memory/v2/__tests__/harness-replay-input.test.ts +1 -1
  659. package/src/memory/v2/__tests__/sweep-job.test.ts +2 -2
  660. package/src/memory/v3-eval/__tests__/eval-packets.test.ts +38 -0
  661. package/src/memory/v3-eval/__tests__/eval-tally.test.ts +139 -0
  662. package/src/memory/v3-eval/eval-packets.ts +197 -12
  663. package/src/memory/v3-eval/eval-tally.ts +234 -0
  664. package/src/messaging/provider.ts +10 -0
  665. package/src/messaging/providers/gmail/adapter.ts +1 -0
  666. package/src/messaging/providers/gmail/client.ts +14 -0
  667. package/src/messaging/providers/index.ts +1 -1
  668. package/src/messaging/providers/slack/send.test.ts +87 -39
  669. package/src/messaging/providers/slack/send.ts +84 -105
  670. package/src/notifications/README.md +9 -5
  671. package/src/notifications/__tests__/deterministic-checks.test.ts +43 -1
  672. package/src/notifications/adapters/slack.ts +12 -10
  673. package/src/notifications/approval-card-builder.ts +81 -20
  674. package/src/notifications/approval-card-data.ts +8 -5
  675. package/src/notifications/canonical-delivery-recorder.ts +7 -5
  676. package/src/notifications/conversation-candidates.ts +24 -59
  677. package/src/notifications/copy-composer.ts +48 -68
  678. package/src/notifications/deterministic-checks.ts +19 -16
  679. package/src/notifications/emit-signal.ts +29 -1
  680. package/src/notifications/trusted-contact-payloads.ts +70 -0
  681. package/src/oauth/byo-connection.test.ts +9 -0
  682. package/src/oauth/connection-resolver.test.ts +146 -6
  683. package/src/oauth/connection-resolver.ts +132 -5
  684. package/src/oauth/oauth-store.ts +16 -3
  685. package/src/oauth/scope-utils.ts +21 -0
  686. package/src/plugin-api/index.ts +9 -4
  687. package/src/plugin-api/model-profiles.test.ts +123 -0
  688. package/src/plugin-api/model-profiles.ts +5 -1
  689. package/src/plugin-api/vision-support.test.ts +149 -0
  690. package/src/plugin-api/vision-support.ts +78 -0
  691. package/src/plugins/defaults/compaction/window-manager.ts +45 -64
  692. package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +13 -4
  693. package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +302 -0
  694. package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +103 -0
  695. package/src/plugins/defaults/image-fallback/package.json +14 -0
  696. package/src/plugins/defaults/image-fallback/src/caption-cache.ts +49 -0
  697. package/src/plugins/defaults/image-fallback/src/image-persist.ts +59 -0
  698. package/src/plugins/defaults/image-fallback/src/vision-caption.ts +120 -0
  699. package/src/plugins/defaults/index.ts +23 -0
  700. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +14 -1
  701. package/src/plugins/defaults/memory-retrieval/injectors.ts +4 -4
  702. package/src/plugins/external-plugin-loader.ts +47 -6
  703. package/src/plugins/mtime-cache.ts +772 -0
  704. package/src/plugins/pipeline.ts +7 -2
  705. package/src/plugins/registry.ts +16 -5
  706. package/src/plugins/user-loader.ts +22 -76
  707. package/src/prompts/persona-resolver.ts +29 -11
  708. package/src/prompts/system-prompt.ts +1 -1
  709. package/src/prompts/templates/system-sections.ts +4 -4
  710. package/src/providers/__tests__/count-tokens-forwarding.test.ts +98 -0
  711. package/src/providers/anthropic/client.ts +254 -185
  712. package/src/providers/call-site-routing.ts +10 -0
  713. package/src/providers/gemini/client.ts +43 -0
  714. package/src/providers/inference/adapter-factory.ts +6 -0
  715. package/src/providers/inference/connections.ts +6 -1
  716. package/src/providers/model-catalog.ts +37 -0
  717. package/src/providers/platform-proxy/constants.ts +5 -0
  718. package/src/providers/ratelimit.ts +9 -0
  719. package/src/providers/retry.ts +10 -0
  720. package/src/providers/together/client.ts +35 -0
  721. package/src/providers/types.ts +16 -0
  722. package/src/providers/usage-tracking.ts +7 -0
  723. package/src/runtime/AGENTS.md +9 -1
  724. package/src/runtime/__tests__/agent-wake.test.ts +259 -4
  725. package/src/runtime/__tests__/slack-block-formatting.test.ts +39 -10
  726. package/src/runtime/__tests__/trust-verdict-consumer.test.ts +417 -0
  727. package/src/runtime/actor-trust-resolver.ts +8 -16
  728. package/src/runtime/agent-wake.ts +183 -60
  729. package/src/runtime/channel-reply-delivery.ts +6 -3
  730. package/src/runtime/guardian-decision-types.ts +3 -22
  731. package/src/runtime/http-server.ts +1 -15
  732. package/src/runtime/invite-redemption-service.ts +155 -6
  733. package/src/runtime/invite-service.ts +113 -62
  734. package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +3 -0
  735. package/src/runtime/routes/__tests__/acp-routes.test.ts +1 -1
  736. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +1 -1
  737. package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +277 -0
  738. package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +140 -0
  739. package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +26 -7
  740. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +14 -10
  741. package/src/runtime/routes/__tests__/contact-routes-update-channel-relay.test.ts +164 -0
  742. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
  743. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +1 -1
  744. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +8 -8
  745. package/src/runtime/routes/__tests__/conversation-surface-routes.test.ts +1 -1
  746. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +1 -3
  747. package/src/runtime/routes/__tests__/invite-relay-routes.test.ts +240 -0
  748. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +4 -0
  749. package/src/runtime/routes/__tests__/plugins-routes.test.ts +143 -0
  750. package/src/runtime/routes/__tests__/retrospective-routes.test.ts +1 -1
  751. package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +1 -1
  752. package/src/runtime/routes/acp-routes-list.test.ts +4 -0
  753. package/src/runtime/routes/acp-routes.test.ts +5 -6
  754. package/src/runtime/routes/attachment-routes.ts +21 -17
  755. package/src/runtime/routes/browser-routes.ts +19 -1
  756. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +5 -9
  757. package/src/runtime/routes/channel-verification-routes.ts +12 -1
  758. package/src/runtime/routes/contact-routes.ts +275 -164
  759. package/src/runtime/routes/conversation-query-routes.ts +15 -5
  760. package/src/runtime/routes/conversation-routes.ts +24 -3
  761. package/src/runtime/routes/conversation-starter-routes.ts +7 -8
  762. package/src/runtime/routes/guardian-approval-interception.ts +13 -274
  763. package/src/runtime/routes/inbound-message-handler.ts +20 -15
  764. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +285 -0
  765. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +45 -34
  766. package/src/runtime/routes/inbound-stages/admission-policy.ts +20 -5
  767. package/src/runtime/routes/log-export-routes.ts +2 -2
  768. package/src/runtime/routes/memory-eval-routes.ts +92 -0
  769. package/src/runtime/routes/memory-item-routes.test.ts +12 -11
  770. package/src/runtime/routes/migration-routes.ts +51 -40
  771. package/src/runtime/routes/plugins-routes.ts +164 -8
  772. package/src/runtime/routes/schedule-routes.ts +1 -0
  773. package/src/runtime/routes/usage-routes.ts +3 -0
  774. package/src/runtime/routes/work-items-routes.test.ts +1 -1
  775. package/src/runtime/slack-block-formatting.ts +46 -48
  776. package/src/runtime/trust-verdict-consumer.ts +172 -0
  777. package/src/schedule/scheduler.ts +6 -9
  778. package/src/telemetry/usage-telemetry-reporter.test.ts +1 -1
  779. package/src/tools/ask-question/ask-question-tool.test.ts +60 -52
  780. package/src/tools/ask-question/ask-question-tool.ts +14 -73
  781. package/src/tools/browser/__tests__/browser-status.test.ts +20 -0
  782. package/src/tools/browser/browser-execution.ts +16 -4
  783. package/src/tools/document/document-comment-tool.test.ts +1 -1
  784. package/src/tools/executor.ts +15 -3
  785. package/src/tools/host-terminal/host-shell.ts +28 -9
  786. package/src/tools/memory/register.test.ts +32 -0
  787. package/src/tools/skills/load.ts +43 -2
  788. package/src/tools/subagent/spawn.ts +4 -10
  789. package/src/tools/terminal/shell.ts +16 -5
  790. package/src/tools/types.ts +1 -0
  791. package/src/util/fs-watcher-error.ts +36 -0
  792. package/src/util/logs-db-path.ts +22 -0
  793. package/src/util/memory-db-path.ts +23 -0
  794. package/src/watcher/providers/gmail.ts +7 -2
  795. package/src/workflows/engine-integration.test.ts +1 -1
  796. package/src/workflows/engine.test.ts +1 -1
  797. package/src/workflows/engine.ts +22 -0
  798. package/src/workflows/fanout-load.test.ts +1 -1
  799. package/src/workflows/journal-store.test.ts +1 -1
  800. package/src/workflows/leaf-runner.test.ts +40 -1
  801. package/src/workflows/leaf-runner.ts +26 -1
  802. package/src/workspace/git-service.ts +144 -29
  803. package/src/workspace/migrations/109-swap-quality-profile-to-glm-5p2.ts +121 -0
  804. package/src/workspace/migrations/110-flip-balanced-profile-to-together.ts +82 -0
  805. package/src/workspace/migrations/registry.ts +4 -0
  806. package/src/workspace/migrations/runner.ts +32 -2
  807. package/src/__tests__/access-request-decision.test.ts +0 -375
  808. package/src/__tests__/guardian-grant-minting.test.ts +0 -607
  809. package/src/__tests__/plugin-source-watcher.test.ts +0 -302
  810. package/src/api/events/turn-profile-auto-routed.ts +0 -28
  811. package/src/daemon/__tests__/switch-inference-profile-tool.test.ts +0 -107
  812. package/src/daemon/plugin-source-watcher.ts +0 -278
  813. package/src/daemon/switch-inference-profile-tool.ts +0 -62
  814. package/src/memory/guardian-approvals.ts +0 -361
  815. package/src/memory/migrations/010-ext-conv-bindings-channel-chat-unique.ts +0 -66
  816. package/src/memory/migrations/038-actor-token-records.ts +0 -45
  817. package/src/memory/migrations/039-actor-refresh-token-records.ts +0 -57
  818. package/src/memory/migrations/103-complex-migrations.ts +0 -23
  819. package/src/memory/migrations/113-late-migrations.ts +0 -30
  820. package/src/memory/migrations/index.ts +0 -301
  821. package/src/runtime/routes/access-request-decision.ts +0 -297
  822. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +0 -963
  823. package/src/runtime/routes/channel-guardian-routes.ts +0 -19
  824. package/src/runtime/routes/guardian-expiry-sweep.ts +0 -132
@@ -15,7 +15,7 @@
15
15
  * - conversation-usage.ts — recordUsage
16
16
  */
17
17
 
18
- import type { AgentLoopConfig, ResolvedSystemPrompt } from "../agent/loop.js";
18
+ import type { AgentLoopConfig } from "../agent/loop.js";
19
19
  import { AgentLoop } from "../agent/loop.js";
20
20
  import type { AssistantActivityStateEvent } from "../api/events/assistant-activity-state.js";
21
21
  import type {
@@ -296,7 +296,7 @@ export class Conversation {
296
296
  outputTokens: 0,
297
297
  estimatedCost: 0,
298
298
  };
299
- /** @internal */ readonly systemPrompt: string;
299
+ /** @internal */ systemPrompt: string;
300
300
  /** @internal */ contextCompactedMessageCount = 0;
301
301
  /** @internal */ contextCompactedAt: number | null = null;
302
302
  /** @internal */ contextSummary: string | null = null;
@@ -376,7 +376,6 @@ export class Conversation {
376
376
  */
377
377
  wakePersonaOverride?: SystemPromptPersonaOverride;
378
378
  /** @internal */ currentTurnOverrideProfile?: string;
379
- /** @internal */ toolRoutedProfile?: string;
380
379
  /** @internal */ authContext?: AuthContext;
381
380
  /** @internal */ currentTurnAuthContext?: AuthContext;
382
381
  /** @internal */ currentTurnSourceActorPrincipalId?: string;
@@ -537,6 +536,7 @@ export class Conversation {
537
536
  };
538
537
  public readonly traceEmitter: TraceEmitter;
539
538
  /** @internal */ hasSystemPromptOverride: boolean;
539
+ /** @internal */ modelOverride: string | undefined;
540
540
  /** @internal */ readonly graphMemory: ConversationGraphMemory;
541
541
  /** @internal */ activeContextNodeIds?: string[];
542
542
  /** @internal */ streamThinking: boolean;
@@ -666,34 +666,9 @@ export class Conversation {
666
666
  const hasSystemPromptOverride = systemPrompt !== buildSystemPrompt();
667
667
  this.hasSystemPromptOverride = hasSystemPromptOverride;
668
668
 
669
- // If an explicit modelOverride is supplied, use it verbatim. Otherwise
670
- // leave the model unset and let `RetryProvider`'s call-site resolver pick
671
- // it up from `llm.default` / `llm.callSites.<id>` on every turn.
672
- const resolvedModel: string | undefined = modelOverride;
673
-
674
- const resolveSystemPromptCallback = (
675
- _history: Message[],
676
- ): ResolvedSystemPrompt => {
677
- const resolved: ResolvedSystemPrompt = {
678
- systemPrompt: this.hasSystemPromptOverride
679
- ? systemPrompt
680
- : buildSystemPrompt({
681
- hasNoClient: this.hasNoClient,
682
- trustContext: this.currentTurnTrustContext,
683
- channelCapabilities: this.currentTurnChannelCapabilities,
684
- personaOverride: this.wakePersonaOverride,
685
- onboardingContext: this.getOnboardingContext(),
686
- conversationId: this.conversationId,
687
- }),
688
- };
689
- if (configuredMaxTokens !== undefined) {
690
- resolved.maxTokens = configuredMaxTokens;
691
- }
692
- if (resolvedModel !== undefined) {
693
- resolved.model = resolvedModel;
694
- }
695
- return resolved;
696
- };
669
+ // Store the model override for per-run resolution. The loop receives it
670
+ // as a top-level `model` param on `run()`.
671
+ this.modelOverride = modelOverride;
697
672
 
698
673
  const fastModeEnabled = isAssistantFeatureFlagEnabled("fast-mode", config);
699
674
  const resolvedSpeed = speedOverride ?? resolvedMainAgent.speed;
@@ -726,7 +701,6 @@ export class Conversation {
726
701
  tools: toolDefs.length > 0 ? toolDefs : undefined,
727
702
  toolExecutor: toolDefs.length > 0 ? toolExecutor : undefined,
728
703
  resolveTools,
729
- resolveSystemPrompt: resolveSystemPromptCallback,
730
704
  resolveConversationDir: () => {
731
705
  const conv = getConversation(this.conversationId);
732
706
  if (!conv) return null;
@@ -738,7 +712,6 @@ export class Conversation {
738
712
  });
739
713
  createContextWindowManager({
740
714
  provider,
741
- systemPrompt: () => resolveSystemPromptCallback([]).systemPrompt,
742
715
  config: initialContextWindowConfig,
743
716
  toolTokenBudget: this.agentLoop.getToolTokenBudget(),
744
717
  conversationId: this.conversationId,
@@ -799,6 +772,29 @@ export class Conversation {
799
772
  this.inferenceProfileExpiresAt = state.expiresAt;
800
773
  }
801
774
 
775
+ /**
776
+ * Build the system prompt for the current conversation state. When a
777
+ * system-prompt override was supplied at construction, use it as-is;
778
+ * otherwise rebuild the full prompt (picks up workspace file changes,
779
+ * live trust/channel context, persona overrides, onboarding context).
780
+ *
781
+ * Called by the caller before invoking `agentLoop.run()` — the loop
782
+ * itself never re-resolves the prompt mid-loop (re-resolving would bust
783
+ * the provider's prefix cache).
784
+ */
785
+ buildCurrentSystemPrompt(): string {
786
+ return this.hasSystemPromptOverride
787
+ ? this.systemPrompt
788
+ : buildSystemPrompt({
789
+ hasNoClient: this.hasNoClient,
790
+ trustContext: this.currentTurnTrustContext,
791
+ channelCapabilities: this.currentTurnChannelCapabilities,
792
+ personaOverride: this.wakePersonaOverride,
793
+ onboardingContext: this.getOnboardingContext(),
794
+ conversationId: this.conversationId,
795
+ });
796
+ }
797
+
802
798
  // ── Prompt Cache Warming ─────────────────────────────────────────
803
799
 
804
800
  /**
@@ -811,16 +807,7 @@ export class Conversation {
811
807
  const abort = new AbortController();
812
808
  this.cacheWarmAbort = abort;
813
809
 
814
- const systemPrompt = this.hasSystemPromptOverride
815
- ? this.systemPrompt
816
- : buildSystemPrompt({
817
- hasNoClient: this.hasNoClient,
818
- trustContext: this.currentTurnTrustContext,
819
- channelCapabilities: this.currentTurnChannelCapabilities,
820
- personaOverride: this.wakePersonaOverride,
821
- onboardingContext: this.getOnboardingContext(),
822
- conversationId: this.conversationId,
823
- });
810
+ const systemPrompt = this.buildCurrentSystemPrompt();
824
811
  const tools = getAllToolDefinitions();
825
812
  const provider = this.provider;
826
813
 
@@ -976,6 +963,18 @@ export class Conversation {
976
963
  const meta = JSON.parse(m.metadata);
977
964
  const isTail = index === arr.length - 1;
978
965
 
966
+ // `<non_interactive_context>` is the only rehydrated block that
967
+ // APPENDS to the tail (live injection appends it in Step 3), so it
968
+ // must land after the original content. Apply it first — before the
969
+ // prepends below — so the prepends stack in front of it and it stays
970
+ // last, matching the live layout.
971
+ if (!isTail && typeof meta.nonInteractiveContextBlock === "string") {
972
+ content = [
973
+ ...content,
974
+ { type: "text" as const, text: meta.nonInteractiveContextBlock },
975
+ ];
976
+ }
977
+
979
978
  // Rehydrate in reverse injection order (innermost block first)
980
979
  // so the resulting layout matches `applyRuntimeInjections`'s
981
980
  // after-memory-prefix splices in ascending injector order
@@ -1086,6 +1085,17 @@ export class Conversation {
1086
1085
  ];
1087
1086
  }
1088
1087
 
1088
+ // `<channel_capabilities>` lands just below `<turn_context>`: live
1089
+ // injection prepends it (Step 3) before the prepend-user-tail chain
1090
+ // blocks (Step 4), so it must be prepended BEFORE turnContextBlock
1091
+ // here to land one slot deeper than `<turn_context>`.
1092
+ if (!isTail && typeof meta.channelCapabilitiesBlock === "string") {
1093
+ content = [
1094
+ { type: "text" as const, text: meta.channelCapabilitiesBlock },
1095
+ ...content,
1096
+ ];
1097
+ }
1098
+
1089
1099
  if (!isTail && typeof meta.turnContextBlock === "string") {
1090
1100
  content = [
1091
1101
  { type: "text" as const, text: meta.turnContextBlock },
@@ -1093,6 +1103,16 @@ export class Conversation {
1093
1103
  ];
1094
1104
  }
1095
1105
 
1106
+ // `<background_turn>` lands between `<workspace>` and `<turn_context>`
1107
+ // (injector order 15, between workspace 10 and unified-turn-context
1108
+ // 20), so prepend it AFTER turnContextBlock and BEFORE workspaceBlock.
1109
+ if (!isTail && typeof meta.backgroundTurnBlock === "string") {
1110
+ content = [
1111
+ { type: "text" as const, text: meta.backgroundTurnBlock },
1112
+ ...content,
1113
+ ];
1114
+ }
1115
+
1096
1116
  if (!isTail && typeof meta.workspaceBlock === "string") {
1097
1117
  content = [
1098
1118
  { type: "text" as const, text: meta.workspaceBlock },
@@ -1529,9 +1549,7 @@ export class Conversation {
1529
1549
 
1530
1550
  ensureHostProxiesForTurn(
1531
1551
  sourceInterface: import("../channels/types.js").InterfaceId | undefined,
1532
- sourceActorPrincipalId = this.currentTurnSourceActorPrincipalId ??
1533
- this.currentTurnAuthContext?.actorPrincipalId ??
1534
- this.authContext?.actorPrincipalId,
1552
+ sourceActorPrincipalId = this.getTurnActorPrincipalId(),
1535
1553
  ): void {
1536
1554
  if (
1537
1555
  shouldAttachHostProxyForCapability(
@@ -1606,8 +1624,65 @@ export class Conversation {
1606
1624
  }
1607
1625
  }
1608
1626
 
1627
+ /**
1628
+ * Token count for `messages` used to render the user-facing `/compact` and
1629
+ * `/clean` figures. Prefers the provider's real `count_tokens` tokenizer (so
1630
+ * the numbers match the context-window indicator's provider-reported usage)
1631
+ * and falls back to the context-window manager's local estimate when the
1632
+ * provider has no count endpoint or the count call fails — both measure the
1633
+ * same system-prompt + tools composition the manager sizes against.
1634
+ *
1635
+ * The count is a network round-trip with its own rate limit, so this is for
1636
+ * user-initiated actions only, never the per-turn auto-compaction gate.
1637
+ */
1638
+ private async calculateTokens(messages: Message[]): Promise<number> {
1639
+ const countInputTokens = this.provider.countInputTokens;
1640
+ if (!countInputTokens) {
1641
+ return this.contextWindowManager.estimateInputTokens(messages);
1642
+ }
1643
+ try {
1644
+ const { systemPrompt, tools } =
1645
+ this.contextWindowManager.tokenCountInputs;
1646
+ return await countInputTokens.call(
1647
+ this.provider,
1648
+ messages,
1649
+ systemPrompt,
1650
+ tools,
1651
+ );
1652
+ } catch (err) {
1653
+ log.warn(
1654
+ { err, conversationId: this.conversationId },
1655
+ "Provider token count failed — falling back to local estimate",
1656
+ );
1657
+ return this.contextWindowManager.estimateInputTokens(messages);
1658
+ }
1659
+ }
1660
+
1609
1661
  async forceCompact(): Promise<ContextWindowResult> {
1610
- return this.runCompaction(true);
1662
+ // Report the user-facing before/after using the provider's real tokenizer
1663
+ // (count_tokens) so the `/compact` line matches the context-window
1664
+ // indicator, which reflects the provider's actual reported usage — rather
1665
+ // than the local chars/4 estimate the compaction pipeline runs internally
1666
+ // (it under-counts by ~25% on typical histories). `calculateTokens`
1667
+ // falls back to that estimate when the provider has no count endpoint or
1668
+ // the count call fails, so behavior degrades gracefully.
1669
+ //
1670
+ // Only the *displayed* numbers are overridden — the compaction log and
1671
+ // circuit-breaker accounting inside `runCompaction` keep the estimate-based
1672
+ // figures, leaving calibration and historical logs untouched.
1673
+ const before = await this.calculateTokens(this.messages);
1674
+ const result = await this.runCompaction(true);
1675
+ // `runCompaction` applies the compacted history to `this.messages` in
1676
+ // place, so after a successful compaction this re-counts the new history;
1677
+ // a no-op leaves the context unchanged, so before === after.
1678
+ const after = result.compacted
1679
+ ? await this.calculateTokens(this.messages)
1680
+ : before;
1681
+ return {
1682
+ ...result,
1683
+ previousEstimatedInputTokens: before,
1684
+ estimatedInputTokens: after,
1685
+ };
1611
1686
  }
1612
1687
 
1613
1688
  /**
@@ -1726,15 +1801,17 @@ export class Conversation {
1726
1801
  * activations are no longer deduped against the prior session.
1727
1802
  */
1728
1803
  async forceClean(): Promise<CleanResult> {
1729
- const previousEstimatedInputTokens =
1730
- this.contextWindowManager.estimateInputTokens(this.messages);
1804
+ // Use the provider's real tokenizer for the displayed before/after (see
1805
+ // `forceCompact` for why); falls back to the local estimate when count
1806
+ // isn't available.
1807
+ const previousEstimatedInputTokens = await this.calculateTokens(
1808
+ this.messages,
1809
+ );
1731
1810
  const stripped = stripInjectionsForCompaction(this.messages);
1732
1811
  this.messages = stripped;
1733
1812
  await this.graphMemory.onCompacted(0);
1734
1813
  setConversationHistoryStrippedAt(this.conversationId, Date.now());
1735
- const estimatedInputTokens = this.contextWindowManager.estimateInputTokens(
1736
- this.messages,
1737
- );
1814
+ const estimatedInputTokens = await this.calculateTokens(this.messages);
1738
1815
  return {
1739
1816
  previousEstimatedInputTokens,
1740
1817
  estimatedInputTokens,
@@ -1767,6 +1844,21 @@ export class Conversation {
1767
1844
  return this.authContext;
1768
1845
  }
1769
1846
 
1847
+ /**
1848
+ * The actor principal that owns the current turn, for host-proxy routing.
1849
+ * Prefers the in-flight turn's actor over the conversation's resting
1850
+ * authContext so a /v1/messages turn (which sets only
1851
+ * `currentTurnSourceActorPrincipalId`/`currentTurnAuthContext`) scopes
1852
+ * correctly. Returns `undefined` when no actor identity is known.
1853
+ */
1854
+ getTurnActorPrincipalId(): string | undefined {
1855
+ return (
1856
+ this.currentTurnSourceActorPrincipalId ??
1857
+ this.currentTurnAuthContext?.actorPrincipalId ??
1858
+ this.authContext?.actorPrincipalId
1859
+ );
1860
+ }
1861
+
1770
1862
  setVoiceCallControlPrompt(prompt: string | null): void {
1771
1863
  this.voiceCallControlPrompt = prompt ?? undefined;
1772
1864
  }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Tests for the event-loop block watchdog.
3
+ *
4
+ * - `evaluateTick` must derive the blocked duration as elapsed-beyond-interval
5
+ * and apply the threshold inclusively, clamping early/normal ticks to zero so
6
+ * a healthy loop never reports.
7
+ * - `start`/`stop` must be idempotent and safe to call in any order so daemon
8
+ * startup and the two shutdown paths can call them unconditionally.
9
+ */
10
+ import { describe, expect, mock, test } from "bun:test";
11
+
12
+ mock.module("../util/logger.js", () => ({
13
+ getLogger: () =>
14
+ new Proxy({} as Record<string, unknown>, { get: () => () => {} }),
15
+ }));
16
+
17
+ const { evaluateTick, startEventLoopWatchdog, stopEventLoopWatchdog } =
18
+ await import("./event-loop-watchdog.js");
19
+
20
+ describe("evaluateTick", () => {
21
+ const INTERVAL = 1_000;
22
+ const THRESHOLD = 5_000;
23
+
24
+ test("a healthy tick at the scheduled interval is not a block", () => {
25
+ // GIVEN the timer fired right on schedule
26
+ // WHEN the tick is evaluated
27
+ const { blockedMs, exceeded } = evaluateTick(INTERVAL, INTERVAL, THRESHOLD);
28
+ // THEN no block is observed
29
+ expect(blockedMs).toBe(0);
30
+ expect(exceeded).toBe(false);
31
+ });
32
+
33
+ test("an early tick clamps the blocked duration to zero", () => {
34
+ // GIVEN the timer fired sooner than the interval (e.g. clock jitter)
35
+ // WHEN the tick is evaluated
36
+ const { blockedMs, exceeded } = evaluateTick(200, INTERVAL, THRESHOLD);
37
+ // THEN the blocked duration never goes negative
38
+ expect(blockedMs).toBe(0);
39
+ expect(exceeded).toBe(false);
40
+ });
41
+
42
+ test("lateness under the threshold is measured but not reported", () => {
43
+ // GIVEN the loop was blocked ~2s (below the 5s threshold)
44
+ // WHEN the tick is evaluated
45
+ const { blockedMs, exceeded } = evaluateTick(3_000, INTERVAL, THRESHOLD);
46
+ // THEN the block is quantified but does not trip a report
47
+ expect(blockedMs).toBe(2_000);
48
+ expect(exceeded).toBe(false);
49
+ });
50
+
51
+ test("the threshold is inclusive", () => {
52
+ // GIVEN the blocked duration lands exactly on the threshold
53
+ // WHEN the tick is evaluated
54
+ const { blockedMs, exceeded } = evaluateTick(
55
+ INTERVAL + THRESHOLD,
56
+ INTERVAL,
57
+ THRESHOLD,
58
+ );
59
+ // THEN it counts as exceeded
60
+ expect(blockedMs).toBe(THRESHOLD);
61
+ expect(exceeded).toBe(true);
62
+ });
63
+
64
+ test("a multi-minute freeze reports the full blocked duration", () => {
65
+ // GIVEN a ~123s freeze (the observed daemon-freeze magnitude) with a 1s tick
66
+ // WHEN the first tick after unblock is evaluated
67
+ const { blockedMs, exceeded } = evaluateTick(124_000, INTERVAL, THRESHOLD);
68
+ // THEN the reported block excludes the one normal interval of wait
69
+ expect(blockedMs).toBe(123_000);
70
+ expect(exceeded).toBe(true);
71
+ });
72
+ });
73
+
74
+ describe("start/stop lifecycle", () => {
75
+ test("start and stop are idempotent and order-independent", () => {
76
+ // GIVEN a fresh module
77
+ // WHEN start/stop are called repeatedly and out of order
78
+ // THEN none of the calls throw (daemon boot + both shutdown paths are safe)
79
+ expect(() => stopEventLoopWatchdog()).not.toThrow();
80
+ expect(() => startEventLoopWatchdog()).not.toThrow();
81
+ expect(() => startEventLoopWatchdog()).not.toThrow();
82
+ expect(() => stopEventLoopWatchdog()).not.toThrow();
83
+ expect(() => stopEventLoopWatchdog()).not.toThrow();
84
+ });
85
+ });
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Event-loop block watchdog.
3
+ *
4
+ * The daemon runs all request handling, synchronous `bun:sqlite` access, and
5
+ * background jobs on a single event-loop thread. Any synchronous operation that
6
+ * runs long — a large conversation-history load, a memory retrospective
7
+ * assembling an oversized conversation, a VACUUM or WAL checkpoint — blocks that
8
+ * thread, so the daemon stops answering health probes and SSE for the duration
9
+ * (a proxied `vellum ps` health check then reports `timeout` even though the
10
+ * process is alive). Such a freeze is otherwise invisible: the blocked thread is
11
+ * too busy to emit logs, so it leaves only a gap that self-heals when the
12
+ * operation returns, and is noticed only by chance.
13
+ *
14
+ * This watchdog makes those freezes observable. It schedules a timer every
15
+ * `TICK_INTERVAL_MS`; when the loop is blocked the callback cannot run, so it
16
+ * fires late by roughly the block duration. On the first tick after the loop
17
+ * frees up, the elapsed-since-last-tick beyond a normal interval is how long the
18
+ * loop was unavailable; above a threshold it emits a warn log + Sentry capture.
19
+ *
20
+ * What it does NOT do: capture the JS stack of the blocking operation. JS is
21
+ * single-threaded, so while the loop is blocked no callback — including this one
22
+ * — can run; by the time the tick fires, the offending synchronous call has
23
+ * returned and its stack is gone. The watchdog reports *that* and *how long* a
24
+ * freeze happened, not *what* caused it. The report lands at unblock, so the
25
+ * surrounding log lines (which job or turn was active) are the correlation
26
+ * handle. For deterministic attribution of a specific subsystem, time that
27
+ * subsystem's synchronous calls at their source.
28
+ *
29
+ * A cumulative event-loop-delay histogram is separately exposed pull-based over
30
+ * SSE diagnostics (`runtime/routes/events-routes.ts`); this watchdog is the
31
+ * push/alert counterpart and runs unconditionally for the daemon's lifetime.
32
+ */
33
+
34
+ import * as Sentry from "@sentry/node";
35
+
36
+ import { getLogger } from "../util/logger.js";
37
+
38
+ const log = getLogger("event-loop-watchdog");
39
+
40
+ /** How often the probe timer is scheduled. */
41
+ const TICK_INTERVAL_MS = 1_000;
42
+
43
+ /**
44
+ * Report only when the loop was unavailable for at least this long beyond a
45
+ * normal tick. Set above the floor of the daemon's known-legitimate
46
+ * multi-second main-thread operations so the signal stays actionable rather than
47
+ * noisy; tune here.
48
+ */
49
+ const DEFAULT_BLOCK_THRESHOLD_MS = 5_000;
50
+
51
+ /**
52
+ * Minimum spacing between reports. A single long freeze fires the timer once on
53
+ * unblock (an overdue interval is not replayed per missed tick), but a loop that
54
+ * blocks repeatedly could trip every tick; the cooldown bounds that to one
55
+ * report per window.
56
+ */
57
+ const REPORT_COOLDOWN_MS = 30_000;
58
+
59
+ let tickTimer: ReturnType<typeof setInterval> | null = null;
60
+ let lastTickAt = 0;
61
+ let lastReportAt = Number.NEGATIVE_INFINITY;
62
+
63
+ /**
64
+ * Given the wall-clock elapsed since the previous tick and the scheduled tick
65
+ * interval, the loop was blocked for the excess over the interval. Pure so the
66
+ * threshold decision is unit-testable without real timers or a blocked loop.
67
+ */
68
+ export function evaluateTick(
69
+ elapsedMs: number,
70
+ intervalMs: number,
71
+ thresholdMs: number,
72
+ ): { blockedMs: number; exceeded: boolean } {
73
+ const blockedMs = Math.max(0, elapsedMs - intervalMs);
74
+ return { blockedMs, exceeded: blockedMs >= thresholdMs };
75
+ }
76
+
77
+ function reportBlock(blockedMs: number, thresholdMs: number): void {
78
+ log.warn(
79
+ { blockedMs, thresholdMs, tickIntervalMs: TICK_INTERVAL_MS },
80
+ "event loop blocked",
81
+ );
82
+ try {
83
+ Sentry.withScope((scope) => {
84
+ scope.setLevel("warning");
85
+ scope.setTag("event_loop_blocked_ms", String(blockedMs));
86
+ scope.setContext("event_loop_block", {
87
+ blocked_ms: blockedMs,
88
+ threshold_ms: thresholdMs,
89
+ tick_interval_ms: TICK_INTERVAL_MS,
90
+ });
91
+ Sentry.captureMessage("event_loop_blocked");
92
+ });
93
+ } catch {
94
+ // Never let a telemetry failure escape the timer callback.
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Start the event-loop block watchdog. Idempotent. The timer is `unref`'d so it
100
+ * never keeps the process alive on its own.
101
+ */
102
+ export function startEventLoopWatchdog(
103
+ thresholdMs: number = DEFAULT_BLOCK_THRESHOLD_MS,
104
+ ): void {
105
+ if (tickTimer) return;
106
+ lastTickAt = performance.now();
107
+ lastReportAt = Number.NEGATIVE_INFINITY;
108
+ tickTimer = setInterval(() => {
109
+ const now = performance.now();
110
+ const { blockedMs, exceeded } = evaluateTick(
111
+ now - lastTickAt,
112
+ TICK_INTERVAL_MS,
113
+ thresholdMs,
114
+ );
115
+ lastTickAt = now;
116
+ if (exceeded && now - lastReportAt >= REPORT_COOLDOWN_MS) {
117
+ lastReportAt = now;
118
+ reportBlock(blockedMs, thresholdMs);
119
+ }
120
+ }, TICK_INTERVAL_MS);
121
+ tickTimer.unref?.();
122
+ log.info(
123
+ { tickIntervalMs: TICK_INTERVAL_MS, thresholdMs },
124
+ "Event-loop watchdog started",
125
+ );
126
+ }
127
+
128
+ export function stopEventLoopWatchdog(): void {
129
+ if (tickTimer) {
130
+ clearInterval(tickTimer);
131
+ tickTimer = null;
132
+ }
133
+ }
@@ -56,7 +56,7 @@
56
56
  * plugin level so the plugin name is attributed.
57
57
  */
58
58
 
59
- import { mkdirSync } from "node:fs";
59
+ import { existsSync, mkdirSync } from "node:fs";
60
60
  import { join } from "node:path";
61
61
 
62
62
  import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
@@ -64,13 +64,7 @@ import { getConfig } from "../config/loader.js";
64
64
  import type { AssistantConfig } from "../config/schema.js";
65
65
  import { HOOKS } from "../plugin-api/constants.js";
66
66
  import { registerDefaultPlugins } from "../plugins/defaults/index.js";
67
- import { buildExternalPlugin } from "../plugins/external-plugin-loader.js";
68
- import {
69
- getRegisteredPlugin,
70
- getRegisteredPlugins,
71
- setRegisteredPlugin,
72
- unregisterPlugin,
73
- } from "../plugins/registry.js";
67
+ import { getRegisteredPlugins, unregisterPlugin } from "../plugins/registry.js";
74
68
  import {
75
69
  type Plugin,
76
70
  PluginExecutionError,
@@ -88,7 +82,7 @@ import {
88
82
  unregisterPluginTools,
89
83
  } from "../tools/registry.js";
90
84
  import { getLogger } from "../util/logger.js";
91
- import { getWorkspaceDir } from "../util/platform.js";
85
+ import { getWorkspaceDir, getWorkspacePluginsDir } from "../util/platform.js";
92
86
  import { APP_VERSION } from "../version.js";
93
87
  import { registerShutdownHook } from "./shutdown-registry.js";
94
88
 
@@ -269,6 +263,29 @@ export async function bootstrapPlugins(): Promise<void> {
269
263
  continue;
270
264
  }
271
265
 
266
+ // Check for the .disabled sentinel. Both default and user plugins
267
+ // can be disabled by creating a `.disabled` file at
268
+ // <workspace>/plugins/<manifest-name>/.disabled. For user plugins
269
+ // this is the plugin's own directory; for default plugins (which
270
+ // live in the source tree) the workspace directory acts as an
271
+ // out-of-band kill switch — the operator creates a directory named
272
+ // after the plugin's manifest name (e.g. `plugins/default-advisor/`)
273
+ // and drops a `.disabled` file inside it. Runs before init so no
274
+ // hooks, tools, or routes from the disabled plugin are ever wired.
275
+ const disabledSentinelPath = join(
276
+ getWorkspacePluginsDir(),
277
+ name,
278
+ ".disabled",
279
+ );
280
+ if (existsSync(disabledSentinelPath)) {
281
+ log.info(
282
+ { plugin: name, sentinel: disabledSentinelPath },
283
+ `skipping plugin ${name}: disabled via .disabled sentinel`,
284
+ );
285
+ unregisterPlugin(name);
286
+ continue;
287
+ }
288
+
272
289
  try {
273
290
  activePlugins.push(await initializePlugin(plugin, assistantConfig));
274
291
  } catch (err) {
@@ -467,74 +484,3 @@ async function teardownPlugin(
467
484
  }
468
485
  }
469
486
  }
470
-
471
- /** Rebuild a changed external plugin and swap it into the live registry. */
472
- export async function reregisterExternalPlugin(
473
- pluginName: string,
474
- ): Promise<void> {
475
- const pluginDir = join(getWorkspaceDir(), "plugins", pluginName);
476
- const plugin = await buildExternalPlugin(pluginDir);
477
- if (plugin === undefined) return;
478
-
479
- if (plugin.manifest.name !== pluginName) {
480
- log.warn(
481
- { plugin: pluginName, manifestName: plugin.manifest.name, pluginDir },
482
- `external plugin reload skipped: directory name "${pluginName}" does not match manifest.name "${plugin.manifest.name}"`,
483
- );
484
- return;
485
- }
486
-
487
- const assistantConfig = getConfig();
488
- const disabledFlag = getDisabledPluginFlag(plugin, assistantConfig);
489
- if (disabledFlag !== undefined) {
490
- log.info(
491
- { plugin: pluginName, flag: disabledFlag },
492
- `external plugin reload skipped: feature flag ${disabledFlag} is disabled`,
493
- );
494
- return;
495
- }
496
-
497
- const existing = getRegisteredPlugin(pluginName);
498
- if (existing === undefined) {
499
- try {
500
- await initializePlugin(plugin, assistantConfig);
501
- setRegisteredPlugin(plugin);
502
- log.info({ plugin: pluginName }, "external plugin registered post-boot");
503
- } catch (err) {
504
- log.error(
505
- { err, plugin: pluginName },
506
- "external plugin post-boot registration failed",
507
- );
508
- }
509
- return;
510
- }
511
-
512
- try {
513
- unregisterPluginTools(pluginName);
514
- } catch (err) {
515
- log.warn(
516
- { err, plugin: pluginName },
517
- "external plugin reload: tool unregister failed (continuing)",
518
- );
519
- }
520
-
521
- setRegisteredPlugin(plugin);
522
-
523
- if (plugin.tools && plugin.tools.length > 0) {
524
- try {
525
- const accepted = registerPluginTools(pluginName, plugin.tools);
526
- log.info(
527
- { plugin: pluginName, count: accepted.length },
528
- "external plugin reloaded",
529
- );
530
- } catch (err) {
531
- log.error(
532
- { err, plugin: pluginName },
533
- "external plugin reload: tool registration failed",
534
- );
535
- }
536
- return;
537
- }
538
-
539
- log.info({ plugin: pluginName }, "external plugin reloaded");
540
- }
@@ -30,7 +30,7 @@ import { getSqlite } from "../../../memory/db-connection.js";
30
30
  import { initializeDb } from "../../../memory/db-init.js";
31
31
  import { acceptA2AInvite, createA2AInvite } from "../config-a2a.js";
32
32
 
33
- initializeDb();
33
+ await initializeDb();
34
34
 
35
35
  // ---------------------------------------------------------------------------
36
36
  // Helpers
@@ -29,7 +29,7 @@ import { initializeDb } from "../../../memory/db-init.js";
29
29
  import { findById } from "../../../memory/invite-store.js";
30
30
  import { completeA2AInvite, createA2AInvite } from "../config-a2a.js";
31
31
 
32
- initializeDb();
32
+ await initializeDb();
33
33
 
34
34
  function resetTables(): void {
35
35
  const sqlite = getSqlite();