@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
@@ -1,34 +1,33 @@
1
1
  /**
2
2
  * Tests for the inbound admission-floor enforcement in `routeSetup`.
3
3
  *
4
- * `routeSetup` is pure routing logic but reads several module-level singletons
5
- * (config, trust resolver, pending verification session, invite store). These
6
- * are mocked so the table below can drive trust class, member status, pending
7
- * challenge, and active invites independently of any DB.
4
+ * `routeSetup` reads several module-level singletons (config, trust resolver,
5
+ * pending verification session, invite store, contact store). Those I/O
6
+ * collaborators are mocked so the tables below can drive trust class, member
7
+ * status, pending challenge, active invites, and the bound invite contact
8
+ * directly — no database is touched.
8
9
  *
9
- * The floor verdict is exercised through the REAL `enforceAdmissionPolicy`
10
- * floor tables (`TRUST_CLASS_RANK` × `ADMISSION_FLOOR`), with the exempt-channel
11
- * short-circuit bypassed in the mock so the tests assert the true floor
12
- * semantics independent of any channel's exempt status (`phone` is now
13
- * enforced).
10
+ * The admission floor is exercised through the REAL, pure `enforceAdmissionPolicy`:
11
+ * `phone` is an enforced (non-exempt) channel, so the real function applies the
12
+ * true `rank >= floor` semantics. We deliberately do not reimplement the floor
13
+ * here a test-local copy of production logic would silently drift from it.
14
14
  */
15
15
 
16
16
  import { beforeEach, describe, expect, mock, test } from "bun:test";
17
17
 
18
- import {
19
- ADMISSION_FLOOR,
20
- type AdmissionPolicy,
21
- } from "@vellumai/gateway-client";
18
+ import type { AdmissionPolicy } from "@vellumai/gateway-client";
22
19
 
23
20
  import type {
24
21
  ChannelPolicy,
25
22
  ChannelStatus,
23
+ ContactChannel,
24
+ ContactRole,
25
+ ContactWithChannels,
26
26
  } from "../../contacts/types.js";
27
27
  import type {
28
28
  ActorTrustContext,
29
29
  TrustClass,
30
30
  } from "../../runtime/actor-trust-resolver.js";
31
- import { TRUST_CLASS_RANK } from "../../runtime/actor-trust-resolver.js";
32
31
 
33
32
  mock.module("../../util/logger.js", () => ({
34
33
  getLogger: () =>
@@ -43,8 +42,6 @@ mock.module("../../config/loader.js", () => ({
43
42
  let nextTrust: ActorTrustContext;
44
43
  mock.module("../../runtime/actor-trust-resolver.js", () => ({
45
44
  resolveActorTrust: () => nextTrust,
46
- // Re-export the real rank table; the floor mock below consumes it.
47
- TRUST_CLASS_RANK,
48
45
  }));
49
46
 
50
47
  // Controllable pending verification challenge.
@@ -55,6 +52,7 @@ mock.module("../../runtime/channel-verification-service.js", () => ({
55
52
 
56
53
  // Controllable active voice invites.
57
54
  let activeInvites: Array<{
55
+ contactId: string;
58
56
  friendName: string | null;
59
57
  guardianName: string | null;
60
58
  expiresAt?: number;
@@ -63,38 +61,11 @@ mock.module("../../memory/invite-store.js", () => ({
63
61
  findActiveVoiceInvites: () => activeInvites,
64
62
  }));
65
63
 
66
- // Real floor semantics, exemption bypassed (see file header).
67
- mock.module(
68
- "../../runtime/routes/inbound-stages/admission-policy.js",
69
- () => ({
70
- enforceAdmissionPolicy: (input: {
71
- trustClass: TrustClass;
72
- memberStatus: ChannelStatus | undefined;
73
- policy: AdmissionPolicy;
74
- }) => {
75
- if (input.memberStatus === "blocked" || input.memberStatus === "revoked") {
76
- return {
77
- admitted: false,
78
- reason:
79
- input.memberStatus === "blocked"
80
- ? "member_blocked"
81
- : "member_revoked",
82
- shouldChallenge: false,
83
- effectivePolicy: input.policy,
84
- };
85
- }
86
- const rank = TRUST_CLASS_RANK[input.trustClass];
87
- const floor = ADMISSION_FLOOR[input.policy];
88
- if (rank >= floor) return { admitted: true };
89
- return {
90
- admitted: false,
91
- reason: `admission_policy_${input.policy}`,
92
- shouldChallenge: false,
93
- effectivePolicy: input.policy,
94
- };
95
- },
96
- }),
97
- );
64
+ // Controllable bound contact for invite-redemption name resolution.
65
+ let boundContact: { displayName?: string | null } | null = null;
66
+ mock.module("../../contacts/contact-store.js", () => ({
67
+ getContact: () => boundContact,
68
+ }));
98
69
 
99
70
  const { routeSetup } = await import("../relay-setup-router.js");
100
71
 
@@ -102,30 +73,74 @@ const { routeSetup } = await import("../relay-setup-router.js");
102
73
  // Fixtures
103
74
  // ---------------------------------------------------------------------------
104
75
 
76
+ function makeChannel(overrides: Partial<ContactChannel> = {}): ContactChannel {
77
+ return {
78
+ id: "ch_1",
79
+ contactId: "ct_1",
80
+ type: "phone",
81
+ address: "+12025550142",
82
+ isPrimary: true,
83
+ externalChatId: null,
84
+ status: "active",
85
+ policy: "allow",
86
+ verifiedAt: null,
87
+ verifiedVia: null,
88
+ inviteId: null,
89
+ revokedReason: null,
90
+ blockedReason: null,
91
+ lastSeenAt: null,
92
+ interactionCount: 0,
93
+ lastInteraction: null,
94
+ updatedAt: null,
95
+ createdAt: 0,
96
+ ...overrides,
97
+ };
98
+ }
99
+
100
+ function makeContact(
101
+ overrides: Partial<ContactWithChannels> = {},
102
+ ): ContactWithChannels {
103
+ return {
104
+ id: "ct_1",
105
+ displayName: "Test Caller",
106
+ notes: null,
107
+ lastInteraction: null,
108
+ interactionCount: 0,
109
+ createdAt: 0,
110
+ updatedAt: 0,
111
+ role: "contact",
112
+ contactType: "human",
113
+ principalId: null,
114
+ userFile: null,
115
+ channels: [],
116
+ ...overrides,
117
+ };
118
+ }
119
+
105
120
  function makeTrust(
106
121
  trustClass: TrustClass,
107
- channel?: { status: ChannelStatus; policy?: ChannelPolicy; role?: string },
122
+ channel?: {
123
+ status: ChannelStatus;
124
+ policy?: ChannelPolicy;
125
+ role?: ContactRole;
126
+ },
108
127
  ): ActorTrustContext {
109
128
  const memberRecord = channel
110
129
  ? {
111
- contact: {
112
- displayName: "Test Caller",
113
- role: channel.role ?? "trusted_contact",
114
- } as never,
115
- channel: {
116
- id: "ch_1",
130
+ contact: makeContact({ role: channel.role ?? "contact" }),
131
+ channel: makeChannel({
117
132
  status: channel.status,
118
133
  policy: channel.policy ?? "allow",
119
- } as never,
134
+ }),
120
135
  }
121
136
  : null;
122
137
  return {
123
- canonicalSenderId: "+15551234567",
138
+ canonicalSenderId: "+12025550142",
124
139
  guardianBindingMatch: null,
125
140
  memberRecord,
126
141
  trustClass,
127
142
  actorMetadata: {
128
- identifier: "+15551234567",
143
+ identifier: "+12025550142",
129
144
  displayName: undefined,
130
145
  senderDisplayName: undefined,
131
146
  memberDisplayName: undefined,
@@ -133,15 +148,15 @@ function makeTrust(
133
148
  channel: "phone",
134
149
  trustStatus: trustClass,
135
150
  },
136
- } as ActorTrustContext;
151
+ };
137
152
  }
138
153
 
139
154
  function route(admissionPolicy?: AdmissionPolicy | null) {
140
155
  return routeSetup({
141
156
  callSessionId: "cs_1",
142
157
  session: null, // inbound
143
- from: "+15551234567",
144
- to: "+15559999999",
158
+ from: "+12025550142",
159
+ to: "+12025550199",
145
160
  admissionPolicy,
146
161
  });
147
162
  }
@@ -149,6 +164,7 @@ function route(admissionPolicy?: AdmissionPolicy | null) {
149
164
  beforeEach(() => {
150
165
  pendingChallenge = null;
151
166
  activeInvites = [];
167
+ boundContact = null;
152
168
  });
153
169
 
154
170
  // ---------------------------------------------------------------------------
@@ -334,9 +350,19 @@ describe("routeSetup — permissive floor admits to normal_call", () => {
334
350
  describe("routeSetup — floor bypasses", () => {
335
351
  test("active voice invite bypasses the floor (no_one policy)", () => {
336
352
  nextTrust = makeTrust("unknown");
337
- activeInvites = [{ friendName: "Friend", guardianName: "Guardian" }];
353
+ activeInvites = [
354
+ {
355
+ contactId: "contact-123",
356
+ friendName: "Friend",
357
+ guardianName: "Guardian",
358
+ },
359
+ ];
360
+ boundContact = { displayName: "Friend Name" };
338
361
  const { outcome } = route("no_one");
339
362
  expect(outcome.action).toBe("invite_redemption");
363
+ if (outcome.action === "invite_redemption") {
364
+ expect(outcome.inviteeName).toBe("Friend Name");
365
+ }
340
366
  });
341
367
 
342
368
  test("pending verification challenge bypasses the floor (no_one policy)", () => {
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Gateway-backed per-actor inbound trust verdict reader.
3
+ *
4
+ * Resolves the inbound sender's {@link TrustVerdict} from the gateway via the
5
+ * `resolve_inbound_trust` IPC route. Unlike the channel-admission reader this
6
+ * is per-actor, NOT per-channel, so there is NO caching.
7
+ *
8
+ * Returns `null` on ANY failure (transport failure, `undefined`, malformed
9
+ * shape, or thrown error). The caller owns the deny policy (fail-open vs
10
+ * fail-closed); this reader only reports the verdict or `null`.
11
+ */
12
+
13
+ import { type TrustVerdict, TrustVerdictSchema } from "@vellumai/gateway-client";
14
+
15
+ import type { ChannelId } from "../channels/types.js";
16
+ import { ipcCall } from "../ipc/gateway-client.js";
17
+
18
+ // Short IPC timeout so the read resolves promptly rather than stalling call
19
+ // setup on a gateway that accepts the socket but hangs.
20
+ const TRUST_IPC_TIMEOUT_MS = 2_000;
21
+
22
+ export async function getInboundTrustVerdict(input: {
23
+ channelType: ChannelId;
24
+ actorExternalId?: string;
25
+ }): Promise<TrustVerdict | null> {
26
+ try {
27
+ const result = (await ipcCall(
28
+ "resolve_inbound_trust",
29
+ input,
30
+ TRUST_IPC_TIMEOUT_MS,
31
+ )) as { verdict?: unknown } | null | undefined;
32
+
33
+ if (!result) return null;
34
+
35
+ const parsed = TrustVerdictSchema.safeParse(result.verdict);
36
+ return parsed.success ? parsed.data : null;
37
+ } catch {
38
+ return null;
39
+ }
40
+ }
@@ -71,6 +71,17 @@ const log = getLogger("relay-server");
71
71
  const UUID_SHAPED_NAME =
72
72
  /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
73
73
 
74
+ /**
75
+ * Return the first whitespace-delimited token of a name, or `null` when the
76
+ * input is null/blank. Used for greetings so "Carolina Flaherty" -> "Carolina".
77
+ */
78
+ function firstToken(name: string | null | undefined): string | null {
79
+ if (!name) return null;
80
+ const trimmed = name.trim();
81
+ if (!trimmed) return null;
82
+ return trimmed.split(/\s+/)[0] ?? null;
83
+ }
84
+
74
85
  // ── ConversationRelay message types ──────────────────────────────────
75
86
 
76
87
  // Messages FROM Twilio
@@ -213,11 +224,14 @@ export class RelayConnection {
213
224
 
214
225
  // Inbound voice invite redemption state
215
226
  private inviteRedemptionActive = false;
227
+ // In-flight guard: true while an async redemption attempt is awaiting the
228
+ // gateway-backed claim, so a rapidly-repeated code is deduped rather than
229
+ // launching a second concurrent redeemVoiceInviteCode.
230
+ private inviteRedemptionInFlight = false;
216
231
  private inviteRedemptionAssistantId: string | null = null;
217
232
  private inviteRedemptionFromNumber: string | null = null;
218
233
  private inviteRedemptionCodeLength = 6;
219
- private inviteRedemptionFriendName: string | null = null;
220
- private inviteRedemptionGuardianName: string | null = null;
234
+ private inviteRedemptionInviteeName: string | null = null;
221
235
 
222
236
  // In-call guardian approval wait state (friend-initiated)
223
237
  private accessRequestWaitActive = false;
@@ -646,8 +660,7 @@ export class RelayConnection {
646
660
  this.startInviteRedemption(
647
661
  outcome.assistantId,
648
662
  outcome.fromNumber,
649
- outcome.friendName,
650
- outcome.guardianName,
663
+ outcome.inviteeName,
651
664
  !resolved.isInbound,
652
665
  );
653
666
  return;
@@ -872,8 +885,14 @@ export class RelayConnection {
872
885
  | "invite_redeemed"
873
886
  | "access_approved"
874
887
  | "trusted_contact_verified";
875
- friendName?: string;
876
- guardianName?: string;
888
+ /**
889
+ * Display name resolved from the bound contact (or, for outbound invite
890
+ * calls, the session's recorded invitee name). Greeting uses only the
891
+ * first whitespace-delimited token; an empty/blank value triggers the
892
+ * neutral "Hi there" greeting rather than substituting the channel
893
+ * address.
894
+ */
895
+ inviteeName?: string | null;
877
896
  }): void {
878
897
  const { assistantId, fromNumber } = params;
879
898
 
@@ -898,17 +917,16 @@ export class RelayConnection {
898
917
  let handoffText: string;
899
918
 
900
919
  if (params.activationReason === "invite_redeemed") {
901
- const name = params.friendName;
920
+ const firstName = firstToken(params.inviteeName);
902
921
  const assistantName = this.resolveAssistantLabel();
903
- const gLabel = params.guardianName || guardianLabel;
904
- if (name) {
922
+ if (firstName) {
905
923
  handoffText = assistantName
906
- ? `Great, I've verified that you are ${name}. It's nice to meet you! I'm ${assistantName}, ${gLabel}'s assistant. How can I help?`
907
- : `Great, I've verified that you are ${name}. It's nice to meet you! How can I help?`;
924
+ ? `Great, I've verified that you are ${firstName}. It's nice to meet you! I'm ${assistantName}, ${guardianLabel}'s assistant. How can I help?`
925
+ : `Great, I've verified that you are ${firstName}. It's nice to meet you! How can I help?`;
908
926
  } else {
909
927
  handoffText = assistantName
910
- ? `Great, I've verified your identity. It's nice to meet you! I'm ${assistantName}, ${gLabel}'s assistant. How can I help?`
911
- : `Great, I've verified your identity. It's nice to meet you! How can I help?`;
928
+ ? `Hi there! I'm ${assistantName}, ${guardianLabel}'s assistant. How can I help?`
929
+ : `Hi there! How can I help?`;
912
930
  }
913
931
  } else {
914
932
  handoffText = `Great! ${guardianLabel} said I can speak with you. How can I help?`;
@@ -1195,15 +1213,14 @@ export class RelayConnection {
1195
1213
  private startInviteRedemption(
1196
1214
  assistantId: string,
1197
1215
  fromNumber: string,
1198
- friendName: string | null,
1199
- guardianName: string | null,
1216
+ inviteeName: string | null,
1200
1217
  isOutbound: boolean,
1201
1218
  ): void {
1202
1219
  this.inviteRedemptionActive = true;
1220
+ this.inviteRedemptionInFlight = false;
1203
1221
  this.inviteRedemptionAssistantId = assistantId;
1204
1222
  this.inviteRedemptionFromNumber = fromNumber;
1205
- this.inviteRedemptionFriendName = friendName;
1206
- this.inviteRedemptionGuardianName = guardianName;
1223
+ this.inviteRedemptionInviteeName = inviteeName;
1207
1224
  this.connectionState = "verification_pending";
1208
1225
  this.verificationAttempts = 0;
1209
1226
  this.verificationMaxAttempts = 1;
@@ -1216,8 +1233,8 @@ export class RelayConnection {
1216
1233
  maxAttempts: this.verificationMaxAttempts,
1217
1234
  });
1218
1235
 
1219
- const displayFriend = friendName ?? "there";
1220
- const displayGuardian = guardianName ?? "your contact";
1236
+ const displayFriend = firstToken(inviteeName) ?? "there";
1237
+ const displayGuardian = this.resolveGuardianLabel();
1221
1238
 
1222
1239
  let promptText: string;
1223
1240
  if (isOutbound) {
@@ -1620,11 +1637,37 @@ export class RelayConnection {
1620
1637
  return;
1621
1638
  }
1622
1639
 
1623
- const result = attemptInviteCodeRedemption({
1640
+ // Dedup concurrent attempts: a repeated code (re-spoken / re-entered)
1641
+ // arriving while the async gateway-backed claim is still in flight is
1642
+ // ignored, so we never run a second redeemVoiceInviteCode that would see
1643
+ // the invite already consumed and wrongly mark the call failed. The flag
1644
+ // is set synchronously before awaiting and cleared in finally.
1645
+ if (this.inviteRedemptionInFlight) {
1646
+ log.info(
1647
+ { callSessionId: this.callSessionId },
1648
+ "Ignoring repeated invite code — redemption already in flight",
1649
+ );
1650
+ return;
1651
+ }
1652
+ this.inviteRedemptionInFlight = true;
1653
+
1654
+ try {
1655
+ await this.runInviteCodeRedemption(enteredCode);
1656
+ } finally {
1657
+ this.inviteRedemptionInFlight = false;
1658
+ }
1659
+ }
1660
+
1661
+ private async runInviteCodeRedemption(enteredCode: string): Promise<void> {
1662
+ if (!this.inviteRedemptionAssistantId || !this.inviteRedemptionFromNumber) {
1663
+ return;
1664
+ }
1665
+
1666
+ const result = await attemptInviteCodeRedemption({
1624
1667
  inviteRedemptionAssistantId: this.inviteRedemptionAssistantId,
1625
1668
  inviteRedemptionFromNumber: this.inviteRedemptionFromNumber,
1626
1669
  enteredCode,
1627
- inviteRedemptionGuardianName: this.inviteRedemptionGuardianName,
1670
+ guardianLabel: this.resolveGuardianLabel(),
1628
1671
  });
1629
1672
 
1630
1673
  if (result.outcome === "success") {
@@ -1649,8 +1692,7 @@ export class RelayConnection {
1649
1692
  assistantId: this.inviteRedemptionAssistantId,
1650
1693
  fromNumber: this.inviteRedemptionFromNumber,
1651
1694
  activationReason: "invite_redeemed",
1652
- friendName: this.inviteRedemptionFriendName ?? undefined,
1653
- guardianName: this.inviteRedemptionGuardianName ?? undefined,
1695
+ inviteeName: this.inviteRedemptionInviteeName,
1654
1696
  });
1655
1697
  } else {
1656
1698
  this.inviteRedemptionActive = false;
@@ -9,6 +9,7 @@
9
9
  import type { AdmissionPolicy } from "@vellumai/gateway-client";
10
10
 
11
11
  import { getConfig } from "../config/loader.js";
12
+ import { getContact } from "../contacts/contact-store.js";
12
13
  import { findActiveVoiceInvites } from "../memory/invite-store.js";
13
14
  import {
14
15
  type ActorTrustContext,
@@ -64,8 +65,15 @@ type SetupOutcome =
64
65
  action: "invite_redemption";
65
66
  assistantId: string;
66
67
  fromNumber: string;
67
- friendName: string | null;
68
- guardianName: string | null;
68
+ /**
69
+ * Display name of the invitee. For inbound redemptions, resolved from the
70
+ * bound contact's `displayName`; falls back to the legacy `friend_name`
71
+ * column for pre-contact-binding invites. For outbound invite calls,
72
+ * carries the session-recorded `inviteFriendName`. When null/empty, the
73
+ * relay uses a neutral "Hi there" greeting instead of substituting the
74
+ * channel address.
75
+ */
76
+ inviteeName: string | null;
69
77
  }
70
78
  | { action: "name_capture"; assistantId: string; fromNumber: string }
71
79
  | {
@@ -128,8 +136,7 @@ export function routeSetup(ctx: SetupContext): {
128
136
  action: "invite_redemption" as const,
129
137
  assistantId,
130
138
  fromNumber: ctx.to,
131
- friendName: ctx.session?.inviteFriendName ?? null,
132
- guardianName: ctx.session?.inviteGuardianName ?? null,
139
+ inviteeName: ctx.session?.inviteFriendName ?? null,
133
140
  },
134
141
  resolved,
135
142
  };
@@ -289,13 +296,20 @@ export function routeSetup(ctx: SetupContext): {
289
296
  { callSessionId: ctx.callSessionId, from: ctx.from },
290
297
  "Inbound voice ACL: unknown caller has active voice invite — entering redemption flow",
291
298
  );
299
+ // Resolve the invitee's name from the bound contact's displayName so
300
+ // the post-redemption greeting matches what the guardian sees in the
301
+ // contact graph. `contact_id` is NOT NULL on the invite row, so every
302
+ // invite is bound — when the contact has no displayName the greeting
303
+ // falls through to the neutral "Hi there" copy in relay-server.ts
304
+ // rather than a stale free-text `friend_name` label.
305
+ const boundContact = getContact(matchedInvite.contactId);
306
+ const inviteeName = boundContact?.displayName?.trim() || null;
292
307
  return {
293
308
  outcome: {
294
309
  action: "invite_redemption",
295
310
  assistantId,
296
311
  fromNumber: ctx.from,
297
- friendName: matchedInvite.friendName,
298
- guardianName: matchedInvite.guardianName,
312
+ inviteeName: inviteeName ?? null,
299
313
  },
300
314
  resolved,
301
315
  };
@@ -224,7 +224,8 @@ interface InviteRedemptionParams {
224
224
  inviteRedemptionAssistantId: string;
225
225
  inviteRedemptionFromNumber: string;
226
226
  enteredCode: string;
227
- inviteRedemptionGuardianName: string | null;
227
+ /** Resolved guardian label used in the failure TTS message. */
228
+ guardianLabel: string;
228
229
  }
229
230
 
230
231
  type InviteRedemptionResult =
@@ -244,17 +245,17 @@ type InviteRedemptionResult =
244
245
  * caller. Returns a structured result so the caller can handle state
245
246
  * mutations and session updates.
246
247
  */
247
- export function attemptInviteCodeRedemption(
248
+ export async function attemptInviteCodeRedemption(
248
249
  params: InviteRedemptionParams,
249
- ): InviteRedemptionResult {
250
+ ): Promise<InviteRedemptionResult> {
250
251
  const {
251
252
  inviteRedemptionAssistantId,
252
253
  inviteRedemptionFromNumber,
253
254
  enteredCode,
254
- inviteRedemptionGuardianName,
255
+ guardianLabel,
255
256
  } = params;
256
257
 
257
- const result = redeemVoiceInviteCode({
258
+ const result = await redeemVoiceInviteCode({
258
259
  assistantId: inviteRedemptionAssistantId,
259
260
  callerExternalUserId: inviteRedemptionFromNumber,
260
261
  sourceChannel: "phone",
@@ -270,9 +271,8 @@ export function attemptInviteCodeRedemption(
270
271
  };
271
272
  }
272
273
 
273
- const displayGuardian = inviteRedemptionGuardianName ?? "your contact";
274
274
  return {
275
275
  outcome: "failure",
276
- ttsMessage: `Sorry, the code you provided is incorrect or has since expired. Please ask ${displayGuardian} for a new code. Goodbye.`,
276
+ ttsMessage: `Sorry, the code you provided is incorrect or has since expired. Please ask ${guardianLabel} for a new code. Goodbye.`,
277
277
  };
278
278
  }
@@ -614,22 +614,10 @@ Examples:
614
614
  .option("--note <note>", "Optional note")
615
615
  .option("--max-uses <n>", "Max redemptions")
616
616
  .option("--expires-in-ms <ms>", "Expiry duration in milliseconds")
617
- .option(
618
- "--contact-name <name>",
619
- "Contact name for personalizing instructions",
620
- )
621
617
  .option(
622
618
  "--expected-external-user-id <id>",
623
619
  "E.164 phone number (required for voice invites)",
624
620
  )
625
- .option(
626
- "--friend-name <name>",
627
- "Friend name (required for voice invites)",
628
- )
629
- .option(
630
- "--guardian-name <name>",
631
- "Guardian name (required for voice invites)",
632
- )
633
621
  .requiredOption(
634
622
  "--contact-id <id>",
635
623
  "Contact ID to bind the invite to",
@@ -640,20 +628,20 @@ Examples:
640
628
  Creates a new invite token for the specified source channel. The --source-channel
641
629
  flag is required and must be one of: telegram, phone, email, whatsapp.
642
630
 
631
+ The invitee's display name is read from the bound contact (--contact-id);
632
+ the guardian label is resolved at runtime. There are no free-text name flags.
633
+
643
634
  Optional fields:
644
635
  --note Free-text note attached to the invite
645
636
  --max-uses Maximum number of times the invite can be redeemed
646
637
  --expires-in-ms Expiry duration in milliseconds from creation
647
- --contact-name Name used to personalize invite instructions
648
638
 
649
- Voice invites require three additional fields:
639
+ Voice invites also require:
650
640
  --expected-external-user-id E.164 phone number of the expected caller (e.g. +15551234567)
651
- --friend-name Name the contact uses for the assistant's owner
652
- --guardian-name Name of the guardian associated with this invite
653
641
 
654
642
  Examples:
655
- $ assistant contacts invites create --source-channel telegram --note "For Alice" --max-uses 1
656
- $ assistant contacts invites create --source-channel phone --expected-external-user-id "+15551234567" --friend-name "Alice" --guardian-name "Bob" --contact-name "Alice Smith"`,
643
+ $ assistant contacts invites create --source-channel telegram --contact-id <id> --note "For Alice" --max-uses 1
644
+ $ assistant contacts invites create --source-channel phone --contact-id <id> --expected-external-user-id "+15551234567"`,
657
645
  )
658
646
  .action(
659
647
  async (
@@ -662,10 +650,7 @@ Examples:
662
650
  note?: string;
663
651
  maxUses?: string;
664
652
  expiresInMs?: string;
665
- contactName?: string;
666
653
  expectedExternalUserId?: string;
667
- friendName?: string;
668
- guardianName?: string;
669
654
  contactId: string;
670
655
  },
671
656
  cmd: Command,
@@ -704,10 +689,7 @@ Examples:
704
689
  note: opts.note,
705
690
  maxUses,
706
691
  expiresInMs,
707
- contactName: opts.contactName,
708
692
  expectedExternalUserId: opts.expectedExternalUserId,
709
- friendName: opts.friendName,
710
- guardianName: opts.guardianName,
711
693
  contactId: opts.contactId,
712
694
  },
713
695
  });
@@ -431,20 +431,29 @@ async function initSchema(): Promise<void> {
431
431
  // The repair step opens its own bun:sqlite handle but expects the schema
432
432
  // to already exist (production-wise, the daemon creates it). Touching the
433
433
  // global init triggers schema creation against the env-isolated path.
434
- const { initializeDb } = await import("../../../../memory/db-init.js");
435
- initializeDb();
436
- // Close the singleton so backfill can open its own handle without
437
- // collision. WAL allows concurrent handles but cleaner ownership avoids
438
- // test cross-talk through the in-process cache.
439
434
  const { getDb, getSqliteFrom } =
440
435
  await import("../../../../memory/db-connection.js");
441
436
  const { clearStoredDb } = await import("../../../../memory/db-singleton.js");
437
+ // Drop any connections a prior test (or test file) left open against a
438
+ // now-deleted workspace, so init below opens fresh handles — main and the
439
+ // dedicated logs/memory connections — at THIS test's workspace.
440
+ clearStoredDb("main");
441
+ clearStoredDb("logs");
442
+ clearStoredDb("memory");
443
+
444
+ const { initializeDb } = await import("../../../../memory/db-init.js");
445
+ await initializeDb();
446
+ // Close the singletons so backfill can open its own handle without
447
+ // collision. WAL allows concurrent handles but cleaner ownership avoids
448
+ // test cross-talk through the in-process cache.
442
449
  try {
443
450
  getSqliteFrom(getDb()).close();
444
451
  } catch {
445
452
  /* already closed */
446
453
  }
447
- clearStoredDb();
454
+ clearStoredDb("main");
455
+ clearStoredDb("logs");
456
+ clearStoredDb("memory");
448
457
  }
449
458
 
450
459
  describe("assistant db repair — conversation-backfill step", () => {