@vellumai/assistant 0.9.0 → 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 (572) hide show
  1. package/ARCHITECTURE.md +18 -34
  2. package/bun.lock +7 -8
  3. package/docs/activation-funnel-telemetry.md +28 -22
  4. package/docs/architecture/security.md +29 -28
  5. package/docs/stt-provider-onboarding.md +3 -5
  6. package/docs/workflows-testing.md +13 -44
  7. package/docs/workflows.md +3 -5
  8. package/node_modules/@vellumai/ces-client/src/__tests__/ces-client.test.ts +47 -0
  9. package/node_modules/@vellumai/ces-client/src/rpc-client.ts +28 -5
  10. package/node_modules/@vellumai/environments/src/seeds.ts +2 -5
  11. package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +97 -0
  12. package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +10 -0
  13. package/node_modules/@vellumai/gateway-client/src/index.ts +32 -6
  14. package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +119 -0
  15. package/node_modules/@vellumai/gateway-client/src/types.ts +15 -84
  16. package/openapi.yaml +976 -63
  17. package/package.json +2 -1
  18. package/scripts/sync-llm-catalog.ts +6 -15
  19. package/scripts/sync-web-search-catalog.ts +3 -11
  20. package/src/__tests__/access-request-card-view.test.ts +98 -0
  21. package/src/__tests__/access-request-seed-content-blocks.test.ts +2 -4
  22. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +72 -32
  23. package/src/__tests__/agent-loop-compaction-strip.test.ts +241 -0
  24. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +16 -13
  25. package/src/__tests__/agent-loop-output-hooks.test.ts +69 -0
  26. package/src/__tests__/agent-loop-override-profile.test.ts +25 -0
  27. package/src/__tests__/always-loaded-tools-guard.test.ts +2 -3
  28. package/src/__tests__/app-compiler.test.ts +15 -1
  29. package/src/__tests__/app-dir-path-guard.test.ts +0 -1
  30. package/src/__tests__/assistant-feature-flag-guard.test.ts +1 -4
  31. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +0 -2
  32. package/src/__tests__/auth-fallback-events-store.test.ts +6 -14
  33. package/src/__tests__/avatar-identity-sync.test.ts +2 -27
  34. package/src/__tests__/btw-routes.test.ts +6 -8
  35. package/src/__tests__/call-pointer-messages.test.ts +28 -0
  36. package/src/__tests__/cancel-clears-processing.test.ts +89 -0
  37. package/src/__tests__/channel-approval-routes.test.ts +0 -4
  38. package/src/__tests__/channel-inbound-disk-pressure.test.ts +5 -15
  39. package/src/__tests__/checker.test.ts +0 -3
  40. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +3 -4
  41. package/src/__tests__/compactor-image-manifest-trust.test.ts +21 -1
  42. package/src/__tests__/compactor-summary-call-truncation.test.ts +223 -0
  43. package/src/__tests__/config-loader-backfill.test.ts +268 -27
  44. package/src/__tests__/config-schema.test.ts +35 -0
  45. package/src/__tests__/config-watcher.test.ts +0 -18
  46. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +2 -2
  47. package/src/__tests__/contact-store-user-file.test.ts +0 -6
  48. package/src/__tests__/contacts-tools.test.ts +29 -0
  49. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +22 -0
  50. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
  51. package/src/__tests__/conversation-agent-loop.test.ts +58 -0
  52. package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
  53. package/src/__tests__/conversation-lifecycle.test.ts +7 -9
  54. package/src/__tests__/conversation-load-history-repair.test.ts +101 -0
  55. package/src/__tests__/conversation-routes-guardian-reply.test.ts +15 -12
  56. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +6 -3
  57. package/src/__tests__/conversation-title-service.test.ts +62 -0
  58. package/src/__tests__/credential-broker.test.ts +449 -1
  59. package/src/__tests__/credential-execution-shell-lockdown.test.ts +18 -11
  60. package/src/__tests__/credential-execution-tools.test.ts +0 -1
  61. package/src/__tests__/credential-prompt-route.test.ts +4 -4
  62. package/src/__tests__/credential-routes.test.ts +360 -0
  63. package/src/__tests__/credential-security-invariants.test.ts +4 -13
  64. package/src/__tests__/disk-pressure-policy.test.ts +12 -0
  65. package/src/__tests__/disk-usage.test.ts +65 -0
  66. package/src/__tests__/dynamic-page-surface.test.ts +152 -1
  67. package/src/__tests__/fixtures/credential-security-fixtures.ts +2 -33
  68. package/src/__tests__/gateway-flag-listener.test.ts +110 -1
  69. package/src/__tests__/gateway-only-guard.test.ts +3 -7
  70. package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
  71. package/src/__tests__/guardian-card-withdrawal.test.ts +403 -0
  72. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +5 -3
  73. package/src/__tests__/guardian-grant-minting.test.ts +3 -35
  74. package/src/__tests__/guardian-routing-invariants.test.ts +64 -26
  75. package/src/__tests__/guardian-routing-state.test.ts +0 -1
  76. package/src/__tests__/headless-browser-mode.test.ts +10 -0
  77. package/src/__tests__/headless-browser-navigate.test.ts +8 -3
  78. package/src/__tests__/helpers/create-guardian-binding.ts +0 -1
  79. package/src/__tests__/host-browser-proxy.test.ts +87 -0
  80. package/src/__tests__/identity-routes.test.ts +0 -189
  81. package/src/__tests__/inbound-invite-redemption.test.ts +4 -4
  82. package/src/__tests__/injector-v3-suppression.test.ts +27 -20
  83. package/src/__tests__/internal-telemetry-routes.test.ts +6 -14
  84. package/src/__tests__/invite-redemption-service.test.ts +4 -7
  85. package/src/__tests__/llm-callsite-catalog.test.ts +5 -6
  86. package/src/__tests__/llm-catalog-parity.test.ts +30 -23
  87. package/src/__tests__/llm-resolver.test.ts +70 -24
  88. package/src/__tests__/llm-schema.test.ts +1 -0
  89. package/src/__tests__/managed-profile-guard.test.ts +163 -4
  90. package/src/__tests__/mcp-health-check.test.ts +6 -7
  91. package/src/__tests__/media-stream-server-integration.test.ts +317 -13
  92. package/src/__tests__/oauth-provider-seed-logos.test.ts +4 -6
  93. package/src/__tests__/onboarding-persona-write.test.ts +1 -1
  94. package/src/__tests__/path-policy.test.ts +34 -0
  95. package/src/__tests__/persona-resolver.test.ts +49 -14
  96. package/src/__tests__/plugin-api-model-profiles.test.ts +178 -0
  97. package/src/__tests__/plugin-api-provider.test.ts +24 -0
  98. package/src/__tests__/plugin-tool-contribution.test.ts +6 -3
  99. package/src/__tests__/post-compaction-reinjection-idempotency.test.ts +214 -0
  100. package/src/__tests__/provider-send-message-override-profile.test.ts +76 -0
  101. package/src/__tests__/reaction-persistence.test.ts +150 -29
  102. package/src/__tests__/registry.test.ts +2 -7
  103. package/src/__tests__/relay-server.test.ts +285 -0
  104. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
  105. package/src/__tests__/schedule-routes-workflow-validation.test.ts +1 -10
  106. package/src/__tests__/schedule-routes.test.ts +0 -30
  107. package/src/__tests__/schedule-tools.test.ts +2 -18
  108. package/src/__tests__/scheduler-reuse-conversation.test.ts +8 -5
  109. package/src/__tests__/skill-execute-input.test.ts +51 -1
  110. package/src/__tests__/skill-runtime-path.test.ts +2 -3
  111. package/src/__tests__/skills.test.ts +51 -0
  112. package/src/__tests__/slack-notification-approval-card.test.ts +176 -0
  113. package/src/__tests__/slack-reaction-canonical-approval.test.ts +285 -0
  114. package/src/__tests__/subagent-tools.test.ts +266 -0
  115. package/src/__tests__/surface-completion-nudge-hook.test.ts +367 -0
  116. package/src/__tests__/task-progress-nudge-hook.test.ts +1 -1
  117. package/src/__tests__/title-generate-hook.test.ts +100 -3
  118. package/src/__tests__/token-estimator-accuracy.benchmark.test.ts +1 -29
  119. package/src/__tests__/token-manager.test.ts +519 -0
  120. package/src/__tests__/tool-approval-seed-content-blocks.test.ts +1 -1
  121. package/src/__tests__/tool-audit-listener.test.ts +7 -7
  122. package/src/__tests__/tool-executor-lifecycle-events.test.ts +6 -3
  123. package/src/__tests__/tool-executor.test.ts +0 -79
  124. package/src/__tests__/trusted-contact-approval-notifier.test.ts +4 -2
  125. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +220 -3
  126. package/src/__tests__/trusted-contact-multichannel.test.ts +3 -3
  127. package/src/__tests__/trusted-contact-verification.test.ts +8 -10
  128. package/src/__tests__/twilio-routes.test.ts +81 -1
  129. package/src/__tests__/voice-invite-redemption.test.ts +2 -3
  130. package/src/__tests__/weak-open-model.test.ts +30 -0
  131. package/src/__tests__/web-search-catalog-parity.test.ts +6 -25
  132. package/src/__tests__/workspace-greetings.test.ts +152 -0
  133. package/src/__tests__/workspace-migration-105-enable-memory-v3-live-for-new-workspaces.test.ts +149 -0
  134. package/src/__tests__/workspace-migration-108-drop-balanced-economy-profile.test.ts +285 -0
  135. package/src/__tests__/workspace-migration-add-send-diagnostics.test.ts +1 -1
  136. package/src/__tests__/workspace-migration-drop-collect-usage-data.test.ts +118 -0
  137. package/src/__tests__/workspace-migration-drop-send-diagnostics.test.ts +118 -0
  138. package/src/a2a/__tests__/e2e-a2a-channel.test.ts +0 -4
  139. package/src/agent/loop.ts +49 -29
  140. package/src/api/README.md +6 -6
  141. package/src/api/events/tool-result.ts +6 -0
  142. package/src/api/events/workflow-completed.ts +53 -0
  143. package/src/api/events/workflow-leaf-finished.ts +38 -0
  144. package/src/api/events/workflow-leaf-started.ts +35 -0
  145. package/src/api/events/workflow-progress.ts +32 -0
  146. package/src/api/events/workflow-started.ts +31 -0
  147. package/src/api/index.ts +40 -0
  148. package/src/api/responses/conversation-message.ts +28 -4
  149. package/src/api/responses/home.ts +26 -4
  150. package/src/api/responses/workflow-journal.ts +53 -0
  151. package/src/approvals/guardian-card-withdrawal.ts +145 -0
  152. package/src/approvals/guardian-decision-primitive.ts +26 -3
  153. package/src/approvals/guardian-request-resolvers.ts +183 -80
  154. package/src/calls/__tests__/channel-admission-reader.test.ts +132 -0
  155. package/src/calls/__tests__/relay-setup-router.test.ts +350 -0
  156. package/src/calls/call-pointer-messages.ts +10 -4
  157. package/src/calls/channel-admission-reader.ts +104 -0
  158. package/src/calls/guardian-dispatch.ts +17 -45
  159. package/src/calls/media-stream-server.ts +84 -2
  160. package/src/calls/relay-access-wait.ts +1 -1
  161. package/src/calls/relay-server.ts +66 -0
  162. package/src/calls/relay-setup-router.ts +82 -1
  163. package/src/calls/twilio-routes.ts +17 -8
  164. package/src/calls/voice-session-bridge.ts +2 -2
  165. package/src/cli/commands/clients.ts +3 -0
  166. package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2-compare-render.test.ts +1 -1
  167. package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2.test.ts +8 -7
  168. package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v3.test.ts +5 -4
  169. package/src/cli/commands/memory/index.ts +30 -0
  170. package/src/cli/commands/{memory-v2-compare-render.ts → memory/memory-v2-compare-render.ts} +1 -1
  171. package/src/cli/commands/{memory-v2.ts → memory/memory-v2.ts} +6 -15
  172. package/src/cli/commands/{memory-v3.ts → memory/memory-v3.ts} +97 -11
  173. package/src/cli/commands/oauth/status.test.ts +36 -0
  174. package/src/cli/commands/oauth/status.ts +23 -3
  175. package/src/cli/commands/plugins.ts +197 -4
  176. package/src/cli/lib/__tests__/diff-plugin.test.ts +443 -0
  177. package/src/cli/lib/__tests__/inspect-plugin.test.ts +54 -0
  178. package/src/cli/lib/__tests__/merge-plugin-tree.test.ts +443 -0
  179. package/src/cli/lib/__tests__/plugin-surfaces.test.ts +111 -0
  180. package/src/cli/lib/__tests__/upgrade-plugin.test.ts +295 -2
  181. package/src/cli/lib/diff-plugin.ts +346 -0
  182. package/src/cli/lib/inspect-plugin.ts +12 -1
  183. package/src/cli/lib/install-from-github.ts +105 -17
  184. package/src/cli/lib/merge-plugin-tree.ts +328 -0
  185. package/src/cli/lib/plugin-fingerprint.ts +14 -0
  186. package/src/cli/lib/plugin-surfaces.ts +104 -0
  187. package/src/cli/lib/upgrade-plugin.ts +298 -10
  188. package/src/cli/program.ts +2 -6
  189. package/src/config/__tests__/sync-gated-profiles.test.ts +368 -0
  190. package/src/config/assistant-feature-flags.ts +22 -7
  191. package/src/config/bundled-skills/contacts/tools/contact-search.ts +0 -1
  192. package/src/config/bundled-skills/messaging/SKILL.md +6 -4
  193. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +9 -8
  194. package/src/config/bundled-skills/subagent/SKILL.md +4 -0
  195. package/src/config/bundled-skills/subagent/TOOLS.json +4 -0
  196. package/src/config/bundled-skills/workflows/SKILL.md +14 -8
  197. package/src/config/bundled-tool-registry.ts +2 -7
  198. package/src/config/call-site-defaults.ts +15 -2
  199. package/src/config/feature-flag-registry.json +46 -31
  200. package/src/config/inference-profile-validation.ts +26 -0
  201. package/src/config/llm-resolver.ts +3 -0
  202. package/src/config/loader.ts +4 -0
  203. package/src/config/memory-v3-gate.ts +11 -0
  204. package/src/config/profile-order.ts +28 -0
  205. package/src/config/schema.ts +8 -6
  206. package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
  207. package/src/config/schemas/call-site-catalog.ts +7 -0
  208. package/src/config/schemas/channels.ts +11 -0
  209. package/src/config/schemas/elevenlabs.ts +0 -1
  210. package/src/config/schemas/llm.ts +31 -0
  211. package/src/config/schemas/memory-lifecycle.ts +3 -7
  212. package/src/config/schemas/memory-v3.ts +6 -0
  213. package/src/config/schemas/platform.ts +0 -8
  214. package/src/config/schemas/services.ts +18 -0
  215. package/src/config/seed-inference-profiles.ts +109 -44
  216. package/src/config/skills.ts +21 -0
  217. package/src/config/sync-gated-profiles.ts +220 -0
  218. package/src/contacts/contact-store.ts +89 -106
  219. package/src/contacts/contacts-write.ts +5 -22
  220. package/src/contacts/types.ts +0 -1
  221. package/src/context/compactor.ts +88 -54
  222. package/src/context/strip-injections.ts +58 -10
  223. package/src/context/token-estimator.ts +1 -1
  224. package/src/credential-execution/process-manager.ts +55 -14
  225. package/src/credential-execution/prompted-credential.ts +2 -3
  226. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -2
  227. package/src/daemon/config-watcher.ts +0 -4
  228. package/src/daemon/conversation-agent-loop-handlers.ts +2 -0
  229. package/src/daemon/conversation-agent-loop.ts +114 -22
  230. package/src/daemon/conversation-history.ts +1 -1
  231. package/src/daemon/conversation-lifecycle.ts +3 -5
  232. package/src/daemon/conversation-process.ts +13 -5
  233. package/src/daemon/conversation-runtime-assembly.ts +13 -15
  234. package/src/daemon/conversation-slash.ts +2 -23
  235. package/src/daemon/conversation-surfaces.ts +26 -0
  236. package/src/daemon/conversation-tool-setup.ts +27 -14
  237. package/src/daemon/conversation.ts +66 -14
  238. package/src/daemon/disk-pressure-policy.ts +5 -3
  239. package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +0 -1
  240. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -1
  241. package/src/daemon/handlers/config-a2a.ts +0 -2
  242. package/src/daemon/handlers/config-channels.ts +15 -16
  243. package/src/daemon/handlers/config-slack-channel.ts +22 -3
  244. package/src/daemon/handlers/conversations.ts +107 -0
  245. package/src/daemon/host-browser-proxy.ts +41 -0
  246. package/src/daemon/lifecycle.ts +55 -27
  247. package/src/daemon/message-provenance.ts +2 -0
  248. package/src/daemon/message-types/contacts.ts +0 -1
  249. package/src/daemon/message-types/conversations.ts +3 -3
  250. package/src/daemon/message-types/sync.ts +0 -1
  251. package/src/daemon/message-types/web-activity.ts +7 -1
  252. package/src/daemon/message-types/workflows.ts +83 -1
  253. package/src/daemon/orphan-reaper.test.ts +0 -19
  254. package/src/daemon/orphan-reaper.ts +2 -24
  255. package/src/daemon/server.ts +0 -10
  256. package/src/daemon/tool-setup-types.ts +4 -0
  257. package/src/daemon/trust-context.ts +1 -1
  258. package/src/events/tool-audit-listener.ts +2 -2
  259. package/src/home/feed-source-enrichment.test.ts +151 -0
  260. package/src/home/feed-source-enrichment.ts +176 -0
  261. package/src/home/relationship-state.ts +2 -4
  262. package/src/instrument.ts +18 -6
  263. package/src/ipc/__tests__/binary-result-ipc.test.ts +81 -0
  264. package/src/ipc/__tests__/clients-list-ipc.test.ts +20 -0
  265. package/src/ipc/assistant-server.ts +37 -4
  266. package/src/ipc/gateway-flag-listener.ts +18 -2
  267. package/src/memory/__tests__/auto-analysis-enqueue.test.ts +5 -16
  268. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +7 -11
  269. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +37 -7
  270. package/src/memory/__tests__/memory-retrospective-job.test.ts +229 -401
  271. package/src/memory/__tests__/onboarding-events-store.test.ts +7 -7
  272. package/src/memory/auth-fallback-events-store.ts +2 -2
  273. package/src/memory/auto-analysis-enqueue.ts +3 -5
  274. package/src/memory/bookmark-crud.ts +1 -2
  275. package/src/memory/canonical-guardian-store.ts +39 -1
  276. package/src/memory/conversation-crud.ts +9 -4
  277. package/src/memory/conversation-key-store.ts +17 -2
  278. package/src/memory/conversation-title-service.ts +64 -7
  279. package/src/memory/db-init.ts +17 -17
  280. package/src/memory/embedding-backend.ts +38 -1
  281. package/src/memory/embedding-billing-breaker.ts +96 -0
  282. package/src/memory/jobs-store.ts +25 -13
  283. package/src/memory/jobs-worker.ts +54 -1
  284. package/src/memory/lifecycle-events-store.ts +2 -2
  285. package/src/memory/memory-retrospective-constants.ts +4 -4
  286. package/src/memory/memory-retrospective-enqueue.ts +31 -6
  287. package/src/memory/memory-retrospective-job.ts +28 -227
  288. package/src/memory/migrations/129-contact-channels-access-fields.ts +18 -9
  289. package/src/memory/migrations/131-drop-legacy-member-guardian-tables.ts +14 -2
  290. package/src/memory/migrations/289-contact-channels-unique-ext-user.ts +10 -0
  291. package/src/memory/migrations/291-contact-channels-renormalize-addresses.ts +72 -0
  292. package/src/memory/migrations/292-schedule-default-no-reuse-conversation.test.ts +67 -0
  293. package/src/memory/migrations/292-schedule-default-no-reuse-conversation.ts +25 -0
  294. package/src/memory/migrations/293-workflow-journal-leaf-tokens.ts +32 -0
  295. package/src/memory/migrations/294-drop-external-user-id.ts +31 -0
  296. package/src/memory/migrations/295-drop-approval-prompt-ts-tracker.ts +20 -0
  297. package/src/memory/migrations/296-rewrite-balanced-economy-profile-pins.test.ts +110 -0
  298. package/src/memory/migrations/296-rewrite-balanced-economy-profile-pins.ts +68 -0
  299. package/src/memory/migrations/__tests__/131-drop-legacy-member-guardian-tables.test.ts +154 -0
  300. package/src/memory/migrations/__tests__/289-contact-channels-unique-ext-user.test.ts +31 -0
  301. package/src/memory/migrations/__tests__/291-contact-channels-renormalize-addresses.test.ts +341 -0
  302. package/src/memory/migrations/__tests__/run-migrations.test.ts +52 -0
  303. package/src/memory/migrations/index.ts +6 -0
  304. package/src/memory/migrations/run-migrations.ts +41 -0
  305. package/src/memory/migrations/validate-migration-state.ts +1 -1
  306. package/src/memory/onboarding-events-store.ts +3 -3
  307. package/src/memory/schema/contacts.ts +0 -5
  308. package/src/memory/skill-loaded-events-store.test.ts +7 -15
  309. package/src/memory/skill-loaded-events-store.ts +2 -2
  310. package/src/memory/tool-executed-events-store.test.ts +7 -7
  311. package/src/memory/turn-trace-store.test.ts +736 -0
  312. package/src/memory/turn-trace-store.ts +364 -0
  313. package/src/memory/v2/__tests__/consolidation-job.test.ts +8 -0
  314. package/src/memory/v2/__tests__/skill-content.test.ts +30 -0
  315. package/src/memory/v2/consolidation-job.ts +2 -2
  316. package/src/memory/v2/skill-content.ts +25 -7
  317. package/src/memory/v2/skill-store.ts +7 -1
  318. package/src/memory/v3-eval/__tests__/eval-packets.test.ts +248 -0
  319. package/src/memory/v3-eval/eval-packets.ts +546 -0
  320. package/src/messaging/providers/slack/adapter.ts +1 -1
  321. package/src/messaging/providers/slack/api.ts +31 -0
  322. package/src/messaging/providers/slack/send.test.ts +114 -2
  323. package/src/messaging/providers/slack/send.ts +30 -7
  324. package/src/messaging/providers/slack/withdraw.test.ts +200 -0
  325. package/src/messaging/providers/slack/withdraw.ts +161 -0
  326. package/src/notifications/AGENTS.md +2 -0
  327. package/src/notifications/access-request-copy.ts +72 -59
  328. package/src/notifications/adapters/shared.ts +29 -0
  329. package/src/notifications/adapters/slack.ts +58 -103
  330. package/src/notifications/adapters/telegram.ts +2 -20
  331. package/src/notifications/approval-card-data.ts +333 -0
  332. package/src/notifications/broadcaster.ts +16 -3
  333. package/src/notifications/canonical-delivery-recorder.ts +139 -0
  334. package/src/notifications/copy-composer.ts +3 -3
  335. package/src/notifications/decision-engine.ts +4 -2
  336. package/src/notifications/destination-resolver.ts +4 -6
  337. package/src/notifications/guardian-question-mode.ts +10 -0
  338. package/src/notifications/home-feed-side-effect.ts +7 -16
  339. package/src/notifications/notification-utils.ts +19 -20
  340. package/src/notifications/signal.ts +79 -43
  341. package/src/notifications/types.ts +98 -121
  342. package/src/oauth/AGENTS.md +5 -24
  343. package/src/permissions/checker.test.ts +51 -0
  344. package/src/permissions/checker.ts +185 -26
  345. package/src/permissions/ipc-risk-types.ts +24 -0
  346. package/src/permissions/question-prompter.test.ts +27 -0
  347. package/src/permissions/question-prompter.ts +4 -0
  348. package/src/platform/client.test.ts +119 -0
  349. package/src/platform/client.ts +66 -0
  350. package/src/platform/consent-cache.test.ts +267 -0
  351. package/src/platform/consent-cache.ts +174 -0
  352. package/src/plugin-api/constants.ts +1 -1
  353. package/src/plugin-api/index.ts +33 -1
  354. package/src/plugin-api/model-profiles.ts +33 -0
  355. package/src/plugin-api/types.ts +50 -2
  356. package/src/plugins/defaults/advisor/__tests__/advisor-gate.test.ts +56 -0
  357. package/src/plugins/defaults/advisor/__tests__/advisor-state-store.test.ts +43 -0
  358. package/src/plugins/defaults/advisor/__tests__/agent-loop-integration.test.ts +137 -0
  359. package/src/plugins/defaults/advisor/__tests__/consult.test.ts +153 -0
  360. package/src/plugins/defaults/advisor/__tests__/hooks.test.ts +138 -0
  361. package/src/plugins/defaults/advisor/__tests__/transcript.test.ts +147 -0
  362. package/src/plugins/defaults/advisor/advisor-gate.ts +29 -0
  363. package/src/plugins/defaults/advisor/advisor-state-store.ts +94 -0
  364. package/src/plugins/defaults/advisor/config.ts +21 -0
  365. package/src/plugins/defaults/advisor/consult.ts +93 -0
  366. package/src/plugins/defaults/advisor/hooks/post-model-call.ts +34 -0
  367. package/src/plugins/defaults/advisor/hooks/pre-model-call.ts +30 -0
  368. package/src/plugins/defaults/advisor/hooks/user-prompt-submit.ts +19 -0
  369. package/src/plugins/defaults/advisor/package.json +14 -0
  370. package/src/plugins/defaults/advisor/steering.ts +67 -0
  371. package/src/plugins/defaults/advisor/tools/advisor.ts +65 -0
  372. package/src/plugins/defaults/advisor/transcript.ts +76 -0
  373. package/src/plugins/defaults/index.ts +60 -0
  374. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +22 -9
  375. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +2 -2
  376. package/src/plugins/defaults/memory-retrieval/tail-reinjection-strip.ts +64 -0
  377. package/src/plugins/defaults/memory-retrieval/unified-turn-context.ts +29 -21
  378. package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +1 -0
  379. package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +1 -0
  380. package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +129 -9
  381. package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +31 -4
  382. package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +77 -2
  383. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +1 -0
  384. package/src/plugins/defaults/memory-v3-shadow/injector.ts +7 -10
  385. package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +144 -11
  386. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +32 -20
  387. package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +56 -3
  388. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +23 -2
  389. package/src/plugins/defaults/surface-completion-nudge/hooks/post-model-call.ts +276 -0
  390. package/src/plugins/defaults/surface-completion-nudge/hooks/stop.ts +22 -0
  391. package/src/plugins/defaults/surface-completion-nudge/nudge-state-store.ts +46 -0
  392. package/src/plugins/defaults/surface-completion-nudge/package.json +14 -0
  393. package/src/plugins/defaults/task-progress-nudge/hooks/post-tool-use.ts +3 -13
  394. package/src/plugins/defaults/title-generate/hooks/stop.ts +56 -21
  395. package/src/prompts/persona-resolver.ts +14 -4
  396. package/src/prompts/templates/system-sections.ts +7 -2
  397. package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
  398. package/src/providers/__tests__/provider-secret-catalog.test.ts +1 -0
  399. package/src/providers/__tests__/retry-callsite.test.ts +176 -0
  400. package/src/providers/atlascloud/client.ts +85 -0
  401. package/src/providers/fetch-provider-catalog.ts +85 -0
  402. package/src/providers/inference/adapter-factory.ts +3 -0
  403. package/src/providers/model-catalog.ts +58 -0
  404. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +33 -0
  405. package/src/providers/openai/chat-completions-provider.ts +7 -0
  406. package/src/providers/openai/responses-provider.ts +10 -0
  407. package/src/providers/provider-send-message.ts +11 -3
  408. package/src/providers/retry.ts +53 -12
  409. package/src/providers/search-provider-catalog.ts +10 -0
  410. package/src/providers/weak-open-model.ts +22 -0
  411. package/src/runtime/AGENTS.md +0 -1
  412. package/src/runtime/__tests__/agent-wake.test.ts +181 -0
  413. package/src/runtime/__tests__/client-health.test.ts +44 -0
  414. package/src/runtime/access-request-helper.ts +21 -53
  415. package/src/runtime/actor-trust-resolver.ts +59 -63
  416. package/src/runtime/agent-wake.ts +52 -0
  417. package/src/runtime/assistant-event-hub.ts +18 -4
  418. package/src/runtime/auth/__tests__/route-policy.test.ts +12 -0
  419. package/src/runtime/auth/require-bound-guardian.ts +1 -4
  420. package/src/runtime/btw-sidechain.ts +3 -6
  421. package/src/runtime/capabilities.test.ts +120 -0
  422. package/src/runtime/capabilities.ts +197 -0
  423. package/src/runtime/channel-approval-types.ts +22 -45
  424. package/src/runtime/channel-invite-transports/telegram.ts +4 -4
  425. package/src/runtime/channel-retry-sweep.ts +1 -0
  426. package/src/runtime/channel-verification-service.ts +3 -3
  427. package/src/runtime/client-health.ts +26 -0
  428. package/src/runtime/confirmation-request-guardian-bridge.ts +38 -29
  429. package/src/runtime/effective-capabilities.test.ts +128 -0
  430. package/src/runtime/effective-capabilities.ts +84 -0
  431. package/src/runtime/guardian-reply-router.ts +106 -21
  432. package/src/runtime/invite-redemption-service.ts +9 -25
  433. package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +123 -0
  434. package/src/runtime/migrations/vbundle-builder.ts +49 -20
  435. package/src/runtime/pending-interactions.ts +15 -0
  436. package/src/runtime/routes/__tests__/client-routes.test.ts +13 -0
  437. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +67 -0
  438. package/src/runtime/routes/__tests__/plugins-routes.test.ts +240 -1
  439. package/src/runtime/routes/app-routes.ts +1 -1
  440. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +2 -2
  441. package/src/runtime/routes/assets/vellum-design-system.css +1959 -0
  442. package/src/runtime/routes/browser-tabs-routes.ts +9 -0
  443. package/src/runtime/routes/btw-routes.ts +1 -27
  444. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +17 -8
  445. package/src/runtime/routes/client-routes.ts +10 -0
  446. package/src/runtime/routes/contact-routes.ts +31 -8
  447. package/src/runtime/routes/conversation-compaction-routes.ts +1 -1
  448. package/src/runtime/routes/conversation-management-routes.ts +80 -1
  449. package/src/runtime/routes/conversation-query-routes.ts +68 -22
  450. package/src/runtime/routes/conversation-routes.ts +39 -14
  451. package/src/runtime/routes/credential-routes.ts +40 -16
  452. package/src/runtime/routes/empty-state-greeting-cache.ts +1 -2
  453. package/src/runtime/routes/events-routes.ts +1 -3
  454. package/src/runtime/routes/guardian-approval-interception.ts +14 -73
  455. package/src/runtime/routes/guardian-approval-prompt.ts +22 -4
  456. package/src/runtime/routes/home-feed-routes.ts +8 -3
  457. package/src/runtime/routes/identity-routes.ts +1 -296
  458. package/src/runtime/routes/inbound-message-handler.ts +214 -228
  459. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +89 -7
  460. package/src/runtime/routes/inbound-stages/admission-policy.test.ts +154 -0
  461. package/src/runtime/routes/inbound-stages/admission-policy.ts +140 -0
  462. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +3 -3
  463. package/src/runtime/routes/inbound-stages/background-dispatch.ts +11 -6
  464. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +1 -2
  465. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +1 -2
  466. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +7 -7
  467. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +47 -28
  468. package/src/runtime/routes/inbound-stages/reaction-intercept.ts +358 -0
  469. package/src/runtime/routes/index.ts +2 -0
  470. package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +8 -0
  471. package/src/runtime/routes/integrations/slack/channel.ts +36 -0
  472. package/src/runtime/routes/internal-telemetry-routes.ts +1 -1
  473. package/src/runtime/routes/mcp-auth-routes.ts +233 -41
  474. package/src/runtime/routes/memory-eval-routes.ts +87 -0
  475. package/src/runtime/routes/notification-routes.ts +122 -133
  476. package/src/runtime/routes/platform-routes.ts +2 -2
  477. package/src/runtime/routes/plugins-routes.ts +202 -3
  478. package/src/runtime/routes/schedule-routes.ts +0 -22
  479. package/src/runtime/routes/secret-routes.ts +10 -0
  480. package/src/runtime/routes/surface-action-routes.ts +2 -1
  481. package/src/runtime/routes/tool-call-question-enrichment.test.ts +146 -0
  482. package/src/runtime/routes/tool-call-question-enrichment.ts +66 -0
  483. package/src/runtime/routes/workflow-routes.test.ts +229 -44
  484. package/src/runtime/routes/workflow-routes.ts +131 -29
  485. package/src/runtime/routes/workspace-greetings.ts +55 -0
  486. package/src/runtime/sync/resource-sync-events.ts +1 -11
  487. package/src/runtime/tool-grant-request-helper.ts +18 -16
  488. package/src/runtime/trust-context-resolver.ts +8 -5
  489. package/src/schedule/inference-profile.ts +2 -14
  490. package/src/schedule/schedule-store.ts +1 -1
  491. package/src/schedule/scheduler-types.ts +5 -1
  492. package/src/security/__tests__/provider-key-env-fallback.test.ts +6 -0
  493. package/src/security/secret-patterns.ts +3 -0
  494. package/src/subagent/manager.ts +17 -4
  495. package/src/subagent/types.ts +6 -0
  496. package/src/telemetry/trace-collection-policy.test.ts +28 -0
  497. package/src/telemetry/trace-collection-policy.ts +30 -0
  498. package/src/telemetry/types.ts +89 -0
  499. package/src/telemetry/usage-telemetry-reporter.test.ts +586 -36
  500. package/src/telemetry/usage-telemetry-reporter.ts +148 -41
  501. package/src/tools/AGENTS.md +3 -3
  502. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +31 -0
  503. package/src/tools/browser/browser-execution.ts +30 -19
  504. package/src/tools/document/document-tool.ts +2 -3
  505. package/src/tools/executor.ts +5 -3
  506. package/src/tools/host-terminal/host-shell.ts +5 -4
  507. package/src/tools/memory/register.ts +2 -2
  508. package/src/tools/network/__tests__/web-fetch-firecrawl.test.ts +360 -0
  509. package/src/tools/network/__tests__/web-search.test.ts +143 -0
  510. package/src/tools/network/web-fetch.ts +372 -1
  511. package/src/tools/network/web-search-error.ts +1 -1
  512. package/src/tools/network/web-search.ts +213 -10
  513. package/src/tools/permission-checker.ts +4 -3
  514. package/src/tools/registry.ts +20 -0
  515. package/src/tools/schedule/create.ts +7 -12
  516. package/src/tools/schedule/update.ts +4 -11
  517. package/src/tools/shared/filesystem/path-policy.ts +39 -13
  518. package/src/tools/side-effects.ts +2 -17
  519. package/src/tools/skills/execute.ts +33 -0
  520. package/src/tools/subagent/spawn.ts +61 -12
  521. package/src/tools/terminal/shell.ts +10 -4
  522. package/src/tools/tool-approval-handler.ts +18 -13
  523. package/src/tools/tool-manifest.ts +0 -2
  524. package/src/tools/types.ts +9 -0
  525. package/src/tools/ui-surface/definitions.ts +64 -3
  526. package/src/tools/verification-control-plane-policy.ts +3 -1
  527. package/src/tools/workflows/run-workflow.test.ts +8 -18
  528. package/src/tools/workflows/run-workflow.ts +1 -0
  529. package/src/util/disk-usage.ts +78 -23
  530. package/src/util/platform.ts +10 -3
  531. package/src/watcher/telemetry.ts +2 -2
  532. package/src/workflows/capabilities.ts +2 -3
  533. package/src/workflows/engine.test.ts +175 -1
  534. package/src/workflows/engine.ts +82 -0
  535. package/src/workflows/journal-store.test.ts +70 -0
  536. package/src/workflows/journal-store.ts +18 -3
  537. package/src/workflows/run-manager.test.ts +171 -28
  538. package/src/workflows/run-manager.ts +66 -24
  539. package/src/workspace/migrations/105-enable-memory-v3-live-for-new-workspaces.ts +63 -0
  540. package/src/workspace/migrations/106-drop-collect-usage-data.ts +47 -0
  541. package/src/workspace/migrations/107-drop-send-diagnostics.ts +47 -0
  542. package/src/workspace/migrations/108-drop-balanced-economy-profile.ts +129 -0
  543. package/src/workspace/migrations/registry.ts +8 -0
  544. package/src/__tests__/app-control-no-global-cgevent.test.ts +0 -98
  545. package/src/__tests__/credential-security-e2e.test.ts +0 -362
  546. package/src/__tests__/credential-vault-unit.test.ts +0 -1528
  547. package/src/__tests__/credential-vault.test.ts +0 -1706
  548. package/src/__tests__/identity-intro-cache.test.ts +0 -315
  549. package/src/__tests__/secret-onetime-send.test.ts +0 -182
  550. package/src/cli/commands/__tests__/task.test.ts +0 -914
  551. package/src/cli/commands/task.ts +0 -771
  552. package/src/config/bundled-skills/personal-page/SKILL.md +0 -57
  553. package/src/config/bundled-skills/personal-page/TOOLS.json +0 -27
  554. package/src/config/bundled-skills/personal-page/tools/app-refresh.ts +0 -17
  555. package/src/config/preloaded-apps/personal-page/src/components/About.tsx +0 -22
  556. package/src/config/preloaded-apps/personal-page/src/components/App.tsx +0 -16
  557. package/src/config/preloaded-apps/personal-page/src/components/Features.tsx +0 -77
  558. package/src/config/preloaded-apps/personal-page/src/components/Hero.tsx +0 -57
  559. package/src/config/preloaded-apps/personal-page/src/components/Pending.tsx +0 -28
  560. package/src/config/preloaded-apps/personal-page/src/components/animations.tsx +0 -234
  561. package/src/config/preloaded-apps/personal-page/src/components/icons.tsx +0 -48
  562. package/src/config/preloaded-apps/personal-page/src/components/media.ts +0 -16
  563. package/src/config/preloaded-apps/personal-page/src/index.html +0 -20
  564. package/src/config/preloaded-apps/personal-page/src/main.tsx +0 -7
  565. package/src/config/preloaded-apps/personal-page/src/profile-data.ts +0 -82
  566. package/src/config/preloaded-apps/personal-page/src/styles.css +0 -759
  567. package/src/memory/__tests__/preloaded-apps.test.ts +0 -85
  568. package/src/memory/preloaded-apps.ts +0 -116
  569. package/src/notifications/tool-approval-copy.ts +0 -142
  570. package/src/runtime/routes/approval-prompt-ts-tracker.ts +0 -78
  571. package/src/runtime/routes/identity-intro-cache.ts +0 -172
  572. package/src/tools/credentials/vault.ts +0 -712
@@ -0,0 +1,118 @@
1
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
2
+
3
+ // ---------------------------------------------------------------------------
4
+ // Mock state
5
+ // ---------------------------------------------------------------------------
6
+
7
+ const existsSyncFn = mock((_path: string): boolean => false);
8
+ const readFileSyncFn = mock((_path: string, _encoding: string): string => "");
9
+ const writeFileSyncFn = mock((_path: string, _data: string): void => undefined);
10
+
11
+ // ---------------------------------------------------------------------------
12
+ // Mock modules — before importing module under test
13
+ // ---------------------------------------------------------------------------
14
+
15
+ mock.module("node:fs", () => ({
16
+ existsSync: existsSyncFn,
17
+ readFileSync: readFileSyncFn,
18
+ writeFileSync: writeFileSyncFn,
19
+ }));
20
+
21
+ // Import after mocking
22
+ import { dropCollectUsageDataMigration } from "../workspace/migrations/106-drop-collect-usage-data.js";
23
+
24
+ // ---------------------------------------------------------------------------
25
+ // Helpers
26
+ // ---------------------------------------------------------------------------
27
+
28
+ const WORKSPACE_DIR = "/tmp/test-workspace";
29
+ const CONFIG_PATH = `${WORKSPACE_DIR}/config.json`;
30
+
31
+ function setupConfigExists(config: unknown) {
32
+ existsSyncFn.mockImplementation((path: string) => path === CONFIG_PATH);
33
+ readFileSyncFn.mockImplementation(() => JSON.stringify(config));
34
+ }
35
+
36
+ function getWrittenConfig(): Record<string, unknown> {
37
+ expect(writeFileSyncFn).toHaveBeenCalledTimes(1);
38
+ const [path, data] = writeFileSyncFn.mock.calls[0] as [string, string];
39
+ expect(path).toBe(CONFIG_PATH);
40
+ return JSON.parse(data) as Record<string, unknown>;
41
+ }
42
+
43
+ // ---------------------------------------------------------------------------
44
+ // Tests
45
+ // ---------------------------------------------------------------------------
46
+
47
+ describe("106-drop-collect-usage-data migration", () => {
48
+ beforeEach(() => {
49
+ existsSyncFn.mockClear();
50
+ readFileSyncFn.mockClear();
51
+ writeFileSyncFn.mockClear();
52
+ });
53
+
54
+ test("no-op when config.json is absent", () => {
55
+ existsSyncFn.mockImplementation(() => false);
56
+
57
+ dropCollectUsageDataMigration.run(WORKSPACE_DIR);
58
+
59
+ expect(readFileSyncFn).not.toHaveBeenCalled();
60
+ expect(writeFileSyncFn).not.toHaveBeenCalled();
61
+ });
62
+
63
+ test("explicit opt-out is preserved as legacyTelemetryOptOut", () => {
64
+ setupConfigExists({ collectUsageData: false, someSetting: "value" });
65
+
66
+ dropCollectUsageDataMigration.run(WORKSPACE_DIR);
67
+
68
+ const written = getWrittenConfig();
69
+ expect(written.collectUsageData).toBeUndefined();
70
+ expect(written.legacyTelemetryOptOut).toBe(true);
71
+ expect(written.someSetting).toBe("value");
72
+ });
73
+
74
+ test("collectUsageData: true is removed without setting the marker", () => {
75
+ setupConfigExists({ collectUsageData: true });
76
+
77
+ dropCollectUsageDataMigration.run(WORKSPACE_DIR);
78
+
79
+ const written = getWrittenConfig();
80
+ expect(written.collectUsageData).toBeUndefined();
81
+ expect(written.legacyTelemetryOptOut).toBeUndefined();
82
+ });
83
+
84
+ test("non-false value is removed without setting the marker", () => {
85
+ setupConfigExists({ collectUsageData: "yes" });
86
+
87
+ dropCollectUsageDataMigration.run(WORKSPACE_DIR);
88
+
89
+ const written = getWrittenConfig();
90
+ expect(written.collectUsageData).toBeUndefined();
91
+ expect(written.legacyTelemetryOptOut).toBeUndefined();
92
+ });
93
+
94
+ test("no-op when collectUsageData is absent (no marker)", () => {
95
+ setupConfigExists({ someSetting: "value" });
96
+
97
+ dropCollectUsageDataMigration.run(WORKSPACE_DIR);
98
+
99
+ expect(writeFileSyncFn).not.toHaveBeenCalled();
100
+ });
101
+
102
+ test("malformed config is handled gracefully", () => {
103
+ existsSyncFn.mockImplementation((path: string) => path === CONFIG_PATH);
104
+ readFileSyncFn.mockImplementation(() => "not valid json {{{");
105
+
106
+ dropCollectUsageDataMigration.run(WORKSPACE_DIR);
107
+
108
+ expect(writeFileSyncFn).not.toHaveBeenCalled();
109
+ });
110
+
111
+ test("no-op when config is an array", () => {
112
+ setupConfigExists([1, 2, 3]);
113
+
114
+ dropCollectUsageDataMigration.run(WORKSPACE_DIR);
115
+
116
+ expect(writeFileSyncFn).not.toHaveBeenCalled();
117
+ });
118
+ });
@@ -0,0 +1,118 @@
1
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
2
+
3
+ // ---------------------------------------------------------------------------
4
+ // Mock state
5
+ // ---------------------------------------------------------------------------
6
+
7
+ const existsSyncFn = mock((_path: string): boolean => false);
8
+ const readFileSyncFn = mock((_path: string, _encoding: string): string => "");
9
+ const writeFileSyncFn = mock((_path: string, _data: string): void => undefined);
10
+
11
+ // ---------------------------------------------------------------------------
12
+ // Mock modules — before importing module under test
13
+ // ---------------------------------------------------------------------------
14
+
15
+ mock.module("node:fs", () => ({
16
+ existsSync: existsSyncFn,
17
+ readFileSync: readFileSyncFn,
18
+ writeFileSync: writeFileSyncFn,
19
+ }));
20
+
21
+ // Import after mocking
22
+ import { dropSendDiagnosticsMigration } from "../workspace/migrations/107-drop-send-diagnostics.js";
23
+
24
+ // ---------------------------------------------------------------------------
25
+ // Helpers
26
+ // ---------------------------------------------------------------------------
27
+
28
+ const WORKSPACE_DIR = "/tmp/test-workspace";
29
+ const CONFIG_PATH = `${WORKSPACE_DIR}/config.json`;
30
+
31
+ function setupConfigExists(config: unknown) {
32
+ existsSyncFn.mockImplementation((path: string) => path === CONFIG_PATH);
33
+ readFileSyncFn.mockImplementation(() => JSON.stringify(config));
34
+ }
35
+
36
+ function getWrittenConfig(): Record<string, unknown> {
37
+ expect(writeFileSyncFn).toHaveBeenCalledTimes(1);
38
+ const [path, data] = writeFileSyncFn.mock.calls[0] as [string, string];
39
+ expect(path).toBe(CONFIG_PATH);
40
+ return JSON.parse(data) as Record<string, unknown>;
41
+ }
42
+
43
+ // ---------------------------------------------------------------------------
44
+ // Tests
45
+ // ---------------------------------------------------------------------------
46
+
47
+ describe("107-drop-send-diagnostics migration", () => {
48
+ beforeEach(() => {
49
+ existsSyncFn.mockClear();
50
+ readFileSyncFn.mockClear();
51
+ writeFileSyncFn.mockClear();
52
+ });
53
+
54
+ test("no-op when config.json is absent", () => {
55
+ existsSyncFn.mockImplementation(() => false);
56
+
57
+ dropSendDiagnosticsMigration.run(WORKSPACE_DIR);
58
+
59
+ expect(readFileSyncFn).not.toHaveBeenCalled();
60
+ expect(writeFileSyncFn).not.toHaveBeenCalled();
61
+ });
62
+
63
+ test("explicit opt-out is preserved as legacyDiagnosticsOptOut", () => {
64
+ setupConfigExists({ sendDiagnostics: false, someSetting: "value" });
65
+
66
+ dropSendDiagnosticsMigration.run(WORKSPACE_DIR);
67
+
68
+ const written = getWrittenConfig();
69
+ expect(written.sendDiagnostics).toBeUndefined();
70
+ expect(written.legacyDiagnosticsOptOut).toBe(true);
71
+ expect(written.someSetting).toBe("value");
72
+ });
73
+
74
+ test("sendDiagnostics: true is removed without setting the marker", () => {
75
+ setupConfigExists({ sendDiagnostics: true });
76
+
77
+ dropSendDiagnosticsMigration.run(WORKSPACE_DIR);
78
+
79
+ const written = getWrittenConfig();
80
+ expect(written.sendDiagnostics).toBeUndefined();
81
+ expect(written.legacyDiagnosticsOptOut).toBeUndefined();
82
+ });
83
+
84
+ test("non-false value is removed without setting the marker", () => {
85
+ setupConfigExists({ sendDiagnostics: "yes" });
86
+
87
+ dropSendDiagnosticsMigration.run(WORKSPACE_DIR);
88
+
89
+ const written = getWrittenConfig();
90
+ expect(written.sendDiagnostics).toBeUndefined();
91
+ expect(written.legacyDiagnosticsOptOut).toBeUndefined();
92
+ });
93
+
94
+ test("no-op when sendDiagnostics is absent (no marker)", () => {
95
+ setupConfigExists({ someSetting: "value" });
96
+
97
+ dropSendDiagnosticsMigration.run(WORKSPACE_DIR);
98
+
99
+ expect(writeFileSyncFn).not.toHaveBeenCalled();
100
+ });
101
+
102
+ test("malformed config is handled gracefully", () => {
103
+ existsSyncFn.mockImplementation((path: string) => path === CONFIG_PATH);
104
+ readFileSyncFn.mockImplementation(() => "not valid json {{{");
105
+
106
+ dropSendDiagnosticsMigration.run(WORKSPACE_DIR);
107
+
108
+ expect(writeFileSyncFn).not.toHaveBeenCalled();
109
+ });
110
+
111
+ test("no-op when config is an array", () => {
112
+ setupConfigExists([1, 2, 3]);
113
+
114
+ dropSendDiagnosticsMigration.run(WORKSPACE_DIR);
115
+
116
+ expect(writeFileSyncFn).not.toHaveBeenCalled();
117
+ });
118
+ });
@@ -164,7 +164,6 @@ describe("e2e: trusted contact setup", () => {
164
164
  {
165
165
  type: "a2a",
166
166
  address: "assistant-b",
167
- externalUserId: "assistant-b",
168
167
  status: "active",
169
168
  policy: "allow",
170
169
  },
@@ -367,7 +366,6 @@ describe("e2e: unknown sender blocked (ACL enforcement)", () => {
367
366
  {
368
367
  type: "a2a",
369
368
  address: "trusted-assistant",
370
- externalUserId: "trusted-assistant",
371
369
  status: "active",
372
370
  policy: "allow",
373
371
  },
@@ -403,7 +401,6 @@ describe("e2e: unknown sender blocked (ACL enforcement)", () => {
403
401
  {
404
402
  type: "a2a",
405
403
  address: "blocked-assistant",
406
- externalUserId: "blocked-assistant",
407
404
  status: "blocked",
408
405
  policy: "deny",
409
406
  },
@@ -518,7 +515,6 @@ describe("e2e: full A2A round-trip", () => {
518
515
  {
519
516
  type: "a2a",
520
517
  address: "assistant-b",
521
- externalUserId: "assistant-b",
522
518
  status: "active",
523
519
  policy: "allow",
524
520
  },
package/src/agent/loop.ts CHANGED
@@ -1,10 +1,9 @@
1
1
  import * as Sentry from "@sentry/node";
2
2
 
3
- import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
4
3
  import { getConfig } from "../config/loader.js";
4
+ import { isMemoryV3Live } from "../config/memory-v3-gate.js";
5
5
  import type { LLMCallSite } from "../config/schemas/llm.js";
6
6
  import { recordEstimate } from "../context/estimator-calibration.js";
7
- import { stripInjectionsForCompaction } from "../context/strip-injections.js";
8
7
  import {
9
8
  estimatePromptTokensRaw,
10
9
  estimatePromptTokensWithTools,
@@ -333,12 +332,14 @@ export type AgentEvent =
333
332
  * `stripInjectionsForCompaction`.
334
333
  *
335
334
  * The daemon's event dispatcher commits the stripped pre-compaction
336
- * base as the conversation's durable message state, so re-injection
337
- * (the post-compaction hook) re-applies injections onto the stripped
338
- * base rather than stacking on top of the still-injected messages.
339
- * When `compacted` is set it additionally commits the durable
340
- * compaction result (DB-record fields, graph-memory side effects, SSE)
341
- * and projects Slack provenance from the pre-compaction base.
335
+ * base as the conversation's durable message state. Re-injection (the
336
+ * post-compaction hook) strips runtime injections before re-applying
337
+ * them, so it is idempotent whether the loop continues from the
338
+ * stripped compaction result or from the unchanged injected history.
339
+ * When `compacted` is set the dispatcher additionally commits the
340
+ * durable compaction result (DB-record fields, graph-memory side
341
+ * effects, SSE) and projects Slack provenance from the pre-compaction
342
+ * base.
342
343
  *
343
344
  * Treated as a critical event: a failed durable commit re-throws so the
344
345
  * turn aborts rather than re-injecting against half-applied state.
@@ -358,13 +359,14 @@ export type AgentEvent =
358
359
  } & ContextWindowResult)
359
360
  | {
360
361
  /**
361
- * Emitted right after the loop strips runtime injections from the
362
- * running history, before the compaction pipeline runs. The daemon's
363
- * event dispatcher records the history-stripped marker a Conversation
364
- * DB-record field read back at load time to strip embedded injection
365
- * prefixes from pre-strip messages. Best-effort: a transient marker
366
- * write must not abort the turn, so unlike `compaction_completed` this
367
- * event is not treated as critical.
362
+ * Emitted during the loop's compaction ceremony, before the pipeline
363
+ * runs. The daemon's event dispatcher commits the stripped
364
+ * pre-compaction base as the durable history and records the
365
+ * history-stripped marker — a Conversation DB-record field read back at
366
+ * load time to strip embedded injection prefixes from pre-strip
367
+ * messages. Best-effort: a transient marker write must not abort the
368
+ * turn, so unlike `compaction_completed` this event is not treated as
369
+ * critical.
368
370
  */
369
371
  type: "history_stripped";
370
372
  }
@@ -761,9 +763,12 @@ export class AgentLoop {
761
763
  /**
762
764
  * Compact the running history in place when the budget gate trips.
763
765
  *
764
- * Calls the default compaction plugin on the stripped history, then
765
- * re-applies injections via the supplied hooks. When `overflowSignal` is
766
- * supplied the plugin routes through the manager's reduction ladder (which
766
+ * Calls the default compaction plugin, then re-applies injections via the
767
+ * supplied hooks. Both the budget and overflow paths hand the full injected
768
+ * `history` to the plugin (so the summary call reuses the agent's warm prefix
769
+ * cache); the POST_COMPACT hook owns re-injection idempotency so continuing
770
+ * from injected history does not double-stack blocks. When `overflowSignal`
771
+ * is supplied the plugin routes through the manager's reduction ladder (which
767
772
  * advances one rung per call and reports `exhausted` / `autoCompressApplied`
768
773
  * / `injectionMode`); otherwise it runs ordinary forced compaction. Returns
769
774
  * the re-injected history to continue from alongside the ladder's terminal
@@ -795,11 +800,9 @@ export class AgentLoop {
795
800
  startedAt,
796
801
  messages: history,
797
802
  });
798
- // Strip runtime injections so the compactor summarizes the raw persistent
799
- // messages.
800
- const rawHistory = stripInjectionsForCompaction(history);
801
- // Record the history-stripped marker right after stripping, before the
802
- // pipeline runs.
803
+ // The durable pre-compaction base is stripped by the event dispatcher
804
+ // (re-derived from the start event), so record the history-stripped
805
+ // marker for this compaction before the pipeline runs.
803
806
  await onEvent({ type: "history_stripped" });
804
807
  // The compaction module owns the per-conversation manager; pass the
805
808
  // conversation id and let `defaultCompact` resolve it from the store.
@@ -812,7 +815,7 @@ export class AgentLoop {
812
815
  // routes the request through the reduction ladder when present.
813
816
  const compactResult = await defaultCompact({
814
817
  conversationId: this.conversationId,
815
- messages: rawHistory,
818
+ messages: history,
816
819
  signal,
817
820
  force: true,
818
821
  actorTrustClass: trust.trustClass,
@@ -848,15 +851,17 @@ export class AgentLoop {
848
851
  if (overflowSignal == null && exhausted) {
849
852
  return { history: null, exhausted, autoCompressApplied };
850
853
  }
851
- // Re-inject onto the same base the `compaction_completed` dispatch commits.
852
- // The overflow ladder transforms the history on every rung (truncation /
854
+ // The POST_COMPACT hook strips runtime injections from this base and
855
+ // re-applies them, so continuing from injected history is safe. The
856
+ // overflow ladder transforms the history on every rung (truncation /
853
857
  // media stubbing / injection downgrade) regardless of whether the summary
854
858
  // ran, so continue from its reduced messages; the ordinary path continues
855
- // from the compacted messages only when the pipeline actually compacted.
859
+ // from the compacted messages when the pipeline compacted, otherwise from
860
+ // the unchanged injected history.
856
861
  const base =
857
862
  overflowSignal != null || compactResult.compacted
858
863
  ? compactResult.messages
859
- : rawHistory;
864
+ : history;
860
865
  const postCompactCtx: PostCompactContext = {
861
866
  history: base,
862
867
  requestId,
@@ -1266,7 +1271,7 @@ export class AgentLoop {
1266
1271
  // volatile latest one. Read here alongside the rest of the provider
1267
1272
  // config; only set when true so the wire/config stays byte-identical
1268
1273
  // when off.
1269
- if (isAssistantFeatureFlagEnabled("memory-v3-live", getConfig())) {
1274
+ if (isMemoryV3Live(getConfig())) {
1270
1275
  providerConfig.mutableLatestUserMessage = true;
1271
1276
  }
1272
1277
 
@@ -1434,6 +1439,7 @@ export class AgentLoop {
1434
1439
  conversationId: this.conversationId,
1435
1440
  callSite: callSite ?? null,
1436
1441
  systemPrompt: providerOptions.systemPrompt ?? null,
1442
+ modelProfile: effectiveOverrideProfile ?? null,
1437
1443
  deferAssistantOutput: false,
1438
1444
  logger: rlog,
1439
1445
  };
@@ -1443,6 +1449,20 @@ export class AgentLoop {
1443
1449
  );
1444
1450
  providerOptions.systemPrompt =
1445
1451
  finalPreModelCtx.systemPrompt ?? undefined;
1452
+ // Route this call to the hook's chosen inference profile. The
1453
+ // resolver layers `llm.profiles[overrideProfile]` at the top of
1454
+ // precedence for the user-facing call, so a model router can pick
1455
+ // the profile per message; clearing it drops any seeded override.
1456
+ const hookModelProfile = finalPreModelCtx.modelProfile?.trim();
1457
+ if (hookModelProfile) {
1458
+ providerConfig.overrideProfile = hookModelProfile;
1459
+ if (forceOverrideProfile) {
1460
+ providerConfig.forceOverrideProfile = true;
1461
+ }
1462
+ } else {
1463
+ delete providerConfig.overrideProfile;
1464
+ delete providerConfig.forceOverrideProfile;
1465
+ }
1446
1466
  // The hook owns the policy (it sees `callSite`/conversation and
1447
1467
  // self-gates); the loop honors whatever it decides.
1448
1468
  deferAssistantOutput = finalPreModelCtx.deferAssistantOutput;
package/src/api/README.md CHANGED
@@ -7,7 +7,7 @@ the wire contracts the assistant exposes: schemas, types, and pure helpers.
7
7
  Internal assistant code imports the files in this directory via relative paths
8
8
  (e.g. `../../api/events/open-url.js`). External consumers import the
9
9
  materialized npm-style package `@vellumai/assistant-api`, regenerated into
10
- `apps/web/node_modules/` by `apps/web/scripts/postinstall.ts`.
10
+ `clients/web/node_modules/` by `clients/web/scripts/postinstall.ts`.
11
11
 
12
12
  ## Architecture
13
13
 
@@ -72,7 +72,7 @@ a migrated event is the import and the union membership.
72
72
 
73
73
  ### 3. Cut over web consumers
74
74
 
75
- `apps/web/src/domains/chat/api/event-types.ts` no longer needs to list the
75
+ `clients/web/src/domains/chat/api/event-types.ts` no longer needs to list the
76
76
  migrated event in its `AssistantEvent` union — `APIAssistantEvent` covers it.
77
77
  Drop the per-event member, leaving the union to peel off legacy entries one
78
78
  at a time as each event migrates.
@@ -85,7 +85,7 @@ import them straight from the canonical package.
85
85
  ### 4. Delete the legacy parser cases
86
86
 
87
87
  Remove the matching `case "my_event":` blocks from
88
- `apps/web/src/domains/chat/api/event-parser.ts`. Any per-event helper
88
+ `clients/web/src/domains/chat/api/event-parser.ts`. Any per-event helper
89
89
  (`parseFooBase`, etc.) goes with them.
90
90
 
91
91
  ### 5. Tests
@@ -110,15 +110,15 @@ Handler-level tests in the consuming domain modules typically need no change
110
110
  Run before push, in order:
111
111
 
112
112
  ```bash
113
- # In apps/web — regenerate the @vellumai/assistant-api bundle
113
+ # In clients/web — regenerate the @vellumai/assistant-api bundle
114
114
  bun run scripts/postinstall.ts
115
115
 
116
116
  # Type-check both packages
117
117
  ( cd assistant && bunx tsc --noEmit )
118
- ( cd apps/web && bunx tsc --noEmit )
118
+ ( cd clients/web && bunx tsc --noEmit )
119
119
 
120
120
  # Targeted tests
121
- ( cd apps/web && bun test src/domains/chat/api/event-parser.test.ts )
121
+ ( cd clients/web && bun test src/domains/chat/api/event-parser.test.ts )
122
122
 
123
123
  # Lint + format the touched files
124
124
  bunx eslint <files>
@@ -47,10 +47,15 @@ export const WebSearchProviderIdSchema = z.enum([
47
47
  "brave",
48
48
  "perplexity",
49
49
  "tavily",
50
+ "firecrawl",
50
51
  ]);
51
52
 
52
53
  export type WebSearchProviderId = z.infer<typeof WebSearchProviderIdSchema>;
53
54
 
55
+ export const WebFetchProviderIdSchema = z.enum(["default", "firecrawl"]);
56
+
57
+ export type WebFetchProviderId = z.infer<typeof WebFetchProviderIdSchema>;
58
+
54
59
  export const WebSearchResultItemSchema = z.object({
55
60
  rank: z.number(),
56
61
  title: z.string(),
@@ -78,6 +83,7 @@ export type WebSearchMetadata = z.infer<typeof WebSearchMetadataSchema>;
78
83
  export const WebFetchMetadataSchema = z.object({
79
84
  url: z.string(),
80
85
  finalUrl: z.string(),
86
+ provider: WebFetchProviderIdSchema.optional(),
81
87
  status: z.number(),
82
88
  contentType: z.string().optional(),
83
89
  byteCount: z.number(),
@@ -0,0 +1,53 @@
1
+ /**
2
+ * `workflow_completed` SSE event.
3
+ *
4
+ * Server → client notification that a `run_workflow` run has reached a
5
+ * terminal state. Carries `runId`, the terminal `status`, cumulative
6
+ * `agentsSpawned`/`inputTokens`/`outputTokens` counters, and an optional
7
+ * human-readable `summary`.
8
+ *
9
+ * `conversationId` is present for a run launched from a conversation, so
10
+ * clients can route the event to that conversation's inline workflow card. It
11
+ * is omitted for a conversationless run (e.g. a scheduled workflow with no
12
+ * wake/origin conversation), which broadcasts unscoped for raw SSE listeners.
13
+ *
14
+ * Canonical wire-contract source. Daemon code imports the type
15
+ * directly from this file; external consumers import via
16
+ * `@vellumai/assistant-api`.
17
+ */
18
+
19
+ import { z } from "zod";
20
+
21
+ /**
22
+ * Lifecycle status of a `run_workflow` run. `running` is the live
23
+ * state; the remainder are terminal. `cap_exceeded` is reached when a
24
+ * run hits its configured agent/token cap; `interrupted` when the run
25
+ * is halted by an external signal.
26
+ */
27
+ export const WorkflowRunStatusSchema = z.enum([
28
+ "running",
29
+ "completed",
30
+ "failed",
31
+ "aborted",
32
+ "cap_exceeded",
33
+ "interrupted",
34
+ ]);
35
+
36
+ export type WorkflowRunStatus = z.infer<typeof WorkflowRunStatusSchema>;
37
+
38
+ export const WorkflowCompletedEventSchema = z
39
+ .object({
40
+ type: z.literal("workflow_completed"),
41
+ runId: z.string(),
42
+ conversationId: z.string().optional(),
43
+ status: WorkflowRunStatusSchema,
44
+ agentsSpawned: z.number(),
45
+ inputTokens: z.number(),
46
+ outputTokens: z.number(),
47
+ summary: z.string().optional(),
48
+ })
49
+ .strict();
50
+
51
+ export type WorkflowCompletedEvent = z.infer<
52
+ typeof WorkflowCompletedEventSchema
53
+ >;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * `workflow_leaf_finished` SSE event.
3
+ *
4
+ * Server → client notification that a leaf agent within a
5
+ * `run_workflow` run has finished. Carries `runId`, the parent
6
+ * `conversationId`, the monotonic `seq` identifying the leaf within the
7
+ * run, the terminal `status`, optional `inputTokens`/`outputTokens`
8
+ * counters, and optional human-readable display fields (`label`,
9
+ * `resultSummary`).
10
+ *
11
+ * `conversationId` is present so clients can route the event to the
12
+ * originating conversation's inline workflow card and its live leaf
13
+ * tree.
14
+ *
15
+ * Canonical wire-contract source. Daemon code imports the type
16
+ * directly from this file; external consumers import via
17
+ * `@vellumai/assistant-api`.
18
+ */
19
+
20
+ import { z } from "zod";
21
+
22
+ export const WorkflowLeafFinishedEventSchema = z
23
+ .object({
24
+ type: z.literal("workflow_leaf_finished"),
25
+ runId: z.string(),
26
+ conversationId: z.string(),
27
+ seq: z.number().int(),
28
+ status: z.enum(["completed", "failed"]),
29
+ label: z.string().optional(),
30
+ inputTokens: z.number().optional(),
31
+ outputTokens: z.number().optional(),
32
+ resultSummary: z.string().optional(),
33
+ })
34
+ .strict();
35
+
36
+ export type WorkflowLeafFinishedEvent = z.infer<
37
+ typeof WorkflowLeafFinishedEventSchema
38
+ >;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * `workflow_leaf_started` SSE event.
3
+ *
4
+ * Server → client notification that a leaf agent within a
5
+ * `run_workflow` run has started. Carries `runId`, the parent
6
+ * `conversationId`, the monotonic `seq` identifying the leaf within the
7
+ * run, and optional human-readable display fields (`label`, `phase`,
8
+ * `promptSummary`).
9
+ *
10
+ * `conversationId` is present so clients can route the event to the
11
+ * originating conversation's inline workflow card and its live leaf
12
+ * tree.
13
+ *
14
+ * Canonical wire-contract source. Daemon code imports the type
15
+ * directly from this file; external consumers import via
16
+ * `@vellumai/assistant-api`.
17
+ */
18
+
19
+ import { z } from "zod";
20
+
21
+ export const WorkflowLeafStartedEventSchema = z
22
+ .object({
23
+ type: z.literal("workflow_leaf_started"),
24
+ runId: z.string(),
25
+ conversationId: z.string(),
26
+ seq: z.number().int(),
27
+ label: z.string().optional(),
28
+ phase: z.string().optional(),
29
+ promptSummary: z.string().optional(),
30
+ })
31
+ .strict();
32
+
33
+ export type WorkflowLeafStartedEvent = z.infer<
34
+ typeof WorkflowLeafStartedEventSchema
35
+ >;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * `workflow_progress` SSE event.
3
+ *
4
+ * Server → client incremental progress update for an in-flight
5
+ * `run_workflow` run. Carries `runId`, the running `agentsSpawned` count,
6
+ * and optional human-readable display fields (`phase`, `label`, `message`).
7
+ *
8
+ * `conversationId` is present for a run launched from a conversation, so
9
+ * clients can route the event to that conversation's inline workflow card. It
10
+ * is omitted for a conversationless run (e.g. a scheduled workflow with no
11
+ * wake/origin conversation), which broadcasts unscoped for raw SSE listeners.
12
+ *
13
+ * Canonical wire-contract source. Daemon code imports the type
14
+ * directly from this file; external consumers import via
15
+ * `@vellumai/assistant-api`.
16
+ */
17
+
18
+ import { z } from "zod";
19
+
20
+ export const WorkflowProgressEventSchema = z
21
+ .object({
22
+ type: z.literal("workflow_progress"),
23
+ runId: z.string(),
24
+ conversationId: z.string().optional(),
25
+ agentsSpawned: z.number(),
26
+ phase: z.string().optional(),
27
+ label: z.string().optional(),
28
+ message: z.string().optional(),
29
+ })
30
+ .strict();
31
+
32
+ export type WorkflowProgressEvent = z.infer<typeof WorkflowProgressEventSchema>;