@vellumai/assistant 0.9.1-staging.1 → 0.10.0-staging.2

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 (433) hide show
  1. package/docs/activation-funnel-telemetry.md +24 -18
  2. package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +97 -0
  3. package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +10 -0
  4. package/node_modules/@vellumai/gateway-client/src/index.ts +15 -0
  5. package/openapi.yaml +852 -15
  6. package/package.json +1 -1
  7. package/src/__tests__/access-request-card-view.test.ts +98 -0
  8. package/src/__tests__/access-request-seed-content-blocks.test.ts +2 -4
  9. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +59 -7
  10. package/src/__tests__/agent-loop-compaction-strip.test.ts +17 -16
  11. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +16 -13
  12. package/src/__tests__/app-compiler.test.ts +15 -1
  13. package/src/__tests__/auth-fallback-events-store.test.ts +6 -14
  14. package/src/__tests__/call-pointer-messages.test.ts +28 -0
  15. package/src/__tests__/cancel-clears-processing.test.ts +89 -0
  16. package/src/__tests__/channel-approval-routes.test.ts +0 -4
  17. package/src/__tests__/channel-inbound-disk-pressure.test.ts +5 -15
  18. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +3 -4
  19. package/src/__tests__/compactor-image-manifest-trust.test.ts +21 -1
  20. package/src/__tests__/compactor-summary-call-truncation.test.ts +223 -0
  21. package/src/__tests__/config-loader-backfill.test.ts +174 -30
  22. package/src/__tests__/config-schema.test.ts +35 -0
  23. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +2 -2
  24. package/src/__tests__/contact-store-user-file.test.ts +0 -6
  25. package/src/__tests__/contacts-tools.test.ts +29 -0
  26. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
  27. package/src/__tests__/conversation-agent-loop.test.ts +58 -0
  28. package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
  29. package/src/__tests__/conversation-lifecycle.test.ts +7 -9
  30. package/src/__tests__/conversation-load-history-repair.test.ts +101 -0
  31. package/src/__tests__/conversation-routes-guardian-reply.test.ts +15 -12
  32. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +6 -3
  33. package/src/__tests__/conversation-title-service.test.ts +62 -0
  34. package/src/__tests__/credential-execution-shell-lockdown.test.ts +18 -11
  35. package/src/__tests__/credential-prompt-route.test.ts +1 -0
  36. package/src/__tests__/credential-security-invariants.test.ts +2 -0
  37. package/src/__tests__/disk-pressure-policy.test.ts +12 -0
  38. package/src/__tests__/disk-usage.test.ts +65 -0
  39. package/src/__tests__/dynamic-page-surface.test.ts +51 -0
  40. package/src/__tests__/gateway-flag-listener.test.ts +110 -1
  41. package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
  42. package/src/__tests__/guardian-card-withdrawal.test.ts +403 -0
  43. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +5 -3
  44. package/src/__tests__/guardian-grant-minting.test.ts +3 -35
  45. package/src/__tests__/guardian-routing-invariants.test.ts +64 -26
  46. package/src/__tests__/guardian-routing-state.test.ts +0 -1
  47. package/src/__tests__/headless-browser-mode.test.ts +10 -0
  48. package/src/__tests__/headless-browser-navigate.test.ts +8 -3
  49. package/src/__tests__/helpers/create-guardian-binding.ts +0 -1
  50. package/src/__tests__/host-browser-proxy.test.ts +87 -0
  51. package/src/__tests__/injector-v3-suppression.test.ts +27 -20
  52. package/src/__tests__/internal-telemetry-routes.test.ts +6 -14
  53. package/src/__tests__/invite-redemption-service.test.ts +0 -3
  54. package/src/__tests__/llm-catalog-parity.test.ts +30 -1
  55. package/src/__tests__/llm-resolver.test.ts +21 -0
  56. package/src/__tests__/llm-schema.test.ts +1 -0
  57. package/src/__tests__/managed-profile-guard.test.ts +163 -4
  58. package/src/__tests__/mcp-health-check.test.ts +6 -7
  59. package/src/__tests__/media-stream-server-integration.test.ts +317 -13
  60. package/src/__tests__/path-policy.test.ts +34 -0
  61. package/src/__tests__/persona-resolver.test.ts +38 -0
  62. package/src/__tests__/plugin-api-provider.test.ts +24 -0
  63. package/src/__tests__/plugin-tool-contribution.test.ts +6 -3
  64. package/src/__tests__/post-compaction-reinjection-idempotency.test.ts +214 -0
  65. package/src/__tests__/provider-send-message-override-profile.test.ts +76 -0
  66. package/src/__tests__/reaction-persistence.test.ts +150 -29
  67. package/src/__tests__/relay-server.test.ts +285 -0
  68. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
  69. package/src/__tests__/scheduler-reuse-conversation.test.ts +8 -5
  70. package/src/__tests__/skill-execute-input.test.ts +5 -0
  71. package/src/__tests__/skills.test.ts +51 -0
  72. package/src/__tests__/slack-notification-approval-card.test.ts +176 -0
  73. package/src/__tests__/slack-reaction-canonical-approval.test.ts +285 -0
  74. package/src/__tests__/subagent-tools.test.ts +150 -0
  75. package/src/__tests__/task-progress-nudge-hook.test.ts +1 -1
  76. package/src/__tests__/title-generate-hook.test.ts +100 -3
  77. package/src/__tests__/tool-approval-seed-content-blocks.test.ts +1 -1
  78. package/src/__tests__/tool-audit-listener.test.ts +7 -7
  79. package/src/__tests__/tool-executor-lifecycle-events.test.ts +6 -3
  80. package/src/__tests__/trusted-contact-approval-notifier.test.ts +4 -2
  81. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +220 -3
  82. package/src/__tests__/trusted-contact-verification.test.ts +2 -4
  83. package/src/__tests__/twilio-routes.test.ts +81 -1
  84. package/src/__tests__/voice-invite-redemption.test.ts +0 -1
  85. package/src/__tests__/weak-open-model.test.ts +30 -0
  86. package/src/__tests__/workspace-migration-105-enable-memory-v3-live-for-new-workspaces.test.ts +149 -0
  87. package/src/__tests__/workspace-migration-108-drop-balanced-economy-profile.test.ts +285 -0
  88. package/src/__tests__/workspace-migration-add-send-diagnostics.test.ts +1 -1
  89. package/src/__tests__/workspace-migration-drop-collect-usage-data.test.ts +118 -0
  90. package/src/__tests__/workspace-migration-drop-send-diagnostics.test.ts +118 -0
  91. package/src/a2a/__tests__/e2e-a2a-channel.test.ts +0 -4
  92. package/src/agent/loop.ts +33 -33
  93. package/src/api/events/tool-result.ts +6 -0
  94. package/src/api/events/workflow-completed.ts +53 -0
  95. package/src/api/events/workflow-leaf-finished.ts +38 -0
  96. package/src/api/events/workflow-leaf-started.ts +35 -0
  97. package/src/api/events/workflow-progress.ts +32 -0
  98. package/src/api/events/workflow-started.ts +31 -0
  99. package/src/api/index.ts +40 -0
  100. package/src/api/responses/conversation-message.ts +26 -0
  101. package/src/api/responses/home.ts +26 -0
  102. package/src/api/responses/workflow-journal.ts +53 -0
  103. package/src/approvals/guardian-card-withdrawal.ts +145 -0
  104. package/src/approvals/guardian-decision-primitive.ts +26 -3
  105. package/src/approvals/guardian-request-resolvers.ts +181 -78
  106. package/src/calls/__tests__/channel-admission-reader.test.ts +132 -0
  107. package/src/calls/__tests__/relay-setup-router.test.ts +350 -0
  108. package/src/calls/call-pointer-messages.ts +10 -4
  109. package/src/calls/channel-admission-reader.ts +104 -0
  110. package/src/calls/guardian-dispatch.ts +17 -45
  111. package/src/calls/media-stream-server.ts +84 -2
  112. package/src/calls/relay-server.ts +66 -0
  113. package/src/calls/relay-setup-router.ts +82 -1
  114. package/src/calls/twilio-routes.ts +17 -8
  115. package/src/cli/commands/clients.ts +3 -0
  116. package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2-compare-render.test.ts +1 -1
  117. package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2.test.ts +8 -7
  118. package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v3.test.ts +5 -4
  119. package/src/cli/commands/memory/index.ts +30 -0
  120. package/src/cli/commands/{memory-v2-compare-render.ts → memory/memory-v2-compare-render.ts} +1 -1
  121. package/src/cli/commands/{memory-v2.ts → memory/memory-v2.ts} +6 -15
  122. package/src/cli/commands/{memory-v3.ts → memory/memory-v3.ts} +97 -11
  123. package/src/cli/commands/oauth/status.test.ts +36 -0
  124. package/src/cli/commands/oauth/status.ts +23 -3
  125. package/src/cli/commands/plugins.ts +57 -5
  126. package/src/cli/lib/__tests__/inspect-plugin.test.ts +54 -0
  127. package/src/cli/lib/__tests__/merge-plugin-tree.test.ts +134 -4
  128. package/src/cli/lib/__tests__/plugin-surfaces.test.ts +111 -0
  129. package/src/cli/lib/__tests__/upgrade-plugin.test.ts +53 -11
  130. package/src/cli/lib/inspect-plugin.ts +12 -1
  131. package/src/cli/lib/merge-plugin-tree.ts +149 -49
  132. package/src/cli/lib/plugin-surfaces.ts +104 -0
  133. package/src/cli/lib/upgrade-plugin.ts +64 -36
  134. package/src/cli/program.ts +2 -4
  135. package/src/config/__tests__/sync-gated-profiles.test.ts +368 -0
  136. package/src/config/assistant-feature-flags.ts +22 -7
  137. package/src/config/bundled-skills/contacts/tools/contact-search.ts +0 -1
  138. package/src/config/bundled-skills/messaging/SKILL.md +6 -4
  139. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +9 -8
  140. package/src/config/bundled-skills/workflows/SKILL.md +14 -7
  141. package/src/config/call-site-defaults.ts +3 -0
  142. package/src/config/feature-flag-registry.json +49 -18
  143. package/src/config/llm-resolver.ts +3 -0
  144. package/src/config/memory-v3-gate.ts +11 -0
  145. package/src/config/schema.ts +8 -6
  146. package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
  147. package/src/config/schemas/call-site-catalog.ts +7 -0
  148. package/src/config/schemas/channels.ts +11 -0
  149. package/src/config/schemas/llm.ts +31 -0
  150. package/src/config/schemas/memory-lifecycle.ts +3 -7
  151. package/src/config/schemas/memory-v3.ts +6 -0
  152. package/src/config/schemas/services.ts +18 -0
  153. package/src/config/seed-inference-profiles.ts +94 -34
  154. package/src/config/skills.ts +21 -0
  155. package/src/config/sync-gated-profiles.ts +220 -0
  156. package/src/contacts/contact-store.ts +2 -10
  157. package/src/contacts/contacts-write.ts +1 -2
  158. package/src/contacts/types.ts +0 -1
  159. package/src/context/compactor.ts +86 -52
  160. package/src/context/strip-injections.ts +58 -10
  161. package/src/context/token-estimator.ts +1 -1
  162. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -2
  163. package/src/daemon/conversation-agent-loop-handlers.ts +2 -0
  164. package/src/daemon/conversation-agent-loop.ts +100 -19
  165. package/src/daemon/conversation-history.ts +1 -1
  166. package/src/daemon/conversation-lifecycle.ts +3 -5
  167. package/src/daemon/conversation-process.ts +13 -5
  168. package/src/daemon/conversation-runtime-assembly.ts +13 -15
  169. package/src/daemon/conversation-surfaces.ts +26 -0
  170. package/src/daemon/conversation-tool-setup.ts +16 -11
  171. package/src/daemon/conversation.ts +64 -14
  172. package/src/daemon/disk-pressure-policy.ts +5 -3
  173. package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +0 -1
  174. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -1
  175. package/src/daemon/handlers/config-a2a.ts +0 -2
  176. package/src/daemon/handlers/config-channels.ts +5 -10
  177. package/src/daemon/handlers/config-slack-channel.ts +20 -0
  178. package/src/daemon/handlers/conversations.ts +107 -0
  179. package/src/daemon/host-browser-proxy.ts +41 -0
  180. package/src/daemon/lifecycle.ts +55 -20
  181. package/src/daemon/message-provenance.ts +2 -0
  182. package/src/daemon/message-types/contacts.ts +0 -1
  183. package/src/daemon/message-types/web-activity.ts +7 -1
  184. package/src/daemon/message-types/workflows.ts +83 -1
  185. package/src/daemon/tool-setup-types.ts +4 -0
  186. package/src/daemon/trust-context.ts +1 -1
  187. package/src/events/tool-audit-listener.ts +2 -2
  188. package/src/home/feed-source-enrichment.test.ts +151 -0
  189. package/src/home/feed-source-enrichment.ts +176 -0
  190. package/src/instrument.ts +18 -6
  191. package/src/ipc/__tests__/binary-result-ipc.test.ts +81 -0
  192. package/src/ipc/__tests__/clients-list-ipc.test.ts +20 -0
  193. package/src/ipc/assistant-server.ts +37 -4
  194. package/src/ipc/gateway-flag-listener.ts +18 -2
  195. package/src/memory/__tests__/auto-analysis-enqueue.test.ts +5 -16
  196. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +7 -11
  197. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +37 -7
  198. package/src/memory/__tests__/memory-retrospective-job.test.ts +34 -0
  199. package/src/memory/__tests__/onboarding-events-store.test.ts +7 -7
  200. package/src/memory/auth-fallback-events-store.ts +2 -2
  201. package/src/memory/auto-analysis-enqueue.ts +3 -5
  202. package/src/memory/canonical-guardian-store.ts +39 -1
  203. package/src/memory/conversation-crud.ts +9 -4
  204. package/src/memory/conversation-key-store.ts +17 -2
  205. package/src/memory/conversation-title-service.ts +64 -7
  206. package/src/memory/db-init.ts +10 -0
  207. package/src/memory/embedding-backend.ts +15 -1
  208. package/src/memory/jobs-worker.ts +2 -1
  209. package/src/memory/lifecycle-events-store.ts +2 -2
  210. package/src/memory/memory-retrospective-enqueue.ts +31 -6
  211. package/src/memory/memory-retrospective-job.ts +9 -0
  212. package/src/memory/migrations/129-contact-channels-access-fields.ts +18 -9
  213. package/src/memory/migrations/131-drop-legacy-member-guardian-tables.ts +14 -2
  214. package/src/memory/migrations/289-contact-channels-unique-ext-user.ts +10 -0
  215. package/src/memory/migrations/291-contact-channels-renormalize-addresses.ts +10 -0
  216. package/src/memory/migrations/292-schedule-default-no-reuse-conversation.test.ts +67 -0
  217. package/src/memory/migrations/292-schedule-default-no-reuse-conversation.ts +25 -0
  218. package/src/memory/migrations/293-workflow-journal-leaf-tokens.ts +32 -0
  219. package/src/memory/migrations/294-drop-external-user-id.ts +31 -0
  220. package/src/memory/migrations/295-drop-approval-prompt-ts-tracker.ts +20 -0
  221. package/src/memory/migrations/296-rewrite-balanced-economy-profile-pins.test.ts +110 -0
  222. package/src/memory/migrations/296-rewrite-balanced-economy-profile-pins.ts +68 -0
  223. package/src/memory/migrations/__tests__/131-drop-legacy-member-guardian-tables.test.ts +154 -0
  224. package/src/memory/migrations/__tests__/289-contact-channels-unique-ext-user.test.ts +31 -0
  225. package/src/memory/migrations/__tests__/291-contact-channels-renormalize-addresses.test.ts +30 -0
  226. package/src/memory/migrations/index.ts +5 -0
  227. package/src/memory/onboarding-events-store.ts +3 -3
  228. package/src/memory/schema/contacts.ts +0 -1
  229. package/src/memory/skill-loaded-events-store.test.ts +7 -15
  230. package/src/memory/skill-loaded-events-store.ts +2 -2
  231. package/src/memory/tool-executed-events-store.test.ts +7 -7
  232. package/src/memory/turn-trace-store.test.ts +736 -0
  233. package/src/memory/turn-trace-store.ts +364 -0
  234. package/src/memory/v2/__tests__/consolidation-job.test.ts +8 -0
  235. package/src/memory/v2/__tests__/skill-content.test.ts +30 -0
  236. package/src/memory/v2/consolidation-job.ts +2 -2
  237. package/src/memory/v2/skill-content.ts +25 -7
  238. package/src/memory/v2/skill-store.ts +7 -1
  239. package/src/memory/v3-eval/__tests__/eval-packets.test.ts +248 -0
  240. package/src/memory/v3-eval/eval-packets.ts +546 -0
  241. package/src/messaging/providers/slack/api.ts +31 -0
  242. package/src/messaging/providers/slack/send.test.ts +114 -2
  243. package/src/messaging/providers/slack/send.ts +30 -7
  244. package/src/messaging/providers/slack/withdraw.test.ts +200 -0
  245. package/src/messaging/providers/slack/withdraw.ts +161 -0
  246. package/src/notifications/AGENTS.md +2 -0
  247. package/src/notifications/access-request-copy.ts +72 -59
  248. package/src/notifications/adapters/slack.ts +55 -73
  249. package/src/notifications/approval-card-data.ts +333 -0
  250. package/src/notifications/broadcaster.ts +6 -2
  251. package/src/notifications/canonical-delivery-recorder.ts +139 -0
  252. package/src/notifications/copy-composer.ts +3 -3
  253. package/src/notifications/decision-engine.ts +4 -2
  254. package/src/notifications/destination-resolver.ts +4 -6
  255. package/src/notifications/guardian-question-mode.ts +10 -0
  256. package/src/notifications/home-feed-side-effect.ts +3 -13
  257. package/src/notifications/notification-utils.ts +2 -1
  258. package/src/notifications/signal.ts +79 -43
  259. package/src/notifications/types.ts +98 -128
  260. package/src/permissions/checker.test.ts +51 -0
  261. package/src/permissions/checker.ts +185 -26
  262. package/src/permissions/ipc-risk-types.ts +24 -0
  263. package/src/permissions/question-prompter.test.ts +27 -0
  264. package/src/permissions/question-prompter.ts +4 -0
  265. package/src/platform/client.test.ts +119 -0
  266. package/src/platform/client.ts +66 -0
  267. package/src/platform/consent-cache.test.ts +267 -0
  268. package/src/platform/consent-cache.ts +174 -0
  269. package/src/plugin-api/index.ts +27 -0
  270. package/src/plugins/defaults/advisor/__tests__/advisor-gate.test.ts +56 -0
  271. package/src/plugins/defaults/advisor/__tests__/advisor-state-store.test.ts +43 -0
  272. package/src/plugins/defaults/advisor/__tests__/agent-loop-integration.test.ts +137 -0
  273. package/src/plugins/defaults/advisor/__tests__/consult.test.ts +153 -0
  274. package/src/plugins/defaults/advisor/__tests__/hooks.test.ts +138 -0
  275. package/src/plugins/defaults/advisor/__tests__/transcript.test.ts +147 -0
  276. package/src/plugins/defaults/advisor/advisor-gate.ts +29 -0
  277. package/src/plugins/defaults/advisor/advisor-state-store.ts +94 -0
  278. package/src/plugins/defaults/advisor/config.ts +21 -0
  279. package/src/plugins/defaults/advisor/consult.ts +93 -0
  280. package/src/plugins/defaults/advisor/hooks/post-model-call.ts +34 -0
  281. package/src/plugins/defaults/advisor/hooks/pre-model-call.ts +30 -0
  282. package/src/plugins/defaults/advisor/hooks/user-prompt-submit.ts +19 -0
  283. package/src/plugins/defaults/advisor/package.json +14 -0
  284. package/src/plugins/defaults/advisor/steering.ts +67 -0
  285. package/src/plugins/defaults/advisor/tools/advisor.ts +65 -0
  286. package/src/plugins/defaults/advisor/transcript.ts +76 -0
  287. package/src/plugins/defaults/index.ts +35 -0
  288. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +22 -9
  289. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +2 -2
  290. package/src/plugins/defaults/memory-retrieval/tail-reinjection-strip.ts +64 -0
  291. package/src/plugins/defaults/memory-retrieval/unified-turn-context.ts +29 -21
  292. package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +1 -0
  293. package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +1 -0
  294. package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +75 -7
  295. package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +31 -4
  296. package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +77 -2
  297. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +1 -0
  298. package/src/plugins/defaults/memory-v3-shadow/injector.ts +7 -10
  299. package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +37 -4
  300. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +32 -20
  301. package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +56 -3
  302. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +23 -2
  303. package/src/plugins/defaults/task-progress-nudge/hooks/post-tool-use.ts +2 -12
  304. package/src/plugins/defaults/title-generate/hooks/stop.ts +56 -21
  305. package/src/prompts/persona-resolver.ts +12 -2
  306. package/src/prompts/templates/system-sections.ts +7 -2
  307. package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
  308. package/src/providers/__tests__/provider-secret-catalog.test.ts +1 -0
  309. package/src/providers/__tests__/retry-callsite.test.ts +176 -0
  310. package/src/providers/atlascloud/client.ts +85 -0
  311. package/src/providers/fetch-provider-catalog.ts +85 -0
  312. package/src/providers/inference/adapter-factory.ts +3 -0
  313. package/src/providers/model-catalog.ts +58 -0
  314. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +33 -0
  315. package/src/providers/openai/chat-completions-provider.ts +7 -0
  316. package/src/providers/openai/responses-provider.ts +10 -0
  317. package/src/providers/provider-send-message.ts +11 -3
  318. package/src/providers/retry.ts +53 -12
  319. package/src/providers/search-provider-catalog.ts +10 -0
  320. package/src/providers/weak-open-model.ts +22 -0
  321. package/src/runtime/__tests__/agent-wake.test.ts +181 -0
  322. package/src/runtime/__tests__/client-health.test.ts +44 -0
  323. package/src/runtime/access-request-helper.ts +21 -53
  324. package/src/runtime/actor-trust-resolver.ts +49 -21
  325. package/src/runtime/agent-wake.ts +52 -0
  326. package/src/runtime/assistant-event-hub.ts +18 -4
  327. package/src/runtime/auth/__tests__/route-policy.test.ts +12 -0
  328. package/src/runtime/auth/require-bound-guardian.ts +1 -4
  329. package/src/runtime/capabilities.test.ts +120 -0
  330. package/src/runtime/capabilities.ts +197 -0
  331. package/src/runtime/channel-approval-types.ts +5 -1
  332. package/src/runtime/channel-retry-sweep.ts +1 -0
  333. package/src/runtime/channel-verification-service.ts +1 -2
  334. package/src/runtime/client-health.ts +26 -0
  335. package/src/runtime/confirmation-request-guardian-bridge.ts +38 -29
  336. package/src/runtime/effective-capabilities.test.ts +128 -0
  337. package/src/runtime/effective-capabilities.ts +84 -0
  338. package/src/runtime/guardian-reply-router.ts +106 -21
  339. package/src/runtime/invite-redemption-service.ts +6 -22
  340. package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +123 -0
  341. package/src/runtime/migrations/vbundle-builder.ts +49 -20
  342. package/src/runtime/pending-interactions.ts +15 -0
  343. package/src/runtime/routes/__tests__/client-routes.test.ts +13 -0
  344. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +67 -0
  345. package/src/runtime/routes/__tests__/plugins-routes.test.ts +35 -13
  346. package/src/runtime/routes/browser-tabs-routes.ts +9 -0
  347. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +17 -8
  348. package/src/runtime/routes/client-routes.ts +10 -0
  349. package/src/runtime/routes/contact-routes.ts +31 -8
  350. package/src/runtime/routes/conversation-management-routes.ts +80 -1
  351. package/src/runtime/routes/conversation-query-routes.ts +68 -22
  352. package/src/runtime/routes/conversation-routes.ts +37 -12
  353. package/src/runtime/routes/events-routes.ts +1 -3
  354. package/src/runtime/routes/guardian-approval-interception.ts +14 -73
  355. package/src/runtime/routes/guardian-approval-prompt.ts +22 -4
  356. package/src/runtime/routes/home-feed-routes.ts +8 -3
  357. package/src/runtime/routes/inbound-message-handler.ts +214 -228
  358. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +88 -6
  359. package/src/runtime/routes/inbound-stages/admission-policy.test.ts +154 -0
  360. package/src/runtime/routes/inbound-stages/admission-policy.ts +140 -0
  361. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +3 -3
  362. package/src/runtime/routes/inbound-stages/background-dispatch.ts +11 -6
  363. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +1 -2
  364. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +1 -2
  365. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +7 -7
  366. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +47 -28
  367. package/src/runtime/routes/inbound-stages/reaction-intercept.ts +358 -0
  368. package/src/runtime/routes/index.ts +2 -0
  369. package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +8 -0
  370. package/src/runtime/routes/integrations/slack/channel.ts +36 -0
  371. package/src/runtime/routes/internal-telemetry-routes.ts +1 -1
  372. package/src/runtime/routes/mcp-auth-routes.ts +233 -41
  373. package/src/runtime/routes/memory-eval-routes.ts +87 -0
  374. package/src/runtime/routes/notification-routes.ts +122 -133
  375. package/src/runtime/routes/platform-routes.ts +2 -2
  376. package/src/runtime/routes/plugins-routes.ts +40 -7
  377. package/src/runtime/routes/secret-routes.ts +10 -0
  378. package/src/runtime/routes/surface-action-routes.ts +2 -1
  379. package/src/runtime/routes/tool-call-question-enrichment.test.ts +146 -0
  380. package/src/runtime/routes/tool-call-question-enrichment.ts +66 -0
  381. package/src/runtime/routes/workflow-routes.test.ts +225 -1
  382. package/src/runtime/routes/workflow-routes.ts +131 -1
  383. package/src/runtime/tool-grant-request-helper.ts +18 -16
  384. package/src/runtime/trust-context-resolver.ts +8 -5
  385. package/src/schedule/schedule-store.ts +1 -1
  386. package/src/schedule/scheduler-types.ts +5 -1
  387. package/src/security/__tests__/provider-key-env-fallback.test.ts +6 -0
  388. package/src/security/secret-patterns.ts +3 -0
  389. package/src/subagent/manager.ts +11 -4
  390. package/src/telemetry/trace-collection-policy.test.ts +28 -0
  391. package/src/telemetry/trace-collection-policy.ts +30 -0
  392. package/src/telemetry/types.ts +89 -0
  393. package/src/telemetry/usage-telemetry-reporter.test.ts +586 -36
  394. package/src/telemetry/usage-telemetry-reporter.ts +148 -41
  395. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +31 -0
  396. package/src/tools/browser/browser-execution.ts +29 -18
  397. package/src/tools/document/document-tool.ts +2 -3
  398. package/src/tools/executor.ts +5 -3
  399. package/src/tools/host-terminal/host-shell.ts +5 -4
  400. package/src/tools/memory/register.ts +2 -2
  401. package/src/tools/network/__tests__/web-fetch-firecrawl.test.ts +360 -0
  402. package/src/tools/network/__tests__/web-search.test.ts +143 -0
  403. package/src/tools/network/web-fetch.ts +372 -1
  404. package/src/tools/network/web-search.ts +213 -10
  405. package/src/tools/permission-checker.ts +3 -2
  406. package/src/tools/registry.ts +20 -0
  407. package/src/tools/schedule/create.ts +4 -3
  408. package/src/tools/schedule/update.ts +2 -1
  409. package/src/tools/shared/filesystem/path-policy.ts +39 -13
  410. package/src/tools/skills/execute.ts +1 -2
  411. package/src/tools/subagent/spawn.ts +37 -13
  412. package/src/tools/terminal/shell.ts +10 -4
  413. package/src/tools/tool-approval-handler.ts +17 -10
  414. package/src/tools/types.ts +9 -0
  415. package/src/tools/ui-surface/definitions.ts +25 -2
  416. package/src/tools/verification-control-plane-policy.ts +3 -1
  417. package/src/tools/workflows/run-workflow.ts +1 -0
  418. package/src/util/disk-usage.ts +78 -23
  419. package/src/util/platform.ts +8 -1
  420. package/src/watcher/telemetry.ts +2 -2
  421. package/src/workflows/engine.test.ts +175 -1
  422. package/src/workflows/engine.ts +82 -0
  423. package/src/workflows/journal-store.test.ts +70 -0
  424. package/src/workflows/journal-store.ts +18 -3
  425. package/src/workflows/run-manager.test.ts +171 -3
  426. package/src/workflows/run-manager.ts +64 -0
  427. package/src/workspace/migrations/105-enable-memory-v3-live-for-new-workspaces.ts +63 -0
  428. package/src/workspace/migrations/106-drop-collect-usage-data.ts +47 -0
  429. package/src/workspace/migrations/107-drop-send-diagnostics.ts +47 -0
  430. package/src/workspace/migrations/108-drop-balanced-economy-profile.ts +129 -0
  431. package/src/workspace/migrations/registry.ts +8 -0
  432. package/src/notifications/tool-approval-copy.ts +0 -142
  433. package/src/runtime/routes/approval-prompt-ts-tracker.ts +0 -78
@@ -120,7 +120,10 @@ import { assistantEventHub, broadcastMessage } from "../assistant-event-hub.js";
120
120
  import { DAEMON_INTERNAL_ASSISTANT_ID } from "../assistant-scope.js";
121
121
  import { getPersistedSeq } from "../assistant-stream-state.js";
122
122
  import { ACTOR_PRINCIPALS } from "../auth/route-policy.js";
123
- import { routeGuardianReply } from "../guardian-reply-router.js";
123
+ import {
124
+ type GuardianPendingScope,
125
+ routeGuardianReply,
126
+ } from "../guardian-reply-router.js";
124
127
  import { healGuardianBindingDrift } from "../guardian-vellum-migration.js";
125
128
  import type {
126
129
  ApprovalConversationGenerator,
@@ -148,6 +151,10 @@ import {
148
151
  collectPendingConfirmations,
149
152
  enrichToolCallsWithConfirmation,
150
153
  } from "./tool-call-confirmation-enrichment.js";
154
+ import {
155
+ collectPendingQuestions,
156
+ enrichToolCallsWithQuestion,
157
+ } from "./tool-call-question-enrichment.js";
151
158
  import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
152
159
  import { RouteResponse } from "./types.js";
153
160
 
@@ -486,12 +493,14 @@ async function tryConsumeCanonicalGuardianReply(params: {
486
493
  sourceChannel,
487
494
  conversation,
488
495
  );
489
- // Always pass the hints array (even when empty) so
490
- // findPendingCanonicalRequests respects the in-memory staleness filter
491
- // applied by collectCanonicalGuardianRequestHintIds. Converting empty
492
- // hints to `undefined` caused the router to fall through to raw DB
493
- // queries that rediscovered stale canonical requests.
494
- const pendingRequestIds = pendingRequestHintIds;
496
+ // An empty hint set is `blocked`, not absence: the in-memory staleness
497
+ // filter in collectCanonicalGuardianRequestHintIds found no live requests,
498
+ // so the router must not fall back to identity/DB lookup (which rediscovered
499
+ // stale canonical requests). A non-empty set scopes resolution to it.
500
+ const pendingScope: GuardianPendingScope =
501
+ pendingRequestHintIds.length > 0
502
+ ? { mode: "scoped", requestIds: pendingRequestHintIds }
503
+ : { mode: "blocked" };
495
504
 
496
505
  const routerResult = await routeGuardianReply({
497
506
  messageText: trimmedContent,
@@ -503,7 +512,7 @@ async function tryConsumeCanonicalGuardianReply(params: {
503
512
  guardianPrincipalId: verifiedActorPrincipalId,
504
513
  },
505
514
  conversationId,
506
- pendingRequestIds,
515
+ pendingScope,
507
516
  approvalConversationGenerator,
508
517
  emissionContext: {
509
518
  source: "inline_nl",
@@ -817,6 +826,7 @@ export function handleListMessages({
817
826
  const pendingConfirmations = collectPendingConfirmations(
818
827
  resolvedConversationId,
819
828
  );
829
+ const pendingQuestions = collectPendingQuestions(resolvedConversationId);
820
830
 
821
831
  const messages: RuntimeMessagePayload[] = parsed.map((m) => {
822
832
  const mergedMessageIds = m.id ? (mergedIdMap.get(m.id) ?? []) : [];
@@ -880,10 +890,13 @@ export function handleListMessages({
880
890
  m.id ?? undefined,
881
891
  );
882
892
 
883
- const toolCalls = enrichToolCallsWithConfirmation(rendered.toolCalls, {
884
- workspaceDir,
885
- pendingConfirmations,
886
- });
893
+ const toolCalls = enrichToolCallsWithQuestion(
894
+ enrichToolCallsWithConfirmation(rendered.toolCalls, {
895
+ workspaceDir,
896
+ pendingConfirmations,
897
+ }),
898
+ { pendingQuestions },
899
+ );
887
900
 
888
901
  // Strip <no_response/> markers from assistant messages so web/API clients
889
902
  // never see the raw sentinel. Only assistant messages produce it; user
@@ -1133,6 +1146,7 @@ export async function handleSendMessage(
1133
1146
  bootstrapTemplate?: string;
1134
1147
  initialMessage?: string;
1135
1148
  skills?: string[];
1149
+ title?: string;
1136
1150
  };
1137
1151
  };
1138
1152
 
@@ -1310,8 +1324,13 @@ export async function handleSendMessage(
1310
1324
  : sourceChannel === "vellum"
1311
1325
  ? crypto.randomUUID()
1312
1326
  : `default:${sourceChannel}:${sourceInterface}`;
1327
+ // An onboarding flow may supply an explicit title for the conversation it
1328
+ // mints behind the scenes (e.g. the research pass) so it isn't left with an
1329
+ // auto-generated title. Applied only when this call creates the row.
1330
+ const onboardingTitle = body.onboarding?.title?.trim() || undefined;
1313
1331
  mapping = getOrCreateConversation(resolvedConversationKey, {
1314
1332
  conversationType: "standard",
1333
+ title: onboardingTitle,
1315
1334
  });
1316
1335
  }
1317
1336
 
@@ -2717,6 +2736,12 @@ export const ROUTES: RouteDefinition[] = [
2717
2736
  bootstrapTemplate: z.string().optional(),
2718
2737
  initialMessage: z.string().optional(),
2719
2738
  skills: z.array(z.string()).optional(),
2739
+ title: z
2740
+ .string()
2741
+ .optional()
2742
+ .describe(
2743
+ "Explicit title for the conversation minted on this first message. Persisted as a user-set title (never overwritten by the auto-titler). Used by onboarding flows that mint a conversation behind the scenes.",
2744
+ ),
2720
2745
  })
2721
2746
  .describe("PreChat onboarding context, sent on the first message only")
2722
2747
  .optional(),
@@ -42,6 +42,7 @@ import {
42
42
  import type { ReplaySubscriber } from "../assistant-stream-state.js";
43
43
  import { getReplayWindow } from "../assistant-stream-state.js";
44
44
  import { ACTOR_PRINCIPALS, GATEWAY_PRINCIPALS } from "../auth/route-policy.js";
45
+ import { DEFAULT_HEARTBEAT_INTERVAL_MS } from "../client-health.js";
45
46
  import { resolveActorPrincipalIdForLocalGuardian } from "../local-actor-identity.js";
46
47
  import {
47
48
  BadRequestError,
@@ -52,9 +53,6 @@ import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
52
53
 
53
54
  const log = getLogger("events-routes");
54
55
 
55
- /** Keep-alive comment sent to idle clients every 7 s by default. */
56
- const DEFAULT_HEARTBEAT_INTERVAL_MS = 7_000;
57
-
58
56
  /**
59
57
  * Resolution of the event-loop delay histogram, per
60
58
  * https://nodejs.org/api/perf_hooks.html#perf_hooksmonitoreventloopdelayoptions.
@@ -10,7 +10,6 @@ import { applyGuardianDecision } from "../../approvals/guardian-decision-primiti
10
10
  import type { ChannelId } from "../../channels/types.js";
11
11
  import type { TrustContext } from "../../daemon/trust-context.js";
12
12
  import {
13
- getAllPendingApprovalsByGuardianChat,
14
13
  getPendingApprovalForRequest,
15
14
  getUnresolvedApprovalForRequest,
16
15
  updateApprovalDecision,
@@ -18,6 +17,7 @@ import {
18
17
  import { getLogger } from "../../util/logger.js";
19
18
  import { runApprovalConversationTurn } from "../approval-conversation-turn.js";
20
19
  import { composeApprovalMessageGenerative } from "../approval-message-composer.js";
20
+ import { resolveCapabilities } from "../capabilities.js";
21
21
  import type { ApprovalDecisionResult } from "../channel-approval-types.js";
22
22
  import {
23
23
  getApprovalInfoByConversation,
@@ -31,13 +31,11 @@ import type {
31
31
  ApprovalCopyGenerator,
32
32
  } from "../http-types.js";
33
33
  import { parseApprovalIntent } from "../nl-approval-parser.js";
34
- import { isTrackedApprovalPromptTs } from "./approval-prompt-ts-tracker.js";
35
34
  import { handleGuardianCallbackDecision } from "./approval-strategies/guardian-callback-strategy.js";
36
35
  import { handleGuardianTextEngineDecision } from "./approval-strategies/guardian-text-engine-strategy.js";
37
36
  import {
38
37
  buildGuardianDenyContext,
39
38
  parseCallbackData,
40
- parseReactionCallbackData,
41
39
  } from "./channel-route-shared.js";
42
40
  import { deliverStaleApprovalReply } from "./guardian-approval-reply-helpers.js";
43
41
 
@@ -106,7 +104,10 @@ export async function handleApprovalInterception(
106
104
  // When the sender is the guardian and there's a pending guardian approval
107
105
  // request targeting this chat, the message might be a decision on behalf
108
106
  // of a non-guardian requester. Delegated to the guardian callback strategy.
109
- if (trustCtx.trustClass === "guardian" && actorExternalId) {
107
+ if (
108
+ resolveCapabilities(trustCtx.trustClass).canSelfApproveTools &&
109
+ actorExternalId
110
+ ) {
110
111
  const guardianResult = await handleGuardianCallbackDecision({
111
112
  content,
112
113
  callbackData,
@@ -124,71 +125,10 @@ export async function handleApprovalInterception(
124
125
  }
125
126
  }
126
127
 
127
- // ── Slack reaction path ──
128
- // Reactions produce `callbackData` of the form `reaction:<emoji_name>`.
129
- // Handled before the pendingPrompt guard because guardian reactions arrive
130
- // on the guardian's chat (guardianChatId), not the requester's conversation,
131
- // so getChannelApprovalPrompt(conversationId) would return null.
132
- // Only guardians can approve via reaction — non-guardian reactions are
133
- // silently ignored to prevent self-approval.
134
- //
135
- // `reaction_removed:` callbackData never expresses an approval intent, and
136
- // `isSlackReactionEvent` short-circuits before reaching here for removals,
137
- // but guard explicitly so a future refactor can't turn an un-react into an
138
- // unintended approval.
139
- if (
140
- callbackData?.startsWith("reaction:") &&
141
- !callbackData.startsWith("reaction_removed:")
142
- ) {
143
- if (trustCtx.trustClass !== "guardian" || !actorExternalId) {
144
- return { handled: true, type: "stale_ignored" };
145
- }
146
- const reactionDecision = parseReactionCallbackData(callbackData);
147
- if (!reactionDecision) {
148
- // Unknown emoji — ignore silently
149
- return { handled: true, type: "stale_ignored" };
150
- }
151
-
152
- // Require the reacted-to message to be a tracked approval prompt. Without
153
- // this check, any unrelated 👍 reaction from the guardian in a subscribed
154
- // channel would approve the outstanding pending request (now that
155
- // reactions are admitted from any subscribed channel, not just tracked
156
- // bot threads). `approvalMessageTs` is `item.ts` of the reacted-to
157
- // Slack message, propagated from `sourceMetadata.messageId`.
158
- if (
159
- !approvalMessageTs ||
160
- !isTrackedApprovalPromptTs(
161
- sourceChannel,
162
- conversationExternalId,
163
- approvalMessageTs,
164
- )
165
- ) {
166
- return { handled: true, type: "stale_ignored" };
167
- }
168
-
169
- const allPending = getAllPendingApprovalsByGuardianChat(
170
- sourceChannel,
171
- conversationExternalId,
172
- );
173
- const guardianPending = allPending.filter(
174
- (approval) => approval.guardianExternalUserId === actorExternalId,
175
- );
176
- if (guardianPending.length !== 1) {
177
- return { handled: true, type: "stale_ignored" };
178
- }
179
-
180
- const result = await applyGuardianDecision({
181
- approval: guardianPending[0],
182
- decision: reactionDecision,
183
- actorPrincipalId: undefined,
184
- actorExternalUserId: actorExternalId,
185
- actorChannel: sourceChannel,
186
- });
187
- if (result.applied) {
188
- return { handled: true, type: "guardian_decision_applied" };
189
- }
190
- return { handled: true, type: "stale_ignored" };
191
- }
128
+ // Slack emoji reactions are handled by the canonical guardian decision
129
+ // pipeline (`routeGuardianReply`), invoked from the inbound reaction stage:
130
+ // it resolves the target request from the reacted card's delivery record.
131
+ // See `guardian-reply-router.ts`.
192
132
 
193
133
  // ── Standard approval interception (existing flow) ──
194
134
  const pendingPrompt = getChannelApprovalPrompt(conversationId);
@@ -220,10 +160,11 @@ export async function handleApprovalInterception(
220
160
 
221
161
  // When the sender is a non-guardian with established identity and a guardian
222
162
  // binding, block self-approval. The non-guardian must wait for the guardian
223
- // to decide. This covers trusted contacts and identity-known non-member
224
- // senders in shared channels.
163
+ // to decide. This covers trusted contacts, unverified contacts, and
164
+ // identity-known non-member senders in shared channels.
225
165
  const isIdentityKnownNonGuardian =
226
- trustCtx.trustClass === "trusted_contact" ||
166
+ resolveCapabilities(trustCtx.trustClass).sensitiveToolApproval ===
167
+ "escalate-and-wait" ||
227
168
  (trustCtx.trustClass === "unknown" &&
228
169
  !!trustCtx.requesterExternalUserId &&
229
170
  !!trustCtx.guardianExternalUserId);
@@ -465,7 +406,7 @@ export async function handleApprovalInterception(
465
406
  // standard conversational engine / legacy parser and resolve their own
466
407
  // pending request via handleChannelDecision.
467
408
  if (
468
- trustCtx.trustClass !== "guardian" &&
409
+ !resolveCapabilities(trustCtx.trustClass).canSelfApproveTools &&
469
410
  trustCtx.guardianExternalUserId
470
411
  ) {
471
412
  log.info(
@@ -2,6 +2,7 @@
2
2
  * Approval prompt delivery: rich UI (buttons) with plain-text fallback.
3
3
  */
4
4
  import type { ChannelId } from "../../channels/types.js";
5
+ import { recordApprovalCardDelivery } from "../../notifications/canonical-delivery-recorder.js";
5
6
  import { redactSecrets } from "../../security/secret-scanner.js";
6
7
  import { getLogger } from "../../util/logger.js";
7
8
  import type { ApprovalMessageContext } from "../approval-message-composer.js";
@@ -17,7 +18,6 @@ import {
17
18
  } from "../gateway-client.js";
18
19
  import { buildActionLegend } from "../guardian-decision-types.js";
19
20
  import type { ApprovalCopyGenerator } from "../http-types.js";
20
- import { trackApprovalPromptTs } from "./approval-prompt-ts-tracker.js";
21
21
  import { requiredDecisionKeywords } from "./channel-route-shared.js";
22
22
 
23
23
  const log = getLogger("runtime-http");
@@ -148,7 +148,13 @@ export async function deliverGeneratedApprovalPrompt(
148
148
  assistantId,
149
149
  );
150
150
  if (deliveryResult.ts) {
151
- trackApprovalPromptTs(sourceChannel, chatId, deliveryResult.ts);
151
+ recordApprovalCardDelivery({
152
+ requestId: uiMetadata.requestId,
153
+ channel: sourceChannel,
154
+ chatId,
155
+ messageId: deliveryResult.ts,
156
+ status: "sent",
157
+ });
152
158
  }
153
159
  return true;
154
160
  } catch (err) {
@@ -175,7 +181,13 @@ export async function deliverGeneratedApprovalPrompt(
175
181
  assistantId,
176
182
  });
177
183
  if (fallbackResult.ts) {
178
- trackApprovalPromptTs(sourceChannel, chatId, fallbackResult.ts);
184
+ recordApprovalCardDelivery({
185
+ requestId: uiMetadata.requestId,
186
+ channel: sourceChannel,
187
+ chatId,
188
+ messageId: fallbackResult.ts,
189
+ status: "sent",
190
+ });
179
191
  }
180
192
  return true;
181
193
  } catch (err) {
@@ -203,7 +215,13 @@ export async function deliverGeneratedApprovalPrompt(
203
215
  assistantId,
204
216
  });
205
217
  if (plainResult.ts) {
206
- trackApprovalPromptTs(sourceChannel, chatId, plainResult.ts);
218
+ recordApprovalCardDelivery({
219
+ requestId: uiMetadata.requestId,
220
+ channel: sourceChannel,
221
+ chatId,
222
+ messageId: plainResult.ts,
223
+ status: "sent",
224
+ });
207
225
  }
208
226
  return true;
209
227
  } catch (err) {
@@ -28,6 +28,7 @@ import {
28
28
  type FeedItemStatus,
29
29
  HomeFeedResponseSchema,
30
30
  } from "../../api/responses/home.js";
31
+ import { enrichFeedItemsWithSource } from "../../home/feed-source-enrichment.js";
31
32
  import { patchFeedItemStatus, readHomeFeed } from "../../home/feed-writer.js";
32
33
  import { revalidateHomeContentInBackground } from "../../home/home-content-refresh.js";
33
34
  import { getPersonalizedGreeting } from "../../home/home-greeting.js";
@@ -135,8 +136,10 @@ export async function handleGetHomeFeed({
135
136
  // v2 schema dropped per-item `minTimeAway` gating; surface every item
136
137
  // and let the client decide what to render based on its own
137
138
  // session state. `timeAwaySeconds` survives only to feed the
138
- // context-banner relative-time label.
139
- const filtered = feed.items;
139
+ // context-banner relative-time label. Each item is enriched with its
140
+ // source-conversation classification (`sourceType`/`sourceKey`/
141
+ // `sourceLabel`) so clients can filter the feed by what produced it.
142
+ const filtered = enrichFeedItemsWithSource(feed.items);
140
143
 
141
144
  const now = new Date();
142
145
 
@@ -287,7 +290,9 @@ export function handleListHomeFeed({
287
290
  const total = filtered.length;
288
291
  const offset = params.offset ?? 0;
289
292
  const limit = params.limit ?? 20;
290
- const items = filtered.slice(offset, offset + limit);
293
+ const items = enrichFeedItemsWithSource(
294
+ filtered.slice(offset, offset + limit),
295
+ );
291
296
 
292
297
  return {
293
298
  items,