@vellumai/assistant 0.10.4 → 0.10.5-dev.202607022248.91fa053

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 (864) 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/runtime/AGENTS.md +5 -4
  639. package/src/runtime/__tests__/agent-wake.test.ts +158 -1
  640. package/src/runtime/__tests__/channel-verification-service.test.ts +2 -2
  641. package/src/runtime/__tests__/trust-verdict-consumer.test.ts +37 -8
  642. package/src/runtime/access-request-helper.ts +154 -3
  643. package/src/runtime/actor-trust-resolver.ts +7 -21
  644. package/src/runtime/agent-wake.ts +41 -1
  645. package/src/runtime/assistant-event.ts +86 -12
  646. package/src/runtime/auth/__tests__/route-policy.test.ts +31 -0
  647. package/src/runtime/channel-approval-types.ts +52 -2
  648. package/src/runtime/channel-approvals.ts +23 -8
  649. package/src/runtime/channel-invite-transport.ts +2 -2
  650. package/src/runtime/channel-invite-transports/voice.ts +1 -1
  651. package/src/runtime/channel-readiness-service.ts +3 -5
  652. package/src/runtime/channel-retry-sweep.ts +18 -24
  653. package/src/runtime/channel-verification-service.ts +9 -11
  654. package/src/runtime/finalize-event-delivery.ts +30 -16
  655. package/src/runtime/guardian-action-service.ts +10 -11
  656. package/src/runtime/guardian-reply-router.ts +122 -21
  657. package/src/runtime/http-server.ts +44 -101
  658. package/src/runtime/introduction-policy.test.ts +214 -0
  659. package/src/runtime/introduction-policy.ts +284 -0
  660. package/src/runtime/invite-service.ts +104 -361
  661. package/src/runtime/local-actor-identity.test.ts +38 -0
  662. package/src/runtime/local-actor-identity.ts +14 -0
  663. package/src/runtime/middleware/__tests__/rate-limiter.test.ts +22 -0
  664. package/src/runtime/middleware/rate-limiter.ts +30 -0
  665. package/src/runtime/middleware/twilio-validation.ts +5 -7
  666. package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +28 -0
  667. package/src/runtime/migrations/origin-mode.ts +6 -6
  668. package/src/runtime/pre-first-message-gate.ts +1 -0
  669. package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +6 -35
  670. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +24 -3
  671. package/src/runtime/routes/__tests__/contact-routes.test.ts +80 -15
  672. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +7 -1
  673. package/src/runtime/routes/__tests__/global-search-routes.test.ts +0 -3
  674. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +142 -1
  675. package/src/runtime/routes/__tests__/invite-relay-routes.test.ts +119 -30
  676. package/src/runtime/routes/__tests__/migration-import-allowed-hosts-env.test.ts +70 -0
  677. package/src/runtime/routes/__tests__/monitoring-routes.test.ts +194 -0
  678. package/src/runtime/routes/__tests__/plugins-routes.test.ts +755 -29
  679. package/src/runtime/routes/__tests__/retrospective-routes.test.ts +4 -0
  680. package/src/runtime/routes/__tests__/schedule-routes-create.test.ts +70 -0
  681. package/src/runtime/routes/__tests__/schedule-worker-routes.test.ts +161 -0
  682. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +1 -1
  683. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +1 -1
  684. package/src/runtime/routes/acp-routes.ts +15 -3
  685. package/src/runtime/routes/app-management-routes.ts +4 -7
  686. package/src/runtime/routes/approval-routes.ts +4 -0
  687. package/src/runtime/routes/attachment-routes.ts +54 -3
  688. package/src/runtime/routes/avatar-routes.ts +0 -4
  689. package/src/runtime/routes/background-tool-routes.ts +34 -5
  690. package/src/runtime/routes/btw-routes.ts +32 -4
  691. package/src/runtime/routes/channel-route-shared.ts +18 -14
  692. package/src/runtime/routes/channel-verification-routes.ts +0 -3
  693. package/src/runtime/routes/contact-routes.ts +298 -117
  694. package/src/runtime/routes/conversation-list-routes.ts +6 -0
  695. package/src/runtime/routes/conversation-management-routes.ts +74 -37
  696. package/src/runtime/routes/conversation-query-routes.ts +5 -2
  697. package/src/runtime/routes/conversation-routes.ts +222 -82
  698. package/src/runtime/routes/conversations-import-routes.ts +8 -1
  699. package/src/runtime/routes/credential-prompt-routes.ts +20 -5
  700. package/src/runtime/routes/debug-routes.ts +1 -0
  701. package/src/runtime/routes/documents-routes.ts +5 -2
  702. package/src/runtime/routes/empty-state-greeting-cache.ts +37 -10
  703. package/src/runtime/routes/global-search-routes.ts +2 -1
  704. package/src/runtime/routes/guardian-approval-interception.ts +51 -0
  705. package/src/runtime/routes/home-feed-routes.ts +60 -1
  706. package/src/runtime/routes/identity-routes.ts +4 -87
  707. package/src/runtime/routes/inbound-message-handler.ts +82 -41
  708. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +430 -57
  709. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +302 -572
  710. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +76 -270
  711. package/src/runtime/routes/inbound-stages/background-dispatch.ts +21 -116
  712. package/src/runtime/routes/inbound-stages/edit-intercept.ts +9 -1
  713. package/src/runtime/routes/inbound-stages/escalation-intercept.test.ts +158 -0
  714. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +22 -1
  715. package/src/runtime/routes/index.ts +6 -0
  716. package/src/runtime/routes/inference-provider-connection-routes.ts +22 -16
  717. package/src/runtime/routes/internal-twilio-routes.ts +0 -15
  718. package/src/runtime/routes/messages-lexical-routes.ts +75 -0
  719. package/src/runtime/routes/migration-routes.ts +69 -6
  720. package/src/runtime/routes/monitoring-routes.ts +237 -0
  721. package/src/runtime/routes/plugins-routes.ts +329 -8
  722. package/src/runtime/routes/schedule-routes.ts +49 -8
  723. package/src/runtime/routes/schedule-worker-routes.ts +210 -0
  724. package/src/runtime/routes/secret-routes.ts +1 -1
  725. package/src/runtime/routes/surface-conversation-resolver.ts +1 -0
  726. package/src/runtime/services/__tests__/analyze-conversation.test.ts +54 -9
  727. package/src/runtime/services/__tests__/auto-analysis-enqueue.test.ts +30 -6
  728. package/src/runtime/services/__tests__/conversation-analyze-job.test.ts +43 -8
  729. package/src/runtime/services/__tests__/conversation-serializer.test.ts +20 -0
  730. package/src/runtime/services/analyze-conversation.ts +14 -4
  731. package/src/runtime/services/conversation-serializer.ts +5 -0
  732. package/src/runtime/slack-no-response.ts +47 -0
  733. package/src/runtime/slack-reply-session.test.ts +633 -0
  734. package/src/runtime/slack-reply-session.ts +382 -0
  735. package/src/runtime/slack-task-progress.ts +95 -0
  736. package/src/runtime/sync/resource-sync-events.ts +25 -0
  737. package/src/runtime/tool-grant-request-helper.ts +17 -1
  738. package/src/runtime/trust-class.test.ts +141 -0
  739. package/src/runtime/trust-class.ts +121 -0
  740. package/src/runtime/trust-verdict-consumer.ts +7 -6
  741. package/src/schedule/__tests__/run-script.test.ts +21 -0
  742. package/src/schedule/__tests__/worker-control.test.ts +241 -0
  743. package/src/schedule/run-script.ts +13 -6
  744. package/src/schedule/schedule-usage-store.ts +1 -0
  745. package/src/schedule/scheduler.ts +178 -127
  746. package/src/schedule/worker-control.ts +118 -0
  747. package/src/schedule/worker.ts +131 -0
  748. package/src/skills/__tests__/categories-cache.test.ts +38 -0
  749. package/src/skills/categories-cache.ts +40 -5
  750. package/src/skills/managed-store.ts +41 -6
  751. package/src/skills/validate-input.ts +47 -0
  752. package/src/stt/types.ts +5 -9
  753. package/src/subagent/manager.ts +267 -39
  754. package/src/subagent/types.ts +6 -2
  755. package/src/subagent/validate-allowlists.ts +65 -0
  756. package/src/telemetry/watchdog-direct-emit.test.ts +109 -0
  757. package/src/telemetry/watchdog-direct-emit.ts +89 -0
  758. package/src/tools/acp/list-agents.test.ts +0 -6
  759. package/src/tools/background-tool-registry.ts +61 -0
  760. package/src/tools/document/document-comment-tool.test.ts +4 -0
  761. package/src/tools/host-terminal/host-shell.test.ts +397 -0
  762. package/src/tools/host-terminal/host-shell.ts +203 -14
  763. package/src/tools/skills/find-similar-skills.test.ts +152 -1
  764. package/src/tools/skills/find-similar-skills.ts +30 -4
  765. package/src/tools/skills/load.ts +36 -0
  766. package/src/tools/skills/scaffold-managed.ts +66 -34
  767. package/src/tools/skills/skill-script-runner.ts +17 -0
  768. package/src/tools/skills/skill-tool-factory.ts +5 -1
  769. package/src/tools/terminal/safe-env.ts +3 -0
  770. package/src/tools/terminal/shell.test.ts +177 -0
  771. package/src/tools/terminal/shell.ts +98 -4
  772. package/src/tools/tool-approval-handler.ts +106 -29
  773. package/{node_modules/@vellumai/skill-host-contracts/src → src/tools}/tool-types.ts +16 -17
  774. package/src/tools/types.ts +29 -17
  775. package/src/tools/ui-surface/definitions.ts +3 -1
  776. package/src/tts/__tests__/provider-adapters.test.ts +37 -0
  777. package/src/tts/__tests__/provider-catalog.test.ts +21 -0
  778. package/src/tts/provider-catalog.ts +40 -9
  779. package/src/tts/providers/fish-audio-provider.ts +19 -10
  780. package/src/tts/types.ts +3 -4
  781. package/src/util/__tests__/process-tree.test.ts +10 -2
  782. package/src/util/__tests__/text-spacing.test.ts +53 -0
  783. package/src/util/cgroup-memory.ts +142 -0
  784. package/src/util/image-conversion.ts +281 -0
  785. package/src/util/phone.ts +1 -8
  786. package/src/util/platform.ts +33 -0
  787. package/src/util/process-tree.ts +10 -2
  788. package/src/util/text-spacing.ts +53 -0
  789. package/src/util/worker-process.ts +271 -0
  790. package/src/workflows/journal-store.ts +16 -1
  791. package/src/workflows/library.test.ts +35 -20
  792. package/src/workflows/library.ts +105 -66
  793. package/src/workspace/git-service.ts +1 -0
  794. package/src/workspace/migrations/011-backfill-installation-id.ts +83 -31
  795. package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +41 -22
  796. package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +1 -1
  797. package/src/workspace/migrations/118-seed-now-md.ts +64 -0
  798. package/src/workspace/migrations/119-strip-persisted-memory-v3-tuning-defaults.ts +169 -0
  799. package/src/workspace/migrations/120-revise-onboarding-threads.ts +47 -0
  800. package/src/workspace/migrations/121-seed-default-user-guardrails.ts +82 -0
  801. package/src/workspace/migrations/122-relocate-default-user-boundary.ts +111 -0
  802. package/src/workspace/migrations/123-swap-quality-profile-to-fable.ts +85 -0
  803. package/src/workspace/migrations/__tests__/119-strip-persisted-memory-v3-tuning-defaults.test.ts +181 -0
  804. package/src/workspace/migrations/registry.ts +12 -0
  805. package/drizzle/0000_dizzy_maggott.sql +0 -301
  806. package/drizzle/meta/0000_snapshot.json +0 -1933
  807. package/drizzle/meta/_journal.json +0 -13
  808. package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +0 -887
  809. package/node_modules/@vellumai/skill-host-contracts/bun.lock +0 -24
  810. package/node_modules/@vellumai/skill-host-contracts/package.json +0 -18
  811. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -97
  812. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +0 -1349
  813. package/node_modules/@vellumai/skill-host-contracts/src/index.ts +0 -6
  814. package/node_modules/@vellumai/skill-host-contracts/src/runtime-mode.ts +0 -11
  815. package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +0 -32
  816. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +0 -333
  817. package/node_modules/@vellumai/skill-host-contracts/tsconfig.json +0 -20
  818. package/node_modules/@vellumai/skill-host-contracts/tsconfig.test.json +0 -12
  819. package/src/__tests__/invite-redemption-service.test.ts +0 -1180
  820. package/src/__tests__/invite-service-ipc.test.ts +0 -350
  821. package/src/__tests__/job-handler-registry-guard.test.ts +0 -125
  822. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +0 -203
  823. package/src/__tests__/relay-server.test.ts +0 -6153
  824. package/src/__tests__/telephony-stt-routing.test.ts +0 -329
  825. package/src/__tests__/voice-invite-redemption.test.ts +0 -702
  826. package/src/calls/relay-server.ts +0 -2463
  827. package/src/calls/telephony-stt-routing.ts +0 -145
  828. package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +0 -128
  829. package/src/daemon/__tests__/daemon-skill-host.test.ts +0 -273
  830. package/src/daemon/daemon-skill-host.ts +0 -262
  831. package/src/daemon/message-types/meet.ts +0 -143
  832. package/src/daemon/shutdown-registry.ts +0 -40
  833. package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -253
  834. package/src/ipc/__tests__/skill-server.test.ts +0 -182
  835. package/src/ipc/skill-ipc-types.ts +0 -54
  836. package/src/ipc/skill-routes/__tests__/config.test.ts +0 -146
  837. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +0 -448
  838. package/src/ipc/skill-routes/__tests__/identity.test.ts +0 -62
  839. package/src/ipc/skill-routes/__tests__/log.test.ts +0 -133
  840. package/src/ipc/skill-routes/__tests__/memory.test.ts +0 -203
  841. package/src/ipc/skill-routes/__tests__/platform.test.ts +0 -111
  842. package/src/ipc/skill-routes/__tests__/providers.test.ts +0 -265
  843. package/src/ipc/skill-routes/__tests__/registries.test.ts +0 -400
  844. package/src/ipc/skill-routes/config.ts +0 -47
  845. package/src/ipc/skill-routes/events.ts +0 -147
  846. package/src/ipc/skill-routes/identity.ts +0 -21
  847. package/src/ipc/skill-routes/index.ts +0 -37
  848. package/src/ipc/skill-routes/log.ts +0 -40
  849. package/src/ipc/skill-routes/memory.ts +0 -92
  850. package/src/ipc/skill-routes/platform.ts +0 -39
  851. package/src/ipc/skill-routes/providers.ts +0 -162
  852. package/src/ipc/skill-routes/registries.ts +0 -338
  853. package/src/ipc/skill-server.ts +0 -831
  854. package/src/ipc/skill-socket-path.ts +0 -20
  855. package/src/jobs/register-job-handlers.ts +0 -74
  856. package/src/persistence/invite-store.ts +0 -481
  857. package/src/plugins/job-handler-registry.ts +0 -94
  858. package/src/providers/cache-control.ts +0 -26
  859. package/src/runtime/__tests__/runtime-mode.test.ts +0 -62
  860. package/src/runtime/invite-redemption-service.ts +0 -828
  861. package/src/runtime/invite-redemption-templates.ts +0 -46
  862. package/src/runtime/runtime-mode.ts +0 -40
  863. package/src/runtime/slack-dm-text-delivery.ts +0 -177
  864. package/src/util/voice-code.ts +0 -31
@@ -17,68 +17,6 @@ import type {
17
17
  TelephonySttMode,
18
18
  } from "../../stt/types.js";
19
19
 
20
- // ---------------------------------------------------------------------------
21
- // Telephony routing metadata
22
- // ---------------------------------------------------------------------------
23
-
24
- /**
25
- * Strategy kind for telephony call setup.
26
- *
27
- * Determines how the telephony routing resolver (`telephony-stt-routing.ts`)
28
- * wires the STT provider into a Twilio call:
29
- *
30
- * - `"conversation-relay-native"` — the provider is natively supported by
31
- * Twilio ConversationRelay. TwiML includes `transcriptionProvider` /
32
- * `speechModel` attributes and Twilio handles audio ingestion.
33
- * - `"media-stream-custom"` — the provider is not natively supported by
34
- * Twilio. A `<Stream>` media-stream is opened and the daemon transcribes
35
- * audio server-side via the provider's batch API.
36
- */
37
- type TelephonyStrategyKind =
38
- | "conversation-relay-native"
39
- | "media-stream-custom";
40
-
41
- /**
42
- * Twilio-native ConversationRelay provider name.
43
- *
44
- * These are the values Twilio accepts in the `transcriptionProvider` TwiML
45
- * attribute on `<ConversationRelay>`.
46
- */
47
- export type TwilioNativeProvider = "Deepgram" | "Google";
48
-
49
- /**
50
- * Twilio-native mapping details for providers routed through
51
- * ConversationRelay. Only present when `strategyKind` is
52
- * `"conversation-relay-native"`.
53
- */
54
- interface TwilioNativeMapping {
55
- /** Twilio-native provider name for the TwiML `transcriptionProvider` attribute. */
56
- readonly provider: TwilioNativeProvider;
57
- /**
58
- * Default ASR speech model identifier, or `undefined` to use the
59
- * provider's default model. Individual providers override as needed
60
- * (e.g. Deepgram defaults to `"nova-3"`).
61
- */
62
- readonly defaultSpeechModel: string | undefined;
63
- }
64
-
65
- /**
66
- * Telephony routing metadata — the single source of truth for how a
67
- * provider is wired into Twilio call setup.
68
- *
69
- * The telephony routing resolver reads these fields from the catalog
70
- * instead of maintaining its own hardcoded maps.
71
- */
72
- interface TelephonyRouting {
73
- /** Which Twilio call-setup strategy this provider uses. */
74
- readonly strategyKind: TelephonyStrategyKind;
75
- /**
76
- * Twilio-native mapping details. Present when `strategyKind` is
77
- * `"conversation-relay-native"`, absent for `"media-stream-custom"`.
78
- */
79
- readonly twilioNativeMapping?: TwilioNativeMapping;
80
- }
81
-
82
20
  // ---------------------------------------------------------------------------
83
21
  // Client display metadata
84
22
  // ---------------------------------------------------------------------------
@@ -161,13 +99,6 @@ interface SttProviderEntry {
161
99
  */
162
100
  readonly supportsDiarization: boolean;
163
101
 
164
- /**
165
- * Telephony routing metadata — describes how this provider is wired
166
- * into Twilio call setup. This is the single source of truth for
167
- * strategy selection and Twilio-native mapping details.
168
- */
169
- readonly telephonyRouting: TelephonyRouting;
170
-
171
102
  /** Guide for obtaining API credentials from this provider. */
172
103
  readonly credentialsGuide?: SttCredentialsGuide;
173
104
  }
@@ -206,13 +137,6 @@ const CATALOG: ReadonlyMap<SttProviderId, SttProviderEntry> = new Map<
206
137
  telephonyMode: "realtime-ws",
207
138
  conversationStreamingMode: "realtime-ws",
208
139
  supportsDiarization: true,
209
- telephonyRouting: {
210
- strategyKind: "conversation-relay-native",
211
- twilioNativeMapping: {
212
- provider: "Deepgram",
213
- defaultSpeechModel: "nova-3",
214
- },
215
- },
216
140
  credentialsGuide: {
217
141
  description:
218
142
  "Sign in to the Deepgram console, navigate to API Keys, and create a new key.",
@@ -239,13 +163,6 @@ const CATALOG: ReadonlyMap<SttProviderId, SttProviderEntry> = new Map<
239
163
  telephonyMode: "batch-only",
240
164
  conversationStreamingMode: "realtime-ws",
241
165
  supportsDiarization: false,
242
- telephonyRouting: {
243
- strategyKind: "conversation-relay-native",
244
- twilioNativeMapping: {
245
- provider: "Google",
246
- defaultSpeechModel: undefined,
247
- },
248
- },
249
166
  credentialsGuide: {
250
167
  description:
251
168
  "Visit Google AI Studio, sign in with your Google account, and create an API key.",
@@ -271,9 +188,6 @@ const CATALOG: ReadonlyMap<SttProviderId, SttProviderEntry> = new Map<
271
188
  telephonyMode: "batch-only",
272
189
  conversationStreamingMode: "incremental-batch",
273
190
  supportsDiarization: false,
274
- telephonyRouting: {
275
- strategyKind: "media-stream-custom",
276
- },
277
191
  credentialsGuide: {
278
192
  description:
279
193
  "Log in to the OpenAI platform, go to API Keys, and generate a new secret key.",
@@ -299,9 +213,6 @@ const CATALOG: ReadonlyMap<SttProviderId, SttProviderEntry> = new Map<
299
213
  telephonyMode: "batch-only",
300
214
  conversationStreamingMode: "realtime-ws",
301
215
  supportsDiarization: true,
302
- telephonyRouting: {
303
- strategyKind: "media-stream-custom",
304
- },
305
216
  credentialsGuide: {
306
217
  description:
307
218
  "Sign in to the xAI console, navigate to API Keys, and create a new key.",
@@ -260,6 +260,17 @@ export interface ResolveStreamingTranscriberOptions {
260
260
  * See {@link DiarizePreference} for semantics.
261
261
  */
262
262
  diarize?: DiarizePreference;
263
+ /**
264
+ * Emit `final` events only at utterance boundaries. Supported only by
265
+ * providers whose catalog `telephonyMode` is `"realtime-ws"` (Deepgram,
266
+ * where it also enables `utterance_end_ms` endpointing). All other
267
+ * providers resolve to `null` so the caller falls back to per-turn
268
+ * batch transcription — e.g. openai-whisper fires `final` only from
269
+ * `stop()` (end-of-stream, not end-of-utterance) and xAI emits a
270
+ * `final` per committed segment. Used by telephony call ingestion.
271
+ * Default: false.
272
+ */
273
+ utteranceBoundaryFinals?: boolean;
263
274
  }
264
275
 
265
276
  /**
@@ -277,6 +288,8 @@ export interface ResolveStreamingTranscriberOptions {
277
288
  * - No credentials are configured for the resolved provider.
278
289
  * - No streaming adapter exists for the configured provider.
279
290
  * - `diarize` is `"required"` but the configured provider cannot diarize.
291
+ * - `utteranceBoundaryFinals` is set but the configured provider's catalog
292
+ * `telephonyMode` is not `"realtime-ws"`.
280
293
  */
281
294
  export async function resolveStreamingTranscriber(
282
295
  options: ResolveStreamingTranscriberOptions = {},
@@ -298,6 +311,26 @@ export async function resolveStreamingTranscriber(
298
311
  return null;
299
312
  }
300
313
 
314
+ // Boundary-requiring callers (telephony) can only stream on providers
315
+ // whose catalog telephonyMode is "realtime-ws" (Deepgram gates finals on
316
+ // utterance boundaries). Everything else fires `final` either only from
317
+ // stop() — end-of-stream, not end-of-utterance (openai-whisper) — or per
318
+ // committed segment (xAI), so streaming would yield no replies until
319
+ // hangup, or mid-sentence replies. Resolve to null so the caller falls
320
+ // back to per-turn batch transcription.
321
+ if (options.utteranceBoundaryFinals) {
322
+ const telephonyMode = getProviderEntry(
323
+ provider as SttProviderId,
324
+ )?.telephonyMode;
325
+ if (telephonyMode !== "realtime-ws") {
326
+ log.warn(
327
+ { providerId: provider, telephonyMode },
328
+ "utterance-boundary finals requested but the configured STT provider has no realtime telephony streaming — falling back to batch transcription",
329
+ );
330
+ return null;
331
+ }
332
+ }
333
+
301
334
  // Resolve diarization capability against the catalog. For `"required"`
302
335
  // callers, bail early (with a warning) when the configured provider can't
303
336
  // diarize so the caller can surface a clear error to the user.
@@ -323,9 +356,18 @@ export async function resolveStreamingTranscriber(
323
356
  return createStreamingTranscriber(apiKey, provider as SttProviderId, {
324
357
  sampleRate: options.sampleRate,
325
358
  diarize: enableDiarization,
359
+ utteranceBoundaryFinals: options.utteranceBoundaryFinals ?? false,
326
360
  });
327
361
  }
328
362
 
363
+ /**
364
+ * Deepgram `utterance_end_ms` used when utterance-boundary finals are
365
+ * requested. Deepgram requires >= 1000 ms; this is the pause length after
366
+ * which an `UtteranceEnd` frame confirms the utterance is complete even
367
+ * when `speech_final` endpointing never fired (e.g. background noise).
368
+ */
369
+ const UTTERANCE_BOUNDARY_END_MS = 1_000;
370
+
329
371
  /**
330
372
  * Options forwarded to individual streaming adapter constructors.
331
373
  */
@@ -338,6 +380,13 @@ interface CreateStreamingTranscriberOptions {
338
380
  * support.
339
381
  */
340
382
  diarize?: boolean;
383
+ /**
384
+ * Whether `final` events should be gated on utterance boundaries.
385
+ * Only forwarded to Deepgram; the resolver never sets this for
386
+ * providers without realtime telephony streaming (they resolve to
387
+ * `null` instead).
388
+ */
389
+ utteranceBoundaryFinals?: boolean;
341
390
  }
342
391
 
343
392
  /**
@@ -361,6 +410,12 @@ async function createStreamingTranscriber(
361
410
  return new DeepgramRealtimeTranscriber(apiKey, {
362
411
  sampleRate: options.sampleRate,
363
412
  ...(options.diarize ? { diarize: true } : {}),
413
+ ...(options.utteranceBoundaryFinals
414
+ ? {
415
+ utteranceBoundaryFinals: true,
416
+ utteranceEndMs: UTTERANCE_BOUNDARY_END_MS,
417
+ }
418
+ : {}),
364
419
  });
365
420
  }
366
421
  case "google-gemini": {
@@ -0,0 +1,50 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import { createToolProgressEmitter } from "./tool-progress-events.js";
4
+ import type { ProviderEvent } from "./types.js";
5
+
6
+ describe("createToolProgressEmitter", () => {
7
+ test("flushes the latest throttled argument progress after activity pauses", async () => {
8
+ const events: ProviderEvent[] = [];
9
+ const progress = createToolProgressEmitter((event) => events.push(event));
10
+
11
+ progress.emitInputJsonDelta("call-1", "app_create", '{"a":1}');
12
+ progress.emitInputJsonDelta("call-1", "app_create", '{"a":12}');
13
+
14
+ expect(events).toEqual([
15
+ {
16
+ type: "tool_use_preview_start",
17
+ toolUseId: "call-1",
18
+ toolName: "app_create",
19
+ },
20
+ {
21
+ type: "input_json_delta",
22
+ toolUseId: "call-1",
23
+ toolName: "app_create",
24
+ accumulatedJson: '{"a":1}',
25
+ },
26
+ ]);
27
+
28
+ await Bun.sleep(180);
29
+
30
+ expect(events).toEqual([
31
+ {
32
+ type: "tool_use_preview_start",
33
+ toolUseId: "call-1",
34
+ toolName: "app_create",
35
+ },
36
+ {
37
+ type: "input_json_delta",
38
+ toolUseId: "call-1",
39
+ toolName: "app_create",
40
+ accumulatedJson: '{"a":1}',
41
+ },
42
+ {
43
+ type: "input_json_delta",
44
+ toolUseId: "call-1",
45
+ toolName: "app_create",
46
+ accumulatedJson: '{"a":12}',
47
+ },
48
+ ]);
49
+ });
50
+ });
@@ -0,0 +1,99 @@
1
+ import type { ProviderEvent } from "./types.js";
2
+
3
+ const INPUT_JSON_DELTA_EMIT_INTERVAL_MS = 150;
4
+
5
+ export function createToolProgressEmitter(
6
+ onEvent: ((event: ProviderEvent) => void) | undefined,
7
+ ): {
8
+ emitPreviewStart: (toolUseId: string, toolName: string) => void;
9
+ emitInputJsonDelta: (
10
+ toolUseId: string,
11
+ toolName: string,
12
+ accumulatedJson: string,
13
+ opts?: { force?: boolean },
14
+ ) => void;
15
+ } {
16
+ const previewedToolUseIds = new Set<string>();
17
+ const lastInputEmitByToolUseId = new Map<
18
+ string,
19
+ { emittedAt: number; accumulatedJson: string }
20
+ >();
21
+ const pendingInputEmitByToolUseId = new Map<
22
+ string,
23
+ {
24
+ timeout: ReturnType<typeof setTimeout>;
25
+ toolName: string;
26
+ accumulatedJson: string;
27
+ }
28
+ >();
29
+
30
+ const emitPreviewStart = (toolUseId: string, toolName: string): void => {
31
+ if (!onEvent || !toolUseId || !toolName) return;
32
+ if (previewedToolUseIds.has(toolUseId)) return;
33
+ previewedToolUseIds.add(toolUseId);
34
+ onEvent({ type: "tool_use_preview_start", toolUseId, toolName });
35
+ };
36
+
37
+ const emitInputJsonDelta = (
38
+ toolUseId: string,
39
+ toolName: string,
40
+ accumulatedJson: string,
41
+ opts?: { force?: boolean },
42
+ ): void => {
43
+ if (!onEvent || !toolUseId || !toolName || !accumulatedJson) return;
44
+ emitPreviewStart(toolUseId, toolName);
45
+
46
+ const last = lastInputEmitByToolUseId.get(toolUseId);
47
+ if (last?.accumulatedJson === accumulatedJson) return;
48
+
49
+ const now = Date.now();
50
+ if (
51
+ !opts?.force &&
52
+ last &&
53
+ now - last.emittedAt < INPUT_JSON_DELTA_EMIT_INTERVAL_MS
54
+ ) {
55
+ const pending = pendingInputEmitByToolUseId.get(toolUseId);
56
+ if (pending) {
57
+ pending.toolName = toolName;
58
+ pending.accumulatedJson = accumulatedJson;
59
+ return;
60
+ }
61
+ const delay = INPUT_JSON_DELTA_EMIT_INTERVAL_MS - (now - last.emittedAt);
62
+ const timeout = setTimeout(() => {
63
+ const latest = pendingInputEmitByToolUseId.get(toolUseId);
64
+ if (!latest) return;
65
+ pendingInputEmitByToolUseId.delete(toolUseId);
66
+ lastInputEmitByToolUseId.set(toolUseId, {
67
+ emittedAt: Date.now(),
68
+ accumulatedJson: latest.accumulatedJson,
69
+ });
70
+ onEvent({
71
+ type: "input_json_delta",
72
+ toolName: latest.toolName,
73
+ toolUseId,
74
+ accumulatedJson: latest.accumulatedJson,
75
+ });
76
+ }, delay);
77
+ timeout.unref?.();
78
+ pendingInputEmitByToolUseId.set(toolUseId, {
79
+ timeout,
80
+ toolName,
81
+ accumulatedJson,
82
+ });
83
+ return;
84
+ }
85
+
86
+ const pending = pendingInputEmitByToolUseId.get(toolUseId);
87
+ if (pending) {
88
+ clearTimeout(pending.timeout);
89
+ pendingInputEmitByToolUseId.delete(toolUseId);
90
+ }
91
+ lastInputEmitByToolUseId.set(toolUseId, {
92
+ emittedAt: now,
93
+ accumulatedJson,
94
+ });
95
+ onEvent({ type: "input_json_delta", toolName, toolUseId, accumulatedJson });
96
+ };
97
+
98
+ return { emitPreviewStart, emitInputJsonDelta };
99
+ }
@@ -1,4 +1,4 @@
1
- import type { ToolDefinition } from "@vellumai/skill-host-contracts";
1
+ import type { ToolDefinition } from "../tools/tool-types.js";
2
2
  export type { ToolDefinition };
3
3
 
4
4
  import type { LLMCallSite } from "../config/schemas/llm.js";
@@ -163,15 +163,16 @@ Verification SESSION state (pending sessions, codes, resend, rate-limit) is assi
163
163
 
164
164
  The verified outcome is written in-process by the gateway: the HTTP guardian-attest handler calls `ContactStore.markChannelVerified` directly (verifiedVia "manual"), and the inbound code-match path (`gateway/src/verification/text-verification.ts`) writes via `upsertVerifiedContactChannel` / `createGuardianBinding` (verifiedVia "challenge"). The revoke/downgrade outcome is relayed from the daemon via `ipcCallPersistent("mark_channel_revoked", …)` to `ContactStore.markChannelRevoked`.
165
165
 
166
- The `mark_channel_verified` IPC method exists as the daemon/CLI relay surface (symmetric with `mark_channel_revoked`) but has no caller: the trusted-contact CLI path sends codes only, and the outcome arrives via the inbound code-match path.
167
-
168
166
  ## Rate Limiting & Diagnostics
169
167
 
170
- All `/v1/*` endpoints share a per-client-IP sliding-window rate limiter (`middleware/rate-limiter.ts`):
168
+ Most `/v1/*` endpoints share a per-client-IP sliding-window rate limiter (`middleware/rate-limiter.ts`):
171
169
 
172
- - **Authenticated**: 300 requests/minute
170
+ - **Authenticated (loopback)**: 1200 requests/minute — desktop app, CLI, anything on the daemon's own host (`127.0.0.0/8`, `::1`). A cold sidebar load at thousands of conversations legitimately bursts far beyond the remote budget.
171
+ - **Authenticated (remote)**: 300 requests/minute — proxied non-loopback clients, keyed by the forwarded client IP.
173
172
  - **Unauthenticated**: 20 requests/minute
174
173
 
174
+ **Exempt endpoints** (`isRateLimitExemptEndpoint`): the SSE stream (`events`) and liveness/readiness probes (`health`, `healthz`, `readyz`) bypass the per-minute limiter entirely. The stream is one long-lived connection, not a burst of requests, and 429-ing it drops the stream — which drives a client reconnect + full re-bootstrap loop that generates far more load than the limiter saves. Liveness probes must always answer or the client treats the assistant as down and reconnects harder. The events route still enforces auth downstream, and stream memory is bounded by SSE backpressure shedding + subscriber caps.
175
+
175
176
  When the limit is exceeded, the limiter returns 429 and logs a structured warning (module: `rate-limiter`) with the denied endpoint and a breakdown of which endpoints consumed the budget in the current window. This makes it easy to identify whether the cause is rapid conversation switching, polling, or unexpected request volume.
176
177
 
177
178
  Logs rotate daily into `$VELLUM_WORKSPACE_DIR/data/logs/assistant-YYYY-MM-DD.log` (or into the directory configured via `logFile.dir`). To watch rate limit events in real time:
@@ -87,6 +87,13 @@ interface WakeConversationProbe {
87
87
  * persistent `setTrustContext`) and restores the prior value in its finally.
88
88
  */
89
89
  turnTrustContextSets: Array<{ ctx: unknown; order: number }>;
90
+ /**
91
+ * `setTrustContext` writes to the persistent `conversation.trustContext`,
92
+ * in order. A trust-carrying wake's resolver leaves its trust here; the
93
+ * wake must put the prior value back so it doesn't linger for a later
94
+ * no-trust wake.
95
+ */
96
+ trustContextSets: unknown[];
90
97
  /**
91
98
  * Every assignment to `conversation.wakePersonaOverride`, in order. A
92
99
  * wake that applies an override records `[override, undefined]` — the
@@ -340,6 +347,10 @@ import type {
340
347
  AgentLoopRunResult,
341
348
  } from "../../agent/loop.js";
342
349
  import type { Conversation } from "../../daemon/conversation.js";
350
+ import {
351
+ deleteConversation,
352
+ setConversation,
353
+ } from "../../daemon/conversation-registry.js";
343
354
  import { ContextOverflowError, type Message } from "../../providers/types.js";
344
355
  import {
345
356
  __resetWakeChainForTests,
@@ -387,6 +398,8 @@ function makeWakeConversation(options: {
387
398
  * (always under the mocked 200k window).
388
399
  */
389
400
  estimatedInputTokens?: number;
401
+ /** Seed for the conversation's resting `trustContext`. */
402
+ initialTrustContext?: unknown;
390
403
  }): WakeConversation {
391
404
  const conversationId = options.conversationId ?? "conv-test";
392
405
  const probe: WakeConversationProbe = {
@@ -401,6 +414,7 @@ function makeWakeConversation(options: {
401
414
  processingDuringDrain: [],
402
415
  allowedToolSnapshots: [],
403
416
  turnTrustContextSets: [],
417
+ trustContextSets: [],
404
418
  personaOverrideSets: [],
405
419
  persistedAtEachEmit: [],
406
420
  maybeCompactOrders: [],
@@ -413,6 +427,7 @@ function makeWakeConversation(options: {
413
427
  let activeAllowedTools = options.initialAllowedTools;
414
428
  let wakePersonaOverride: unknown;
415
429
  let currentTurnTrustContext: unknown;
430
+ let persistentTrustContext: unknown = options.initialTrustContext;
416
431
  const snapshotAllowedTools = (): string[] | undefined =>
417
432
  activeAllowedTools ? [...activeAllowedTools].sort() : undefined;
418
433
 
@@ -526,7 +541,14 @@ function makeWakeConversation(options: {
526
541
  },
527
542
  getTurnChannelContext: () => null,
528
543
  getTurnInterfaceContext: () => null,
529
- trustContext: undefined,
544
+ get trustContext() {
545
+ return persistentTrustContext;
546
+ },
547
+ // Mirrors Conversation.setTrustContext (coerces null → undefined).
548
+ setTrustContext(ctx: unknown) {
549
+ persistentTrustContext = ctx ?? undefined;
550
+ probe.trustContextSets.push(ctx);
551
+ },
530
552
  buildCurrentSystemPrompt: () => "mock-system-prompt",
531
553
  modelOverride: undefined,
532
554
  ...(drainQueue ? { drainQueue } : {}),
@@ -1535,6 +1557,141 @@ describe("wakeAgentForOpportunity", () => {
1535
1557
  expect(conversation.currentTurnTrustContext).toBeUndefined();
1536
1558
  });
1537
1559
 
1560
+ // ── Persistent-trust restore ────────────────────────────────────────
1561
+ // The resolver leaves the wake's trust on the conversation. The wake must
1562
+ // put the prior resting value back, or a later no-trust wake inherits it
1563
+ // through tool setup's `currentTurnTrustContext ?? trustContext` fallback.
1564
+
1565
+ const GUARDIAN_TRUST = {
1566
+ sourceChannel: "vellum",
1567
+ trustClass: "guardian",
1568
+ } as const;
1569
+
1570
+ // The wake reads the prior trust from the live registry, so a test that
1571
+ // wants to exercise the restore registers its double there and simulates
1572
+ // the resolver's write by setting the trust in resolveTarget.
1573
+ const withRegisteredConversation = async (
1574
+ conversation: WakeConversation,
1575
+ run: () => Promise<unknown>,
1576
+ ): Promise<void> => {
1577
+ setConversation(conversation.conversationId, conversation as Conversation);
1578
+ try {
1579
+ await run();
1580
+ } finally {
1581
+ deleteConversation(conversation.conversationId);
1582
+ }
1583
+ };
1584
+
1585
+ test("restores the conversation's prior trust once the wake ends", async () => {
1586
+ const priorTrust = {
1587
+ sourceChannel: "slack",
1588
+ trustClass: "trusted_contact",
1589
+ } as const;
1590
+ const conversation = makeWakeConversation({
1591
+ conversationId: "conv-trust-restore",
1592
+ initialTrustContext: priorTrust,
1593
+ });
1594
+
1595
+ await withRegisteredConversation(conversation, () =>
1596
+ wakeAgentForOpportunity(
1597
+ {
1598
+ conversationId: "conv-trust-restore",
1599
+ hint: "x",
1600
+ source: "t",
1601
+ trustContext: GUARDIAN_TRUST,
1602
+ },
1603
+ {
1604
+ resolveTarget: async () => {
1605
+ conversation.setTrustContext(GUARDIAN_TRUST);
1606
+ return conversation;
1607
+ },
1608
+ },
1609
+ ),
1610
+ );
1611
+
1612
+ // Resolver installs guardian, wake restores the prior value.
1613
+ expect(conversation.trustContextSets).toEqual([GUARDIAN_TRUST, priorTrust]);
1614
+ expect(conversation.trustContext).toEqual(priorTrust);
1615
+ });
1616
+
1617
+ test("restores the prior trust even when the agent loop throws", async () => {
1618
+ const conversation = makeWakeConversation({
1619
+ conversationId: "conv-trust-restore-throw",
1620
+ runImpl: async () => {
1621
+ throw new Error("boom");
1622
+ },
1623
+ });
1624
+
1625
+ await withRegisteredConversation(conversation, () =>
1626
+ wakeAgentForOpportunity(
1627
+ {
1628
+ conversationId: "conv-trust-restore-throw",
1629
+ hint: "x",
1630
+ source: "t",
1631
+ trustContext: GUARDIAN_TRUST,
1632
+ },
1633
+ {
1634
+ resolveTarget: async () => {
1635
+ conversation.setTrustContext(GUARDIAN_TRUST);
1636
+ return conversation;
1637
+ },
1638
+ },
1639
+ ),
1640
+ );
1641
+
1642
+ // Nothing was resting before the wake, so it goes back to unset.
1643
+ expect(conversation.trustContext).toBeUndefined();
1644
+ });
1645
+
1646
+ test("leaves a trust that was re-set mid-run alone (identity guard)", async () => {
1647
+ const replaced = {
1648
+ sourceChannel: "vellum",
1649
+ trustClass: "unknown",
1650
+ } as const;
1651
+ const conversation = makeWakeConversation({
1652
+ conversationId: "conv-trust-guard",
1653
+ runImpl: async (input) => {
1654
+ conversation.setTrustContext(replaced);
1655
+ return runResult(input);
1656
+ },
1657
+ });
1658
+
1659
+ await withRegisteredConversation(conversation, () =>
1660
+ wakeAgentForOpportunity(
1661
+ {
1662
+ conversationId: "conv-trust-guard",
1663
+ hint: "x",
1664
+ source: "t",
1665
+ trustContext: GUARDIAN_TRUST,
1666
+ },
1667
+ {
1668
+ resolveTarget: async () => {
1669
+ conversation.setTrustContext(GUARDIAN_TRUST);
1670
+ return conversation;
1671
+ },
1672
+ },
1673
+ ),
1674
+ );
1675
+
1676
+ // The wake sees a different reference than it installed, so it doesn't
1677
+ // restore: two writes (resolver install, mid-run replacement), no third.
1678
+ expect(conversation.trustContext).toEqual(replaced);
1679
+ expect(conversation.trustContextSets).toHaveLength(2);
1680
+ });
1681
+
1682
+ test("never touches the persistent trust when the wake carries none", async () => {
1683
+ const conversation = makeWakeConversation({
1684
+ conversationId: "conv-trust-none",
1685
+ });
1686
+
1687
+ await wakeAgentForOpportunity(
1688
+ { conversationId: "conv-trust-none", hint: "x", source: "t" },
1689
+ { resolveTarget: async () => conversation },
1690
+ );
1691
+
1692
+ expect(conversation.trustContextSets).toHaveLength(0);
1693
+ });
1694
+
1538
1695
  test("two concurrent wakes on the same conversation are serialized", async () => {
1539
1696
  // Build a target whose agentLoop.run resolves only when we signal.
1540
1697
  const gate1 = Promise.withResolvers<void>();
@@ -73,7 +73,7 @@ describe("getGuardianBinding", () => {
73
73
  expect(binding?.verifiedVia).toBe("verified");
74
74
  });
75
75
 
76
- test("falls back to empty strings for absent optional delivery fields", async () => {
76
+ test("a missing principal surfaces as null (unresolved), never an empty string", async () => {
77
77
  mockGuardianList = [
78
78
  {
79
79
  channelType: "telegram",
@@ -85,7 +85,7 @@ describe("getGuardianBinding", () => {
85
85
 
86
86
  const binding = await getGuardianBinding("asst-1", "telegram");
87
87
 
88
- expect(binding?.guardianPrincipalId).toBe("");
88
+ expect(binding?.guardianPrincipalId).toBeNull();
89
89
  expect(binding?.guardianDeliveryChatId).toBe("");
90
90
  expect(binding?.verifiedAt).toBe(0);
91
91
  });