@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
@@ -5,11 +5,15 @@ import {
5
5
  getCanonicalGuardianRequest,
6
6
  updateCanonicalGuardianRequest,
7
7
  } from "../contacts/canonical-guardian-store.js";
8
+ import type { AutoApproveThreshold } from "../permissions/approval-policy.js";
8
9
  import {
9
10
  isUnparseableToolArgs,
10
11
  unparseableToolArgsMessage,
11
12
  } from "../providers/unparseable-tool-args.js";
12
- import { resolveCapabilities } from "../runtime/capabilities.js";
13
+ import {
14
+ resolveCapabilities,
15
+ type SensitiveToolApproval,
16
+ } from "../runtime/capabilities.js";
13
17
  import { createOrReuseToolGrantRequest } from "../runtime/tool-grant-request-helper.js";
14
18
  import { redactSecrets } from "../security/secret-scanner.js";
15
19
  import { computeToolApprovalDigest } from "../security/tool-approval-digest.js";
@@ -29,20 +33,27 @@ import { enforceVerificationControlPlanePolicy } from "./verification-control-pl
29
33
 
30
34
  const log = getLogger("tool-approval-handler");
31
35
 
36
+ /**
37
+ * Compose the guardian-facing approval question. The question is about the
38
+ * tool — phrased with the same `Approve tool:` pattern the
39
+ * confirmation-request bridge uses — and the requester appears only as
40
+ * parenthetical context, never as the subject of the decision.
41
+ */
32
42
  function buildToolGrantQuestionText(
33
43
  toolName: string,
34
44
  input: Record<string, unknown>,
35
45
  context: ToolContext,
36
46
  ): string {
37
- const senderLabel =
47
+ const requesterLabel =
38
48
  context.requesterDisplayName ||
39
49
  context.requesterIdentifier ||
40
- context.requesterExternalUserId ||
41
- "A trusted contact";
50
+ context.requesterExternalUserId;
51
+ const requesterNote = requesterLabel
52
+ ? ` (requested by ${requesterLabel})`
53
+ : "";
42
54
  const inputSummary = redactSecrets(summarizeToolInput(toolName, input));
43
- return inputSummary
44
- ? `${senderLabel} wants to use "${toolName}": ${inputSummary}`
45
- : `${senderLabel} is requesting permission to use "${toolName}"`;
55
+ const summaryPart = inputSummary ? ` — ${inputSummary}` : "";
56
+ return `Approve tool: ${toolName}${summaryPart}${requesterNote}`;
46
57
  }
47
58
 
48
59
  /** Default polling interval for inline grant wait (ms). */
@@ -155,31 +166,94 @@ export async function waitForInlineGrant(
155
166
 
156
167
  const UI_SURFACE_TOOLS = new Set(["ui_show", "ui_update", "ui_dismiss"]);
157
168
 
158
- function requiresGuardianApprovalForActor(
169
+ /**
170
+ * Tool-sensitivity predicate: does invoking this tool require an approval
171
+ * decision at all? This is purely about the tool and where it executes —
172
+ * actor identity never feeds in here (it enters the decision only through
173
+ * the `CapabilitySet` floor, see {@link resolveSensitiveToolDecision}).
174
+ */
175
+ export function isSensitiveTool(
159
176
  toolName: string,
160
177
  executionTarget: ExecutionTarget,
161
178
  ): boolean {
162
179
  // UI surface tools are passive, user-visible operations (cards, forms,
163
- // tables). User input is voluntary and user-controlled — skip the guardian
164
- // gate so they work during fresh onboarding before trust is established.
180
+ // tables). User input is voluntary and user-controlled — they are not
181
+ // sensitive, so they work during fresh onboarding before trust is
182
+ // established.
165
183
  if (UI_SURFACE_TOOLS.has(toolName)) {
166
184
  return false;
167
185
  }
168
186
 
169
- // Side-effect tools always require guardian approval for untrusted actors.
170
- // Read-only host execution is also blocked because it can leak sensitive
171
- // local information (e.g. shell/file reads).
187
+ // Side-effect tools are sensitive. Read-only host execution is too,
188
+ // because it can leak sensitive local information (e.g. shell/file reads).
172
189
  return isSideEffectTool(toolName) || executionTarget === "host";
173
190
  }
174
191
 
175
- function guardianApprovalDeniedMessage(
176
- trustClass: ToolContext["trustClass"],
192
+ /**
193
+ * Threshold for the approval cell governing an invocation — the matrix axis
194
+ * of the sensitive-tool composition. Shares the auto-approve threshold
195
+ * vocabulary defined in `permissions/approval-policy.ts`.
196
+ */
197
+ export type ApprovalCellThreshold = AutoApproveThreshold;
198
+
199
+ /**
200
+ * Outcome of the sensitive-tool composition:
201
+ * - `proceed`: no scoped grant needed (tool not sensitive, or the actor's
202
+ * capability set self-approves; lane-B risk/threshold policy in
203
+ * `permissions/approval-policy.ts` still applies downstream).
204
+ * - `escalate-and-wait`: a scoped grant is required; on a grant miss,
205
+ * escalate to the guardian and wait inline.
206
+ * - `deny`: a scoped grant is required; on a grant miss, fail closed.
207
+ */
208
+ export type SensitiveToolDecision = "proceed" | "escalate-and-wait" | "deny";
209
+
210
+ /**
211
+ * Single composition point for the sensitive-tool approval decision:
212
+ * approval-cell threshold × tool risk level × `CapabilitySet` floor.
213
+ *
214
+ * The decision is about the tool; actor identity feeds in only through the
215
+ * already-resolved `sensitiveToolApproval` capability. That floor is
216
+ * deterministic and cannot be lifted by the other axes: when the capability
217
+ * is not `"self"`, a sensitive invocation without a grant always escalates
218
+ * or denies. `cellThreshold` and `riskLevel` are composition axes the
219
+ * decision does not consult — no threshold/risk combination may lift the
220
+ * outcome above the floor.
221
+ */
222
+ export function resolveSensitiveToolDecision(input: {
223
+ sensitive: boolean;
224
+ /**
225
+ * Approval-matrix cell axis. The decision does not consult it — the floor
226
+ * alone resolves the outcome — so callers pass `undefined` rather than
227
+ * paying a threshold lookup to populate it.
228
+ */
229
+ cellThreshold: ApprovalCellThreshold | undefined;
230
+ /**
231
+ * Risk level as known at gate time. The full risk classification runs
232
+ * after this gate (in the permission checker), so callers may only have
233
+ * the pre-classification level here — composing decisions on this axis
234
+ * requires moving classification ahead of the gate first.
235
+ */
236
+ riskLevel: string;
237
+ sensitiveToolApproval: SensitiveToolApproval;
238
+ }): SensitiveToolDecision {
239
+ if (!input.sensitive || input.sensitiveToolApproval === "self") {
240
+ return "proceed";
241
+ }
242
+ return input.sensitiveToolApproval;
243
+ }
244
+
245
+ /**
246
+ * Denial copy is about the tool (an action requiring guardian approval),
247
+ * never about who the requester is.
248
+ */
249
+ function sensitiveToolDeniedMessage(
250
+ decision: SensitiveToolDecision,
177
251
  toolName: string,
178
252
  ): string {
179
- if (resolveCapabilities(trustClass).sensitiveToolApproval === "deny") {
253
+ if (decision === "deny") {
180
254
  return `Permission denied for "${toolName}": this action requires guardian approval from a verified channel identity.`;
181
255
  }
182
- return `Permission denied for "${toolName}": this action requires guardian approval and the current actor is not the guardian.`;
256
+ return `Permission denied for "${toolName}": this action requires guardian approval before it can run.`;
183
257
  }
184
258
 
185
259
  export type PreExecutionGateResult =
@@ -317,16 +391,20 @@ export class ToolApprovalHandler {
317
391
  | Parameters<typeof consumeGrantForInvocation>[0]
318
392
  | null = null;
319
393
 
320
- const guardianApprovalRequired = requiresGuardianApprovalForActor(
321
- name,
322
- executionTarget,
323
- );
394
+ const sensitive = isSensitiveTool(name, executionTarget);
395
+ const { sensitiveToolApproval } = resolveCapabilities(context.trustClass);
396
+ // cellThreshold stays unresolved: the decision does not consult it
397
+ // (the floor is deterministic), and resolving a live threshold here
398
+ // would block grant consumption — including already-approved calls and
399
+ // voice abort handling — on a gateway IPC read.
400
+ const sensitiveDecision = resolveSensitiveToolDecision({
401
+ sensitive,
402
+ cellThreshold: undefined,
403
+ riskLevel,
404
+ sensitiveToolApproval,
405
+ });
324
406
 
325
- if (
326
- resolveCapabilities(context.trustClass).sensitiveToolApproval !==
327
- "self" &&
328
- guardianApprovalRequired
329
- ) {
407
+ if (sensitiveDecision !== "proceed") {
330
408
  const inputDigest = computeToolApprovalDigest(name, input);
331
409
  needsGrantConsumption = true;
332
410
  deferredConsumeParams = {
@@ -544,8 +622,7 @@ export class ToolApprovalHandler {
544
622
  // Actors with no identity (unknown) remain fail-closed with no
545
623
  // escalation or wait.
546
624
  if (
547
- resolveCapabilities(context.trustClass).sensitiveToolApproval ===
548
- "escalate-and-wait" &&
625
+ sensitiveDecision === "escalate-and-wait" &&
549
626
  context.assistantId &&
550
627
  context.executionChannel &&
551
628
  context.requesterExternalUserId
@@ -692,7 +769,7 @@ export class ToolApprovalHandler {
692
769
  }
693
770
 
694
771
  // Unknown/unverified actors or escalation failures - generic denial.
695
- const reason = guardianApprovalDeniedMessage(context.trustClass, name);
772
+ const reason = sensitiveToolDeniedMessage(sensitiveDecision, name);
696
773
  log.warn(
697
774
  {
698
775
  toolName: name,
@@ -1,25 +1,24 @@
1
1
  /**
2
- * Tool-related type declarations shared between the daemon and any
3
- * skill-side package that needs to describe tools, permission risk, or tool
4
- * execution results on the wire.
2
+ * Tool-related type declarations: the neutral leaf module describing
3
+ * tools, permission risk, and tool execution results.
5
4
  *
6
- * Pure type-level declarations only (+ the `RiskLevel` enum, which is a value
7
- * but is safely cross-package). No runtime helpers live here — the assistant
8
- * keeps all behavior functions in `assistant/src/tools/` and re-exports the
9
- * types from this file.
5
+ * Pure type-level declarations only (+ the `RiskLevel` enum, which is a
6
+ * value). No runtime helpers live here — the assistant keeps all behavior
7
+ * functions in `assistant/src/tools/` and re-exports the types from this
8
+ * file. This module imports nothing, so it can sit at the bottom of the
9
+ * import graph and be consumed by `tools/types.ts`, `providers/types.ts`,
10
+ * and `permissions/types.ts` without creating cycles.
10
11
  *
11
12
  * Heavy daemon-internal references (CES client, host-proxy classes, trust
12
13
  * classifications, interface IDs, content blocks, CES `ApprovalRequired`)
13
- * are held as opaque `unknown` / broadened-`string` placeholders on this
14
- * side so the contracts package never reaches into the assistant or the
15
- * service-contracts runtime. The assistant redeclares `Tool`, `ToolContext`,
16
- * `ToolExecutionResult`, `ToolExecutedEvent`, `ToolLifecycleEvent`,
17
- * `ToolLifecycleEventHandler`, and `ProxyToolResolver` in
18
- * `assistant/src/tools/types.ts` with the concrete types in place, so
19
- * existing call sites keep their full type information. The two sides are
20
- * structurally independent — no inheritance, no intersection — which
21
- * avoids TypeScript's contravariance mismatches on lifecycle-event
22
- * handlers.
14
+ * are held as opaque `unknown` / broadened-`string` placeholders here. The
15
+ * assistant redeclares `Tool`, `ToolContext`, `ToolExecutionResult`,
16
+ * `ToolExecutedEvent`, `ToolLifecycleEvent`, `ToolLifecycleEventHandler`,
17
+ * and `ProxyToolResolver` in `assistant/src/tools/types.ts` with the
18
+ * concrete types in place, so existing call sites keep their full type
19
+ * information. The two sides are structurally independent — no inheritance,
20
+ * no intersection which avoids TypeScript's contravariance mismatches on
21
+ * lifecycle-event handlers.
23
22
  */
24
23
 
25
24
  // ---------------------------------------------------------------------------
@@ -1,15 +1,4 @@
1
1
  import type { ApprovalRequired } from "@vellumai/service-contracts/credential-rpc";
2
- import type {
3
- DiffInfo,
4
- ExecutionTarget,
5
- ProxyApprovalCallback,
6
- SensitiveOutputBinding,
7
- ToolExecutionErrorEvent as ContractsToolExecutionErrorEvent,
8
- ToolExecutionStartEvent,
9
- ToolPermissionDeniedEvent,
10
- ToolPermissionPromptEvent,
11
- } from "@vellumai/skill-host-contracts";
12
- import { RiskLevel } from "@vellumai/skill-host-contracts";
13
2
  import { z } from "zod";
14
3
 
15
4
  import type { InterfaceId } from "../channels/types.js";
@@ -19,6 +8,17 @@ import type { SecretPromptResult } from "../permissions/secret-prompter.js";
19
8
  import type { ContentBlock } from "../providers/types.js";
20
9
  import type { TrustClass } from "../runtime/actor-trust-resolver.js";
21
10
  import type { UsageAttributionSnapshot } from "../usage/attribution.js";
11
+ import type {
12
+ DiffInfo,
13
+ ExecutionTarget,
14
+ ProxyApprovalCallback,
15
+ SensitiveOutputBinding,
16
+ ToolExecutionErrorEvent as ContractsToolExecutionErrorEvent,
17
+ ToolExecutionStartEvent,
18
+ ToolPermissionDeniedEvent,
19
+ ToolPermissionPromptEvent,
20
+ } from "./tool-types.js";
21
+ import { RiskLevel } from "./tool-types.js";
22
22
 
23
23
  export const DISK_PRESSURE_CLEANUP_TOOL_NAMES: ReadonlySet<string> = new Set([
24
24
  "bash",
@@ -37,11 +37,11 @@ export function isDiskPressureCleanupToolName(name: string): boolean {
37
37
 
38
38
  // ---------------------------------------------------------------------------
39
39
  // Re-exports + concrete overlays for types that live in
40
- // @vellumai/skill-host-contracts.
40
+ // ./tool-types.js.
41
41
  //
42
- // The canonical declarations moved into the neutral contracts package as
43
- // part of the skill-isolation work. This file preserves existing import
44
- // paths (`"../tools/types.js"`) so all callers keep resolving.
42
+ // The canonical declarations live in the neutral leaf module
43
+ // `./tool-types.js`. This file preserves existing import paths
44
+ // (`"../tools/types.js"`) so all callers keep resolving.
45
45
  //
46
46
  // Pure re-exports below cover types the contracts package could declare
47
47
  // without any assistant-side references. The remaining interfaces (`Tool`,
@@ -73,8 +73,8 @@ export type {
73
73
  ToolExecutionStartEvent,
74
74
  ToolPermissionDeniedEvent,
75
75
  ToolPermissionPromptEvent,
76
- } from "@vellumai/skill-host-contracts";
77
- export { RiskLevel } from "@vellumai/skill-host-contracts";
76
+ } from "./tool-types.js";
77
+ export { RiskLevel } from "./tool-types.js";
78
78
 
79
79
  // ---------------------------------------------------------------------------
80
80
  // Assistant-side concrete overlays
@@ -483,6 +483,18 @@ export interface ToolContext {
483
483
  * @legacy
484
484
  */
485
485
  sourceActorPrincipalId?: string;
486
+ /**
487
+ * The conversation's effective per-chat plugin scope, as produced by
488
+ * `getEffectiveEnabledPluginSet`: `null` means no per-chat restriction;
489
+ * otherwise a Set of allowed plugin ids (the user's selection unioned with
490
+ * the always-on first-party defaults). Skill-surface tools that resolve
491
+ * skills by id outside the per-turn projection — `skill_load` (body load)
492
+ * and `find_similar_skills` (discovery) — read this to drop skills owned by
493
+ * plugins outside the conversation's scope. Populated per tool call from the
494
+ * live conversation state.
495
+ * @legacy
496
+ */
497
+ enabledPluginSet?: Set<string> | null;
486
498
  }
487
499
 
488
500
  /**
@@ -243,7 +243,8 @@ export const uiShowTool = {
243
243
  "- dynamic_page: { html, width?, height?, preview?: { title, subtitle?, description?, icon?, metrics?: [{ label, value }] } }\n" +
244
244
  "- file_upload: { prompt, acceptedTypes?, maxFiles? }\n" +
245
245
  "- task_preferences: {} (no data needed — categories are rendered client-side)\n" +
246
- '- work_result: { eyebrow?, status?: "completed"|"partial"|"failed"|"in_progress", summary?, metrics?: [{ label, value, detail?, tone?: "neutral"|"positive"|"warning"|"negative" }], sections?: [{ id?, title, description?, type?: "items"|"timeline"|"diff"|"artifacts"|"warnings", items?: [{ id?, title, description?, status?, tone?, metadata?: [{ label, value }], href? }], diffs?: [{ label?, before?, after? }] }] }. Shows a structured receipt after real work: what changed, what was skipped, proof points, and next actions. Keep display-only unless explicit follow-up buttons are needed.\n\n' +
246
+ '- work_result: { eyebrow?, status?: "completed"|"partial"|"failed"|"in_progress", summary?, metrics?: [{ label, value, detail?, tone?: "neutral"|"positive"|"warning"|"negative" }], sections?: [{ id?, title, description?, type?: "items"|"timeline"|"diff"|"artifacts"|"warnings", items?: [{ id?, title, description?, status?, tone?, metadata?: [{ label, value }], href? }], diffs?: [{ label?, before?, after? }] }] }. Shows a structured receipt after real work: what changed, what was skipped, proof points, and next actions. Keep display-only unless explicit follow-up buttons are needed.\n' +
247
+ '- channel_setup: { channel: "slack" | "telegram" | "phone" }. Opens the channel setup panel in a side drawer. Returns success only after a connected client confirms the panel rendered (an error means the user does NOT see the panel — never claim it is open after an error). The user then completes credential entry at their own pace. Slack shows a full setup wizard; Telegram and Phone show credential forms (the assistant handles remaining setup steps like webhooks in chat after the user saves credentials).\n\n' +
247
248
  "For multi-step or long-running turns (web searches, file operations, research), show a task_progress card early and keep its steps updated as work progresses. Coarse steps are fine, and you can add or revise them as the work takes shape — a rough card beats no signal.",
248
249
  category: "ui-surface",
249
250
  defaultRiskLevel: RiskLevel.Low,
@@ -256,6 +257,7 @@ export const uiShowTool = {
256
257
  type: "string",
257
258
  enum: [
258
259
  "card",
260
+ "channel_setup",
259
261
  "choice",
260
262
  "copy_block",
261
263
  "oauth_connect",
@@ -537,6 +537,43 @@ describe("Fish Audio TTS provider adapter", () => {
537
537
  );
538
538
  });
539
539
 
540
+ test("pcm output request maps to wav format at 8 kHz", async () => {
541
+ const provider = createFishAudioProvider();
542
+ await provider.synthesize(makeRequest({ outputFormat: "pcm" }));
543
+
544
+ const [, config, options] = mockSynthesizeWithFishAudio.mock.calls[0]!;
545
+ expect((config as { format: string }).format).toBe("wav");
546
+ expect((options as { sampleRate?: number } | undefined)?.sampleRate).toBe(
547
+ 8000,
548
+ );
549
+ });
550
+
551
+ test("synthesizeStream pcm output request maps to wav format at 8 kHz", async () => {
552
+ const provider = createFishAudioProvider();
553
+ await provider.synthesizeStream!(
554
+ makeRequest({ outputFormat: "pcm" }),
555
+ () => {},
556
+ );
557
+
558
+ const [, config, options] = mockSynthesizeWithFishAudio.mock.calls[0]!;
559
+ expect((config as { format: string }).format).toBe("wav");
560
+ expect((options as { sampleRate?: number } | undefined)?.sampleRate).toBe(
561
+ 8000,
562
+ );
563
+ });
564
+
565
+ test("explicit format request does not set a sample rate", async () => {
566
+ mockFishAudioConfig.format = "wav";
567
+ const provider = createFishAudioProvider();
568
+ await provider.synthesize(makeRequest());
569
+
570
+ const [, config, options] = mockSynthesizeWithFishAudio.mock.calls[0]!;
571
+ expect((config as { format: string }).format).toBe("wav");
572
+ expect(
573
+ (options as { sampleRate?: number } | undefined)?.sampleRate,
574
+ ).toBeUndefined();
575
+ });
576
+
540
577
  // -- Streaming -----------------------------------------------------------
541
578
 
542
579
  test("synthesizeStream passes onChunk callback through", async () => {
@@ -53,6 +53,15 @@ describe("TTS provider catalog", () => {
53
53
  }
54
54
  });
55
55
 
56
+ test("every entry declares a valid mediaStreamPlayback output format", () => {
57
+ const validFormats = new Set(["pcm", "wav", "none"]);
58
+ for (const entry of entries) {
59
+ expect(validFormats.has(entry.mediaStreamPlayback.outputFormat)).toBe(
60
+ true,
61
+ );
62
+ }
63
+ });
64
+
56
65
  test("every entry has at least one secret requirement", () => {
57
66
  for (const entry of entries) {
58
67
  expect(entry.secretRequirements.length).toBeGreaterThan(0);
@@ -120,6 +129,10 @@ describe("ElevenLabs catalog entry", () => {
120
129
  expect(entry.capabilities.supportedFormats).toContain("mp3");
121
130
  });
122
131
 
132
+ test("plays over media-stream via PCM output", () => {
133
+ expect(entry.mediaStreamPlayback.outputFormat).toBe("pcm");
134
+ });
135
+
123
136
  test("requires a credential stored under 'credential/elevenlabs/api_key'", () => {
124
137
  const apiKeySecret = entry.secretRequirements.find(
125
138
  (s) => s.credentialStoreKey === "credential/elevenlabs/api_key",
@@ -146,6 +159,10 @@ describe("Fish Audio catalog entry", () => {
146
159
  expect(entry.capabilities.supportedFormats).toContain("opus");
147
160
  });
148
161
 
162
+ test("plays over media-stream via WAV output", () => {
163
+ expect(entry.mediaStreamPlayback.outputFormat).toBe("wav");
164
+ });
165
+
149
166
  test("requires an API key stored under 'credential/fish-audio/api_key'", () => {
150
167
  const apiKeySecret = entry.secretRequirements.find(
151
168
  (s) => s.credentialStoreKey === "credential/fish-audio/api_key",
@@ -172,6 +189,10 @@ describe("Deepgram catalog entry", () => {
172
189
  expect(entry.capabilities.supportedFormats).toContain("opus");
173
190
  });
174
191
 
192
+ test("plays over media-stream via PCM output", () => {
193
+ expect(entry.mediaStreamPlayback.outputFormat).toBe("pcm");
194
+ });
195
+
175
196
  test("requires an API key stored under 'credential/deepgram/api_key'", () => {
176
197
  const apiKeySecret = entry.secretRequirements.find(
177
198
  (s) => s.credentialStoreKey === "credential/deepgram/api_key",
@@ -55,6 +55,27 @@ interface TtsProviderCatalogCapabilities {
55
55
  readonly supportedFormats: readonly string[];
56
56
  }
57
57
 
58
+ /**
59
+ * Output format the provider's adapter produces when a caller requests
60
+ * PCM output (`outputFormat: "pcm"`) for media-stream playback.
61
+ *
62
+ * The media-stream transport can only transcode raw PCM or WAV
63
+ * (PCM-in-container) to mu-law — compressed formats (mp3, opus) produce
64
+ * garbled audio. Providers whose adapter honours the PCM hint declare
65
+ * `"pcm"`; providers that substitute WAV declare `"wav"`; providers that
66
+ * can only produce compressed audio declare `"none"` and are not playable
67
+ * over media-stream transports.
68
+ */
69
+ export type TtsMediaStreamOutputFormat = "pcm" | "wav" | "none";
70
+
71
+ /**
72
+ * How the provider's synthesized audio plays over media-stream transports.
73
+ */
74
+ export interface TtsMediaStreamPlayback {
75
+ /** Format the adapter produces for media-stream (PCM-hinted) requests. */
76
+ readonly outputFormat: TtsMediaStreamOutputFormat;
77
+ }
78
+
58
79
  /**
59
80
  * Link to a provider's API-key management page, shown in settings UI.
60
81
  */
@@ -71,7 +92,7 @@ interface TtsCredentialsGuide {
71
92
  * metadata level — identity, display name, telephony call mode,
72
93
  * capabilities, secret requirements, and client-facing display metadata.
73
94
  */
74
- interface TtsProviderCatalogEntry {
95
+ export interface TtsProviderCatalogEntry {
75
96
  /** Unique provider identifier matching {@link TtsProviderId}. */
76
97
  readonly id: TtsProviderId;
77
98
 
@@ -94,22 +115,24 @@ interface TtsProviderCatalogEntry {
94
115
  readonly callMode: TtsCallMode;
95
116
 
96
117
  /**
97
- * Whether the call path may fall back to native Twilio token-based
98
- * TTS when synthesized audio fails.
118
+ * Whether the call path may fall back to the text-token path when
119
+ * synthesized audio fails.
99
120
  *
100
121
  * Providers with `callMode: "native-twilio"` always set this to `true`.
101
- * Synthesized-play providers that also work through Twilio's built-in
102
- * TTS (e.g. Fish Audio) set this to `true` so callers still hear
103
- * a response if synthesis fails. Providers that have **no** native
104
- * Twilio integration (e.g. Deepgram) set this to `false` a synthesis
105
- * failure must propagate so the outer error handler can surface a
106
- * user-facing recovery message.
122
+ * Synthesized-play providers with a usable token fallback (e.g. Fish
123
+ * Audio) set this to `true` so callers still hear a response if
124
+ * synthesis fails. Providers without one (e.g. Deepgram) set this to
125
+ * `false` a synthesis failure must propagate so the outer error
126
+ * handler can surface a user-facing recovery message.
107
127
  */
108
128
  readonly allowNativeFallback: boolean;
109
129
 
110
130
  /** Static provider-level capabilities. */
111
131
  readonly capabilities: Readonly<TtsProviderCatalogCapabilities>;
112
132
 
133
+ /** How the provider's audio plays over media-stream transports. */
134
+ readonly mediaStreamPlayback: Readonly<TtsMediaStreamPlayback>;
135
+
113
136
  /** Secrets the provider requires to function. */
114
137
  readonly secretRequirements: readonly Readonly<TtsProviderSecretRequirement>[];
115
138
  }
@@ -143,6 +166,8 @@ const CATALOG: readonly TtsProviderCatalogEntry[] = [
143
166
  supportsStreaming: false,
144
167
  supportedFormats: ["mp3"],
145
168
  },
169
+ // The adapter honours the PCM hint via `pcm_16000` output.
170
+ mediaStreamPlayback: { outputFormat: "pcm" },
146
171
  secretRequirements: [
147
172
  {
148
173
  credentialStoreKey: "credential/elevenlabs/api_key",
@@ -171,6 +196,8 @@ const CATALOG: readonly TtsProviderCatalogEntry[] = [
171
196
  supportsStreaming: true,
172
197
  supportedFormats: ["mp3", "wav", "opus"],
173
198
  },
199
+ // The adapter substitutes WAV for the PCM hint (no raw PCM support).
200
+ mediaStreamPlayback: { outputFormat: "wav" },
174
201
  secretRequirements: [
175
202
  {
176
203
  credentialStoreKey: "credential/fish-audio/api_key",
@@ -199,6 +226,8 @@ const CATALOG: readonly TtsProviderCatalogEntry[] = [
199
226
  supportsStreaming: false,
200
227
  supportedFormats: ["mp3", "wav", "opus"],
201
228
  },
229
+ // The adapter honours the PCM hint via `linear16` + `container=none`.
230
+ mediaStreamPlayback: { outputFormat: "pcm" },
202
231
  secretRequirements: [
203
232
  {
204
233
  credentialStoreKey: "credential/deepgram/api_key",
@@ -226,6 +255,8 @@ const CATALOG: readonly TtsProviderCatalogEntry[] = [
226
255
  supportsStreaming: false,
227
256
  supportedFormats: ["mp3", "wav"],
228
257
  },
258
+ // The adapter honours the PCM hint via the `pcm` codec.
259
+ mediaStreamPlayback: { outputFormat: "pcm" },
229
260
  secretRequirements: [
230
261
  {
231
262
  credentialStoreKey: "credential/xai/api_key",
@@ -23,6 +23,13 @@ import type {
23
23
 
24
24
  const log = getLogger("tts:fish-audio");
25
25
 
26
+ /**
27
+ * Sample rate requested when the caller wants PCM (the phone path).
28
+ * Twilio media streams consume 8 kHz; without this Fish defaults WAV
29
+ * to 44.1 kHz, which the media-stream transcoder would play ~5.5x slow.
30
+ */
31
+ const TELEPHONY_SAMPLE_RATE_HZ = 8000;
32
+
26
33
  // ---------------------------------------------------------------------------
27
34
  // Error types
28
35
  // ---------------------------------------------------------------------------
@@ -92,11 +99,12 @@ export function createFishAudioProvider(): TtsProvider {
92
99
  const config = getConfig().services.tts.providers["fish-audio"];
93
100
  const referenceId = resolveReferenceId(request, config);
94
101
 
95
- // When PCM output is requested, override to WAV. Fish Audio
96
- // doesn't support raw PCM, but WAV gives us PCM in a container
97
- // that audioBufferToFrames can extract.
98
- const effectiveFormat =
99
- request.outputFormat === "pcm" ? "wav" : config.format;
102
+ // When PCM output is requested, override to WAV at 8 kHz. Fish Audio
103
+ // doesn't support raw PCM, but WAV gives us PCM in a container that
104
+ // audioBufferToFrames can extract; the explicit sample rate avoids
105
+ // Fish's 44.1 kHz WAV default.
106
+ const pcmRequested = request.outputFormat === "pcm";
107
+ const effectiveFormat = pcmRequested ? "wav" : config.format;
100
108
 
101
109
  // Build an effective config with the resolved reference ID
102
110
  // and the potentially overridden format.
@@ -119,6 +127,7 @@ export function createFishAudioProvider(): TtsProvider {
119
127
  try {
120
128
  audio = await synthesizeWithFishAudio(request.text, effectiveConfig, {
121
129
  signal: request.signal,
130
+ sampleRate: pcmRequested ? TELEPHONY_SAMPLE_RATE_HZ : undefined,
122
131
  });
123
132
  } catch (err) {
124
133
  if (err instanceof Error && err.name === "AbortError") throw err;
@@ -140,11 +149,10 @@ export function createFishAudioProvider(): TtsProvider {
140
149
  const config = getConfig().services.tts.providers["fish-audio"];
141
150
  const referenceId = resolveReferenceId(request, config);
142
151
 
143
- // When PCM output is requested, override to WAV. Fish Audio
144
- // doesn't support raw PCM, but WAV gives us PCM in a container
145
- // that audioBufferToFrames can extract.
146
- const effectiveFormat =
147
- request.outputFormat === "pcm" ? "wav" : config.format;
152
+ // When PCM output is requested, override to WAV at 8 kHz (see
153
+ // synthesize above).
154
+ const pcmRequested = request.outputFormat === "pcm";
155
+ const effectiveFormat = pcmRequested ? "wav" : config.format;
148
156
 
149
157
  const effectiveConfig: TtsFishAudioProviderConfig = {
150
158
  ...config,
@@ -166,6 +174,7 @@ export function createFishAudioProvider(): TtsProvider {
166
174
  audio = await synthesizeWithFishAudio(request.text, effectiveConfig, {
167
175
  onChunk,
168
176
  signal: request.signal,
177
+ sampleRate: pcmRequested ? TELEPHONY_SAMPLE_RATE_HZ : undefined,
169
178
  });
170
179
  } catch (err) {
171
180
  if (err instanceof Error && err.name === "AbortError") throw err;
package/src/tts/types.ts CHANGED
@@ -30,10 +30,9 @@ export type TtsProviderId =
30
30
  /**
31
31
  * Describes how a TTS provider integrates with the telephony call path.
32
32
  *
33
- * - `native-twilio` — Twilio handles TTS natively via ConversationRelay;
34
- * text tokens are forwarded to the relay and Twilio
35
- * synthesises audio using the provider's built-in
36
- * integration.
33
+ * - `native-twilio` — Twilio handles TTS natively; text tokens are
34
+ * forwarded to Twilio, which synthesises audio
35
+ * using the provider's built-in integration.
37
36
  * - `synthesized-play` — The assistant synthesises audio via the provider's
38
37
  * HTTP API and streams chunks to Twilio via `play`
39
38
  * messages. Used when the provider is not natively
@@ -39,8 +39,16 @@ describe("deriveName", () => {
39
39
  expect(deriveName("bun run /worker.ts")).toBe("worker");
40
40
  });
41
41
 
42
- test("falls back to the interpreter when there is no script arg", () => {
43
- expect(deriveName("bun repl")).toBe("bun");
42
+ test("surfaces the arguments when an interpreter runs no script file", () => {
43
+ expect(deriveName("bun repl")).toBe("bun repl");
44
+ expect(deriveName("bun run dev")).toBe("bun run dev");
45
+ expect(deriveName("bun x prettier --write .")).toBe("bun x prettier .");
46
+ expect(deriveName("node --inspect server")).toBe("node server");
47
+ });
48
+
49
+ test("falls back to the bare interpreter when only flags follow", () => {
50
+ expect(deriveName("bun --version")).toBe("bun");
51
+ expect(deriveName("bun")).toBe("bun");
44
52
  });
45
53
 
46
54
  test("handles empty input", () => {