@vellumai/assistant 0.5.6 → 0.5.8

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 (442) hide show
  1. package/.env.example +16 -2
  2. package/ARCHITECTURE.md +6 -75
  3. package/Dockerfile +3 -2
  4. package/README.md +0 -2
  5. package/bun.lock +0 -414
  6. package/docker-entrypoint.sh +9 -0
  7. package/docs/architecture/keychain-broker.md +45 -240
  8. package/docs/architecture/memory.md +13 -11
  9. package/docs/architecture/security.md +0 -17
  10. package/docs/credential-execution-service.md +2 -2
  11. package/node_modules/@vellumai/ces-contracts/package.json +1 -0
  12. package/node_modules/@vellumai/ces-contracts/src/error.ts +1 -1
  13. package/node_modules/@vellumai/ces-contracts/src/grants.ts +1 -1
  14. package/node_modules/@vellumai/ces-contracts/src/handles.ts +1 -1
  15. package/node_modules/@vellumai/ces-contracts/src/index.ts +1 -1
  16. package/node_modules/@vellumai/ces-contracts/src/rpc.ts +120 -1
  17. package/node_modules/@vellumai/credential-storage/package.json +1 -0
  18. package/node_modules/@vellumai/egress-proxy/package.json +1 -0
  19. package/package.json +2 -3
  20. package/src/__tests__/actor-token-service.test.ts +0 -114
  21. package/src/__tests__/approval-cascade.test.ts +0 -1
  22. package/src/__tests__/assistant-feature-flags-integration.test.ts +30 -29
  23. package/src/__tests__/browser-fill-credential.test.ts +1 -1
  24. package/src/__tests__/browser-skill-endstate.test.ts +6 -5
  25. package/src/__tests__/btw-routes.test.ts +0 -39
  26. package/src/__tests__/call-controller.test.ts +0 -1
  27. package/src/__tests__/call-domain.test.ts +0 -128
  28. package/src/__tests__/ces-rpc-credential-backend.test.ts +199 -0
  29. package/src/__tests__/ces-startup-timeout.test.ts +40 -0
  30. package/src/__tests__/channel-approval-routes.test.ts +0 -5
  31. package/src/__tests__/channel-readiness-service.test.ts +1 -60
  32. package/src/__tests__/checker.test.ts +4 -2
  33. package/src/__tests__/cli-command-risk-guard.test.ts +112 -0
  34. package/src/__tests__/config-schema-cmd.test.ts +0 -2
  35. package/src/__tests__/config-schema.test.ts +3 -1
  36. package/src/__tests__/conversation-abort-tool-results.test.ts +0 -1
  37. package/src/__tests__/conversation-agent-loop-overflow.test.ts +0 -2
  38. package/src/__tests__/conversation-agent-loop.test.ts +2 -4
  39. package/src/__tests__/conversation-attention-telegram.test.ts +0 -5
  40. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -1
  41. package/src/__tests__/conversation-error.test.ts +15 -1
  42. package/src/__tests__/conversation-init.benchmark.test.ts +0 -2
  43. package/src/__tests__/conversation-messaging-secret-redirect.test.ts +1 -1
  44. package/src/__tests__/conversation-pre-run-repair.test.ts +0 -1
  45. package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -1
  46. package/src/__tests__/conversation-queue.test.ts +0 -1
  47. package/src/__tests__/conversation-skill-tools.test.ts +0 -54
  48. package/src/__tests__/conversation-slash-queue.test.ts +0 -1
  49. package/src/__tests__/conversation-slash-unknown.test.ts +0 -1
  50. package/src/__tests__/conversation-title-service.test.ts +87 -0
  51. package/src/__tests__/conversation-workspace-injection.test.ts +0 -1
  52. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -1
  53. package/src/__tests__/credential-execution-client.test.ts +5 -2
  54. package/src/__tests__/credential-execution-feature-gates.test.ts +59 -30
  55. package/src/__tests__/credential-execution-managed-contract.test.ts +35 -20
  56. package/src/__tests__/credential-security-e2e.test.ts +1 -67
  57. package/src/__tests__/credential-security-invariants.test.ts +6 -50
  58. package/src/__tests__/credentials-cli.test.ts +82 -3
  59. package/src/__tests__/daemon-credential-client.test.ts +123 -0
  60. package/src/__tests__/db-migration-rollback.test.ts +2015 -1
  61. package/src/__tests__/deterministic-verification-control-plane.test.ts +1 -0
  62. package/src/__tests__/docker-signing-key-bootstrap.test.ts +34 -143
  63. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +6 -4
  64. package/src/__tests__/gateway-client-managed-outbound.test.ts +79 -1
  65. package/src/__tests__/guardian-routing-state.test.ts +0 -5
  66. package/src/__tests__/host-shell-tool.test.ts +6 -7
  67. package/src/__tests__/http-user-message-parity.test.ts +3 -103
  68. package/src/__tests__/inbound-invite-redemption.test.ts +0 -4
  69. package/src/__tests__/inline-skill-load-permissions.test.ts +6 -8
  70. package/src/__tests__/intent-routing.test.ts +0 -13
  71. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +178 -0
  72. package/src/__tests__/journal-context.test.ts +335 -0
  73. package/src/__tests__/keychain-broker-client.test.ts +161 -22
  74. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +0 -3
  75. package/src/__tests__/memory-jobs-worker-backoff.test.ts +150 -0
  76. package/src/__tests__/memory-lifecycle-e2e.test.ts +70 -25
  77. package/src/__tests__/memory-recall-quality.test.ts +48 -17
  78. package/src/__tests__/memory-regressions.test.ts +408 -363
  79. package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -3
  80. package/src/__tests__/migration-export-http.test.ts +2 -2
  81. package/src/__tests__/migration-import-commit-http.test.ts +2 -2
  82. package/src/__tests__/migration-import-preflight-http.test.ts +2 -2
  83. package/src/__tests__/migration-validate-http.test.ts +2 -2
  84. package/src/__tests__/non-member-access-request.test.ts +2 -7
  85. package/src/__tests__/notification-decision-fallback.test.ts +4 -0
  86. package/src/__tests__/notification-decision-identity.test.ts +4 -0
  87. package/src/__tests__/notification-decision-strategy.test.ts +71 -0
  88. package/src/__tests__/oauth-cli.test.ts +5 -1
  89. package/src/__tests__/permission-types.test.ts +1 -0
  90. package/src/__tests__/provider-commit-message-generator.test.ts +0 -37
  91. package/src/__tests__/provider-error-scenarios.test.ts +0 -267
  92. package/src/__tests__/provider-managed-proxy-integration.test.ts +5 -6
  93. package/src/__tests__/provider-streaming.benchmark.test.ts +2 -81
  94. package/src/__tests__/qdrant-manager.test.ts +28 -2
  95. package/src/__tests__/registry.test.ts +0 -6
  96. package/src/__tests__/relay-server.test.ts +1 -2
  97. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -4
  98. package/src/__tests__/script-proxy-injection-runtime.test.ts +1 -1
  99. package/src/__tests__/secret-onetime-send.test.ts +1 -1
  100. package/src/__tests__/secret-routes-managed-proxy.test.ts +0 -4
  101. package/src/__tests__/secure-keys.test.ts +95 -272
  102. package/src/__tests__/shell-identity.test.ts +96 -6
  103. package/src/__tests__/skill-feature-flags-integration.test.ts +22 -14
  104. package/src/__tests__/skill-feature-flags.test.ts +46 -45
  105. package/src/__tests__/skill-load-feature-flag.test.ts +7 -10
  106. package/src/__tests__/skill-load-inline-command.test.ts +8 -12
  107. package/src/__tests__/skill-load-inline-includes.test.ts +6 -10
  108. package/src/__tests__/skill-load-tool.test.ts +0 -2
  109. package/src/__tests__/skill-memory.test.ts +17 -3
  110. package/src/__tests__/skill-projection-feature-flag.test.ts +33 -29
  111. package/src/__tests__/skills.test.ts +0 -2
  112. package/src/__tests__/slack-inbound-verification.test.ts +0 -4
  113. package/src/__tests__/stale-approval-dedup.test.ts +171 -0
  114. package/src/__tests__/stt-hints.test.ts +437 -0
  115. package/src/__tests__/suggestion-routes.test.ts +1 -32
  116. package/src/__tests__/system-prompt.test.ts +0 -1
  117. package/src/__tests__/task-memory-cleanup.test.ts +14 -0
  118. package/src/__tests__/tool-executor-shell-integration.test.ts +5 -3
  119. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +0 -5
  120. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -4
  121. package/src/__tests__/twilio-routes-twiml.test.ts +139 -1
  122. package/src/__tests__/update-bulletin.test.ts +0 -2
  123. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +6 -9
  124. package/src/__tests__/voice-quality.test.ts +58 -0
  125. package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -7
  126. package/src/__tests__/workspace-migration-015-migrate-credentials-to-keychain.test.ts +252 -0
  127. package/src/__tests__/workspace-migration-016-migrate-credentials-from-keychain.test.ts +220 -0
  128. package/src/__tests__/workspace-migration-down-functions.test.ts +1009 -0
  129. package/src/__tests__/workspace-migrations-runner.test.ts +114 -0
  130. package/src/acp/agent-process.ts +9 -1
  131. package/src/agent/loop.ts +1 -1
  132. package/src/approvals/guardian-request-resolvers.ts +164 -38
  133. package/src/calls/__tests__/tts-text-sanitizer.test.ts +254 -0
  134. package/src/calls/audio-store.test.ts +97 -0
  135. package/src/calls/audio-store.ts +205 -0
  136. package/src/calls/call-controller.ts +90 -8
  137. package/src/calls/call-domain.ts +3 -0
  138. package/src/calls/call-store.ts +10 -3
  139. package/src/calls/fish-audio-client.ts +129 -0
  140. package/src/calls/relay-server.ts +27 -0
  141. package/src/calls/stt-hints.ts +189 -0
  142. package/src/calls/tts-text-sanitizer.ts +61 -0
  143. package/src/calls/twilio-routes.ts +34 -5
  144. package/src/calls/types.ts +1 -0
  145. package/src/calls/voice-ingress-preflight.ts +0 -42
  146. package/src/calls/voice-quality.ts +38 -5
  147. package/src/calls/voice-session-bridge.ts +7 -12
  148. package/src/cli/commands/avatar.ts +2 -2
  149. package/src/cli/commands/config.ts +1 -4
  150. package/src/cli/commands/credentials.ts +128 -82
  151. package/src/cli/commands/doctor.ts +2 -2
  152. package/src/cli/commands/keys.ts +7 -7
  153. package/src/cli/commands/memory.ts +1 -1
  154. package/src/cli/commands/oauth/connections.ts +11 -29
  155. package/src/cli/commands/oauth/index.ts +7 -0
  156. package/src/cli/commands/oauth/platform.ts +525 -0
  157. package/src/cli/commands/platform.ts +3 -3
  158. package/src/cli/lib/daemon-credential-client.ts +284 -0
  159. package/src/cli.ts +1 -1
  160. package/src/config/assistant-feature-flags.ts +186 -5
  161. package/src/config/bundled-skills/AGENTS.md +34 -0
  162. package/src/config/bundled-skills/acp/SKILL.md +10 -0
  163. package/src/config/bundled-skills/app-builder/SKILL.md +0 -4
  164. package/src/config/bundled-skills/messaging/SKILL.md +5 -5
  165. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +2 -2
  166. package/src/config/bundled-skills/phone-calls/TOOLS.json +4 -0
  167. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +1 -0
  168. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +1 -0
  169. package/src/config/bundled-skills/settings/SKILL.md +15 -2
  170. package/src/config/bundled-skills/settings/TOOLS.json +47 -2
  171. package/src/config/bundled-skills/settings/tools/avatar-remove.ts +59 -0
  172. package/src/config/bundled-skills/settings/tools/avatar-update.ts +80 -0
  173. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +42 -0
  174. package/src/config/bundled-skills/slack/SKILL.md +1 -1
  175. package/src/config/bundled-tool-registry.ts +5 -11
  176. package/src/config/defaults.ts +0 -2
  177. package/src/config/env-registry.ts +5 -5
  178. package/src/config/env.ts +21 -14
  179. package/src/config/feature-flag-registry.json +49 -9
  180. package/src/config/loader.ts +106 -42
  181. package/src/config/schema.ts +9 -29
  182. package/src/config/schemas/calls.ts +30 -0
  183. package/src/config/schemas/fish-audio.ts +39 -0
  184. package/src/config/schemas/inference.ts +2 -2
  185. package/src/config/schemas/journal.ts +16 -0
  186. package/src/config/schemas/memory-processing.ts +2 -2
  187. package/src/config/schemas/security.ts +0 -4
  188. package/src/config/types.ts +1 -1
  189. package/src/contacts/contact-store.ts +39 -0
  190. package/src/contacts/types.ts +2 -0
  191. package/src/credential-execution/approval-bridge.ts +1 -0
  192. package/src/credential-execution/executable-discovery.ts +28 -4
  193. package/src/credential-execution/feature-gates.ts +16 -0
  194. package/src/credential-execution/process-manager.ts +38 -0
  195. package/src/credential-execution/startup-timeout.ts +36 -0
  196. package/src/daemon/approval-generators.ts +3 -9
  197. package/src/daemon/assistant-attachments.ts +9 -0
  198. package/src/daemon/config-watcher.ts +5 -0
  199. package/src/daemon/conversation-error.ts +13 -1
  200. package/src/daemon/conversation-memory.ts +1 -2
  201. package/src/daemon/conversation-process.ts +18 -1
  202. package/src/daemon/conversation-surfaces.ts +30 -1
  203. package/src/daemon/conversation-tool-setup.ts +0 -105
  204. package/src/daemon/conversation.ts +21 -1
  205. package/src/daemon/guardian-action-generators.ts +3 -9
  206. package/src/daemon/handlers/config-vercel.ts +92 -0
  207. package/src/daemon/handlers/skills.ts +2 -15
  208. package/src/daemon/install-symlink.ts +195 -0
  209. package/src/daemon/lifecycle.ts +234 -51
  210. package/src/daemon/message-types/conversations.ts +4 -4
  211. package/src/daemon/message-types/diagnostics.ts +3 -22
  212. package/src/daemon/message-types/messages.ts +0 -2
  213. package/src/daemon/message-types/upgrades.ts +8 -0
  214. package/src/daemon/server.ts +32 -95
  215. package/src/events/domain-events.ts +2 -1
  216. package/src/inbound/platform-callback-registration.ts +3 -3
  217. package/src/instrument.ts +8 -5
  218. package/src/memory/app-store.ts +31 -0
  219. package/src/memory/conversation-title-service.ts +50 -1
  220. package/src/memory/db-init.ts +16 -0
  221. package/src/memory/indexer.ts +19 -10
  222. package/src/memory/items-extractor.ts +328 -321
  223. package/src/memory/job-handlers/conversation-starters.ts +4 -1
  224. package/src/memory/job-handlers/summarization.ts +26 -16
  225. package/src/memory/jobs-store.ts +63 -6
  226. package/src/memory/jobs-worker.ts +31 -7
  227. package/src/memory/journal-memory.ts +214 -0
  228. package/src/memory/migrations/001-job-deferrals.ts +19 -0
  229. package/src/memory/migrations/004-entity-relation-dedup.ts +10 -0
  230. package/src/memory/migrations/005-fingerprint-scope-unique.ts +76 -0
  231. package/src/memory/migrations/006-scope-salted-fingerprints.ts +50 -0
  232. package/src/memory/migrations/007-assistant-id-to-self.ts +10 -0
  233. package/src/memory/migrations/008-remove-assistant-id-columns.ts +34 -0
  234. package/src/memory/migrations/009-llm-usage-events-drop-assistant-id.ts +26 -0
  235. package/src/memory/migrations/014-backfill-inbox-thread-state.ts +10 -0
  236. package/src/memory/migrations/015-drop-active-search-index.ts +17 -0
  237. package/src/memory/migrations/019-notification-tables-schema-migration.ts +12 -0
  238. package/src/memory/migrations/020-rename-macos-ios-channel-to-vellum.ts +121 -0
  239. package/src/memory/migrations/024-embedding-vector-blob.ts +74 -0
  240. package/src/memory/migrations/026a-embeddings-nullable-vector-json.ts +82 -0
  241. package/src/memory/migrations/036-normalize-phone-identities.ts +11 -0
  242. package/src/memory/migrations/116-messages-fts.ts +106 -1
  243. package/src/memory/migrations/126-backfill-guardian-principal-id.ts +52 -0
  244. package/src/memory/migrations/127-guardian-principal-id-not-null.ts +77 -0
  245. package/src/memory/migrations/134-contacts-notes-column.ts +13 -0
  246. package/src/memory/migrations/135-backfill-contact-interaction-stats.ts +20 -0
  247. package/src/memory/migrations/136-drop-assistant-id-columns.ts +52 -0
  248. package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +13 -0
  249. package/src/memory/migrations/141-rename-verification-table.ts +54 -0
  250. package/src/memory/migrations/142-rename-verification-session-id-column.ts +25 -0
  251. package/src/memory/migrations/143-rename-guardian-verification-values.ts +35 -0
  252. package/src/memory/migrations/144-rename-voice-to-phone.ts +136 -0
  253. package/src/memory/migrations/145-drop-accounts-table.ts +32 -0
  254. package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +14 -1
  255. package/src/memory/migrations/148-drop-reminders-table.ts +35 -1
  256. package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +69 -1
  257. package/src/memory/migrations/162-guardian-timestamps-epoch-ms.ts +290 -0
  258. package/src/memory/migrations/169-rename-gmail-provider-key-to-google.ts +51 -1
  259. package/src/memory/migrations/174-rename-thread-starters-table.ts +47 -1
  260. package/src/memory/migrations/176-drop-capability-card-state.ts +13 -0
  261. package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +16 -0
  262. package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +28 -1
  263. package/src/memory/migrations/190-call-session-skip-disclosure.ts +15 -0
  264. package/src/memory/migrations/191-backfill-audio-attachment-mime-types.ts +64 -0
  265. package/src/memory/migrations/192-contacts-user-file-column.ts +15 -0
  266. package/src/memory/migrations/193-add-source-type-columns.ts +81 -0
  267. package/src/memory/migrations/index.ts +5 -0
  268. package/src/memory/migrations/registry.ts +98 -0
  269. package/src/memory/migrations/validate-migration-state.ts +137 -11
  270. package/src/memory/qdrant-circuit-breaker.ts +9 -0
  271. package/src/memory/qdrant-manager.ts +64 -7
  272. package/src/memory/retriever.test.ts +37 -25
  273. package/src/memory/retriever.ts +24 -49
  274. package/src/memory/schema/calls.ts +1 -0
  275. package/src/memory/schema/contacts.ts +1 -0
  276. package/src/memory/schema/memory-core.ts +2 -0
  277. package/src/memory/search/formatting.ts +7 -44
  278. package/src/memory/search/staleness.ts +4 -0
  279. package/src/memory/search/tier-classifier.ts +10 -2
  280. package/src/memory/search/types.ts +2 -5
  281. package/src/memory/task-memory-cleanup.ts +4 -3
  282. package/src/notifications/adapters/slack.ts +168 -6
  283. package/src/notifications/broadcaster.ts +1 -0
  284. package/src/notifications/copy-composer.ts +59 -2
  285. package/src/notifications/decision-engine.ts +4 -1
  286. package/src/notifications/signal.ts +2 -0
  287. package/src/notifications/types.ts +2 -0
  288. package/src/oauth/connection-resolver.ts +6 -4
  289. package/src/permissions/checker.ts +0 -38
  290. package/src/permissions/shell-identity.ts +76 -22
  291. package/src/permissions/types.ts +4 -2
  292. package/src/platform/client.ts +35 -7
  293. package/src/prompts/journal-context.ts +133 -0
  294. package/src/prompts/persona-resolver.ts +194 -0
  295. package/src/prompts/system-prompt.ts +44 -4
  296. package/src/prompts/templates/SOUL.md +10 -0
  297. package/src/prompts/templates/users/default.md +1 -0
  298. package/src/providers/provider-send-message.ts +3 -32
  299. package/src/providers/registry.ts +29 -179
  300. package/src/providers/types.ts +1 -1
  301. package/src/runtime/access-request-helper.ts +4 -0
  302. package/src/runtime/auth/__tests__/credential-service.test.ts +0 -1
  303. package/src/runtime/auth/__tests__/external-assistant-id.test.ts +13 -68
  304. package/src/runtime/auth/__tests__/guard-tests.test.ts +9 -50
  305. package/src/runtime/auth/external-assistant-id.ts +13 -59
  306. package/src/runtime/auth/route-policy.ts +17 -1
  307. package/src/runtime/auth/token-service.ts +43 -138
  308. package/src/runtime/channel-readiness-service.ts +1 -16
  309. package/src/runtime/gateway-client.ts +47 -4
  310. package/src/runtime/guardian-decision-types.ts +45 -4
  311. package/src/runtime/http-server.ts +31 -3
  312. package/src/runtime/middleware/error-handler.ts +1 -9
  313. package/src/runtime/routes/access-request-decision.ts +2 -2
  314. package/src/runtime/routes/app-management-routes.ts +2 -1
  315. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +219 -30
  316. package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +37 -14
  317. package/src/runtime/routes/audio-routes.ts +40 -0
  318. package/src/runtime/routes/btw-routes.ts +0 -17
  319. package/src/runtime/routes/channel-readiness-routes.ts +9 -4
  320. package/src/runtime/routes/conversation-query-routes.ts +63 -1
  321. package/src/runtime/routes/conversation-routes.ts +4 -44
  322. package/src/runtime/routes/debug-routes.ts +12 -9
  323. package/src/runtime/routes/diagnostics-routes.ts +1 -477
  324. package/src/runtime/routes/guardian-approval-interception.ts +168 -11
  325. package/src/runtime/routes/guardian-approval-prompt.ts +6 -1
  326. package/src/runtime/routes/guardian-approval-reply-helpers.ts +103 -21
  327. package/src/runtime/routes/identity-routes.ts +19 -30
  328. package/src/runtime/routes/inbound-message-handler.ts +31 -1
  329. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +64 -5
  330. package/src/runtime/routes/inbound-stages/background-dispatch.ts +52 -40
  331. package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +4 -33
  332. package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +1 -1
  333. package/src/runtime/routes/integrations/twilio.ts +52 -10
  334. package/src/runtime/routes/integrations/vercel.ts +89 -0
  335. package/src/runtime/routes/log-export-routes.ts +5 -0
  336. package/src/runtime/routes/memory-item-routes.test.ts +3 -3
  337. package/src/runtime/routes/memory-item-routes.ts +46 -14
  338. package/src/runtime/routes/migration-rollback-routes.ts +209 -0
  339. package/src/runtime/routes/migration-routes.ts +17 -1
  340. package/src/runtime/routes/notification-routes.ts +58 -0
  341. package/src/runtime/routes/schedule-routes.ts +65 -0
  342. package/src/runtime/routes/secret-routes.ts +141 -10
  343. package/src/runtime/routes/settings-routes.ts +41 -1
  344. package/src/runtime/routes/tts-routes.ts +96 -0
  345. package/src/runtime/routes/upgrade-broadcast-routes.ts +26 -2
  346. package/src/runtime/routes/workspace-commit-routes.ts +62 -0
  347. package/src/runtime/routes/workspace-routes.test.ts +22 -1
  348. package/src/runtime/routes/workspace-routes.ts +1 -1
  349. package/src/runtime/routes/workspace-utils.ts +86 -2
  350. package/src/security/ces-credential-client.ts +75 -29
  351. package/src/security/ces-rpc-credential-backend.ts +86 -0
  352. package/src/security/credential-backend.ts +22 -92
  353. package/src/security/keychain-broker-client.ts +10 -2
  354. package/src/security/secure-keys.ts +113 -115
  355. package/src/skills/catalog-install.ts +6 -32
  356. package/src/skills/skill-memory.ts +1 -0
  357. package/src/subagent/manager.ts +2 -5
  358. package/src/telemetry/usage-telemetry-reporter.ts +4 -2
  359. package/src/tools/acp/spawn.ts +78 -1
  360. package/src/tools/calls/call-start.ts +1 -0
  361. package/src/tools/credentials/vault.ts +5 -3
  362. package/src/tools/executor.ts +0 -4
  363. package/src/tools/memory/definitions.ts +3 -2
  364. package/src/tools/memory/handlers.ts +10 -7
  365. package/src/tools/network/script-proxy/session-manager.ts +19 -4
  366. package/src/tools/network/web-fetch.ts +3 -1
  367. package/src/tools/skills/execute.ts +1 -1
  368. package/src/tools/terminal/safe-env.ts +1 -0
  369. package/src/tools/types.ts +0 -8
  370. package/src/util/browser.ts +15 -0
  371. package/src/util/errors.ts +0 -12
  372. package/src/util/platform.ts +4 -51
  373. package/src/workspace/git-service.ts +5 -2
  374. package/src/workspace/migrations/001-avatar-rename.ts +15 -0
  375. package/src/workspace/migrations/003-seed-device-id.ts +17 -1
  376. package/src/workspace/migrations/004-extract-collect-usage-data.ts +33 -0
  377. package/src/workspace/migrations/005-add-send-diagnostics.ts +3 -0
  378. package/src/workspace/migrations/006-services-config.ts +49 -0
  379. package/src/workspace/migrations/007-web-search-provider-rename.ts +27 -0
  380. package/src/workspace/migrations/008-voice-timeout-and-max-steps.ts +3 -0
  381. package/src/workspace/migrations/009-backfill-conversation-disk-view.ts +4 -0
  382. package/src/workspace/migrations/010-app-dir-rename.ts +78 -0
  383. package/src/workspace/migrations/011-backfill-installation-id.ts +11 -0
  384. package/src/workspace/migrations/012-rename-conversation-disk-view-dirs.ts +44 -0
  385. package/src/workspace/migrations/013-repair-conversation-disk-view.ts +5 -0
  386. package/src/workspace/migrations/015-migrate-credentials-to-keychain.ts +153 -0
  387. package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +156 -0
  388. package/src/workspace/migrations/016-migrate-credentials-from-keychain.ts +150 -0
  389. package/src/workspace/migrations/017-seed-persona-dirs.ts +96 -0
  390. package/src/workspace/migrations/018-rekey-compound-credential-keys.ts +184 -0
  391. package/src/workspace/migrations/019-scope-journal-to-guardian.ts +103 -0
  392. package/src/workspace/migrations/migrate-to-workspace-volume.ts +27 -5
  393. package/src/workspace/migrations/registry.ts +12 -0
  394. package/src/workspace/migrations/runner.ts +106 -2
  395. package/src/workspace/migrations/types.ts +4 -0
  396. package/src/workspace/provider-commit-message-generator.ts +12 -21
  397. package/src/__tests__/claude-code-skill-regression.test.ts +0 -206
  398. package/src/__tests__/claude-code-tool-profiles.test.ts +0 -99
  399. package/src/__tests__/diagnostics-export.test.ts +0 -288
  400. package/src/__tests__/local-gateway-health.test.ts +0 -209
  401. package/src/__tests__/provider-fail-open-selection.test.ts +0 -271
  402. package/src/__tests__/provider-failover-actual-provider.test.ts +0 -66
  403. package/src/__tests__/secret-ingress-handler.test.ts +0 -120
  404. package/src/__tests__/swarm-conversation-integration.test.ts +0 -358
  405. package/src/__tests__/swarm-dag-pathological.test.ts +0 -547
  406. package/src/__tests__/swarm-orchestrator.test.ts +0 -463
  407. package/src/__tests__/swarm-plan-validator.test.ts +0 -384
  408. package/src/__tests__/swarm-recursion.test.ts +0 -197
  409. package/src/__tests__/swarm-router-planner.test.ts +0 -234
  410. package/src/__tests__/swarm-tool.test.ts +0 -185
  411. package/src/__tests__/swarm-worker-backend.test.ts +0 -144
  412. package/src/__tests__/swarm-worker-runner.test.ts +0 -288
  413. package/src/commands/__tests__/cc-command-registry.test.ts +0 -396
  414. package/src/commands/cc-command-registry.ts +0 -248
  415. package/src/config/bundled-skills/claude-code/SKILL.md +0 -53
  416. package/src/config/bundled-skills/claude-code/TOOLS.json +0 -47
  417. package/src/config/bundled-skills/claude-code/tools/claude-code.ts +0 -12
  418. package/src/config/bundled-skills/orchestration/SKILL.md +0 -33
  419. package/src/config/bundled-skills/orchestration/TOOLS.json +0 -35
  420. package/src/config/bundled-skills/orchestration/tools/swarm-delegate.ts +0 -12
  421. package/src/config/schemas/swarm.ts +0 -82
  422. package/src/logfire.ts +0 -135
  423. package/src/memory/search/lexical.ts +0 -48
  424. package/src/providers/failover.ts +0 -186
  425. package/src/runtime/local-gateway-health.ts +0 -275
  426. package/src/security/secret-ingress.ts +0 -68
  427. package/src/swarm/backend-claude-code.ts +0 -225
  428. package/src/swarm/checkpoint.ts +0 -137
  429. package/src/swarm/graph-utils.ts +0 -53
  430. package/src/swarm/index.ts +0 -55
  431. package/src/swarm/limits.ts +0 -66
  432. package/src/swarm/orchestrator.ts +0 -424
  433. package/src/swarm/plan-validator.ts +0 -117
  434. package/src/swarm/router-planner.ts +0 -162
  435. package/src/swarm/router-prompts.ts +0 -39
  436. package/src/swarm/synthesizer.ts +0 -81
  437. package/src/swarm/types.ts +0 -72
  438. package/src/swarm/worker-backend.ts +0 -131
  439. package/src/swarm/worker-prompts.ts +0 -80
  440. package/src/swarm/worker-runner.ts +0 -170
  441. package/src/tools/claude-code/claude-code.ts +0 -610
  442. package/src/tools/swarm/delegate.ts +0 -205
@@ -7,6 +7,13 @@ export interface ServiceGroupUpdateStarting {
7
7
  expectedDowntimeSeconds: number;
8
8
  }
9
9
 
10
+ /** Broadcast to connected clients with a progress update during an upgrade or rollback. */
11
+ export interface ServiceGroupUpdateProgress {
12
+ type: "service_group_update_progress";
13
+ /** A short, user-friendly status message describing what's happening right now. */
14
+ statusMessage: string;
15
+ }
16
+
10
17
  /** Broadcast to connected clients when a service group update has completed. */
11
18
  export interface ServiceGroupUpdateComplete {
12
19
  type: "service_group_update_complete";
@@ -20,4 +27,5 @@ export interface ServiceGroupUpdateComplete {
20
27
 
21
28
  export type _UpgradesServerMessages =
22
29
  | ServiceGroupUpdateStarting
30
+ | ServiceGroupUpdateProgress
23
31
  | ServiceGroupUpdateComplete;
@@ -20,13 +20,7 @@ import {
20
20
  import { getConfig } from "../config/loader.js";
21
21
  import { onContactChange } from "../contacts/contact-events.js";
22
22
  import type { CesClient } from "../credential-execution/client.js";
23
- import { createCesClient } from "../credential-execution/client.js";
24
- import { isCesToolsEnabled } from "../credential-execution/feature-gates.js";
25
- import {
26
- type CesProcessManager,
27
- CesUnavailableError,
28
- createCesProcessManager,
29
- } from "../credential-execution/process-manager.js";
23
+ import type { CesProcessManager } from "../credential-execution/process-manager.js";
30
24
  import type { HeartbeatService } from "../heartbeat/heartbeat-service.js";
31
25
  import * as attachmentsStore from "../memory/attachments-store.js";
32
26
  import {
@@ -45,10 +39,9 @@ import {
45
39
  import { updateMetaFile } from "../memory/conversation-disk-view.js";
46
40
  import { getOrCreateConversation } from "../memory/conversation-key-store.js";
47
41
  import { buildSystemPrompt } from "../prompts/system-prompt.js";
48
- import { resolveManagedProxyContext } from "../providers/managed-proxy/context.js";
49
42
  import { RateLimitProvider } from "../providers/ratelimit.js";
50
43
  import {
51
- getFailoverProvider,
44
+ getProvider,
52
45
  initializeProviders,
53
46
  } from "../providers/registry.js";
54
47
  import { buildAssistantEvent } from "../runtime/assistant-event.js";
@@ -57,13 +50,11 @@ import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
57
50
  import { getSigningKeyFingerprint } from "../runtime/auth/token-service.js";
58
51
  import { bridgeConfirmationRequestToGuardian } from "../runtime/confirmation-request-guardian-bridge.js";
59
52
  import * as pendingInteractions from "../runtime/pending-interactions.js";
60
- import { checkIngressForSecrets } from "../security/secret-ingress.js";
61
53
  import { registerCancelCallback } from "../signals/cancel.js";
62
54
  import { registerConversationUndoCallback } from "../signals/conversation-undo.js";
63
55
  import { appendEventToStream } from "../signals/event-stream.js";
64
56
  import { registerUserMessageCallback } from "../signals/user-message.js";
65
57
  import { getSubagentManager } from "../subagent/index.js";
66
- import { IngressBlockedError } from "../util/errors.js";
67
58
  import { getLogger } from "../util/logger.js";
68
59
  import {
69
60
  getSandboxWorkingDir,
@@ -253,7 +244,6 @@ export class DaemonServer {
253
244
  private conversationOptions = new Map<string, ConversationCreateOptions>();
254
245
  private conversationCreating = new Map<string, Promise<Conversation>>();
255
246
  private sharedRequestTimestamps: number[] = [];
256
- private httpPort: number | undefined;
257
247
  private unsubscribeContactChange: (() => void) | null = null;
258
248
  private evictor: ConversationEvictor;
259
249
  private _hubChain: Promise<void> = Promise.resolve();
@@ -262,8 +252,8 @@ export class DaemonServer {
262
252
  private configWatcher = new ConfigWatcher();
263
253
 
264
254
  // CES (Credential Execution Service) — process-level singleton.
265
- // The CES sidecar accepts exactly one bootstrap connection, so we must
266
- // hold that connection at the server level rather than per-conversation.
255
+ // Lifecycle is managed by startCesProcess() in lifecycle.ts; the server
256
+ // receives the result via setCes().
267
257
  private cesProcessManager?: CesProcessManager;
268
258
  private cesClientPromise?: Promise<CesClient | undefined>;
269
259
  private cesInitAbortController?: AbortController;
@@ -274,6 +264,31 @@ export class DaemonServer {
274
264
  */
275
265
  assistantId: string = DAEMON_INTERNAL_ASSISTANT_ID;
276
266
 
267
+ /**
268
+ * Inject the CES client and process manager from the caller (lifecycle.ts).
269
+ * Must be called before start().
270
+ */
271
+ setCes(result: {
272
+ client: CesClient | undefined;
273
+ processManager: CesProcessManager | undefined;
274
+ clientPromise: Promise<CesClient | undefined> | undefined;
275
+ abortController: AbortController | undefined;
276
+ }): void {
277
+ this.cesClientRef = result.client;
278
+ this.cesProcessManager = result.processManager;
279
+ this.cesInitAbortController = result.abortController;
280
+
281
+ // Wrap the external promise so that cesClientRef stays in sync once the
282
+ // handshake completes — the async work runs in lifecycle.ts but the
283
+ // server needs the resolved client reference for getCesClient().
284
+ if (result.clientPromise) {
285
+ this.cesClientPromise = result.clientPromise.then((client) => {
286
+ this.cesClientRef = client;
287
+ return client;
288
+ });
289
+ }
290
+ }
291
+
277
292
  /**
278
293
  * Return the CES client reference (if available).
279
294
  * Used by routes that need to push updates to CES (e.g. secret-routes).
@@ -538,73 +553,6 @@ export class DaemonServer {
538
553
  this.broadcast({ type: "contacts_changed" });
539
554
  });
540
555
 
541
- // CES lifecycle — start the CES process and perform the RPC handshake
542
- // once at server level. The managed sidecar accepts exactly one bootstrap
543
- // connection, so this must be a process-level singleton.
544
- if (isCesToolsEnabled(config)) {
545
- const pm = createCesProcessManager({ assistantConfig: config });
546
- this.cesProcessManager = pm;
547
- const abortController = new AbortController();
548
- this.cesInitAbortController = abortController;
549
- this.cesClientPromise = (async () => {
550
- try {
551
- const transport = await pm.start();
552
- if (abortController.signal.aborted) {
553
- throw new Error("CES initialization aborted during shutdown");
554
- }
555
- const client = createCesClient(transport);
556
- this.cesClientRef = client;
557
- // Resolve the assistant API key so CES can use it for platform
558
- // credential materialisation. In managed mode the key is provisioned
559
- // after hatch and stored in the credential store — CES can't read
560
- // the env var, so we pass it via the handshake.
561
- const proxyCtx = await resolveManagedProxyContext();
562
- const { accepted, reason } = await client.handshake(
563
- proxyCtx.assistantApiKey
564
- ? { assistantApiKey: proxyCtx.assistantApiKey }
565
- : undefined,
566
- );
567
- if (abortController.signal.aborted) {
568
- client.close();
569
- throw new Error("CES initialization aborted during shutdown");
570
- }
571
- if (accepted) {
572
- log.info(
573
- "CES client initialized and handshake accepted (server-level)",
574
- );
575
- return client;
576
- }
577
- log.warn(
578
- { reason },
579
- "CES handshake rejected — CES tools will be unavailable",
580
- );
581
- client.close();
582
- this.cesClientRef = undefined;
583
- await pm.stop();
584
- // Reset so next session can retry initialization
585
- this.cesClientPromise = undefined;
586
- return undefined;
587
- } catch (err) {
588
- if (err instanceof CesUnavailableError) {
589
- log.info(
590
- { reason: err.message },
591
- "CES is not available — CES tools will be unavailable",
592
- );
593
- } else {
594
- log.warn(
595
- { error: err instanceof Error ? err.message : String(err) },
596
- "Failed to initialize CES client — CES tools will be unavailable",
597
- );
598
- }
599
- await pm.stop().catch(() => {});
600
- // Reset so next session can retry initialization
601
- this.cesClientRef = undefined;
602
- this.cesClientPromise = undefined;
603
- return undefined;
604
- }
605
- })();
606
- }
607
-
608
556
  log.info("DaemonServer started (HTTP-only mode)");
609
557
  }
610
558
 
@@ -656,11 +604,9 @@ export class DaemonServer {
656
604
 
657
605
  // ── Conversation management ──────────────────────────────────────────────
658
606
 
659
- setHttpPort(port: number): void {
660
- this.httpPort = port;
607
+ broadcastStatus(): void {
661
608
  this.broadcast({
662
- type: "daemon_status",
663
- httpPort: port,
609
+ type: "assistant_status",
664
610
  version: daemonVersion,
665
611
  keyFingerprint: getSigningKeyFingerprint(),
666
612
  });
@@ -756,9 +702,8 @@ export class DaemonServer {
756
702
 
757
703
  const createPromise = (async () => {
758
704
  const config = getConfig();
759
- let provider = getFailoverProvider(
705
+ let provider = getProvider(
760
706
  config.services.inference.provider,
761
- config.providerOrder,
762
707
  );
763
708
  const { rateLimit } = config;
764
709
  if (rateLimit.maxRequestsPerMinute > 0) {
@@ -884,14 +829,6 @@ export class DaemonServer {
884
829
  filePath?: string;
885
830
  }[];
886
831
  }> {
887
- const ingressCheck = checkIngressForSecrets(content);
888
- if (ingressCheck.blocked) {
889
- throw new IngressBlockedError(
890
- ingressCheck.userNotice!,
891
- ingressCheck.detectedTypes,
892
- );
893
- }
894
-
895
832
  const conversation = await this.getOrCreateConversation(
896
833
  conversationId,
897
834
  options,
@@ -25,7 +25,8 @@ export interface ToolDomainEvents {
25
25
  | "always_allow_high_risk"
26
26
  | "deny"
27
27
  | "always_deny"
28
- | "temporary_override";
28
+ | "temporary_override"
29
+ | "dangerously_skip_permissions";
29
30
  riskLevel: string;
30
31
  decidedAtMs: number;
31
32
  };
@@ -2,7 +2,7 @@
2
2
  * Platform callback route registration for containerized deployments.
3
3
  *
4
4
  * When the assistant daemon runs inside a container (IS_CONTAINERIZED=true)
5
- * with a configured PLATFORM_BASE_URL and PLATFORM_ASSISTANT_ID, external
5
+ * with a configured VELLUM_PLATFORM_URL and PLATFORM_ASSISTANT_ID, external
6
6
  * service callbacks (Twilio webhooks, OAuth redirects, Telegram webhooks, etc.)
7
7
  * must route through the platform's gateway proxy instead of hitting the
8
8
  * assistant directly.
@@ -12,7 +12,7 @@
12
12
  * webhooks to the correct containerized assistant instance.
13
13
  *
14
14
  * The platform endpoint is:
15
- * POST {PLATFORM_BASE_URL}/v1/internal/gateway/callback-routes/register/
15
+ * POST {VELLUM_PLATFORM_URL}/v1/internal/gateway/callback-routes/register/
16
16
  *
17
17
  * It accepts { assistant_id, callback_path, type } and returns a stable
18
18
  * callback_url that external services should use.
@@ -30,7 +30,7 @@ const log = getLogger("platform-callback-registration");
30
30
 
31
31
  /**
32
32
  * Whether the daemon should register callback routes with the platform.
33
- * True when IS_CONTAINERIZED, PLATFORM_BASE_URL, and PLATFORM_ASSISTANT_ID
33
+ * True when IS_CONTAINERIZED, VELLUM_PLATFORM_URL, and PLATFORM_ASSISTANT_ID
34
34
  * are all set. Intentionally does **not** require the managed proxy API key
35
35
  * so that callback-only flows (OAuth transport, Telegram/Twilio callback
36
36
  * registration) work during partial bootstrap before the key is injected.
package/src/instrument.ts CHANGED
@@ -39,14 +39,17 @@ function redactObject(obj: unknown): unknown {
39
39
  }
40
40
 
41
41
  /**
42
- * Call after dotenv has loaded so SENTRY_DSN is available.
43
- * Always initializes Sentry to capture early startup crashes. If the user
44
- * later opts out via the sendDiagnostics config key (or VELLUM_DEV=1),
45
- * call closeSentry() after config is loaded to stop future event capturing.
42
+ * Call after dotenv has loaded so SENTRY_DSN_ASSISTANT is available.
43
+ * Initializes Sentry when the DSN is set; no-ops when empty/unset so
44
+ * local dev builds don't send crash reports. If the user later opts out
45
+ * via the sendDiagnostics config key (or VELLUM_DEV=1), call closeSentry()
46
+ * after config is loaded to stop future event capturing.
46
47
  */
47
48
  export function initSentry(): void {
49
+ const dsn = getSentryDsn();
50
+ if (!dsn) return;
48
51
  Sentry.init({
49
- dsn: getSentryDsn(),
52
+ dsn,
50
53
  release: `vellum-assistant@${APP_VERSION}`,
51
54
  dist: COMMIT_SHA,
52
55
  environment: APP_VERSION === "0.0.0-dev" ? "development" : "production",
@@ -64,6 +64,37 @@ export function isMultifileApp(app: AppDefinition): boolean {
64
64
  return app.formatVersion === 2;
65
65
  }
66
66
 
67
+ /**
68
+ * Inline dist assets (main.js, main.css) into the compiled HTML so it can be
69
+ * delivered as a self-contained string via loadHTMLString/SSE without needing
70
+ * the client to resolve external script/stylesheet URLs.
71
+ */
72
+ export function inlineDistAssets(appDir: string, html: string): string {
73
+ const distDir = join(appDir, "dist");
74
+
75
+ // Inline main.js
76
+ const jsPath = join(distDir, "main.js");
77
+ if (existsSync(jsPath)) {
78
+ const js = readFileSync(jsPath, "utf-8");
79
+ html = html.replace(
80
+ /<script\s+type="module"\s+src="main\.js"\s*><\/script>/,
81
+ `<script type="module">${js}</script>`,
82
+ );
83
+ }
84
+
85
+ // Inline main.css
86
+ const cssPath = join(distDir, "main.css");
87
+ if (existsSync(cssPath)) {
88
+ const css = readFileSync(cssPath, "utf-8");
89
+ html = html.replace(
90
+ /<link\s+rel="stylesheet"\s+href="main\.css"\s*>/,
91
+ `<style>${css}</style>`,
92
+ );
93
+ }
94
+
95
+ return html;
96
+ }
97
+
67
98
  export interface AppRecord {
68
99
  id: string;
69
100
  appId: string;
@@ -358,12 +358,61 @@ function deriveFallbackTitle(context?: TitleContext): string | null {
358
358
  return null;
359
359
  }
360
360
 
361
+ /**
362
+ * Extract only human-authored text from stored message content for title
363
+ * generation. Unlike extractTextFromStoredMessageContent (which includes
364
+ * tool metadata like "Tool use (...): {...}"), this only extracts:
365
+ * - `text` blocks (the actual conversation content)
366
+ * - `tool_result` string content (topical signal from tool responses)
367
+ * — web_search_tool_result is skipped (structured search data, not topical)
368
+ *
369
+ * Returns empty string for content-block arrays with no extractable text,
370
+ * preventing raw JSON from polluting the title prompt.
371
+ */
372
+ function extractTextForTitle(raw: string): string {
373
+ try {
374
+ const parsed = JSON.parse(raw);
375
+ if (typeof parsed === "string") return parsed;
376
+ if (!Array.isArray(parsed)) return raw;
377
+ const texts: string[] = [];
378
+ for (const block of parsed) {
379
+ if (!block || typeof block !== "object") continue;
380
+ if (block.type === "text" && typeof block.text === "string") {
381
+ texts.push(block.text);
382
+ // guard:allow-tool-result-only — web_search_tool_result has structured
383
+ // search result arrays, not useful for title generation; only plain
384
+ // tool_result string content carries topical signal.
385
+ } else if (block.type === "tool_result") {
386
+ if (typeof block.content === "string") {
387
+ texts.push(block.content);
388
+ } else if (Array.isArray(block.content)) {
389
+ for (const nested of block.content) {
390
+ if (
391
+ nested &&
392
+ typeof nested === "object" &&
393
+ nested.type === "text" &&
394
+ typeof nested.text === "string"
395
+ ) {
396
+ texts.push(nested.text);
397
+ }
398
+ }
399
+ }
400
+ }
401
+ }
402
+ return texts.join("\n");
403
+ } catch {
404
+ return raw;
405
+ }
406
+ }
407
+
361
408
  function buildRegenerationPrompt(recentMessages: MessageRow[]): string {
362
409
  const parts: string[] = ["Recent messages:"];
363
410
 
364
411
  for (const msg of recentMessages) {
412
+ const text = extractTextForTitle(msg.content);
413
+ if (!text) continue;
365
414
  const role = msg.role === "user" ? "User" : "Assistant";
366
- parts.push(`${role}: ${truncate(msg.content, 200, "")}`);
415
+ parts.push(`${role}: ${truncate(text, 200, "")}`);
367
416
  }
368
417
 
369
418
  return parts.join("\n");
@@ -34,13 +34,16 @@ import {
34
34
  createSequenceTables,
35
35
  createTasksAndWorkItemsTables,
36
36
  createWatchersAndLogsTables,
37
+ migrateAddSourceTypeColumns,
37
38
  migrateAssistantContactMetadata,
39
+ migrateBackfillAudioAttachmentMimeTypes,
38
40
  migrateBackfillContactInteractionStats,
39
41
  migrateBackfillGuardianPrincipalId,
40
42
  migrateBackfillInlineAttachmentsToDisk,
41
43
  migrateBackfillUsageCacheAccounting,
42
44
  migrateCallSessionInviteMetadata,
43
45
  migrateCallSessionMode,
46
+ migrateCallSessionSkipDisclosure,
44
47
  migrateCanonicalGuardianDeliveriesDestinationIndex,
45
48
  migrateCanonicalGuardianRequesterChatId,
46
49
  migrateCapabilityCardColumns,
@@ -51,6 +54,7 @@ import {
51
54
  migrateContactsAssistantId,
52
55
  migrateContactsNotesColumn,
53
56
  migrateContactsRolePrincipal,
57
+ migrateContactsUserFileColumn,
54
58
  migrateConversationForkLineage,
55
59
  migrateConversationsThreadTypeIndex,
56
60
  migrateCreateThreadStartersTable,
@@ -492,6 +496,18 @@ export function initializeDb(): void {
492
496
  // 86. Drop simplified-memory tables and reducer checkpoint columns
493
497
  migrateDropSimplifiedMemory(database);
494
498
 
499
+ // 87. Add skip_disclosure column to call_sessions for per-call disclosure control
500
+ migrateCallSessionSkipDisclosure(database);
501
+
502
+ // 88. Backfill correct MIME types for audio attachments stored as application/octet-stream
503
+ migrateBackfillAudioAttachmentMimeTypes(database);
504
+
505
+ // 89. Add user_file column to contacts for per-user persona file mapping
506
+ migrateContactsUserFileColumn(database);
507
+
508
+ // 90. Add source_type and source_message_role columns to memory_items
509
+ migrateAddSourceTypeColumns(database);
510
+
495
511
  validateMigrationState(database);
496
512
 
497
513
  if (process.env.BUN_TEST === "1") {
@@ -7,7 +7,7 @@ import type { TrustClass } from "../runtime/actor-trust-resolver.js";
7
7
  import { getLogger } from "../util/logger.js";
8
8
  import { getDb } from "./db.js";
9
9
  import { selectedBackendSupportsMultimodal } from "./embedding-backend.js";
10
- import { enqueueMemoryJob } from "./jobs-store.js";
10
+ import { enqueueMemoryJob, upsertDebouncedJob } from "./jobs-store.js";
11
11
  import {
12
12
  extractMediaBlockMeta,
13
13
  extractTextFromStoredMessageContent,
@@ -17,6 +17,11 @@ import { segmentText } from "./segmenter.js";
17
17
 
18
18
  const log = getLogger("memory-indexer");
19
19
 
20
+ /** Delay before a conversation summary job becomes eligible to run.
21
+ * Each new message in the same conversation resets the timer, so the
22
+ * summary is only built once the conversation has been idle for this long. */
23
+ const SUMMARY_DEBOUNCE_MS = 3 * 60 * 1000; // 3 minutes
24
+
20
25
  export interface IndexMessageInput {
21
26
  messageId: string;
22
27
  conversationId: string;
@@ -54,9 +59,11 @@ export async function indexMessageNow(
54
59
 
55
60
  const text = extractTextFromStoredMessageContent(input.content);
56
61
  if (text.length === 0) {
57
- enqueueMemoryJob("build_conversation_summary", {
58
- conversationId: input.conversationId,
59
- });
62
+ upsertDebouncedJob(
63
+ "build_conversation_summary",
64
+ { conversationId: input.conversationId },
65
+ Date.now() + SUMMARY_DEBOUNCE_MS,
66
+ );
60
67
  return { indexedSegments: 0, enqueuedJobs: 1 };
61
68
  }
62
69
 
@@ -152,14 +159,16 @@ export async function indexMessageNow(
152
159
  tx,
153
160
  );
154
161
  }
155
- enqueueMemoryJob(
156
- "build_conversation_summary",
157
- { conversationId: input.conversationId },
158
- Date.now(),
159
- tx,
160
- );
161
162
  });
162
163
 
164
+ // Debounced outside the transaction — each new message pushes the summary
165
+ // job's runAfter forward so it only fires once the conversation is idle.
166
+ upsertDebouncedJob(
167
+ "build_conversation_summary",
168
+ { conversationId: input.conversationId },
169
+ Date.now() + SUMMARY_DEBOUNCE_MS,
170
+ );
171
+
163
172
  if (skippedEmbedJobs > 0) {
164
173
  log.debug(
165
174
  `Skipped ${skippedEmbedJobs}/${segments.length} embed_segment jobs (content unchanged)`,