@vellumai/assistant 0.10.4 → 0.10.5-dev.202607022329.d89bf2f

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 (866) hide show
  1. package/ARCHITECTURE.md +94 -91
  2. package/Dockerfile +5 -16
  3. package/README.md +7 -10
  4. package/bun.lock +0 -4
  5. package/docs/architecture/security.md +20 -20
  6. package/docs/stt-provider-onboarding.md +4 -5
  7. package/docs/trusted-contact-access.md +7 -7
  8. package/eslint-rules/cli-no-daemon-internals.js +4 -0
  9. package/eslint.config.mjs +7 -1
  10. package/knip.json +0 -1
  11. package/node_modules/@vellumai/gateway-client/src/__tests__/contact-read-contracts.test.ts +36 -0
  12. package/node_modules/@vellumai/gateway-client/src/__tests__/invite-contract.test.ts +233 -0
  13. package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +40 -0
  14. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +20 -8
  15. package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +10 -0
  16. package/node_modules/@vellumai/gateway-client/src/index.ts +33 -0
  17. package/node_modules/@vellumai/gateway-client/src/invite-contract.ts +216 -0
  18. package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +91 -0
  19. package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +39 -3
  20. package/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +0 -8
  21. package/node_modules/@vellumai/service-contracts/src/__tests__/package-boundary.test.ts +1 -5
  22. package/node_modules/@vellumai/service-contracts/src/twilio-ingress.ts +3 -14
  23. package/openapi.yaml +1073 -225
  24. package/package.json +1 -4
  25. package/scripts/test.sh +35 -13
  26. package/src/__tests__/access-request-seed-content-blocks.test.ts +60 -4
  27. package/src/__tests__/acp-session.test.ts +4 -1
  28. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +0 -6
  29. package/src/__tests__/add-message-preassigned-id.test.ts +56 -0
  30. package/src/__tests__/agent-loop-set-system-prompt.test.ts +139 -0
  31. package/src/__tests__/app-conversation-ids-backfill.test.ts +3 -0
  32. package/src/__tests__/app-source-watcher.test.ts +11 -0
  33. package/src/__tests__/approval-interception-trust-gates.test.ts +148 -3
  34. package/src/__tests__/assistant-attachments.test.ts +62 -4
  35. package/src/__tests__/assistant-id-boundary-guard.test.ts +0 -1
  36. package/src/__tests__/attachments-store-heic-normalize.test.ts +230 -0
  37. package/src/__tests__/attachments-store.test.ts +3 -0
  38. package/src/__tests__/background-shell-bash.test.ts +34 -0
  39. package/src/__tests__/background-shell-host-bash.test.ts +12 -0
  40. package/src/__tests__/background-tool-registry.test.ts +97 -0
  41. package/src/__tests__/background-tool-routes.test.ts +72 -1
  42. package/src/__tests__/background-workers-disk-pressure.test.ts +2 -1
  43. package/src/__tests__/btw-routes.test.ts +57 -3
  44. package/src/__tests__/call-controller.test.ts +474 -84
  45. package/src/__tests__/call-domain.test.ts +48 -1
  46. package/src/__tests__/call-pointer-messages.test.ts +57 -19
  47. package/src/__tests__/call-pointer-no-hardcoded-copy.guard.test.ts +2 -6
  48. package/src/__tests__/call-routes-http.test.ts +15 -14
  49. package/src/__tests__/call-setup-flow-invite.test.ts +568 -0
  50. package/src/__tests__/call-setup-flow-midcall-trust.test.ts +231 -0
  51. package/src/__tests__/call-setup-flow-name-capture.test.ts +754 -0
  52. package/src/__tests__/call-setup-flow-verification.test.ts +925 -0
  53. package/src/__tests__/call-setup-flow.test.ts +311 -0
  54. package/src/__tests__/cancel-resolves-conversation-key.test.ts +0 -1
  55. package/src/__tests__/channel-guardian.test.ts +4 -7
  56. package/src/__tests__/channel-readiness-service.test.ts +0 -6
  57. package/src/__tests__/channel-readiness-slack-remote.test.ts +0 -4
  58. package/src/__tests__/channel-retry-sweep.test.ts +76 -64
  59. package/src/__tests__/channel-setup-panel-ack.test.ts +184 -0
  60. package/src/__tests__/clear-all-lexical.test.ts +90 -0
  61. package/src/__tests__/compactor-media-strip.test.ts +177 -0
  62. package/src/__tests__/config-loader-backfill.test.ts +5 -5
  63. package/src/__tests__/config-schema.test.ts +17 -0
  64. package/src/__tests__/contact-store-interaction-info.test.ts +27 -70
  65. package/src/__tests__/contacts-relay-reads.test.ts +188 -23
  66. package/src/__tests__/contacts-tools.test.ts +42 -1
  67. package/src/__tests__/contacts-write.test.ts +181 -0
  68. package/src/__tests__/context-search-conversations-source.test.ts +220 -81
  69. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -0
  70. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
  71. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
  72. package/src/__tests__/conversation-agent-loop.test.ts +39 -0
  73. package/src/__tests__/conversation-analysis-routes.test.ts +1 -1
  74. package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -0
  75. package/src/__tests__/conversation-clear-safety.test.ts +0 -1
  76. package/src/__tests__/conversation-crud-enabled-plugins.test.ts +60 -0
  77. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +0 -1
  78. package/src/__tests__/conversation-disk-view.test.ts +1 -0
  79. package/src/__tests__/conversation-enabledplugins-route.test.ts +184 -0
  80. package/src/__tests__/conversation-error.test.ts +0 -18
  81. package/src/__tests__/conversation-fork-crud.test.ts +67 -0
  82. package/src/__tests__/conversation-history-web-search.test.ts +7 -137
  83. package/src/__tests__/conversation-initial-prompt.test.ts +110 -0
  84. package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +191 -0
  85. package/src/__tests__/conversation-process-callsite.test.ts +37 -0
  86. package/src/__tests__/conversation-queue.test.ts +149 -0
  87. package/src/__tests__/conversation-routes-enabled-plugins.test.ts +392 -0
  88. package/src/__tests__/conversation-routes-guardian-reply.test.ts +84 -0
  89. package/src/__tests__/conversation-routes-hidden-queue.test.ts +407 -0
  90. package/src/__tests__/conversation-runtime-assembly.test.ts +36 -16
  91. package/src/__tests__/conversation-skill-tools.test.ts +73 -0
  92. package/src/__tests__/conversation-wipe.test.ts +20 -5
  93. package/src/__tests__/credential-prompt-route.test.ts +69 -0
  94. package/src/__tests__/credential-security-invariants.test.ts +1 -3
  95. package/src/__tests__/db-drop-messages-fts.test.ts +115 -0
  96. package/src/__tests__/deterministic-verification-control-plane.test.ts +1 -62
  97. package/src/__tests__/edit-propagation.test.ts +56 -2
  98. package/src/__tests__/empty-state-greeting-cache.test.ts +9 -0
  99. package/src/__tests__/gateway-only-enforcement.test.ts +15 -110
  100. package/src/__tests__/guardian-expiry-notifier.test.ts +1 -0
  101. package/src/__tests__/guardian-question-mode.test.ts +57 -0
  102. package/src/__tests__/guardian-verification-voice-binding.test.ts +1 -1
  103. package/src/__tests__/guardian-wait-controller.test.ts +619 -0
  104. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +33 -2
  105. package/src/__tests__/heic-fixture.ts +55 -0
  106. package/src/__tests__/helpers/seed-contact-channel.ts +0 -2
  107. package/src/__tests__/http-conversation-lineage.test.ts +6 -1
  108. package/src/__tests__/image-conversion.test.ts +170 -0
  109. package/src/__tests__/inbound-invite-redemption.test.ts +72 -341
  110. package/src/__tests__/introduction-card-resolver.test.ts +354 -0
  111. package/src/__tests__/invite-redeemed-ipc.test.ts +97 -0
  112. package/src/__tests__/invite-routes-http.test.ts +246 -420
  113. package/src/__tests__/job-handler-registration-guard.test.ts +104 -0
  114. package/src/__tests__/lexical-index-dual-write.test.ts +426 -0
  115. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +2 -2
  116. package/src/__tests__/list-messages-attachments.test.ts +159 -0
  117. package/src/__tests__/list-messages-background-tool-completion.test.ts +141 -0
  118. package/src/__tests__/list-messages-queued.test.ts +25 -0
  119. package/src/__tests__/managed-store.test.ts +129 -1
  120. package/src/__tests__/media-stream-audio-transcode.test.ts +113 -0
  121. package/src/__tests__/media-stream-output.test.ts +350 -19
  122. package/src/__tests__/media-stream-server-integration.test.ts +943 -169
  123. package/src/__tests__/media-stream-stt-session.test.ts +498 -1
  124. package/src/__tests__/memory-jobs-worker-lanes.test.ts +2 -2
  125. package/src/__tests__/model-intents.test.ts +1 -1
  126. package/src/__tests__/mtime-cache.test.ts +19 -0
  127. package/src/__tests__/non-member-access-request.test.ts +349 -3
  128. package/src/__tests__/notification-decision-fallback.test.ts +104 -8
  129. package/src/__tests__/notification-decision-strategy.test.ts +57 -8
  130. package/src/__tests__/onboarding-template-contract.test.ts +27 -43
  131. package/src/__tests__/openai-provider.test.ts +33 -0
  132. package/src/__tests__/openai-responses-provider.test.ts +40 -0
  133. package/src/__tests__/persistence-layering-guard.test.ts +29 -20
  134. package/src/__tests__/persona-resolver.test.ts +56 -2
  135. package/src/__tests__/personal-memory-auth-bypass.test.ts +62 -0
  136. package/src/__tests__/phone.test.ts +1 -15
  137. package/src/__tests__/plugin-bootstrap.test.ts +25 -196
  138. package/src/__tests__/plugin-disabled-state.test.ts +33 -0
  139. package/src/__tests__/plugin-effective-enabled-set.test.ts +227 -0
  140. package/src/__tests__/plugin-event-hub-facade.test.ts +323 -0
  141. package/src/__tests__/plugin-import-boundary-guard.test.ts +156 -42
  142. package/src/__tests__/plugin-injector-contribution.test.ts +4 -20
  143. package/src/__tests__/plugin-pipeline.test.ts +63 -1
  144. package/src/__tests__/plugin-route-contribution.test.ts +62 -115
  145. package/src/__tests__/plugin-tool-contribution.test.ts +0 -22
  146. package/src/__tests__/plugin-types.test.ts +0 -1
  147. package/src/__tests__/pointer-conversation-trust.test.ts +38 -6
  148. package/src/__tests__/pre-model-call-sanitize.test.ts +1 -1
  149. package/src/__tests__/prune-old-tool-invocations-job.test.ts +97 -0
  150. package/src/__tests__/public-ingress-urls.test.ts +0 -48
  151. package/src/__tests__/qdrant-collection-migration.test.ts +145 -2
  152. package/src/__tests__/reaction-intercept-member-verdict-warm.test.ts +0 -1
  153. package/src/__tests__/resolve-trust-class.test.ts +28 -10
  154. package/src/__tests__/scaffold-managed-skill-tool.test.ts +137 -0
  155. package/src/__tests__/schedule-retry.test.ts +38 -14
  156. package/src/__tests__/schedule-routes-workflow-validation.test.ts +3 -3
  157. package/src/__tests__/schedule-routes.test.ts +14 -6
  158. package/src/__tests__/schedule-store.test.ts +3 -1
  159. package/src/__tests__/scheduler-disk-pressure.test.ts +17 -6
  160. package/src/__tests__/scheduler-recurrence.test.ts +57 -107
  161. package/src/__tests__/scheduler-reuse-conversation.test.ts +51 -46
  162. package/src/__tests__/scheduler-wake.test.ts +13 -23
  163. package/src/__tests__/scheduler-worker-standdown.test.ts +220 -0
  164. package/src/__tests__/secret-routes-platform-proxy.test.ts +1 -1
  165. package/src/__tests__/shell-observability.test.ts +1 -0
  166. package/src/__tests__/skill-boundary-guard.test.ts +3 -4
  167. package/src/__tests__/skill-load-plugin-scope.test.ts +238 -0
  168. package/src/__tests__/skill-projection-feature-flag.test.ts +2 -0
  169. package/src/__tests__/skill-script-runner-host.test.ts +53 -0
  170. package/src/__tests__/skill-script-runner-sandbox.test.ts +5 -2
  171. package/src/__tests__/skill-tool-factory.test.ts +73 -1
  172. package/src/__tests__/slack-app-setup-skill-regression.test.ts +37 -14
  173. package/src/__tests__/slack-inbound-verification.test.ts +36 -0
  174. package/src/__tests__/slack-notification-approval-card.test.ts +89 -2
  175. package/src/__tests__/slack-reaction-canonical-approval.test.ts +51 -1
  176. package/src/__tests__/stt-hints.test.ts +2 -256
  177. package/src/__tests__/subagent-allowlist-validation.test.ts +47 -0
  178. package/src/__tests__/subagent-call-site-routing.test.ts +72 -0
  179. package/src/__tests__/subagent-fork-notifications.test.ts +14 -2
  180. package/src/__tests__/subagent-persistence.test.ts +122 -0
  181. package/src/__tests__/subagent-spawn-and-await.test.ts +1 -0
  182. package/src/__tests__/subagent-terminal-message.test.ts +99 -0
  183. package/src/__tests__/subagent-tool-gate-mode.test.ts +78 -1
  184. package/src/__tests__/system-prompt.test.ts +17 -118
  185. package/src/__tests__/task-scheduler.test.ts +68 -89
  186. package/src/__tests__/telephony-credential-preflight.test.ts +312 -0
  187. package/src/__tests__/telephony-tts-guard.test.ts +538 -0
  188. package/src/__tests__/title-generate-hook.test.ts +16 -0
  189. package/src/__tests__/tool-approval-handler.test.ts +87 -1
  190. package/src/__tests__/tool-approval-seed-content-blocks.test.ts +45 -20
  191. package/src/__tests__/tool-grant-request-escalation.test.ts +39 -0
  192. package/src/__tests__/trust-context-guards.test.ts +21 -10
  193. package/src/__tests__/trusted-contact-multichannel.test.ts +4 -0
  194. package/src/__tests__/twilio-provider.test.ts +17 -17
  195. package/src/__tests__/twilio-routes-twiml.test.ts +6 -543
  196. package/src/__tests__/twilio-routes.test.ts +257 -387
  197. package/src/__tests__/twilio-validation.test.ts +1 -1
  198. package/src/__tests__/unified-turn-context-client-os.test.ts +45 -0
  199. package/src/__tests__/usage-cache-backfill-migration.test.ts +5 -0
  200. package/src/__tests__/voice-approval-resolver-relay.test.ts +150 -0
  201. package/src/__tests__/voice-ingress-preflight.test.ts +61 -0
  202. package/src/__tests__/voice-quality.test.ts +2 -2
  203. package/src/__tests__/voice-scoped-grant-consumer.test.ts +1 -7
  204. package/src/__tests__/voice-session-bridge-processing-wait.test.ts +27 -0
  205. package/src/__tests__/voice-session-bridge.test.ts +1 -10
  206. package/src/__tests__/workspace-git-service.test.ts +1 -1
  207. package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -0
  208. package/src/__tests__/workspace-migration-118-seed-now-md.test.ts +120 -0
  209. package/src/__tests__/workspace-migration-120-revise-onboarding-threads.test.ts +175 -0
  210. package/src/__tests__/workspace-migration-121-seed-default-user-guardrails.test.ts +118 -0
  211. package/src/__tests__/workspace-migration-122-relocate-default-user-boundary.test.ts +119 -0
  212. package/src/__tests__/workspace-migration-123-swap-quality-profile-to-fable.test.ts +191 -0
  213. package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +235 -241
  214. package/src/acp/__tests__/prepare-agent-env.test.ts +0 -97
  215. package/src/acp/__tests__/session-manager-persistence.test.ts +2 -0
  216. package/src/acp/__tests__/session-manager-resume.test.ts +8 -0
  217. package/src/acp/__tests__/session-manager-usage.test.ts +6 -0
  218. package/src/acp/__tests__/session-manager.test.ts +6 -0
  219. package/src/acp/agent-process.test.ts +116 -0
  220. package/src/acp/agent-process.ts +71 -0
  221. package/src/acp/auto-install.ts +12 -8
  222. package/src/acp/failure-error.test.ts +109 -0
  223. package/src/acp/failure-error.ts +111 -0
  224. package/src/acp/prepare-agent-env.ts +0 -12
  225. package/src/acp/resolve-agent.test.ts +6 -45
  226. package/src/acp/resolve-agent.ts +2 -4
  227. package/src/acp/session-manager.test.ts +312 -0
  228. package/src/acp/session-manager.ts +102 -46
  229. package/src/agent/ax-tree-compaction.test.ts +4 -1
  230. package/src/agent/image-optimize.ts +17 -127
  231. package/src/agent/loop.ts +45 -192
  232. package/src/api/events/background-tool-completed.test.ts +51 -0
  233. package/src/api/events/background-tool-completed.ts +29 -0
  234. package/src/api/events/background-tool-started.test.ts +36 -0
  235. package/src/api/events/background-tool-started.ts +28 -0
  236. package/src/api/events/conversation-error.ts +0 -1
  237. package/src/api/events/open-panel.ts +33 -0
  238. package/src/api/events/subagent-status-changed.ts +4 -1
  239. package/src/api/index.ts +19 -0
  240. package/src/api/responses/conversation-message.ts +34 -0
  241. package/src/approvals/guardian-decision-primitive.ts +74 -24
  242. package/src/approvals/guardian-request-resolvers.ts +450 -122
  243. package/src/apps/app-store.ts +1 -0
  244. package/src/apps/shared-app-links-store.ts +1 -0
  245. package/src/avatar/identity-avatar.ts +3 -7
  246. package/src/background-wake/wake-intent-hooks.test.ts +1 -1
  247. package/src/calls/__tests__/fish-audio-client.test.ts +73 -0
  248. package/src/calls/__tests__/gateway-invite-reader.test.ts +170 -0
  249. package/src/calls/__tests__/relay-setup-router.test.ts +126 -102
  250. package/src/calls/call-controller.ts +134 -48
  251. package/src/calls/call-domain.ts +18 -42
  252. package/src/calls/call-pointer-messages.ts +51 -67
  253. package/src/calls/call-setup-flow-types.ts +76 -0
  254. package/src/calls/call-setup-flow.ts +1743 -0
  255. package/src/calls/call-speech-output.ts +87 -23
  256. package/src/calls/call-store.ts +4 -0
  257. package/src/calls/call-transport.ts +22 -36
  258. package/src/calls/fish-audio-client.ts +3 -0
  259. package/src/calls/gateway-invite-reader.ts +98 -0
  260. package/src/calls/guardian-wait-controller.ts +451 -0
  261. package/src/calls/media-stream-audio-transcode.ts +82 -2
  262. package/src/calls/media-stream-output.ts +142 -36
  263. package/src/calls/media-stream-server.ts +297 -178
  264. package/src/calls/media-stream-stt-session.ts +393 -50
  265. package/src/calls/media-turn-detector.ts +4 -6
  266. package/src/calls/relay-access-wait.ts +3 -4
  267. package/src/calls/relay-setup-router.ts +22 -43
  268. package/src/calls/relay-verification.ts +17 -24
  269. package/src/calls/resolve-call-tts-provider.ts +96 -29
  270. package/src/calls/stt-hints.ts +24 -87
  271. package/src/calls/telephony-credential-preflight.ts +159 -0
  272. package/src/calls/telephony-tts-capability.ts +183 -0
  273. package/src/calls/tts-call-strategy.ts +18 -20
  274. package/src/calls/twilio-provider.ts +3 -2
  275. package/src/calls/twilio-routes.ts +47 -351
  276. package/src/calls/types.ts +5 -3
  277. package/src/calls/voice-ingress-preflight.ts +9 -0
  278. package/src/calls/voice-quality.ts +13 -18
  279. package/src/calls/voice-session-bridge.ts +25 -35
  280. package/src/channels/__tests__/types.test.ts +28 -0
  281. package/src/channels/channel-verification-sessions.ts +7 -2
  282. package/src/channels/config.ts +0 -42
  283. package/src/channels/slack-thread-store.ts +12 -0
  284. package/src/channels/types.ts +23 -0
  285. package/src/cli/commands/__tests__/conversations-slack.test.ts +1 -1
  286. package/src/cli/commands/__tests__/schedules.test.ts +83 -34
  287. package/src/cli/commands/__tests__/status.test.ts +42 -2
  288. package/src/cli/commands/contacts.ts +2 -2
  289. package/src/cli/commands/credentials.ts +17 -0
  290. package/src/cli/commands/monitoring.ts +191 -0
  291. package/src/cli/commands/schedules-worker.ts +175 -0
  292. package/src/cli/commands/schedules.ts +169 -43
  293. package/src/cli/commands/status.ts +12 -1
  294. package/src/cli/commands/tools.ts +5 -1
  295. package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +1 -0
  296. package/src/cli/lib/__tests__/search-plugins.test.ts +29 -1
  297. package/src/cli/lib/__tests__/toggle-plugin.test.ts +7 -0
  298. package/src/cli/lib/search-plugins.ts +6 -0
  299. package/src/cli/lib/toggle-plugin.ts +21 -2
  300. package/src/cli/program.ts +3 -1
  301. package/src/config/__tests__/deployment-context-defaults.test.ts +23 -0
  302. package/src/config/acp-defaults.test.ts +0 -10
  303. package/src/config/acp-defaults.ts +0 -6
  304. package/src/config/bundled-skills/acp/SKILL.md +13 -45
  305. package/src/config/bundled-skills/acp/TOOLS.json +3 -3
  306. package/src/config/bundled-skills/app-builder/SKILL.md +3 -3
  307. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +9 -9
  308. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +1 -1
  309. package/src/config/bundled-skills/contacts/tools/contact-search.ts +1 -1
  310. package/src/config/bundled-skills/phone-calls/SKILL.md +1 -1
  311. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +9 -9
  312. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +10 -7
  313. package/src/config/bundled-skills/skill-management/TOOLS.json +10 -0
  314. package/src/config/call-site-defaults.ts +0 -2
  315. package/src/config/feature-flag-registry.json +16 -8
  316. package/src/config/loader.ts +11 -0
  317. package/src/config/schema.ts +9 -1
  318. package/src/config/schemas/__tests__/memory-v2.test.ts +2 -2
  319. package/src/config/schemas/__tests__/memory-v3.test.ts +64 -0
  320. package/src/config/schemas/call-site-catalog.ts +0 -12
  321. package/src/config/schemas/calls.ts +8 -0
  322. package/src/config/schemas/elevenlabs.ts +1 -1
  323. package/src/config/schemas/llm.ts +0 -2
  324. package/src/config/schemas/memory-v2.ts +1 -1
  325. package/src/config/schemas/memory-v3.ts +82 -0
  326. package/src/config/schemas/monitoring.ts +61 -0
  327. package/src/config/schemas/schedules.ts +35 -0
  328. package/src/config/seed-inference-profiles.ts +2 -2
  329. package/src/config/skills-plugin-filter.test.ts +96 -0
  330. package/src/config/skills.ts +26 -0
  331. package/src/contacts/__tests__/member-write-relay.test.ts +156 -4
  332. package/src/contacts/canonical-guardian-store.ts +5 -0
  333. package/src/contacts/contact-store.ts +81 -35
  334. package/src/contacts/contacts-write.ts +50 -25
  335. package/src/contacts/member-write-relay.ts +115 -31
  336. package/src/contacts/types.ts +0 -8
  337. package/src/context/compactor.ts +29 -15
  338. package/src/context/outbound-sanitize.ts +202 -0
  339. package/src/daemon/__tests__/abort-null-controller.test.ts +167 -0
  340. package/src/daemon/__tests__/conversation-tool-setup-plugin-scope.test.ts +122 -0
  341. package/src/daemon/__tests__/embedding-reconcile.test.ts +99 -16
  342. package/src/daemon/__tests__/wake-conversation-ops-completion.test.ts +107 -0
  343. package/src/daemon/abort-watchdog.ts +7 -0
  344. package/src/daemon/app-source-watcher.ts +9 -0
  345. package/src/daemon/assistant-attachments.ts +42 -0
  346. package/src/daemon/conversation-agent-loop-handlers.ts +256 -147
  347. package/src/daemon/conversation-agent-loop.ts +61 -68
  348. package/src/daemon/conversation-error.ts +1 -15
  349. package/src/daemon/conversation-history.ts +32 -236
  350. package/src/daemon/conversation-initial-prompt.ts +77 -0
  351. package/src/daemon/conversation-lifecycle.ts +25 -1
  352. package/src/daemon/conversation-messaging.ts +2 -2
  353. package/src/daemon/conversation-plugin-scope.ts +38 -0
  354. package/src/daemon/conversation-process.ts +50 -14
  355. package/src/daemon/conversation-runtime-assembly.ts +36 -6
  356. package/src/daemon/conversation-skill-tools.ts +19 -3
  357. package/src/daemon/conversation-store.ts +3 -3
  358. package/src/daemon/conversation-surfaces.ts +171 -0
  359. package/src/daemon/conversation-tool-setup.test.ts +95 -0
  360. package/src/daemon/conversation-tool-setup.ts +116 -1
  361. package/src/daemon/conversation-turn-finalize.ts +211 -0
  362. package/src/daemon/conversation.ts +92 -1
  363. package/src/daemon/disk-pressure-policy.ts +2 -1
  364. package/src/daemon/event-loop-watchdog.ts +22 -6
  365. package/src/daemon/external-plugins-bootstrap.ts +47 -134
  366. package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +1 -1
  367. package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +26 -14
  368. package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +27 -14
  369. package/src/daemon/handlers/__tests__/config-channels.test.ts +0 -5
  370. package/src/daemon/handlers/config-a2a.ts +7 -14
  371. package/src/daemon/handlers/config-channels.ts +2 -10
  372. package/src/daemon/handlers/conversation-history.ts +3 -1
  373. package/src/daemon/handlers/conversations.ts +0 -52
  374. package/src/daemon/handlers/shared.ts +4 -24
  375. package/src/daemon/handlers/skills.ts +4 -1
  376. package/src/daemon/host-cu-proxy.ts +1 -1
  377. package/src/daemon/lifecycle.ts +59 -472
  378. package/src/daemon/message-protocol.ts +3 -3
  379. package/src/daemon/message-provenance.ts +12 -14
  380. package/src/daemon/message-types/background-tools.ts +28 -0
  381. package/src/daemon/message-types/contacts.ts +2 -10
  382. package/src/daemon/message-types/conversations.ts +10 -0
  383. package/src/daemon/message-types/integrations.ts +2 -0
  384. package/src/daemon/message-types/surfaces.ts +1 -0
  385. package/src/daemon/message-types/sync.ts +1 -0
  386. package/src/daemon/pointer-conversation-trust.ts +23 -9
  387. package/src/daemon/pointer-turn-runner.ts +174 -0
  388. package/src/daemon/providers-setup.ts +16 -0
  389. package/src/daemon/shutdown-handlers.ts +139 -47
  390. package/src/daemon/skill-memory-refresh.ts +2 -2
  391. package/src/daemon/sqlite-corruption-watchdog.test.ts +217 -0
  392. package/src/daemon/sqlite-corruption-watchdog.ts +155 -0
  393. package/src/daemon/tool-setup-types.ts +8 -0
  394. package/src/daemon/trust-context.ts +21 -6
  395. package/src/daemon/turn-latency-tracker.test.ts +93 -0
  396. package/src/daemon/turn-latency-tracker.ts +38 -0
  397. package/src/daemon/wake-conversation-ops.ts +10 -8
  398. package/src/documents/document-comments-store.test.ts +7 -1
  399. package/src/documents/document-comments-store.ts +8 -0
  400. package/src/documents/document-store.ts +15 -0
  401. package/src/export/__tests__/transcript-formatter.test.ts +11 -0
  402. package/src/export/transcript-formatter.ts +49 -67
  403. package/src/home/__tests__/feed-writer.test.ts +247 -1
  404. package/src/home/conversation-starter-checkpoints.ts +1 -0
  405. package/src/home/feed-writer.ts +61 -0
  406. package/src/home/job-handlers/conversation-starters.ts +1 -0
  407. package/src/hooks/hook-loader.ts +12 -0
  408. package/src/hooks/registry.ts +32 -4
  409. package/src/inbound/public-ingress-urls.ts +0 -17
  410. package/src/ipc/__tests__/contacts-info-ipc.test.ts +285 -0
  411. package/src/ipc/assistant-server.ts +28 -7
  412. package/src/ipc/routes/__tests__/contacts-mirror-apply-atomicity.test.ts +62 -0
  413. package/src/ipc/routes/__tests__/contacts-mirror-apply.test.ts +272 -0
  414. package/src/ipc/routes/__tests__/contacts-mirror-ipc-routes.test.ts +322 -0
  415. package/src/ipc/routes/__tests__/invite-ipc-routes.test.ts +60 -4
  416. package/src/ipc/routes/contacts-info-ipc-routes.ts +239 -0
  417. package/src/ipc/routes/contacts-mirror-ipc-routes.ts +202 -0
  418. package/src/ipc/routes/db-proxy.ts +5 -2
  419. package/src/ipc/routes/invite-ipc-routes.ts +53 -39
  420. package/src/jobs/worker.ts +9 -2
  421. package/src/live-voice/__tests__/live-voice-archive.test.ts +10 -1
  422. package/src/live-voice/live-voice-archive.ts +5 -0
  423. package/src/messaging/providers/__tests__/transport-dispatch.test.ts +22 -6
  424. package/src/messaging/providers/channel-transport.ts +6 -0
  425. package/src/messaging/providers/index.ts +3 -0
  426. package/src/messaging/providers/slack/api.test.ts +49 -1
  427. package/src/messaging/providers/slack/api.ts +110 -0
  428. package/src/messaging/providers/slack/send.test.ts +85 -0
  429. package/src/messaging/providers/slack/send.ts +100 -28
  430. package/src/messaging/providers/slack/transport.ts +7 -13
  431. package/src/messaging/providers/whatsapp/send.ts +29 -9
  432. package/src/monitoring/__tests__/control.test.ts +235 -0
  433. package/src/monitoring/__tests__/sample-ring-buffer.test.ts +96 -0
  434. package/src/monitoring/control.ts +105 -0
  435. package/src/monitoring/resource-sampler.ts +258 -0
  436. package/src/monitoring/sample-ring-buffer.ts +108 -0
  437. package/src/monitoring/worker.ts +94 -0
  438. package/src/notifications/README.md +1 -1
  439. package/src/notifications/access-request-copy.ts +94 -23
  440. package/src/notifications/adapters/slack.ts +89 -21
  441. package/src/notifications/approval-card-builder.ts +33 -18
  442. package/src/notifications/approval-card-data.ts +48 -15
  443. package/src/notifications/broadcaster.ts +25 -16
  444. package/src/notifications/decision-engine.ts +131 -32
  445. package/src/notifications/guardian-question-mode.ts +58 -10
  446. package/src/permissions/approval-policy.ts +8 -1
  447. package/src/permissions/checker.ts +2 -0
  448. package/src/permissions/gateway-threshold-reader.ts +7 -6
  449. package/src/permissions/ipc-risk-types.ts +1 -0
  450. package/src/permissions/secret-prompter.ts +11 -3
  451. package/src/permissions/types.ts +2 -2
  452. package/src/persistence/__tests__/conversation-queries-search.test.ts +397 -0
  453. package/src/persistence/__tests__/conversation-search-lexical.test.ts +103 -0
  454. package/src/persistence/__tests__/jobs-worker-memory-disabled.test.ts +95 -0
  455. package/src/persistence/__tests__/slow-query-log.test.ts +266 -0
  456. package/src/persistence/__tests__/slow-sync-log.test.ts +155 -0
  457. package/src/persistence/a2a-invite-store.ts +205 -0
  458. package/src/persistence/attachments-store.ts +94 -10
  459. package/src/persistence/checkpoints.ts +45 -0
  460. package/src/persistence/conversation-crud.ts +453 -260
  461. package/src/persistence/conversation-display-order-migration.ts +8 -2
  462. package/src/persistence/conversation-group-migration.test.ts +8 -0
  463. package/src/persistence/conversation-group-migration.ts +9 -0
  464. package/src/persistence/conversation-queries.ts +244 -125
  465. package/src/persistence/conversation-row-batch-delete.ts +9 -5
  466. package/src/persistence/conversation-search-lexical.ts +49 -0
  467. package/src/persistence/db-async-query.ts +42 -0
  468. package/src/persistence/db-connection.ts +13 -0
  469. package/src/persistence/delivery-channels.ts +0 -82
  470. package/src/persistence/delivery-crud.ts +27 -6
  471. package/src/persistence/embeddings/__tests__/embedding-identity.test.ts +18 -5
  472. package/src/persistence/embeddings/__tests__/messages-lexical-index.test.ts +334 -0
  473. package/src/persistence/embeddings/embedding-identity.ts +17 -5
  474. package/src/persistence/embeddings/embedding-runtime-manager.ts +31 -0
  475. package/src/persistence/embeddings/messages-lexical-index.ts +396 -0
  476. package/src/persistence/embeddings/qdrant-client.ts +81 -5
  477. package/src/persistence/group-crud.ts +13 -1
  478. package/src/persistence/job-handlers/__tests__/message-lexical-backfill.test.ts +506 -0
  479. package/src/persistence/job-handlers/__tests__/message-lexical-enqueue.test.ts +164 -0
  480. package/src/persistence/job-handlers/__tests__/message-lexical.test.ts +259 -0
  481. package/src/persistence/job-handlers/cleanup.ts +57 -9
  482. package/src/persistence/job-handlers/message-lexical-backfill.ts +187 -0
  483. package/src/persistence/job-handlers/message-lexical.ts +251 -0
  484. package/src/persistence/jobs-store.ts +102 -8
  485. package/src/persistence/jobs-worker.ts +68 -28
  486. package/src/persistence/llm-request-log-store.ts +35 -19
  487. package/src/persistence/llm-usage-store.ts +11 -0
  488. package/src/persistence/memory-lifecycle-hooks.test.ts +65 -0
  489. package/src/persistence/memory-lifecycle-hooks.ts +55 -1
  490. package/src/persistence/migrations/028-call-session-mode.ts +1 -1
  491. package/src/persistence/migrations/116-messages-fts.ts +8 -1
  492. package/src/persistence/migrations/311-create-subagents-table.ts +50 -0
  493. package/src/persistence/migrations/312-drop-inbox-conversation-state-table.ts +15 -0
  494. package/src/persistence/migrations/313-drop-messages-fts.ts +17 -0
  495. package/src/persistence/migrations/314-add-conversation-enabled-plugins.ts +25 -0
  496. package/src/persistence/migrations/315-create-a2a-invites.ts +58 -0
  497. package/src/persistence/migrations/316-drop-contact-channels-invite-id.ts +28 -0
  498. package/src/persistence/migrations/317-canonical-guardian-requester-signals.ts +24 -0
  499. package/src/persistence/migrations/318-drop-contact-channel-telemetry.ts +32 -0
  500. package/src/persistence/migrations/__tests__/315-create-a2a-invites.test.ts +161 -0
  501. package/src/persistence/migrations/__tests__/316-drop-contact-channels-invite-id.test.ts +156 -0
  502. package/src/persistence/migrations/__tests__/318-drop-contact-channel-telemetry.test.ts +134 -0
  503. package/src/persistence/migrations/__tests__/migration-prefix-guard.test.ts +99 -0
  504. package/src/persistence/raw-query.ts +50 -11
  505. package/src/persistence/schema/a2a.ts +14 -0
  506. package/src/persistence/schema/contacts.ts +0 -62
  507. package/src/persistence/schema/conversation-groups.ts +12 -0
  508. package/src/persistence/schema/conversations.ts +2 -0
  509. package/src/persistence/schema/documents.ts +65 -0
  510. package/src/persistence/schema/guardian.ts +4 -0
  511. package/src/persistence/schema/index.ts +4 -0
  512. package/src/persistence/schema/memory-injection.ts +62 -0
  513. package/src/persistence/schema/workflows.ts +55 -0
  514. package/src/persistence/slow-query-log.ts +437 -0
  515. package/src/persistence/slow-sync-log.ts +204 -0
  516. package/src/persistence/steps.ts +16 -0
  517. package/src/persistence/subagent-store.ts +125 -0
  518. package/src/persistence/worker-control.ts +45 -238
  519. package/src/plugin-api/event-hub-facade.ts +172 -0
  520. package/src/plugin-api/index.ts +9 -1
  521. package/src/plugin-api/types.ts +40 -9
  522. package/src/plugins/defaults/default-plugin-names.ts +60 -0
  523. package/src/plugins/defaults/index.ts +19 -29
  524. package/src/plugins/defaults/memory/__tests__/conversation-queries.test.ts +46 -67
  525. package/src/plugins/defaults/memory/__tests__/db-async-query.test.ts +36 -1
  526. package/src/plugins/defaults/memory/__tests__/find-most-recent-retrospective-for.test.ts +2 -4
  527. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +2 -2
  528. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-schedule.test.ts +9 -0
  529. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +7 -4
  530. package/src/plugins/defaults/memory/config.ts +11 -0
  531. package/src/plugins/defaults/memory/context-search/agent-runner.ts +1 -1
  532. package/src/plugins/defaults/memory/context-search/sources/conversations.ts +124 -113
  533. package/src/plugins/defaults/memory/embeddings.ts +77 -0
  534. package/src/plugins/defaults/memory/find-most-recent-retrospective-for.ts +66 -0
  535. package/src/plugins/defaults/memory/frontmatter.ts +50 -0
  536. package/src/plugins/defaults/memory/graph/bootstrap.test.ts +36 -10
  537. package/src/plugins/defaults/memory/graph/bootstrap.ts +6 -5
  538. package/src/plugins/defaults/memory/graph/consolidation.ts +3 -5
  539. package/src/plugins/defaults/memory/graph/extraction.ts +3 -6
  540. package/src/plugins/defaults/memory/graph/graph-search.ts +12 -23
  541. package/src/plugins/defaults/memory/graph/narrative.ts +3 -5
  542. package/src/plugins/defaults/memory/graph/pattern-scan.ts +3 -5
  543. package/src/plugins/defaults/memory/graph/retriever.test.ts +1 -6
  544. package/src/plugins/defaults/memory/graph/retriever.ts +5 -10
  545. package/src/plugins/defaults/memory/graph/tools.ts +1 -1
  546. package/src/plugins/defaults/memory/hooks/init.ts +31 -5
  547. package/src/plugins/defaults/memory/indexer.ts +2 -3
  548. package/src/plugins/defaults/memory/injectors.ts +2 -2
  549. package/src/plugins/defaults/memory/job-handler-registration.ts +96 -0
  550. package/src/plugins/defaults/memory/job-handlers/backfill.ts +4 -26
  551. package/src/plugins/defaults/memory/job-handlers/embedding.test.ts +6 -19
  552. package/src/plugins/defaults/memory/job-handlers/embedding.ts +9 -22
  553. package/src/plugins/defaults/memory/job-handlers/index-maintenance.ts +2 -3
  554. package/src/plugins/defaults/memory/job-handlers.ts +13 -12
  555. package/src/plugins/defaults/memory/jobs/embed-concept-page.ts +1 -1
  556. package/src/plugins/defaults/memory/llm-helpers.ts +76 -0
  557. package/src/plugins/defaults/memory/memory-retrospective-job.ts +8 -5
  558. package/src/plugins/defaults/memory/memory-retrospective-startup-cleanup.ts +2 -2
  559. package/src/plugins/defaults/memory/memory-v2-concept-frequency.ts +2 -0
  560. package/src/plugins/defaults/memory/persistence-hooks.ts +46 -1
  561. package/src/plugins/defaults/memory/pkb/pkb-index.ts +1 -5
  562. package/src/plugins/defaults/memory/pkb/pkb-search.ts +2 -2
  563. package/src/plugins/defaults/memory/routes/__tests__/memory-v2-simulate-route.test.ts +4 -6
  564. package/src/plugins/defaults/memory/routes/memory-item-routes.ts +1 -1
  565. package/src/plugins/defaults/memory/search/semantic.ts +2 -2
  566. package/src/plugins/defaults/memory/startup.ts +244 -0
  567. package/src/plugins/defaults/memory/task-memory-cleanup.ts +8 -0
  568. package/src/{daemon → plugins/defaults/memory/v2}/__tests__/memory-v2-startup.test.ts +6 -6
  569. package/src/plugins/defaults/memory/v2/__tests__/migration.test.ts +2 -13
  570. package/src/plugins/defaults/memory/v2/__tests__/router.test.ts +4 -5
  571. package/src/plugins/defaults/memory/v2/__tests__/sweep-job.test.ts +1 -8
  572. package/src/plugins/defaults/memory/v2/activation.ts +2 -4
  573. package/src/plugins/defaults/memory/v2/cli-command-store.ts +2 -4
  574. package/src/plugins/defaults/memory/v2/frontmatter-sweep.ts +1 -1
  575. package/src/{daemon → plugins/defaults/memory/v2}/memory-v2-startup.test.ts +8 -8
  576. package/src/{daemon → plugins/defaults/memory/v2}/memory-v2-startup.ts +20 -22
  577. package/src/plugins/defaults/memory/v2/migration.ts +2 -5
  578. package/src/plugins/defaults/memory/v2/page-store.ts +1 -1
  579. package/src/plugins/defaults/memory/v2/qdrant.ts +2 -3
  580. package/src/plugins/defaults/memory/v2/router.ts +5 -5
  581. package/src/plugins/defaults/memory/v2/sim.ts +2 -4
  582. package/src/plugins/defaults/memory/v2/skill-store.ts +2 -4
  583. package/src/plugins/defaults/memory/v2/sweep-job.ts +6 -6
  584. package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +11 -9
  585. package/src/plugins/defaults/memory/v3/__tests__/dense.test.ts +107 -2
  586. package/src/plugins/defaults/memory/v3/__tests__/gate-flag.test.ts +69 -0
  587. package/src/plugins/defaults/memory/v3/__tests__/gate.test.ts +181 -0
  588. package/src/plugins/defaults/memory/v3/__tests__/live-integration.test.ts +7 -3
  589. package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +345 -8
  590. package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +1 -4
  591. package/src/plugins/defaults/memory/v3/__tests__/section-needle.test.ts +64 -0
  592. package/src/plugins/defaults/memory/v3/__tests__/shadow-integration.test.ts +18 -13
  593. package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +62 -1
  594. package/src/plugins/defaults/memory/v3/card.ts +1 -4
  595. package/src/plugins/defaults/memory/v3/dense.ts +60 -25
  596. package/src/plugins/defaults/memory/v3/edge.ts +1 -1
  597. package/src/plugins/defaults/memory/v3/gate-flag.ts +20 -0
  598. package/src/plugins/defaults/memory/v3/gate.ts +158 -0
  599. package/src/plugins/defaults/memory/v3/maintain-job.ts +2 -4
  600. package/src/plugins/defaults/memory/v3/orchestrate.ts +186 -25
  601. package/src/plugins/defaults/memory/v3/pool-select.test.ts +7 -9
  602. package/src/plugins/defaults/memory/v3/pool-select.ts +6 -6
  603. package/src/plugins/defaults/memory/v3/prune.ts +2 -2
  604. package/src/plugins/defaults/memory/v3/section-dense-store.ts +8 -11
  605. package/src/plugins/defaults/memory/v3/section-needle.ts +27 -7
  606. package/src/plugins/defaults/memory/v3/shadow-plugin.ts +10 -0
  607. package/src/plugins/defaults/memory/v3-eval/eval-packets.ts +1 -4
  608. package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +5 -0
  609. package/src/plugins/defaults/turn-context/injectors.ts +1 -0
  610. package/src/plugins/defaults/turn-context/unified-turn-context.ts +12 -0
  611. package/src/plugins/injector-registry.ts +13 -2
  612. package/src/plugins/mtime-cache.ts +36 -47
  613. package/src/plugins/pipeline.ts +15 -1
  614. package/src/plugins/types.ts +14 -23
  615. package/src/prompts/__tests__/system-prompt.test.ts +170 -32
  616. package/src/prompts/persona-resolver.ts +13 -9
  617. package/src/prompts/system-prompt.ts +30 -9
  618. package/src/prompts/templates/BOOTSTRAP.md +16 -119
  619. package/src/prompts/templates/SOUL.md +43 -13
  620. package/src/prompts/templates/system-sections.ts +32 -27
  621. package/src/prompts/templates/users/default.md +19 -0
  622. package/src/providers/__tests__/placeholder-sentinels.test.ts +56 -0
  623. package/src/providers/inference/__tests__/base-url-route-validation.test.ts +96 -1
  624. package/src/providers/model-intents.ts +2 -2
  625. package/src/providers/openai/chat-completions-provider.ts +14 -1
  626. package/src/providers/openai/responses-provider.ts +18 -0
  627. package/src/providers/placeholder-sentinels.ts +18 -8
  628. package/src/providers/retry.ts +1 -0
  629. package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +0 -64
  630. package/src/providers/speech-to-text/__tests__/resolve.test.ts +92 -79
  631. package/src/providers/speech-to-text/deepgram-realtime.test.ts +98 -0
  632. package/src/providers/speech-to-text/deepgram-realtime.ts +62 -3
  633. package/src/providers/speech-to-text/provider-catalog.ts +0 -89
  634. package/src/providers/speech-to-text/resolve.ts +55 -0
  635. package/src/providers/tool-progress-events.test.ts +50 -0
  636. package/src/providers/tool-progress-events.ts +99 -0
  637. package/src/providers/types.ts +1 -1
  638. package/src/providers/vellum-model-routing.test.ts +51 -0
  639. package/src/providers/vellum-model-routing.ts +84 -0
  640. package/src/runtime/AGENTS.md +5 -4
  641. package/src/runtime/__tests__/agent-wake.test.ts +158 -1
  642. package/src/runtime/__tests__/channel-verification-service.test.ts +2 -2
  643. package/src/runtime/__tests__/trust-verdict-consumer.test.ts +37 -8
  644. package/src/runtime/access-request-helper.ts +154 -3
  645. package/src/runtime/actor-trust-resolver.ts +7 -21
  646. package/src/runtime/agent-wake.ts +41 -1
  647. package/src/runtime/assistant-event.ts +86 -12
  648. package/src/runtime/auth/__tests__/route-policy.test.ts +31 -0
  649. package/src/runtime/channel-approval-types.ts +52 -2
  650. package/src/runtime/channel-approvals.ts +23 -8
  651. package/src/runtime/channel-invite-transport.ts +2 -2
  652. package/src/runtime/channel-invite-transports/voice.ts +1 -1
  653. package/src/runtime/channel-readiness-service.ts +3 -5
  654. package/src/runtime/channel-retry-sweep.ts +18 -24
  655. package/src/runtime/channel-verification-service.ts +9 -11
  656. package/src/runtime/finalize-event-delivery.ts +30 -16
  657. package/src/runtime/guardian-action-service.ts +10 -11
  658. package/src/runtime/guardian-reply-router.ts +122 -21
  659. package/src/runtime/http-server.ts +44 -101
  660. package/src/runtime/introduction-policy.test.ts +214 -0
  661. package/src/runtime/introduction-policy.ts +284 -0
  662. package/src/runtime/invite-service.ts +104 -361
  663. package/src/runtime/local-actor-identity.test.ts +38 -0
  664. package/src/runtime/local-actor-identity.ts +14 -0
  665. package/src/runtime/middleware/__tests__/rate-limiter.test.ts +22 -0
  666. package/src/runtime/middleware/rate-limiter.ts +30 -0
  667. package/src/runtime/middleware/twilio-validation.ts +5 -7
  668. package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +28 -0
  669. package/src/runtime/migrations/origin-mode.ts +6 -6
  670. package/src/runtime/pre-first-message-gate.ts +1 -0
  671. package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +6 -35
  672. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +24 -3
  673. package/src/runtime/routes/__tests__/contact-routes.test.ts +80 -15
  674. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +7 -1
  675. package/src/runtime/routes/__tests__/global-search-routes.test.ts +0 -3
  676. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +142 -1
  677. package/src/runtime/routes/__tests__/invite-relay-routes.test.ts +119 -30
  678. package/src/runtime/routes/__tests__/migration-import-allowed-hosts-env.test.ts +70 -0
  679. package/src/runtime/routes/__tests__/monitoring-routes.test.ts +194 -0
  680. package/src/runtime/routes/__tests__/plugins-routes.test.ts +755 -29
  681. package/src/runtime/routes/__tests__/retrospective-routes.test.ts +4 -0
  682. package/src/runtime/routes/__tests__/schedule-routes-create.test.ts +70 -0
  683. package/src/runtime/routes/__tests__/schedule-worker-routes.test.ts +161 -0
  684. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +1 -1
  685. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +1 -1
  686. package/src/runtime/routes/acp-routes.ts +15 -3
  687. package/src/runtime/routes/app-management-routes.ts +4 -7
  688. package/src/runtime/routes/approval-routes.ts +4 -0
  689. package/src/runtime/routes/attachment-routes.ts +54 -3
  690. package/src/runtime/routes/avatar-routes.ts +0 -4
  691. package/src/runtime/routes/background-tool-routes.ts +34 -5
  692. package/src/runtime/routes/btw-routes.ts +32 -4
  693. package/src/runtime/routes/channel-route-shared.ts +18 -14
  694. package/src/runtime/routes/channel-verification-routes.ts +0 -3
  695. package/src/runtime/routes/contact-routes.ts +298 -117
  696. package/src/runtime/routes/conversation-list-routes.ts +6 -0
  697. package/src/runtime/routes/conversation-management-routes.ts +74 -37
  698. package/src/runtime/routes/conversation-query-routes.ts +5 -2
  699. package/src/runtime/routes/conversation-routes.ts +222 -82
  700. package/src/runtime/routes/conversations-import-routes.ts +8 -1
  701. package/src/runtime/routes/credential-prompt-routes.ts +20 -5
  702. package/src/runtime/routes/debug-routes.ts +1 -0
  703. package/src/runtime/routes/documents-routes.ts +5 -2
  704. package/src/runtime/routes/empty-state-greeting-cache.ts +37 -10
  705. package/src/runtime/routes/global-search-routes.ts +2 -1
  706. package/src/runtime/routes/guardian-approval-interception.ts +51 -0
  707. package/src/runtime/routes/home-feed-routes.ts +60 -1
  708. package/src/runtime/routes/identity-routes.ts +4 -87
  709. package/src/runtime/routes/inbound-message-handler.ts +82 -41
  710. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +430 -57
  711. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +302 -572
  712. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +76 -270
  713. package/src/runtime/routes/inbound-stages/background-dispatch.ts +21 -116
  714. package/src/runtime/routes/inbound-stages/edit-intercept.ts +9 -1
  715. package/src/runtime/routes/inbound-stages/escalation-intercept.test.ts +158 -0
  716. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +22 -1
  717. package/src/runtime/routes/index.ts +6 -0
  718. package/src/runtime/routes/inference-provider-connection-routes.ts +22 -16
  719. package/src/runtime/routes/internal-twilio-routes.ts +0 -15
  720. package/src/runtime/routes/messages-lexical-routes.ts +75 -0
  721. package/src/runtime/routes/migration-routes.ts +69 -6
  722. package/src/runtime/routes/monitoring-routes.ts +237 -0
  723. package/src/runtime/routes/plugins-routes.ts +329 -8
  724. package/src/runtime/routes/schedule-routes.ts +49 -8
  725. package/src/runtime/routes/schedule-worker-routes.ts +210 -0
  726. package/src/runtime/routes/secret-routes.ts +1 -1
  727. package/src/runtime/routes/surface-conversation-resolver.ts +1 -0
  728. package/src/runtime/services/__tests__/analyze-conversation.test.ts +54 -9
  729. package/src/runtime/services/__tests__/auto-analysis-enqueue.test.ts +30 -6
  730. package/src/runtime/services/__tests__/conversation-analyze-job.test.ts +43 -8
  731. package/src/runtime/services/__tests__/conversation-serializer.test.ts +20 -0
  732. package/src/runtime/services/analyze-conversation.ts +14 -4
  733. package/src/runtime/services/conversation-serializer.ts +5 -0
  734. package/src/runtime/slack-no-response.ts +47 -0
  735. package/src/runtime/slack-reply-session.test.ts +633 -0
  736. package/src/runtime/slack-reply-session.ts +382 -0
  737. package/src/runtime/slack-task-progress.ts +95 -0
  738. package/src/runtime/sync/resource-sync-events.ts +25 -0
  739. package/src/runtime/tool-grant-request-helper.ts +17 -1
  740. package/src/runtime/trust-class.test.ts +141 -0
  741. package/src/runtime/trust-class.ts +121 -0
  742. package/src/runtime/trust-verdict-consumer.ts +7 -6
  743. package/src/schedule/__tests__/run-script.test.ts +21 -0
  744. package/src/schedule/__tests__/worker-control.test.ts +241 -0
  745. package/src/schedule/run-script.ts +13 -6
  746. package/src/schedule/schedule-usage-store.ts +1 -0
  747. package/src/schedule/scheduler.ts +178 -127
  748. package/src/schedule/worker-control.ts +118 -0
  749. package/src/schedule/worker.ts +131 -0
  750. package/src/skills/__tests__/categories-cache.test.ts +38 -0
  751. package/src/skills/categories-cache.ts +40 -5
  752. package/src/skills/managed-store.ts +41 -6
  753. package/src/skills/validate-input.ts +47 -0
  754. package/src/stt/types.ts +5 -9
  755. package/src/subagent/manager.ts +267 -39
  756. package/src/subagent/types.ts +6 -2
  757. package/src/subagent/validate-allowlists.ts +65 -0
  758. package/src/telemetry/watchdog-direct-emit.test.ts +109 -0
  759. package/src/telemetry/watchdog-direct-emit.ts +89 -0
  760. package/src/tools/acp/list-agents.test.ts +0 -6
  761. package/src/tools/background-tool-registry.ts +61 -0
  762. package/src/tools/document/document-comment-tool.test.ts +4 -0
  763. package/src/tools/host-terminal/host-shell.test.ts +397 -0
  764. package/src/tools/host-terminal/host-shell.ts +203 -14
  765. package/src/tools/skills/find-similar-skills.test.ts +152 -1
  766. package/src/tools/skills/find-similar-skills.ts +30 -4
  767. package/src/tools/skills/load.ts +36 -0
  768. package/src/tools/skills/scaffold-managed.ts +66 -34
  769. package/src/tools/skills/skill-script-runner.ts +17 -0
  770. package/src/tools/skills/skill-tool-factory.ts +5 -1
  771. package/src/tools/terminal/safe-env.ts +3 -0
  772. package/src/tools/terminal/shell.test.ts +177 -0
  773. package/src/tools/terminal/shell.ts +98 -4
  774. package/src/tools/tool-approval-handler.ts +106 -29
  775. package/{node_modules/@vellumai/skill-host-contracts/src → src/tools}/tool-types.ts +16 -17
  776. package/src/tools/types.ts +29 -17
  777. package/src/tools/ui-surface/definitions.ts +3 -1
  778. package/src/tts/__tests__/provider-adapters.test.ts +37 -0
  779. package/src/tts/__tests__/provider-catalog.test.ts +21 -0
  780. package/src/tts/provider-catalog.ts +40 -9
  781. package/src/tts/providers/fish-audio-provider.ts +19 -10
  782. package/src/tts/types.ts +3 -4
  783. package/src/util/__tests__/process-tree.test.ts +10 -2
  784. package/src/util/__tests__/text-spacing.test.ts +53 -0
  785. package/src/util/cgroup-memory.ts +142 -0
  786. package/src/util/image-conversion.ts +281 -0
  787. package/src/util/phone.ts +1 -8
  788. package/src/util/platform.ts +33 -0
  789. package/src/util/process-tree.ts +10 -2
  790. package/src/util/text-spacing.ts +53 -0
  791. package/src/util/worker-process.ts +271 -0
  792. package/src/workflows/journal-store.ts +16 -1
  793. package/src/workflows/library.test.ts +35 -20
  794. package/src/workflows/library.ts +105 -66
  795. package/src/workspace/git-service.ts +1 -0
  796. package/src/workspace/migrations/011-backfill-installation-id.ts +83 -31
  797. package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +41 -22
  798. package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +1 -1
  799. package/src/workspace/migrations/118-seed-now-md.ts +64 -0
  800. package/src/workspace/migrations/119-strip-persisted-memory-v3-tuning-defaults.ts +169 -0
  801. package/src/workspace/migrations/120-revise-onboarding-threads.ts +47 -0
  802. package/src/workspace/migrations/121-seed-default-user-guardrails.ts +82 -0
  803. package/src/workspace/migrations/122-relocate-default-user-boundary.ts +111 -0
  804. package/src/workspace/migrations/123-swap-quality-profile-to-fable.ts +85 -0
  805. package/src/workspace/migrations/__tests__/119-strip-persisted-memory-v3-tuning-defaults.test.ts +181 -0
  806. package/src/workspace/migrations/registry.ts +12 -0
  807. package/drizzle/0000_dizzy_maggott.sql +0 -301
  808. package/drizzle/meta/0000_snapshot.json +0 -1933
  809. package/drizzle/meta/_journal.json +0 -13
  810. package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +0 -887
  811. package/node_modules/@vellumai/skill-host-contracts/bun.lock +0 -24
  812. package/node_modules/@vellumai/skill-host-contracts/package.json +0 -18
  813. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -97
  814. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +0 -1349
  815. package/node_modules/@vellumai/skill-host-contracts/src/index.ts +0 -6
  816. package/node_modules/@vellumai/skill-host-contracts/src/runtime-mode.ts +0 -11
  817. package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +0 -32
  818. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +0 -333
  819. package/node_modules/@vellumai/skill-host-contracts/tsconfig.json +0 -20
  820. package/node_modules/@vellumai/skill-host-contracts/tsconfig.test.json +0 -12
  821. package/src/__tests__/invite-redemption-service.test.ts +0 -1180
  822. package/src/__tests__/invite-service-ipc.test.ts +0 -350
  823. package/src/__tests__/job-handler-registry-guard.test.ts +0 -125
  824. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +0 -203
  825. package/src/__tests__/relay-server.test.ts +0 -6153
  826. package/src/__tests__/telephony-stt-routing.test.ts +0 -329
  827. package/src/__tests__/voice-invite-redemption.test.ts +0 -702
  828. package/src/calls/relay-server.ts +0 -2463
  829. package/src/calls/telephony-stt-routing.ts +0 -145
  830. package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +0 -128
  831. package/src/daemon/__tests__/daemon-skill-host.test.ts +0 -273
  832. package/src/daemon/daemon-skill-host.ts +0 -262
  833. package/src/daemon/message-types/meet.ts +0 -143
  834. package/src/daemon/shutdown-registry.ts +0 -40
  835. package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -253
  836. package/src/ipc/__tests__/skill-server.test.ts +0 -182
  837. package/src/ipc/skill-ipc-types.ts +0 -54
  838. package/src/ipc/skill-routes/__tests__/config.test.ts +0 -146
  839. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +0 -448
  840. package/src/ipc/skill-routes/__tests__/identity.test.ts +0 -62
  841. package/src/ipc/skill-routes/__tests__/log.test.ts +0 -133
  842. package/src/ipc/skill-routes/__tests__/memory.test.ts +0 -203
  843. package/src/ipc/skill-routes/__tests__/platform.test.ts +0 -111
  844. package/src/ipc/skill-routes/__tests__/providers.test.ts +0 -265
  845. package/src/ipc/skill-routes/__tests__/registries.test.ts +0 -400
  846. package/src/ipc/skill-routes/config.ts +0 -47
  847. package/src/ipc/skill-routes/events.ts +0 -147
  848. package/src/ipc/skill-routes/identity.ts +0 -21
  849. package/src/ipc/skill-routes/index.ts +0 -37
  850. package/src/ipc/skill-routes/log.ts +0 -40
  851. package/src/ipc/skill-routes/memory.ts +0 -92
  852. package/src/ipc/skill-routes/platform.ts +0 -39
  853. package/src/ipc/skill-routes/providers.ts +0 -162
  854. package/src/ipc/skill-routes/registries.ts +0 -338
  855. package/src/ipc/skill-server.ts +0 -831
  856. package/src/ipc/skill-socket-path.ts +0 -20
  857. package/src/jobs/register-job-handlers.ts +0 -74
  858. package/src/persistence/invite-store.ts +0 -481
  859. package/src/plugins/job-handler-registry.ts +0 -94
  860. package/src/providers/cache-control.ts +0 -26
  861. package/src/runtime/__tests__/runtime-mode.test.ts +0 -62
  862. package/src/runtime/invite-redemption-service.ts +0 -828
  863. package/src/runtime/invite-redemption-templates.ts +0 -46
  864. package/src/runtime/runtime-mode.ts +0 -40
  865. package/src/runtime/slack-dm-text-delivery.ts +0 -177
  866. package/src/util/voice-code.ts +0 -31
@@ -12,6 +12,7 @@ import {
12
12
  extractChannelFromCallbackUrl,
13
13
  extractMessageTsFromCallbackUrl,
14
14
  extractThreadTsFromCallbackUrl,
15
+ isSlackDeliveryCallbackUrl,
15
16
  peekThreadMapping,
16
17
  setThreadTs,
17
18
  } from "../../../channels/slack-thread-store.js";
@@ -22,13 +23,10 @@ import {
22
23
  } from "../../../contacts/guardian-delivery-reader.js";
23
24
  import type { ServerMessage } from "../../../daemon/message-protocol.js";
24
25
  import type { TrustContext } from "../../../daemon/trust-context.js";
25
- import {
26
- addSlackDmLiveDeliveredTextResponseIndex,
27
- getSlackDmLiveDeliveredTextResponseIndexes,
28
- } from "../../../persistence/delivery-channels.js";
29
26
  import {
30
27
  linkMessage,
31
28
  storeReplyMessageId,
29
+ storeStreamedReplyTs,
32
30
  } from "../../../persistence/delivery-crud.js";
33
31
  import {
34
32
  markProcessed,
@@ -48,10 +46,14 @@ import type {
48
46
  MessageProcessor,
49
47
  SlackInboundMessageMetadata,
50
48
  } from "../../http-types.js";
49
+ import { hasDeliverableAssistantText } from "../../slack-no-response.js";
50
+ import { createSlackReplySession } from "../../slack-reply-session.js";
51
+ import type { TaskProgressData } from "../../slack-task-progress.js";
51
52
  import {
52
- createSlackDmTextDeliveryController,
53
- isSlackDeliveryCallbackUrl,
54
- } from "../../slack-dm-text-delivery.js";
53
+ getTaskProgressDataFromSurfaceData,
54
+ mergeTaskProgressData,
55
+ } from "../../slack-task-progress.js";
56
+ import { isContactTrustClass } from "../../trust-class.js";
55
57
  import { resolveRoutingState } from "../../trust-context-resolver.js";
56
58
  import { finalizeEventDelivery } from "../channel-delivery-routes.js";
57
59
  import { deliverGeneratedApprovalPrompt } from "../guardian-approval-prompt.js";
@@ -236,20 +238,14 @@ export function processChannelMessageInBackground(
236
238
  }
237
239
  : undefined;
238
240
  let replyMessageId: string | undefined;
239
- const slackDmTextDelivery = createSlackDmTextDeliveryController({
241
+ const slackReplySession = createSlackReplySession({
240
242
  sourceChannel,
241
243
  chatType,
242
244
  replyCallbackUrl,
243
245
  chatId: externalChatId,
244
246
  assistantId,
245
- deliveredTextResponseIndexes:
246
- getSlackDmLiveDeliveredTextResponseIndexes(eventId),
247
- onTextResponseDelivered: (responseIndex, reason) => {
248
- addSlackDmLiveDeliveredTextResponseIndex(eventId, responseIndex);
249
- if (reason === "before_tool") {
250
- slackThinkingStatus?.refreshAfterReply();
251
- }
252
- },
247
+ recipientUserId: slackInbound?.actorExternalUserId,
248
+ recipientTeamId: slackInbound?.actorTeamId,
253
249
  });
254
250
  const observeAgentEvent = (msg: ServerMessage): void => {
255
251
  if (
@@ -259,7 +255,7 @@ export function processChannelMessageInBackground(
259
255
  ) {
260
256
  replyMessageId = msg.messageId;
261
257
  }
262
- slackDmTextDelivery?.observeEvent(msg);
258
+ slackReplySession?.observeEvent(msg);
263
259
  slackThinkingStatus?.observeEvent(msg);
264
260
  };
265
261
 
@@ -317,8 +313,11 @@ export function processChannelMessageInBackground(
317
313
  { err, conversationId },
318
314
  "Background channel message processing failed",
319
315
  );
320
- if (slackDmTextDelivery) {
321
- await slackDmTextDelivery.waitForPendingDeliveries();
316
+ if (slackReplySession) {
317
+ const reconciliation = await slackReplySession.finish();
318
+ if (reconciliation.mode === "streamed") {
319
+ storeStreamedReplyTs(eventId, reconciliation.messageTs);
320
+ }
322
321
  }
323
322
  recordProcessingFailure(eventId, err);
324
323
  return;
@@ -334,7 +333,7 @@ export function processChannelMessageInBackground(
334
333
  assistantId,
335
334
  replyMessageId,
336
335
  userMessageId,
337
- slackDmTextDelivery,
336
+ slackReplySession,
338
337
  });
339
338
  } catch (err) {
340
339
  log.error(
@@ -414,47 +413,16 @@ function startTelegramTypingHeartbeat(
414
413
 
415
414
  type SlackThinkingStatusController = {
416
415
  observeEvent: (msg: ServerMessage) => void;
417
- refreshAfterReply: () => void;
418
416
  stop: () => void;
419
417
  };
420
418
 
421
419
  type SlackThinkingStatusHandle = {
422
420
  updateLoadingMessages: (loadingMessages?: string[]) => void;
423
- refresh: (loadingMessages?: string[]) => void;
424
421
  clear: () => void;
425
422
  };
426
423
 
427
- type TaskProgressStep = {
428
- label: string;
429
- status: "pending" | "in_progress" | "completed" | "failed";
430
- };
431
-
432
- type TaskProgressData = {
433
- steps: TaskProgressStep[];
434
- };
435
-
436
- const NO_RESPONSE_RE = /^\s*<no_response\s*\/?>\s*$/i;
437
- const NO_RESPONSE_INLINE_RE = /<no_response\s*\/?>/gi;
438
- const NO_RESPONSE_SENTINEL_FORMS = [
439
- "<no_response/>",
440
- "<no_response />",
441
- "<no_response>",
442
- ] as const;
443
-
444
- function isPotentialNoResponsePrefix(text: string): boolean {
445
- const lower = text.toLowerCase();
446
- return NO_RESPONSE_SENTINEL_FORMS.some((sentinel) =>
447
- sentinel.startsWith(lower),
448
- );
449
- }
450
-
451
424
  export function shouldStartSlackThinkingStatusForText(text: string): boolean {
452
- const trimmed = text.trim();
453
- if (trimmed.length === 0) return false;
454
- if (NO_RESPONSE_RE.test(trimmed)) return false;
455
- if (isPotentialNoResponsePrefix(trimmed)) return false;
456
-
457
- return trimmed.replace(NO_RESPONSE_INLINE_RE, "").trim().length > 0;
425
+ return hasDeliverableAssistantText(text);
458
426
  }
459
427
 
460
428
  function shouldEmitSlackThinkingStatus(
@@ -565,13 +533,6 @@ function createSlackThinkingStatusController(params: {
565
533
  start();
566
534
  }
567
535
  },
568
- refreshAfterReply() {
569
- if (stopped || !slackThinkingStatus) return;
570
- // Slack clears assistant thread status when the app sends a reply, so
571
- // live pre-tool replies need to reassert it while work continues.
572
- slackThinkingStatus.refresh(currentLoadingMessages);
573
- lastSentLoadingMessageKey = getLoadingMessagesKey(currentLoadingMessages);
574
- },
575
536
  stop() {
576
537
  stopped = true;
577
538
  slackThinkingStatus?.clear();
@@ -593,53 +554,6 @@ function getLoadingMessagesKey(loadingMessages?: string[]): string | undefined {
593
554
  return loadingMessages?.join("\n");
594
555
  }
595
556
 
596
- function isRecord(value: unknown): value is Record<string, unknown> {
597
- return typeof value === "object" && value !== null && !Array.isArray(value);
598
- }
599
-
600
- function getTaskProgressDataFromSurfaceData(
601
- data: unknown,
602
- ): TaskProgressData | undefined {
603
- if (!isRecord(data)) return undefined;
604
- if (data.template !== "task_progress") return undefined;
605
- return parseTaskProgressData(data.templateData);
606
- }
607
-
608
- function parseTaskProgressData(value: unknown): TaskProgressData | undefined {
609
- if (!isRecord(value) || !Array.isArray(value.steps)) return undefined;
610
-
611
- const steps = value.steps.flatMap((step): TaskProgressStep[] => {
612
- if (!isRecord(step)) return [];
613
- if (typeof step.label !== "string") return [];
614
- if (
615
- step.status !== "pending" &&
616
- step.status !== "in_progress" &&
617
- step.status !== "completed" &&
618
- step.status !== "failed"
619
- ) {
620
- return [];
621
- }
622
- return [{ label: step.label, status: step.status }];
623
- });
624
-
625
- return steps.length > 0 ? { steps } : undefined;
626
- }
627
-
628
- function mergeTaskProgressData(
629
- existing: TaskProgressData | undefined,
630
- data: unknown,
631
- ): TaskProgressData | undefined {
632
- if (!isRecord(data)) return existing;
633
- const update = getTaskProgressDataFromSurfaceData(data);
634
- if (update) return update;
635
- if (!existing || !("templateData" in data)) return existing;
636
-
637
- return parseTaskProgressData({
638
- steps: existing.steps,
639
- ...(isRecord(data.templateData) ? data.templateData : {}),
640
- });
641
- }
642
-
643
557
  function getTaskProgressLoadingMessage(
644
558
  progress: TaskProgressData | undefined,
645
559
  ): string[] | undefined {
@@ -683,7 +597,6 @@ function setSlackThinkingStatus(
683
597
  if (!messageTs) {
684
598
  return {
685
599
  updateLoadingMessages: () => {},
686
- refresh: () => {},
687
600
  clear: () => {},
688
601
  };
689
602
  }
@@ -725,7 +638,6 @@ function setSlackThinkingStatus(
725
638
 
726
639
  return {
727
640
  updateLoadingMessages: () => {},
728
- refresh: () => {},
729
641
  clear: clearReaction,
730
642
  };
731
643
  }
@@ -768,10 +680,6 @@ function setSlackThinkingStatus(
768
680
  );
769
681
  };
770
682
 
771
- const refresh = (nextLoadingMessages?: string[]): void => {
772
- updateLoadingMessages(nextLoadingMessages);
773
- };
774
-
775
683
  const clearStatus = (): void => {
776
684
  if (cleared) return;
777
685
  cleared = true;
@@ -799,7 +707,6 @@ function setSlackThinkingStatus(
799
707
 
800
708
  return {
801
709
  updateLoadingMessages,
802
- refresh,
803
710
  clear: clearStatus,
804
711
  };
805
712
  }
@@ -935,9 +842,7 @@ function startTrustedContactApprovalNotifier(params: {
935
842
 
936
843
  // Only notify identity-known non-guardian contacts (trusted_contact and
937
844
  // unverified_contact) who have a resolvable guardian route.
938
- const isIdentityKnownNonGuardian =
939
- trustClass === "trusted_contact" || trustClass === "unverified_contact";
940
- if (!isIdentityKnownNonGuardian || !guardianExternalUserId) {
845
+ if (!isContactTrustClass(trustClass) || !guardianExternalUserId) {
941
846
  return () => {};
942
847
  }
943
848
 
@@ -28,6 +28,7 @@ import {
28
28
  findMessageBySourceId,
29
29
  recordInbound,
30
30
  } from "../../../persistence/delivery-crud.js";
31
+ import { enqueueLexicalIndexForMessage } from "../../../persistence/job-handlers/message-lexical.js";
31
32
  import { safeParseRecord } from "../../../util/json.js";
32
33
  import { getLogger } from "../../../util/logger.js";
33
34
 
@@ -100,7 +101,9 @@ export async function handleEditIntercept(
100
101
  conversationExternalId,
101
102
  sourceMessageId,
102
103
  );
103
- if (original) break;
104
+ if (original) {
105
+ break;
106
+ }
104
107
  if (attempt < EDIT_LOOKUP_RETRIES) {
105
108
  log.info(
106
109
  {
@@ -156,6 +159,11 @@ export async function handleEditIntercept(
156
159
  } else {
157
160
  updateMessageContent(original.messageId, newContent);
158
161
  }
162
+ // The edit changed searchable text (the no-op guard above already returned
163
+ // for identical content) and this path bypasses `onMessagePersisted`, so
164
+ // reindex the message into the lexical index — the idempotent upsert
165
+ // replaces the stale Qdrant point with the edited content.
166
+ enqueueLexicalIndexForMessage(original.messageId);
159
167
  log.info(
160
168
  { assistantId, sourceMessageId, messageId: original.messageId },
161
169
  "Updated message content from edited_message",
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Unit tests for `handleEscalationIntercept` guardian-principal resolution.
3
+ *
4
+ * A guardian binding whose gateway row carries no principal is UNRESOLVED, not
5
+ * present-but-empty: the intercept adopts the principal from the assistant's
6
+ * vellum anchor (via `resolveDecidableGuardianPrincipalId`), and when neither
7
+ * resolves it fails closed instead of creating an undecidable (principal-less)
8
+ * canonical request. The `""`-is-unresolved contract itself is pinned in
9
+ * `local-actor-identity.test.ts`.
10
+ */
11
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
12
+
13
+ mock.module("../../../util/logger.js", () => ({
14
+ getLogger: () =>
15
+ new Proxy({} as Record<string, unknown>, { get: () => () => {} }),
16
+ }));
17
+
18
+ let mockBindingPrincipalId: string | null = null;
19
+ let mockBindingPresent = true;
20
+ mock.module("../../channel-verification-service.js", () => ({
21
+ getGuardianBinding: async () =>
22
+ mockBindingPresent
23
+ ? {
24
+ guardianExternalUserId: "guardian-1",
25
+ guardianPrincipalId: mockBindingPrincipalId,
26
+ }
27
+ : null,
28
+ }));
29
+
30
+ // Faithful stand-in for the shared adopt/repair helper: binding principal
31
+ // when present, else the (test-controlled) vellum anchor principal.
32
+ let mockAnchorPrincipal: string | undefined;
33
+ mock.module("../../local-actor-identity.js", () => ({
34
+ resolveDecidableGuardianPrincipalId: async (
35
+ bindingPrincipalId: string | null,
36
+ ) => bindingPrincipalId || mockAnchorPrincipal,
37
+ }));
38
+
39
+ const createdRequests: Array<Record<string, unknown>> = [];
40
+ mock.module("../../../contacts/canonical-guardian-store.js", () => ({
41
+ createCanonicalGuardianRequest: (params: Record<string, unknown>) => {
42
+ createdRequests.push(params);
43
+ return { ...params, requestCode: "ABC123" };
44
+ },
45
+ }));
46
+
47
+ mock.module("../../../notifications/emit-signal.js", () => ({
48
+ emitNotificationSignal: async () => ({ deliveryResults: [] }),
49
+ }));
50
+
51
+ mock.module("../../../persistence/delivery-crud.js", () => ({
52
+ storePayload: () => {},
53
+ }));
54
+
55
+ const { handleEscalationIntercept } = await import("./escalation-intercept.js");
56
+ type EscalationInterceptParams = Parameters<
57
+ typeof handleEscalationIntercept
58
+ >[0];
59
+
60
+ function makeParams(
61
+ overrides: Partial<EscalationInterceptParams> = {},
62
+ ): EscalationInterceptParams {
63
+ return {
64
+ resolvedMember: {
65
+ contactId: "contact-1",
66
+ channelId: "channel-1",
67
+ status: "active",
68
+ policy: "escalate",
69
+ verifiedAt: null,
70
+ displayName: "Member",
71
+ },
72
+ canonicalAssistantId: "self",
73
+ sourceChannel: "telegram",
74
+ sourceInterface: "telegram",
75
+ conversationExternalId: "chat-1",
76
+ externalMessageId: "msg-1",
77
+ conversationId: "conv-1",
78
+ eventId: "evt-1",
79
+ content: "hello",
80
+ attachmentIds: undefined,
81
+ sourceMetadata: undefined,
82
+ actorDisplayName: "Member",
83
+ actorExternalId: "member-1",
84
+ actorUsername: "member_one",
85
+ replyCallbackUrl: "http://localhost/deliver",
86
+ canonicalSenderId: "member-1",
87
+ rawSenderId: "member-1",
88
+ ...overrides,
89
+ };
90
+ }
91
+
92
+ beforeEach(() => {
93
+ mockBindingPresent = true;
94
+ mockBindingPrincipalId = null;
95
+ mockAnchorPrincipal = undefined;
96
+ createdRequests.length = 0;
97
+ });
98
+
99
+ describe("handleEscalationIntercept — guardian principal resolution", () => {
100
+ test("binding with a principal creates the request with that principal", async () => {
101
+ mockBindingPrincipalId = "principal-1";
102
+
103
+ const response = await handleEscalationIntercept(makeParams());
104
+
105
+ expect(response).toMatchObject({ accepted: true, escalated: true });
106
+ expect(createdRequests).toHaveLength(1);
107
+ expect(createdRequests[0].guardianPrincipalId).toBe("principal-1");
108
+ });
109
+
110
+ test("null-principal binding adopts the vellum anchor principal (repair path)", async () => {
111
+ mockBindingPrincipalId = null;
112
+ mockAnchorPrincipal = "anchor-principal";
113
+
114
+ const response = await handleEscalationIntercept(makeParams());
115
+
116
+ expect(response).toMatchObject({ accepted: true, escalated: true });
117
+ expect(createdRequests).toHaveLength(1);
118
+ expect(createdRequests[0].guardianPrincipalId).toBe("anchor-principal");
119
+ });
120
+
121
+ test("unresolvable principal fails closed — no principal-less request is created", async () => {
122
+ mockBindingPrincipalId = null;
123
+ mockAnchorPrincipal = undefined;
124
+
125
+ const response = await handleEscalationIntercept(makeParams());
126
+
127
+ expect(response).toMatchObject({
128
+ accepted: true,
129
+ denied: true,
130
+ reason: "escalate_no_guardian",
131
+ });
132
+ expect(createdRequests).toHaveLength(0);
133
+ });
134
+
135
+ test("no binding at all still denies fail-closed", async () => {
136
+ mockBindingPresent = false;
137
+
138
+ const response = await handleEscalationIntercept(makeParams());
139
+
140
+ expect(response).toMatchObject({
141
+ accepted: true,
142
+ denied: true,
143
+ reason: "escalate_no_guardian",
144
+ });
145
+ expect(createdRequests).toHaveLength(0);
146
+ });
147
+
148
+ test("non-escalate member policy is a pass-through", async () => {
149
+ const params = makeParams();
150
+ const response = await handleEscalationIntercept(
151
+ makeParams({
152
+ resolvedMember: { ...params.resolvedMember!, policy: "allow" },
153
+ }),
154
+ );
155
+
156
+ expect(response).toBeNull();
157
+ });
158
+ });
@@ -13,6 +13,7 @@ import { emitNotificationSignal } from "../../../notifications/emit-signal.js";
13
13
  import { storePayload } from "../../../persistence/delivery-crud.js";
14
14
  import { getLogger } from "../../../util/logger.js";
15
15
  import { getGuardianBinding } from "../../channel-verification-service.js";
16
+ import { resolveDecidableGuardianPrincipalId } from "../../local-actor-identity.js";
16
17
  import type { VerdictMember } from "../../trust-verdict-consumer.js";
17
18
  import { GUARDIAN_APPROVAL_TTL_MS } from "../channel-route-shared.js";
18
19
 
@@ -90,6 +91,26 @@ export async function handleEscalationIntercept(
90
91
  };
91
92
  }
92
93
 
94
+ // A binding with no principal is unresolved, not empty: adopt the vellum
95
+ // anchor principal so the resulting request is decidable by the guardian.
96
+ // When neither resolves, fail closed — a principal-less tool_approval
97
+ // request can never be authorized by anyone (it would sit pending with
98
+ // dead Approve/Reject buttons until expiry).
99
+ const guardianPrincipalId = await resolveDecidableGuardianPrincipalId(
100
+ binding.guardianPrincipalId,
101
+ );
102
+ if (!guardianPrincipalId) {
103
+ log.warn(
104
+ { sourceChannel, channelId: resolvedMember.channelId },
105
+ "Ingress ACL: escalate policy but guardian principal unresolved, denying",
106
+ );
107
+ return {
108
+ accepted: true,
109
+ denied: true,
110
+ reason: "escalate_no_guardian",
111
+ };
112
+ }
113
+
93
114
  // Persist the raw payload so the decide handler can recover the original
94
115
  // message content when the escalation is approved.
95
116
  storePayload(eventId, {
@@ -115,7 +136,7 @@ export async function handleEscalationIntercept(
115
136
  conversationId,
116
137
  requesterExternalUserId: canonicalSenderId ?? rawSenderId ?? undefined,
117
138
  guardianExternalUserId: binding.guardianExternalUserId,
118
- guardianPrincipalId: binding.guardianPrincipalId,
139
+ guardianPrincipalId,
119
140
  toolName: "ingress_message",
120
141
  questionText: "Ingress policy requires guardian approval",
121
142
  expiresAt: Date.now() + GUARDIAN_APPROVAL_TTL_MS,
@@ -95,8 +95,10 @@ import { ROUTES as LLM_CALL_SITES_ROUTES } from "./llm-call-sites-routes.js";
95
95
  import { ROUTES as LOG_EXPORT_ROUTES } from "./log-export-routes.js";
96
96
  import { ROUTES as MCP_AUTH_ROUTES } from "./mcp-auth-routes.js";
97
97
  import { ROUTES as MEMORY_WORKER_ROUTES } from "./memory-worker-routes.js";
98
+ import { ROUTES as MESSAGES_LEXICAL_ROUTES } from "./messages-lexical-routes.js";
98
99
  import { ROUTES as MIGRATION_ROLLBACK_ROUTES } from "./migration-rollback-routes.js";
99
100
  import { ROUTES as MIGRATION_ROUTES } from "./migration-routes.js";
101
+ import { ROUTES as MONITORING_ROUTES } from "./monitoring-routes.js";
100
102
  import { ROUTES as NOTIFICATION_ROUTES } from "./notification-routes.js";
101
103
  import { ROUTES as OAUTH_APPS_ROUTES } from "./oauth-apps.js";
102
104
  import { ROUTES as OAUTH_COMMANDS_ROUTES } from "./oauth-commands-routes.js";
@@ -116,6 +118,7 @@ import { ROUTES as RENAME_CONVERSATION_ROUTES } from "./rename-conversation-rout
116
118
  import { ROUTES as RETROSPECTIVE_ROUTES } from "./retrospective-routes.js";
117
119
  import { ROUTES as SANITY_ROUTES } from "./sanity-routes.js";
118
120
  import { ROUTES as SCHEDULE_ROUTES } from "./schedule-routes.js";
121
+ import { ROUTES as SCHEDULE_WORKER_ROUTES } from "./schedule-worker-routes.js";
119
122
  import { ROUTES as SECRET_ROUTES } from "./secret-routes.js";
120
123
  import { ROUTES as SEQUENCE_ROUTES } from "./sequence-routes.js";
121
124
  import { ROUTES as SETTINGS_ROUTES } from "./settings-routes.js";
@@ -230,6 +233,7 @@ export const ROUTES: RouteDefinition[] = [
230
233
  ...MEMORY_V2_ROUTES,
231
234
  ...MEMORY_V3_ROUTES,
232
235
  ...MEMORY_WORKER_ROUTES,
236
+ ...MESSAGES_LEXICAL_ROUTES,
233
237
  ...MIGRATION_ROLLBACK_ROUTES,
234
238
  ...MIGRATION_ROUTES,
235
239
  ...NOTIFICATION_ROUTES,
@@ -247,8 +251,10 @@ export const ROUTES: RouteDefinition[] = [
247
251
  ...QUESTION_ROUTES,
248
252
  ...RECORDING_ROUTES,
249
253
  ...RENAME_CONVERSATION_ROUTES,
254
+ ...MONITORING_ROUTES,
250
255
  ...RETROSPECTIVE_ROUTES,
251
256
  ...SCHEDULE_ROUTES,
257
+ ...SCHEDULE_WORKER_ROUTES,
252
258
  ...SANITY_ROUTES,
253
259
  ...SECRET_ROUTES,
254
260
  ...SETTINGS_ROUTES,
@@ -10,6 +10,7 @@
10
10
 
11
11
  import { z } from "zod";
12
12
 
13
+ import { getIsPlatform } from "../../config/env-registry.js";
13
14
  import { getConfigReadOnly } from "../../config/loader.js";
14
15
  import { getDb } from "../../persistence/db-connection.js";
15
16
  import {
@@ -103,24 +104,29 @@ async function parseCustomProviderFields(
103
104
  );
104
105
  }
105
106
 
106
- // SSRF protection: reject private IPs, localhost, cloud metadata endpoints.
107
- const hostname = parsed.hostname;
108
- if (isPrivateOrLocalHost(hostname)) {
109
- throw new BadRequestError(
110
- `Invalid base_url: must not point to a private or local network address.`,
111
- );
112
- }
107
+ // SSRF protection: reject private IPs, localhost, cloud metadata
108
+ // endpoints but only for platform-hosted daemons where the container
109
+ // runs on Vellum infrastructure. Self-hosted daemons run on the user's
110
+ // own machine, so localhost/private addresses are the expected target
111
+ // (e.g. LM Studio, vLLM, text-generation-webui).
112
+ if (getIsPlatform()) {
113
+ const hostname = parsed.hostname;
114
+ if (isPrivateOrLocalHost(hostname)) {
115
+ throw new BadRequestError(
116
+ `Invalid base_url: must not point to a private or local network address.`,
117
+ );
118
+ }
113
119
 
114
- // DNS resolution check: hostname may resolve to a private IP.
115
- const resolved = await resolveRequestAddress(
116
- hostname,
117
- resolveHostAddresses,
118
- /* allowPrivateNetwork */ false,
119
- );
120
- if (resolved.blockedAddress) {
121
- throw new BadRequestError(
122
- `Invalid base_url: hostname resolves to a private network address.`,
120
+ const resolved = await resolveRequestAddress(
121
+ hostname,
122
+ resolveHostAddresses,
123
+ /* allowPrivateNetwork */ false,
123
124
  );
125
+ if (resolved.blockedAddress) {
126
+ throw new BadRequestError(
127
+ `Invalid base_url: hostname resolves to a private network address.`,
128
+ );
129
+ }
124
130
  }
125
131
 
126
132
  out.baseUrl = raw;
@@ -6,7 +6,6 @@
6
6
  */
7
7
 
8
8
  import {
9
- handleInternalConnectAction,
10
9
  handleInternalStatusCallback,
11
10
  handleInternalVoiceWebhook,
12
11
  } from "../../calls/twilio-routes.js";
@@ -42,18 +41,4 @@ export const ROUTES: RouteDefinition[] = [
42
41
  tags: ["internal"],
43
42
  handler: handleInternalStatusCallback,
44
43
  },
45
- {
46
- operationId: "internal_twilio_connect_action",
47
- endpoint: "internal/twilio/connect-action",
48
- method: "POST",
49
- policy: {
50
- requiredScopes: ["internal.write"],
51
- allowedPrincipalTypes: GATEWAY_PRINCIPALS,
52
- },
53
- summary: "Internal Twilio connect-action",
54
- description:
55
- "Gateway-to-runtime forwarding for ConversationRelay connect-action callback.",
56
- tags: ["internal"],
57
- handler: handleInternalConnectAction,
58
- },
59
44
  ];
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Messages lexical-index route — enqueues the resumable backfill that indexes
3
+ * existing messages into the Qdrant lexical collection.
4
+ *
5
+ * Deliberately NOT gated on `memory.v2.enabled`: the lexical index powers
6
+ * regular message-content search and is independent of the v2 concept-page
7
+ * machinery. The backfill runs off the event loop as a cursor-checkpointed
8
+ * background job. This route enqueues it on demand (operator or client); the
9
+ * one-time, checkpoint-guarded startup auto-enqueue
10
+ * (`maybeEnqueueLexicalBackfillOnUpgrade`) enqueues the same job once per
11
+ * instance on upgrade.
12
+ */
13
+
14
+ import { z } from "zod";
15
+
16
+ import { clearLexicalBackfillComplete } from "../../persistence/checkpoints.js";
17
+ import {
18
+ enqueueMemoryJob,
19
+ type MemoryJobType,
20
+ } from "../../persistence/jobs-store.js";
21
+ import { ACTOR_PRINCIPALS } from "../auth/route-policy.js";
22
+ import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
23
+
24
+ const BACKFILL_LEXICAL_INDEX_JOB: MemoryJobType = "backfill_lexical_index";
25
+
26
+ const MessagesLexicalBackfillParams = z
27
+ .object({
28
+ /**
29
+ * Reset the cursor and re-index every message from the beginning. Omit (or
30
+ * pass false) to resume from the last checkpoint — the common case for
31
+ * continuing an interrupted backfill.
32
+ */
33
+ force: z.boolean().optional(),
34
+ })
35
+ .strict();
36
+
37
+ export type MessagesLexicalBackfillResult = {
38
+ jobId: string;
39
+ };
40
+
41
+ async function handleBackfillLexicalIndex({
42
+ body = {},
43
+ }: RouteHandlerArgs): Promise<MessagesLexicalBackfillResult> {
44
+ const { force } = MessagesLexicalBackfillParams.parse(body);
45
+ if (force === true) {
46
+ // Clear the completion sentinel at enqueue time so `isLexicalBackfillComplete()`
47
+ // flips false immediately — the read paths fall back to SQLite FTS in the window
48
+ // between enqueue and the worker claiming the job, instead of serving from the
49
+ // stale/emptying `messages_lexical` collection the forced rebuild is about to
50
+ // reset. The handler clears it again when it runs (idempotent).
51
+ clearLexicalBackfillComplete();
52
+ }
53
+ const payload: Record<string, unknown> =
54
+ force === true ? { force: true } : {};
55
+ const jobId = enqueueMemoryJob(BACKFILL_LEXICAL_INDEX_JOB, payload);
56
+ return { jobId };
57
+ }
58
+
59
+ export const ROUTES: RouteDefinition[] = [
60
+ {
61
+ operationId: "messages_lexical_backfill",
62
+ method: "POST",
63
+ policy: {
64
+ requiredScopes: ["settings.write"],
65
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
66
+ },
67
+ endpoint: "messages/lexical/backfill",
68
+ handler: handleBackfillLexicalIndex,
69
+ summary: "Enqueue a resumable backfill of messages into the lexical index",
70
+ description:
71
+ "Enqueues the cursor-checkpointed backfill job that indexes existing messages into the Qdrant lexical (BM25-style) collection in batches. Resumable and idempotent — re-running continues from the last checkpoint. Pass `force: true` to reset the cursor and re-index from the beginning. The same backfill is also auto-enqueued once per instance on upgrade at assistant startup.",
72
+ tags: ["memory"],
73
+ requestBody: MessagesLexicalBackfillParams,
74
+ },
75
+ ];