@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
@@ -22,57 +22,6 @@ mock.module("../util/logger.js", () => ({
22
22
  }),
23
23
  }));
24
24
 
25
- const checkpointStore = new Map<string, string>();
26
-
27
- mock.module("../memory/checkpoints.js", () => ({
28
- getMemoryCheckpoint: (key: string) => checkpointStore.get(key) ?? null,
29
- setMemoryCheckpoint: (key: string, value: string) => {
30
- checkpointStore.set(key, value);
31
- },
32
- }));
33
-
34
- const getConfiguredProviderCalls: string[] = [];
35
- const mockProvider = { name: "mock-provider" };
36
-
37
- mock.module("../providers/provider-send-message.js", () => ({
38
- getConfiguredProvider: mock(async (callSite: string) => {
39
- getConfiguredProviderCalls.push(callSite);
40
- return mockProvider;
41
- }),
42
- }));
43
-
44
- type SidechainCall = {
45
- callSite?: string;
46
- content: string;
47
- maxTokens?: number;
48
- systemPrompt?: string;
49
- tools: unknown[];
50
- };
51
-
52
- type SidechainResult = {
53
- text: string;
54
- hadTextDeltas: false;
55
- response: { content: [] };
56
- };
57
-
58
- const sidechainCalls: SidechainCall[] = [];
59
- let sidechainText = "";
60
- let sidechainResultPromise: Promise<SidechainResult> | null = null;
61
-
62
- mock.module("../runtime/btw-sidechain.js", () => ({
63
- runBtwSidechain: mock(async (params: SidechainCall) => {
64
- sidechainCalls.push(params);
65
- if (sidechainResultPromise) {
66
- return sidechainResultPromise;
67
- }
68
- return {
69
- text: sidechainText,
70
- hadTextDeltas: false,
71
- response: { content: [] },
72
- };
73
- }),
74
- }));
75
-
76
25
  import {
77
26
  handleDetailedHealth,
78
27
  handleReadyz,
@@ -86,17 +35,6 @@ import {
86
35
  selectHatchedAtFromStats,
87
36
  } from "../workspace/hatched-date.js";
88
37
 
89
- function createDeferred<T>(): {
90
- promise: Promise<T>;
91
- resolve: (value: T) => void;
92
- } {
93
- let resolve!: (value: T) => void;
94
- const promise = new Promise<T>((res) => {
95
- resolve = res;
96
- });
97
- return { promise, resolve };
98
- }
99
-
100
38
  // ── Env helpers ─────────────────────────────────────────────────────────
101
39
 
102
40
  let savedEnv: Record<string, string | undefined>;
@@ -194,11 +132,6 @@ beforeEach(() => {
194
132
  rmSync(getHatchedSidecarPath(), { force: true });
195
133
  rmSync(join(getWorkspaceDir(), "IDENTITY.md"), { force: true });
196
134
  rmSync(join(getWorkspaceDir(), "SOUL.md"), { force: true });
197
- checkpointStore.clear();
198
- getConfiguredProviderCalls.length = 0;
199
- sidechainCalls.length = 0;
200
- sidechainText = "";
201
- sidechainResultPromise = null;
202
135
  });
203
136
 
204
137
  afterEach(() => {
@@ -564,125 +497,3 @@ describe("identity routes — createdAt selection", () => {
564
497
  expect(existsSync(getHatchedSidecarPath())).toBe(false);
565
498
  });
566
499
  });
567
-
568
- describe("identity routes — intro greetings", () => {
569
- test("returns fallback immediately, generates personalized greetings in the background, then reuses the cache", async () => {
570
- const workspaceDir = getWorkspaceDir();
571
- writeFileSync(
572
- join(workspaceDir, "IDENTITY.md"),
573
- [
574
- "# Identity",
575
- "",
576
- "- **Name:** Example Assistant",
577
- "- **Personality:** enjoys crisp, useful hellos",
578
- "",
579
- "Identity sentinel: chartreuse compass.",
580
- ].join("\n"),
581
- "utf-8",
582
- );
583
- writeFileSync(
584
- join(workspaceDir, "SOUL.md"),
585
- [
586
- "# Soul",
587
- "",
588
- "Soul sentinel: copper lighthouse.",
589
- "",
590
- "Keep greetings warm and specific.",
591
- ].join("\n"),
592
- "utf-8",
593
- );
594
- const deferredSidechain = createDeferred<SidechainResult>();
595
- sidechainResultPromise = deferredSidechain.promise;
596
-
597
- const route = ROUTES.find(
598
- (candidate) => candidate.operationId === "identity_intro",
599
- );
600
- expect(route).toBeDefined();
601
-
602
- const body = route!.handler({
603
- queryParams: { localHour: "8", localMinute: "15" },
604
- }) as {
605
- greetings: string[];
606
- text: string;
607
- source: string;
608
- refreshing: boolean;
609
- };
610
-
611
- expect(body).toEqual({
612
- greetings: [
613
- "What are we working on?",
614
- "I'm here whenever you need me.",
615
- "What's on your mind?",
616
- "Ready when you are.",
617
- ],
618
- text: "What are we working on?",
619
- source: "fallback",
620
- refreshing: true,
621
- });
622
- expect(getConfiguredProviderCalls).toEqual([]);
623
- expect(sidechainCalls).toEqual([]);
624
-
625
- await Promise.resolve();
626
- await Promise.resolve();
627
-
628
- expect(getConfiguredProviderCalls).toEqual(["emptyStateGreeting"]);
629
- expect(sidechainCalls).toHaveLength(1);
630
- expect(sidechainCalls[0]?.callSite).toBe("emptyStateGreeting");
631
- expect(sidechainCalls[0]?.tools).toEqual([]);
632
- expect(sidechainCalls[0]?.content).toContain("Generate 5 short");
633
- expect(sidechainCalls[0]?.content).not.toContain("Current time of day:");
634
- expect(sidechainCalls[0]?.content).toContain(
635
- "do not mention the current time",
636
- );
637
- expect(sidechainCalls[0]?.content).toMatch(
638
- /Current user-local time for subtle tone only: morning \(08:15\)\.$/,
639
- );
640
- expect(sidechainCalls[0]?.content).toContain("JSON array");
641
- expect(sidechainCalls[0]?.systemPrompt).toContain(
642
- "Identity sentinel: chartreuse compass.",
643
- );
644
- expect(sidechainCalls[0]?.systemPrompt).toContain(
645
- "Soul sentinel: copper lighthouse.",
646
- );
647
- deferredSidechain.resolve({
648
- text: JSON.stringify([
649
- "Charting the next useful thing?",
650
- "I brought the compass. Where to?",
651
- "Ready to make this lighter.",
652
- "Morning momentum?",
653
- "Five options, one good start.",
654
- "A useful next step?",
655
- ]),
656
- hadTextDeltas: false,
657
- response: { content: [] },
658
- });
659
-
660
- await sidechainResultPromise;
661
- await new Promise((resolve) => setTimeout(resolve, 0));
662
-
663
- sidechainCalls.length = 0;
664
- getConfiguredProviderCalls.length = 0;
665
-
666
- const cachedBody = (await route!.handler({})) as {
667
- greetings: string[];
668
- text: string;
669
- source: string;
670
- refreshing: boolean;
671
- };
672
-
673
- expect(cachedBody).toEqual({
674
- greetings: [
675
- "Charting the next useful thing?",
676
- "I brought the compass. Where to?",
677
- "Ready to make this lighter.",
678
- "Five options, one good start.",
679
- "A useful next step?",
680
- ],
681
- text: "Charting the next useful thing?",
682
- source: "cache",
683
- refreshing: false,
684
- });
685
- expect(getConfiguredProviderCalls).toEqual([]);
686
- expect(sidechainCalls).toEqual([]);
687
- });
688
- });
@@ -173,7 +173,7 @@ describe("inbound invite redemption intercept", () => {
173
173
  // Verify the user is now an active member
174
174
  const result = findContactChannel({
175
175
  channelType: "telegram",
176
- externalUserId: "user-invite-123",
176
+ address: "user-invite-123",
177
177
  });
178
178
  expect(result).not.toBeNull();
179
179
  expect(result!.channel.status).toBe("active");
@@ -203,7 +203,7 @@ describe("inbound invite redemption intercept", () => {
203
203
  // Verify the user was NOT made a member
204
204
  const result = findContactChannel({
205
205
  channelType: "telegram",
206
- externalUserId: "user-invite-123",
206
+ address: "user-invite-123",
207
207
  });
208
208
  expect(result).toBeNull();
209
209
  });
@@ -400,7 +400,7 @@ describe("inbound invite redemption intercept", () => {
400
400
  // its ID as the invite's contactId (satisfies the FK constraint).
401
401
  const existing = findContactChannel({
402
402
  channelType: "telegram",
403
- externalUserId: "user-invite-123",
403
+ address: "user-invite-123",
404
404
  externalChatId: "chat-invite-test",
405
405
  });
406
406
  const targetContactId = existing!.contact.id;
@@ -422,7 +422,7 @@ describe("inbound invite redemption intercept", () => {
422
422
 
423
423
  const result = findContactChannel({
424
424
  channelType: "telegram",
425
- externalUserId: "user-invite-123",
425
+ address: "user-invite-123",
426
426
  externalChatId: "chat-invite-test",
427
427
  });
428
428
  expect(result).not.toBeNull();
@@ -2,7 +2,7 @@
2
2
  * Tests for the memory-v3 step-0 branch in `applyRuntimeInjections`:
3
3
  * spotlight strip + v2 tail suppression.
4
4
  *
5
- * When the `memory-v3-live` flag is on AND the v3 injector (id `memory-v3`,
5
+ * When `memory.v3.live` is on AND the v3 injector (id `memory-v3`,
6
6
  * placement `after-memory-prefix`) produces a block — possibly EMPTY-TEXT on
7
7
  * an all-repeat turn — runtime assembly strips the v2 `<memory>` prefix from
8
8
  * the TAIL user message only before splicing the v3 block. Historical user
@@ -16,10 +16,11 @@
16
16
  * block lands at the tail.
17
17
  *
18
18
  * v2 suppression stays keyed off whether v3 produced a block, NOT off the
19
- * flag alone: a v3 failure (`produce()` → null) leaves v2's block intact
20
- * (fallback-to-v2). The flag-off path must be byte-for-byte identical to
19
+ * gate alone: a v3 failure (`produce()` → null) leaves v2's block intact
20
+ * (fallback-to-v2). The v3-off path must be byte-for-byte identical to
21
21
  * today — that is the load-bearing regression guard. `applyRuntimeInjections`
22
- * reads the flag itself, so these tests drive it through the override cache.
22
+ * reads the v3-live gate itself, so these tests drive it through the
23
+ * `isMemoryV3Live` mock slot.
23
24
  *
24
25
  * The strip discriminates v2's dynamic block by IDENTITY, not by prefix: v2's
25
26
  * `INJECTION_HEADER` and v3's `V3_CARDS_INJECTION_HEADER` are deliberately
@@ -42,7 +43,6 @@ import type {
42
43
  TurnContext,
43
44
  } from "../plugins/types.js";
44
45
  import type { Message } from "../providers/types.js";
45
- import { setOverridesForTesting } from "./feature-flag-test-helpers.js";
46
46
 
47
47
  // Drive the suppression branch by controlling the static injector chain that
48
48
  // `applyRuntimeInjections` walks. The slot is mutated per-test to stand in for
@@ -52,6 +52,13 @@ mock.module("../plugins/defaults/memory-retrieval/injector-chain.js", () => ({
52
52
  getInjectorChain: () => injectorChainSlot,
53
53
  }));
54
54
 
55
+ // `applyRuntimeInjections` reads the v3-live gate (`config.memory.v3.live`)
56
+ // via `isMemoryV3Live`; drive it directly through this slot per-test.
57
+ let memoryV3LiveSlot = false;
58
+ mock.module("../config/memory-v3-gate.js", () => ({
59
+ isMemoryV3Live: () => memoryV3LiveSlot,
60
+ }));
61
+
55
62
  const { applyRuntimeInjections } =
56
63
  await import("../daemon/conversation-runtime-assembly.js");
57
64
 
@@ -141,9 +148,9 @@ function tailTexts(messages: Message[]): string[] {
141
148
  describe("memory-v3-live v2 suppression", () => {
142
149
  beforeEach(() => {
143
150
  injectorChainSlot.length = 0;
144
- // Clean baseline: no overrides → `memory-v3-live` resolves to its registry
145
- // default (off). Each test seeds the flag it needs.
146
- setOverridesForTesting({});
151
+ // Clean baseline: v3-live off (registry/config default). Each test seeds
152
+ // the gate value it needs.
153
+ memoryV3LiveSlot = false;
147
154
  });
148
155
 
149
156
  afterEach(() => {
@@ -152,7 +159,7 @@ describe("memory-v3-live v2 suppression", () => {
152
159
  });
153
160
 
154
161
  test("flag ON + v3 produced a block → TAIL v2 stripped, historical memory blocks frozen in place", async () => {
155
- setOverridesForTesting({ "memory-v3-live": true });
162
+ memoryV3LiveSlot = true;
156
163
  injectorChainSlot.push(v3Injector("net-new cards"));
157
164
  seedV2Identity("fresh recalled fact");
158
165
 
@@ -194,7 +201,7 @@ describe("memory-v3-live v2 suppression", () => {
194
201
  });
195
202
 
196
203
  test("flag ON + EMPTY-TEXT v3 block (all-repeat turn) → tail v2 stripped, nothing attached", async () => {
197
- setOverridesForTesting({ "memory-v3-live": true });
204
+ memoryV3LiveSlot = true;
198
205
  injectorChainSlot.push(v3Injector(""));
199
206
  seedV2Identity("fresh recalled fact");
200
207
 
@@ -217,7 +224,7 @@ describe("memory-v3-live v2 suppression", () => {
217
224
  });
218
225
 
219
226
  test("stale spotlight blocks are stripped from EVERY user message; the new spotlight lands at the tail", async () => {
220
- setOverridesForTesting({ "memory-v3-live": true });
227
+ memoryV3LiveSlot = true;
221
228
  injectorChainSlot.push(v3Injector(""), spotlightInjector("fresh sections"));
222
229
 
223
230
  const staleSpotlight = {
@@ -253,7 +260,7 @@ describe("memory-v3-live v2 suppression", () => {
253
260
  });
254
261
 
255
262
  test("convergence re-entry: a tail leading with this turn's frozen v3 cards (and <info>) is NOT stripped", async () => {
256
- setOverridesForTesting({ "memory-v3-live": true });
263
+ memoryV3LiveSlot = true;
257
264
  // Re-entry shape: the memo returns the same selections, every slug is now
258
265
  // in the everInjected store, so the injector produces an EMPTY block —
259
266
  // while the tail still carries the v3 card block frozen on first entry
@@ -292,7 +299,7 @@ describe("memory-v3-live v2 suppression", () => {
292
299
  });
293
300
 
294
301
  test("first entry with a v2 prefix AND a frozen v3 block strips ONLY the v2 block", async () => {
295
- setOverridesForTesting({ "memory-v3-live": true });
302
+ memoryV3LiveSlot = true;
296
303
  injectorChainSlot.push(v3Injector(""));
297
304
  seedV2Identity("fresh recalled fact");
298
305
 
@@ -319,7 +326,7 @@ describe("memory-v3-live v2 suppression", () => {
319
326
  });
320
327
 
321
328
  test("REGRESSION: a v2 block leading with the REAL summary header (byte-identical to v3's) is stripped; v3 cards and <info> survive (first entry)", async () => {
322
- setOverridesForTesting({ "memory-v3-live": true });
329
+ memoryV3LiveSlot = true;
323
330
  injectorChainSlot.push(v3Injector(""));
324
331
 
325
332
  // The collision this guards: v2's router block leads with
@@ -358,7 +365,7 @@ describe("memory-v3-live v2 suppression", () => {
358
365
  });
359
366
 
360
367
  test("REGRESSION: re-entry with a header-bearing v2 identity keeps the first entry's frozen v3 cards", async () => {
361
- setOverridesForTesting({ "memory-v3-live": true });
368
+ memoryV3LiveSlot = true;
362
369
  // Re-entry: produce() returns the EMPTY block (cards already claimed by
363
370
  // the store) while the tail carries the FIRST entry's v3 block — and the
364
371
  // graph handle still holds the summary-bearing v2 identity from this
@@ -391,7 +398,7 @@ describe("memory-v3-live v2 suppression", () => {
391
398
  });
392
399
 
393
400
  test("v2 memory-image groups and legacy <memory __injected> blocks are stripped even without an identity", async () => {
394
- setOverridesForTesting({ "memory-v3-live": true });
401
+ memoryV3LiveSlot = true;
395
402
  injectorChainSlot.push(v3Injector("net-new cards"));
396
403
  // No live graph handle: identity unknown (null). Image groups and legacy
397
404
  // blocks are unambiguously v2's and are stripped regardless; the shared
@@ -430,7 +437,7 @@ describe("memory-v3-live v2 suppression", () => {
430
437
  });
431
438
 
432
439
  test("the v3 block's attachment-commit callback fires on a user tail", async () => {
433
- setOverridesForTesting({ "memory-v3-live": true });
440
+ memoryV3LiveSlot = true;
434
441
  const commit = mock(() => {});
435
442
  injectorChainSlot.push(v3Injector("net-new cards", commit));
436
443
 
@@ -443,7 +450,7 @@ describe("memory-v3-live v2 suppression", () => {
443
450
  });
444
451
 
445
452
  test("the commit callback is SKIPPED when the tail is not a user message (block never attaches)", async () => {
446
- setOverridesForTesting({ "memory-v3-live": true });
453
+ memoryV3LiveSlot = true;
447
454
  const commit = mock(() => {});
448
455
  injectorChainSlot.push(v3Injector("net-new cards", commit));
449
456
 
@@ -465,7 +472,7 @@ describe("memory-v3-live v2 suppression", () => {
465
472
  });
466
473
 
467
474
  test("flag ON but v3 produced NOTHING → v2 block left intact (fallback-to-v2)", async () => {
468
- setOverridesForTesting({ "memory-v3-live": true });
475
+ memoryV3LiveSlot = true;
469
476
  injectorChainSlot.push(v3Injector(null));
470
477
 
471
478
  const runMessages: Message[] = [
@@ -524,7 +531,7 @@ describe("memory-v3-live v2 suppression", () => {
524
531
  test("no v3 injector registered + flag ON → no stripping, messages untouched", async () => {
525
532
  // No injector named memory-v3 at all (e.g. plugin not loaded): the
526
533
  // suppression branch keys off the produced block, so nothing is stripped.
527
- setOverridesForTesting({ "memory-v3-live": true });
534
+ memoryV3LiveSlot = true;
528
535
  expect(injectorChainSlot).toHaveLength(0);
529
536
 
530
537
  const runMessages: Message[] = [
@@ -7,23 +7,15 @@ mock.module("../util/logger.js", () => ({
7
7
  }),
8
8
  }));
9
9
 
10
- // Toggle for the collectUsageData opt-out the real store consults. The store
10
+ // Toggle for the share_analytics opt-out the real store consults. The store
11
11
  // module is intentionally NOT mocked here — it has its own DB-backed tests, and
12
12
  // Bun's `mock.module` is process-global, so mocking it would leak into those
13
13
  // tests when files share an invocation. Exercising the real store keeps every
14
14
  // auth-fallback test order-independent.
15
- let collectUsageData = true;
15
+ let shareAnalytics = true;
16
16
 
17
- mock.module("../config/loader.js", () => ({
18
- getConfig: () => ({
19
- ui: {},
20
- model: "test",
21
- provider: "test",
22
- memory: { enabled: false },
23
- rateLimit: { maxRequestsPerMinute: 0 },
24
- secretDetection: { enabled: false },
25
- collectUsageData,
26
- }),
17
+ mock.module("../platform/consent-cache.js", () => ({
18
+ getCachedShareAnalytics: () => shareAnalytics,
27
19
  }));
28
20
 
29
21
  import { queryUnreportedAuthFallbackEvents } from "../memory/auth-fallback-events-store.js";
@@ -61,7 +53,7 @@ const VALID_BODY = {
61
53
 
62
54
  describe("internal-telemetry-routes: auth-fallback", () => {
63
55
  beforeEach(() => {
64
- collectUsageData = true;
56
+ shareAnalytics = true;
65
57
  getDb().delete(authFallbackEvents).run();
66
58
  });
67
59
 
@@ -90,7 +82,7 @@ describe("internal-telemetry-routes: auth-fallback", () => {
90
82
  });
91
83
 
92
84
  test("returns skipped and persists nothing under the opt-out", () => {
93
- collectUsageData = false;
85
+ shareAnalytics = false;
94
86
  expect(call(VALID_BODY)).toEqual({ skipped: true });
95
87
  expect(queryUnreportedAuthFallbackEvents(0, undefined, 100).length).toBe(0);
96
88
  });
@@ -83,7 +83,7 @@ describe("invite-redemption-service", () => {
83
83
 
84
84
  const result = findContactChannel({
85
85
  channelType: "telegram",
86
- externalUserId: "user-1",
86
+ address: "user-1",
87
87
  });
88
88
 
89
89
  expect(result).not.toBeNull();
@@ -112,7 +112,7 @@ describe("invite-redemption-service", () => {
112
112
 
113
113
  const result = findContactChannel({
114
114
  channelType: "telegram",
115
- externalUserId: "code-user-1",
115
+ address: "code-user-1",
116
116
  });
117
117
 
118
118
  expect(result).not.toBeNull();
@@ -292,7 +292,6 @@ describe("invite-redemption-service", () => {
292
292
  {
293
293
  type: "telegram",
294
294
  address: "guardian-tg-id",
295
- externalUserId: "guardian-tg-id",
296
295
  status: "revoked",
297
296
  },
298
297
  ],
@@ -325,7 +324,7 @@ describe("invite-redemption-service", () => {
325
324
  // Verify the redeemer's Telegram ID is now bound to Mom's contact
326
325
  const result = findContactChannel({
327
326
  channelType: "telegram",
328
- externalUserId: "guardian-tg-id",
327
+ address: "guardian-tg-id",
329
328
  });
330
329
  expect(result).not.toBeNull();
331
330
  expect(result!.contact.id).toBe(momContact.id);
@@ -346,7 +345,6 @@ describe("invite-redemption-service", () => {
346
345
  {
347
346
  type: "telegram",
348
347
  address: "guardian-own-id",
349
- externalUserId: "guardian-own-id",
350
348
  status: "revoked",
351
349
  },
352
350
  ],
@@ -381,7 +379,6 @@ describe("invite-redemption-service", () => {
381
379
  {
382
380
  type: "telegram",
383
381
  address: "guardian-code-id",
384
- externalUserId: "guardian-code-id",
385
382
  status: "revoked",
386
383
  },
387
384
  ],
@@ -417,7 +414,7 @@ describe("invite-redemption-service", () => {
417
414
  // Verify the redeemer's Telegram ID is now bound to Mom's contact
418
415
  const result = findContactChannel({
419
416
  channelType: "telegram",
420
- externalUserId: "guardian-code-id",
417
+ address: "guardian-code-id",
421
418
  });
422
419
  expect(result).not.toBeNull();
423
420
  expect(result!.contact.id).toBe(momContact.id);
@@ -54,9 +54,7 @@ describe("LLM call-site catalog", () => {
54
54
 
55
55
  test("CALL_SITE_DEFAULTS covers every LLMCallSite enum value", () => {
56
56
  const defaultIds = new Set(Object.keys(CALL_SITE_DEFAULTS));
57
- const missing = LLMCallSiteEnum.options.filter(
58
- (id) => !defaultIds.has(id),
59
- );
57
+ const missing = LLMCallSiteEnum.options.filter((id) => !defaultIds.has(id));
60
58
  expect(missing).toEqual([]);
61
59
  });
62
60
 
@@ -68,11 +66,12 @@ describe("LLM call-site catalog", () => {
68
66
  expect(extra).toEqual([]);
69
67
  });
70
68
 
71
- test("every CALL_SITE_DEFAULTS entry has a profile field", () => {
69
+ test("every CALL_SITE_DEFAULTS profile, when present, is a non-empty string", () => {
72
70
  for (const [, config] of Object.entries(CALL_SITE_DEFAULTS)) {
73
- expect(config.profile).toBeDefined();
71
+ // A call site may omit `profile` to inherit the workspace default config.
72
+ if (config.profile === undefined) continue;
74
73
  expect(typeof config.profile).toBe("string");
75
- expect(config.profile!.length).toBeGreaterThan(0);
74
+ expect(config.profile.length).toBeGreaterThan(0);
76
75
  }
77
76
  });
78
77
  });
@@ -2,7 +2,10 @@ import { readFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import { describe, expect, test } from "bun:test";
4
4
 
5
- import { PROVIDER_CATALOG } from "../providers/model-catalog.js";
5
+ import {
6
+ isModelInCatalog,
7
+ PROVIDER_CATALOG,
8
+ } from "../providers/model-catalog.js";
6
9
  import { PLATFORM_PROVIDER_META } from "../providers/platform-proxy/constants.js";
7
10
  import { resolvePricing, resolvePricingForUsage } from "../util/pricing.js";
8
11
 
@@ -30,13 +33,6 @@ function getRepoRoot(): string {
30
33
  }
31
34
 
32
35
  const META_JSON_PATH = join(getRepoRoot(), "meta", "llm-provider-catalog.json");
33
- const SWIFTPM_MIRROR_PATH = join(
34
- getRepoRoot(),
35
- "clients",
36
- "shared",
37
- "Resources",
38
- "llm-provider-catalog.json",
39
- );
40
36
 
41
37
  interface ClientCatalogCredentialsGuide {
42
38
  description: string;
@@ -309,6 +305,32 @@ describe("LLM catalog parity: daemon vs client", () => {
309
305
  });
310
306
  });
311
307
 
308
+ test("Fireworks catalog includes GLM 5.2", () => {
309
+ expect(
310
+ isModelInCatalog("fireworks", "accounts/fireworks/models/glm-5p2"),
311
+ ).toBe(true);
312
+
313
+ const fireworks = PROVIDER_CATALOG.find(
314
+ (entry) => entry.id === "fireworks",
315
+ );
316
+ expect(
317
+ fireworks?.models.find(
318
+ (model) => model.id === "accounts/fireworks/models/glm-5p2",
319
+ ),
320
+ ).toMatchObject({
321
+ displayName: "GLM 5.2",
322
+ contextWindowTokens: 1040000,
323
+ maxOutputTokens: 131072,
324
+ supportsToolUse: true,
325
+ supportsVision: false,
326
+ pricing: {
327
+ inputPer1mTokens: 1.4,
328
+ outputPer1mTokens: 4.4,
329
+ cacheReadPer1mTokens: 0.26,
330
+ },
331
+ });
332
+ });
333
+
312
334
  test("MiniMax catalog includes MiniMax M3", () => {
313
335
  const minimax = PROVIDER_CATALOG.find((entry) => entry.id === "minimax");
314
336
  expect(
@@ -457,19 +479,4 @@ describe("LLM catalog parity: daemon vs client", () => {
457
479
  longContextMode: "native-model",
458
480
  });
459
481
  });
460
-
461
- // -----------------------------------------------------------------------
462
- // Mirror byte-equality
463
- // -----------------------------------------------------------------------
464
-
465
- test("SwiftPM mirror is byte-identical to meta/ copy", () => {
466
- // `sync-llm-catalog.ts` writes both files from the same serializer; this
467
- // guard catches any case where one copy is regenerated without the other.
468
- // Byte equality is required because SwiftPM bundles the resource verbatim
469
- // into `VellumAssistantShared` while the meta/ JSON is consumed as a
470
- // cross-package artifact (web codegen, etc.).
471
- const metaBytes = readFileSync(META_JSON_PATH);
472
- const swiftPmBytes = readFileSync(SWIFTPM_MIRROR_PATH);
473
- expect(swiftPmBytes.equals(metaBytes)).toBe(true);
474
- });
475
482
  });