@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
@@ -1,18 +1,5 @@
1
- import { execFileSync } from "node:child_process";
2
- import { createHash } from "node:crypto";
3
- import {
4
- existsSync,
5
- mkdirSync,
6
- readdirSync,
7
- readFileSync,
8
- statSync,
9
- unlinkSync,
10
- writeFileSync,
11
- } from "node:fs";
12
- import { tmpdir } from "node:os";
13
- import { join } from "node:path";
14
-
15
1
  import { parseImageDimensions } from "../context/image-dimensions.js";
2
+ import { convertImageToJpeg } from "../util/image-conversion.js";
16
3
 
17
4
  // Anthropic's documented max dimension — images larger than this are scaled
18
5
  // down server-side anyway, so pre-scaling is zero quality loss.
@@ -28,110 +15,6 @@ const MAX_TRANSPORT_BYTES = Math.floor(3.5 * 1024 * 1024); // ~3.5 MB raw
28
15
 
29
16
  const JPEG_QUALITY = 80;
30
17
 
31
- // Content-addressed disk cache to avoid re-running sips on the same image.
32
- const CACHE_MAX_ENTRIES = 500;
33
-
34
- function getCacheDir(): string {
35
- return join(tmpdir(), "vellum-optimized-images");
36
- }
37
-
38
- function readFromCache(
39
- key: string,
40
- ): { data: string; mediaType: string } | null {
41
- try {
42
- const cachePath = join(getCacheDir(), `${key}.jpg`);
43
- if (!existsSync(cachePath)) return null;
44
- const buf = readFileSync(cachePath) as Buffer;
45
- return { data: buf.toString("base64"), mediaType: "image/jpeg" };
46
- } catch {
47
- return null;
48
- }
49
- }
50
-
51
- function writeToCache(key: string, optimizedBytes: Buffer): void {
52
- try {
53
- const dir = getCacheDir();
54
- mkdirSync(dir, { recursive: true });
55
- writeFileSync(join(dir, `${key}.jpg`), optimizedBytes);
56
- evictIfNeeded(dir);
57
- } catch {
58
- // Cache write failure is non-fatal.
59
- }
60
- }
61
-
62
- function evictIfNeeded(dir: string): void {
63
- try {
64
- const entries = readdirSync(dir)
65
- .filter((f) => f.endsWith(".jpg"))
66
- .map((f) => {
67
- const full = join(dir, f);
68
- return { path: full, mtimeMs: statSync(full).mtimeMs };
69
- })
70
- .sort((a, b) => a.mtimeMs - b.mtimeMs);
71
- const excess = entries.length - CACHE_MAX_ENTRIES;
72
- for (let i = 0; i < excess; i++) {
73
- try {
74
- unlinkSync(entries[i]!.path);
75
- } catch {
76
- /* ignore */
77
- }
78
- }
79
- } catch {
80
- /* ignore */
81
- }
82
- }
83
-
84
- function runSips(inputBytes: Buffer): Buffer | null {
85
- const srcPath = join(tmpdir(), `vellum-img-opt-${Date.now()}-src`);
86
- const outPath = join(tmpdir(), `vellum-img-opt-${Date.now()}-out.jpg`);
87
- try {
88
- writeFileSync(srcPath, inputBytes);
89
- execFileSync(
90
- "sips",
91
- [
92
- "--resampleHeightWidthMax",
93
- String(MAX_DIMENSION),
94
- "-s",
95
- "format",
96
- "jpeg",
97
- "-s",
98
- "formatOptions",
99
- String(JPEG_QUALITY),
100
- srcPath,
101
- "--out",
102
- outPath,
103
- ],
104
- { stdio: "pipe", timeout: 15_000 },
105
- );
106
- return readFileSync(outPath) as Buffer;
107
- } catch {
108
- return null;
109
- } finally {
110
- try {
111
- unlinkSync(srcPath);
112
- } catch {
113
- /* ignore */
114
- }
115
- try {
116
- unlinkSync(outPath);
117
- } catch {
118
- /* ignore */
119
- }
120
- }
121
- }
122
-
123
- /**
124
- * Downscale a base64 image to fit within Anthropic's recommended dimensions
125
- * (1568px max side). Returns the original data unchanged if the image is
126
- * already small enough or if optimization fails.
127
- *
128
- * Anthropic applies the same scaling server-side, so this is zero quality
129
- * loss — we just do it pre-flight to keep request payloads small and avoid
130
- * 413 "request too large" errors when many images accumulate in context.
131
- *
132
- * Results are cached on disk by content hash so repeated sends of the same
133
- * image (or daemon restarts) skip the sips call entirely.
134
- */
135
18
  /**
136
19
  * Decide whether an image needs to be rescaled before sending.
137
20
  *
@@ -157,6 +40,18 @@ export function shouldRescaleImage(
157
40
  return byteLength > OPTIMIZE_THRESHOLD_BYTES;
158
41
  }
159
42
 
43
+ /**
44
+ * Downscale a base64 image to fit within Anthropic's recommended dimensions
45
+ * (1568px max side). Returns the original data unchanged if the image is
46
+ * already small enough or if optimization fails.
47
+ *
48
+ * Anthropic applies the same scaling server-side, so this is zero quality
49
+ * loss — we just do it pre-flight to keep request payloads small and avoid
50
+ * 413 "request too large" errors when many images accumulate in context.
51
+ *
52
+ * Conversion (and its content-addressed disk cache) is shared with attachment
53
+ * storage normalization — see `util/image-conversion.ts`.
54
+ */
160
55
  export function optimizeImageForTransport(
161
56
  base64Data: string,
162
57
  mediaType: string,
@@ -168,18 +63,13 @@ export function optimizeImageForTransport(
168
63
  return { data: base64Data, mediaType };
169
64
  }
170
65
 
171
- // Content-addressed cache lookup.
172
- const hash = createHash("sha256").update(rawBytes).digest("hex");
173
- const cacheKey = hash.slice(0, 16);
174
- const cached = readFromCache(cacheKey);
175
- if (cached) return cached;
176
-
177
- // Run sips (macOS). On other platforms this gracefully returns null.
178
- const optimized = runSips(rawBytes);
66
+ const optimized = convertImageToJpeg(rawBytes, {
67
+ maxDimensionPx: MAX_DIMENSION,
68
+ quality: JPEG_QUALITY,
69
+ });
179
70
  if (!optimized) {
180
71
  return { data: base64Data, mediaType };
181
72
  }
182
73
 
183
- writeToCache(cacheKey, optimized);
184
74
  return { data: optimized.toString("base64"), mediaType: "image/jpeg" };
185
75
  }
package/src/agent/loop.ts CHANGED
@@ -4,6 +4,7 @@ import { getConfig } from "../config/loader.js";
4
4
  import { isMemoryV3Live } from "../config/memory-v3-gate.js";
5
5
  import type { LLMCallSite } from "../config/schemas/llm.js";
6
6
  import { recordEstimate } from "../context/estimator-calibration.js";
7
+ import { preModelCallSanitize } from "../context/outbound-sanitize.js";
7
8
  import {
8
9
  estimatePromptTokensRaw,
9
10
  estimatePromptTokensWithTools,
@@ -14,7 +15,10 @@ import { spoolAndStubOversizedToolResults } from "../context/tool-result-spool.j
14
15
  import type { ToolActivityMetadata } from "../daemon/message-types/web-activity.js";
15
16
  import { parseActualTokensFromError } from "../daemon/parse-actual-tokens-from-error.js";
16
17
  import type { TrustContext } from "../daemon/trust-context.js";
17
- import { stripHistoricalWebSearchResults } from "../daemon/web-search-history.js";
18
+ import {
19
+ timeSyncSection,
20
+ traceAsyncSection,
21
+ } from "../persistence/slow-sync-log.js";
18
22
  import { HOOKS } from "../plugin-api/constants.js";
19
23
  import type {
20
24
  AgentLoopExitReason,
@@ -818,6 +822,19 @@ export class AgentLoop {
818
822
  this.compactionCircuit = new CompactionCircuit(this.conversationId);
819
823
  }
820
824
 
825
+ /**
826
+ * Replace the system prompt used by subsequent runs. The conversation pushes
827
+ * a freshly resolved prompt here between turns when its persona context
828
+ * (trust, channel, persona override) changed, so a conversation that binds
829
+ * that context after construction (e.g. a voice call resolving the caller's
830
+ * identity after the loop is built) does not stay pinned to the
831
+ * construction-time persona. An in-flight `run()` keeps its own snapshot
832
+ * (`runSystemPrompt`), so this never changes the prompt mid-run.
833
+ */
834
+ setSystemPrompt(systemPrompt: string): void {
835
+ this.systemPrompt = systemPrompt;
836
+ }
837
+
821
838
  /**
822
839
  * Resolve the tool definitions sent to the provider for the given turn.
823
840
  *
@@ -1494,15 +1511,20 @@ export class AgentLoop {
1494
1511
  // the existing correction) so the calibrator learns the true
1495
1512
  // bias against provider ground truth instead of ratcheting a
1496
1513
  // feedback loop against its own corrected output.
1497
- const toolTokenBudget =
1498
- currentTools.length > 0 ? estimateToolsTokens(currentTools) : 0;
1499
- const preSendEstimatedTokens = estimatePromptTokensRaw(
1500
- history,
1501
- runSystemPrompt,
1502
- {
1503
- providerName: getCalibrationProviderKey(this.provider),
1504
- toolTokenBudget,
1514
+ const preSendEstimatedTokens = timeSyncSection(
1515
+ "agent-loop:estimate-prompt-tokens",
1516
+ () => {
1517
+ const toolTokenBudget =
1518
+ currentTools.length > 0 ? estimateToolsTokens(currentTools) : 0;
1519
+ return estimatePromptTokensRaw(history, runSystemPrompt, {
1520
+ providerName: getCalibrationProviderKey(this.provider),
1521
+ toolTokenBudget,
1522
+ });
1505
1523
  },
1524
+ (estimatedTokens) => ({
1525
+ estimatedTokens,
1526
+ messageCount: history.length,
1527
+ }),
1506
1528
  );
1507
1529
  lastPreSendEstimatedTokens = preSendEstimatedTokens;
1508
1530
  rlog.info({ turn: toolUseTurns }, "LLM call start");
@@ -1510,7 +1532,11 @@ export class AgentLoop {
1510
1532
  // Sanitize the outbound history right before sending: drop accumulated
1511
1533
  // media, collapse old AX-tree snapshots, and convert historical
1512
1534
  // web-search results to text. See {@link preModelCallSanitize}.
1513
- const providerHistory = preModelCallSanitize(history);
1535
+ const providerHistory = timeSyncSection(
1536
+ "agent-loop:pre-model-call-sanitize",
1537
+ () => preModelCallSanitize(history),
1538
+ (sanitized) => ({ messageCount: sanitized.length }),
1539
+ );
1514
1540
 
1515
1541
  // A `pre-model-call` hook (below) can defer this turn's assistant
1516
1542
  // output; when set, the live text stream is held so an
@@ -1621,9 +1647,9 @@ export class AgentLoop {
1621
1647
  deferAssistantOutput: false,
1622
1648
  logger: rlog,
1623
1649
  };
1624
- const finalPreModelCtx = await runHook(
1625
- HOOKS.PRE_MODEL_CALL,
1626
- preModelCtx,
1650
+ const finalPreModelCtx = await traceAsyncSection(
1651
+ "agent-loop:pre-model-call-hook",
1652
+ () => runHook(HOOKS.PRE_MODEL_CALL, preModelCtx),
1627
1653
  );
1628
1654
  // Emit a changed event when the hook mutated the prompt. Compare
1629
1655
  // against the pre-hook value from providerOptions, not
@@ -1692,9 +1718,8 @@ export class AgentLoop {
1692
1718
  latencyTracker?.mark("request_sent");
1693
1719
  let response: ProviderResponse;
1694
1720
  try {
1695
- response = await this.provider.sendMessage(
1696
- providerHistory,
1697
- providerOptions,
1721
+ response = await traceAsyncSection("agent-loop:provider-send", () =>
1722
+ this.provider.sendMessage(providerHistory, providerOptions),
1698
1723
  );
1699
1724
  } catch (llmCallError) {
1700
1725
  // Skip recording on abort — the user cancelled the request and
@@ -1790,7 +1815,10 @@ export class AgentLoop {
1790
1815
  decision: "stop",
1791
1816
  logger: rlog,
1792
1817
  };
1793
- const result = await runHook(HOOKS.POST_MODEL_CALL, ctx);
1818
+ const result = await traceAsyncSection(
1819
+ "agent-loop:post-model-call-hook",
1820
+ () => runHook(HOOKS.POST_MODEL_CALL, ctx),
1821
+ );
1794
1822
  return {
1795
1823
  finalized: { role: "assistant", content: result.content },
1796
1824
  decision: result.decision,
@@ -2492,178 +2520,3 @@ export class AgentLoop {
2492
2520
  };
2493
2521
  }
2494
2522
  }
2495
-
2496
- /** Number of most-recent AX tree snapshots to keep in conversation history. */
2497
- const MAX_AX_TREES_IN_HISTORY = 2;
2498
-
2499
- /** Regex that matches the `<ax-tree>...</ax-tree>` markers. */
2500
- const AX_TREE_PATTERN = /<ax-tree>[\s\S]*?<\/ax-tree>/g;
2501
- const AX_TREE_PLACEHOLDER = "<ax_tree_omitted />";
2502
-
2503
- /**
2504
- * Escapes any literal `</ax-tree>` occurrences inside AX tree content so
2505
- * that the non-greedy compaction regex (`AX_TREE_PATTERN`) does not stop
2506
- * prematurely when the user happens to be viewing XML/HTML source that
2507
- * contains the closing tag. The escaped content does not need to be
2508
- * unescaped because compaction replaces the entire block with a placeholder.
2509
- */
2510
- export function escapeAxTreeContent(content: string): string {
2511
- return content.replace(/<\/ax-tree>/gi, "&lt;/ax-tree&gt;");
2512
- }
2513
-
2514
- /**
2515
- * Returns a shallow copy of `messages` where all but the most recent
2516
- * `MAX_AX_TREES_IN_HISTORY` `<ax-tree>` blocks have been replaced with a
2517
- * short placeholder. This keeps the conversation context small so that
2518
- * TTFT does not grow linearly with step count in computer-use sessions.
2519
- *
2520
- * Counting is per-block, not per-message — a single user message can
2521
- * contain multiple tool_result blocks each with their own AX tree snapshot.
2522
- */
2523
- export function compactAxTreeHistory(messages: Message[]): Message[] {
2524
- // Collect (messageIndex, blockIndex) for every tool_result block with <ax-tree>
2525
- const axBlocks: Array<{ msgIdx: number; blockIdx: number }> = [];
2526
- for (let i = 0; i < messages.length; i++) {
2527
- const msg = messages[i];
2528
- if (msg.role !== "user") continue;
2529
- for (let j = 0; j < msg.content.length; j++) {
2530
- const block = msg.content[j];
2531
- if (
2532
- block.type === "tool_result" &&
2533
- typeof block.content === "string" &&
2534
- block.content.includes("<ax-tree>")
2535
- ) {
2536
- axBlocks.push({ msgIdx: i, blockIdx: j });
2537
- }
2538
- }
2539
- }
2540
-
2541
- if (axBlocks.length <= MAX_AX_TREES_IN_HISTORY) {
2542
- return messages;
2543
- }
2544
-
2545
- // Build a set of "msgIdx:blockIdx" keys for blocks that should be stripped
2546
- const toStrip = new Set(
2547
- axBlocks
2548
- .slice(0, -MAX_AX_TREES_IN_HISTORY)
2549
- .map((b) => `${b.msgIdx}:${b.blockIdx}`),
2550
- );
2551
-
2552
- return messages.map((msg, idx) => {
2553
- // Quick check: does this message have any blocks to strip?
2554
- const hasStripTarget = msg.content.some((_, j) =>
2555
- toStrip.has(`${idx}:${j}`),
2556
- );
2557
- if (!hasStripTarget) return msg;
2558
-
2559
- return {
2560
- ...msg,
2561
- content: msg.content.map((block, j) => {
2562
- if (
2563
- toStrip.has(`${idx}:${j}`) &&
2564
- block.type === "tool_result" &&
2565
- typeof block.content === "string"
2566
- ) {
2567
- return {
2568
- ...block,
2569
- content: block.content.replace(
2570
- AX_TREE_PATTERN,
2571
- AX_TREE_PLACEHOLDER,
2572
- ),
2573
- };
2574
- }
2575
- return block;
2576
- }),
2577
- };
2578
- });
2579
- }
2580
-
2581
- /**
2582
- * Strip image contentBlocks from all tool_result blocks except those in the
2583
- * most recent user message that contains tool_result blocks. This prevents
2584
- * screenshots from accumulating in the context window — each image is seen
2585
- * once by the LLM on the turn it was captured, then replaced with a text
2586
- * placeholder on subsequent turns.
2587
- *
2588
- * We target the last user message with tool_results (not just the last user
2589
- * message) because a plain-text user message may follow the tool-result
2590
- * turn. Using the last user message unconditionally would leave the most
2591
- * recent tool screenshots unprotected from stripping.
2592
- */
2593
- function stripOldMediaBlocks(history: Message[]): Message[] {
2594
- // Find the last user message that contains tool_result blocks.
2595
- let lastToolResultUserIdx = -1;
2596
- for (let i = history.length - 1; i >= 0; i--) {
2597
- if (
2598
- history[i].role === "user" &&
2599
- history[i].content.some((b) => b.type === "tool_result")
2600
- ) {
2601
- lastToolResultUserIdx = i;
2602
- break;
2603
- }
2604
- }
2605
-
2606
- return history.map((msg, idx) => {
2607
- // Keep the most recent tool-result user message intact (current turn)
2608
- if (idx === lastToolResultUserIdx || msg.role !== "user") return msg;
2609
-
2610
- // Check if any tool_result blocks carry embedded media (image or audio).
2611
- const isMedia = (cb: ContentBlock) =>
2612
- cb.type === "image" || cb.type === "file";
2613
- const hasMedia = msg.content.some(
2614
- (b) =>
2615
- b.type === "tool_result" &&
2616
- (b as ToolResultContent).contentBlocks?.some(isMedia),
2617
- );
2618
- if (!hasMedia) return msg;
2619
-
2620
- // Strip media from tool_result blocks, replacing with a text marker. The
2621
- // model already saw/heard the media in the turn it was captured; resending
2622
- // the bytes every turn (a 12 MB audio clip isn't optimized like images)
2623
- // bloats the request until compaction.
2624
- return {
2625
- ...msg,
2626
- content: msg.content.map((b) => {
2627
- if (b.type !== "tool_result") return b;
2628
- const tr = b as ToolResultContent;
2629
- if (!tr.contentBlocks?.some(isMedia)) return b;
2630
- return {
2631
- ...tr,
2632
- contentBlocks: undefined,
2633
- content:
2634
- (tr.content || "") +
2635
- "\n[Media (image/audio) was captured and shown previously — binary data removed to save context.]",
2636
- };
2637
- }),
2638
- };
2639
- });
2640
- }
2641
-
2642
- /**
2643
- * Sanitize the outbound history immediately before a provider call, bundling
2644
- * the pre-send transforms the loop applies to every request:
2645
- * - {@link stripOldMediaBlocks} drops accumulated screenshot/audio bytes from
2646
- * older tool results — the model saw the media on the turn it was captured.
2647
- * - {@link compactAxTreeHistory} collapses all but the most recent few
2648
- * `<ax-tree>` snapshots so TTFT does not grow linearly with step count.
2649
- * - {@link stripHistoricalWebSearchResults} converts historical
2650
- * `web_search_tool_result` blocks to text summaries; Anthropic's opaque
2651
- * `encrypted_content` tokens expire / are route-scoped, and replaying a stale
2652
- * one is rejected with `Invalid encrypted_content in search_result block`.
2653
- *
2654
- * Transforms the outbound copy only — the durable history keeps the rich
2655
- * originals and each send re-derives the sanitized projection (every transform
2656
- * is idempotent). Because it runs unconditionally before every provider call,
2657
- * it is the single place where oversized media and expired web-search tokens
2658
- * are guaranteed to be removed from a request.
2659
- *
2660
- * This is outbound-request preparation and should eventually move to a default
2661
- * `pre-model-call` plugin hook ({@link HOOKS.PRE_MODEL_CALL}) once that hook's
2662
- * context carries the outbound message list; for now it lives inline next to
2663
- * the provider call it guards.
2664
- */
2665
- export function preModelCallSanitize(history: Message[]): Message[] {
2666
- const mediaStripped = stripOldMediaBlocks(history);
2667
- const axCompacted = compactAxTreeHistory(mediaStripped);
2668
- return stripHistoricalWebSearchResults(axCompacted).messages;
2669
- }
@@ -0,0 +1,51 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import { BackgroundToolCompletedEventSchema } from "./background-tool-completed.js";
4
+
5
+ describe("BackgroundToolCompletedEventSchema", () => {
6
+ test("parses a completed event with exit code and output", () => {
7
+ const event = {
8
+ type: "background_tool_completed" as const,
9
+ id: "bg-1a2b3c4d",
10
+ conversationId: "conv-abc",
11
+ status: "completed" as const,
12
+ exitCode: 0,
13
+ output: "done\n",
14
+ completedAt: 1_700_000_001_000,
15
+ };
16
+
17
+ const result = BackgroundToolCompletedEventSchema.safeParse(event);
18
+
19
+ expect(result.success).toBe(true);
20
+ expect(result.success && result.data).toEqual(event);
21
+ });
22
+
23
+ test("parses a completed event without the optional fields", () => {
24
+ const event = {
25
+ type: "background_tool_completed" as const,
26
+ id: "bg-1a2b3c4d",
27
+ conversationId: "conv-abc",
28
+ status: "cancelled" as const,
29
+ completedAt: 1_700_000_001_000,
30
+ };
31
+
32
+ const result = BackgroundToolCompletedEventSchema.safeParse(event);
33
+
34
+ expect(result.success).toBe(true);
35
+ expect(result.success && result.data).toEqual(event);
36
+ });
37
+
38
+ test("strips an unrecognized field for forward compatibility", () => {
39
+ const result = BackgroundToolCompletedEventSchema.safeParse({
40
+ type: "background_tool_completed",
41
+ id: "bg-1a2b3c4d",
42
+ conversationId: "conv-abc",
43
+ status: "failed",
44
+ completedAt: 1_700_000_001_000,
45
+ unexpected: true,
46
+ });
47
+
48
+ expect(result.success).toBe(true);
49
+ expect(result.success && "unexpected" in result.data).toBe(false);
50
+ });
51
+ });
@@ -0,0 +1,29 @@
1
+ /**
2
+ * `background_tool_completed` SSE event.
3
+ *
4
+ * Server → client notification that a background bash/host_bash command
5
+ * has finished. Carries the background-tool identity (`id`), scoping
6
+ * (`conversationId`), the terminal `status`, the optional `exitCode` and
7
+ * captured `output`, and the `completedAt` timestamp.
8
+ *
9
+ * Canonical wire-contract source. Re-exported to external consumers via
10
+ * `@vellumai/assistant-api` (the `api/index.ts` barrel).
11
+ */
12
+
13
+ import { z } from "zod";
14
+
15
+ // No `.strict()`: unknown server-added fields are stripped, not rejected, so a
16
+ // future field can't make older clients drop the whole lifecycle event.
17
+ export const BackgroundToolCompletedEventSchema = z.object({
18
+ type: z.literal("background_tool_completed"),
19
+ id: z.string(),
20
+ conversationId: z.string(),
21
+ status: z.enum(["completed", "failed", "cancelled"]),
22
+ exitCode: z.number().nullable().optional(),
23
+ output: z.string().optional(),
24
+ completedAt: z.number(),
25
+ });
26
+
27
+ export type BackgroundToolCompletedEvent = z.infer<
28
+ typeof BackgroundToolCompletedEventSchema
29
+ >;
@@ -0,0 +1,36 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import { BackgroundToolStartedEventSchema } from "./background-tool-started.js";
4
+
5
+ describe("BackgroundToolStartedEventSchema", () => {
6
+ test("parses a started event", () => {
7
+ const event = {
8
+ type: "background_tool_started" as const,
9
+ id: "bg-1a2b3c4d",
10
+ toolName: "bash",
11
+ conversationId: "conv-abc",
12
+ command: "sleep 30 && echo done",
13
+ startedAt: 1_700_000_000_000,
14
+ };
15
+
16
+ const result = BackgroundToolStartedEventSchema.safeParse(event);
17
+
18
+ expect(result.success).toBe(true);
19
+ expect(result.success && result.data).toEqual(event);
20
+ });
21
+
22
+ test("strips an unrecognized field for forward compatibility", () => {
23
+ const result = BackgroundToolStartedEventSchema.safeParse({
24
+ type: "background_tool_started",
25
+ id: "bg-1a2b3c4d",
26
+ toolName: "bash",
27
+ conversationId: "conv-abc",
28
+ command: "echo hi",
29
+ startedAt: 1_700_000_000_000,
30
+ unexpected: true,
31
+ });
32
+
33
+ expect(result.success).toBe(true);
34
+ expect(result.success && "unexpected" in result.data).toBe(false);
35
+ });
36
+ });
@@ -0,0 +1,28 @@
1
+ /**
2
+ * `background_tool_started` SSE event.
3
+ *
4
+ * Server → client notification that a background bash/host_bash command
5
+ * has started. Carries the background-tool identity (`id`, a `bg-xxxxxxxx`
6
+ * id), the `toolName`, scoping (`conversationId`), the `command` being run,
7
+ * and the `startedAt` timestamp.
8
+ *
9
+ * Canonical wire-contract source. Re-exported to external consumers via
10
+ * `@vellumai/assistant-api` (the `api/index.ts` barrel).
11
+ */
12
+
13
+ import { z } from "zod";
14
+
15
+ // No `.strict()`: unknown server-added fields are stripped, not rejected, so a
16
+ // future field can't make older clients drop the whole lifecycle event.
17
+ export const BackgroundToolStartedEventSchema = z.object({
18
+ type: z.literal("background_tool_started"),
19
+ id: z.string(),
20
+ toolName: z.string(),
21
+ conversationId: z.string(),
22
+ command: z.string(),
23
+ startedAt: z.number(),
24
+ });
25
+
26
+ export type BackgroundToolStartedEvent = z.infer<
27
+ typeof BackgroundToolStartedEventSchema
28
+ >;
@@ -43,7 +43,6 @@ export const ConversationErrorCodeSchema = z.enum([
43
43
  "CONVERSATION_ABORTED",
44
44
  "CONVERSATION_PROCESSING_FAILED",
45
45
  "DISK_SPACE_CRITICAL",
46
- "REGENERATE_FAILED",
47
46
  "UNKNOWN",
48
47
  ]);
49
48
 
@@ -0,0 +1,33 @@
1
+ /**
2
+ * `open_panel` SSE event.
3
+ *
4
+ * Side-effect-only command: tells the client to open a panel or drawer
5
+ * without rendering anything in the chat transcript. Analogous to
6
+ * `open_url` and `navigate_settings` — the rolling-snapshot reducer
7
+ * has no case for it, so it naturally falls through to "no change."
8
+ *
9
+ * `panelType` identifies which panel to open; `data` carries
10
+ * panel-specific payload (validated by the handler, not the schema).
11
+ *
12
+ * `surfaceId` is the acknowledgment correlation id: the daemon holds the
13
+ * emitting tool call open until the client confirms the panel rendered by
14
+ * POSTing a surface action (`actionId: "ack"` / `"nack"`) with this id.
15
+ * Clients that receive an event without a `surfaceId` have nothing to
16
+ * acknowledge.
17
+ *
18
+ * Canonical wire-contract source. Daemon code imports the type
19
+ * directly from this file; external consumers import via
20
+ * `@vellumai/assistant-api`.
21
+ */
22
+
23
+ import { z } from "zod";
24
+
25
+ export const OpenPanelEventSchema = z.object({
26
+ type: z.literal("open_panel"),
27
+ panelType: z.string(),
28
+ data: z.record(z.string(), z.unknown()).optional(),
29
+ conversationId: z.string().optional(),
30
+ surfaceId: z.string().optional(),
31
+ });
32
+
33
+ export type OpenPanelEvent = z.infer<typeof OpenPanelEventSchema>;
@@ -22,7 +22,9 @@ import { z } from "zod";
22
22
  /**
23
23
  * Subagent lifecycle status. Mirrors `SubagentStatus` in
24
24
  * `assistant/src/subagent/types.ts`. `aborted` is a terminal state
25
- * reached via explicit `subagent_abort` request.
25
+ * reached via explicit `subagent_abort` request; `interrupted` is a
26
+ * terminal state assigned on daemon restart to a subagent that was
27
+ * still in flight (it is not auto-resumed).
26
28
  */
27
29
  export const SubagentStatusSchema = z.enum([
28
30
  "pending",
@@ -31,6 +33,7 @@ export const SubagentStatusSchema = z.enum([
31
33
  "completed",
32
34
  "failed",
33
35
  "aborted",
36
+ "interrupted",
34
37
  ]);
35
38
 
36
39
  export type SubagentStatus = z.infer<typeof SubagentStatusSchema>;