@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
@@ -1,14 +1,24 @@
1
- import { mkdtempSync, rmSync } from "node:fs";
1
+ import { randomBytes } from "node:crypto";
2
+ import { existsSync, mkdirSync, mkdtempSync, rmSync } from "node:fs";
2
3
  import { tmpdir } from "node:os";
3
4
  import { join } from "node:path";
4
5
  import { afterEach, beforeEach, describe, expect, test } from "bun:test";
5
6
 
6
7
  import { credentialKey } from "../security/credential-key.js";
8
+ import { _resetBackend, setSecureKeyAsync } from "../security/secure-keys.js";
7
9
  import { CredentialBroker } from "../tools/credentials/broker.js";
8
10
  import {
9
11
  _setMetadataPath,
10
12
  upsertCredentialMetadata,
11
13
  } from "../tools/credentials/metadata-store.js";
14
+ import { BROWSER_FILL_CAPABILITY } from "../tools/credentials/tool-policy.js";
15
+ import { setStorePathForTesting } from "./encrypted-store-test-helpers.js";
16
+
17
+ const TEST_DIR = join(
18
+ tmpdir(),
19
+ `vellum-broker-test-${randomBytes(4).toString("hex")}`,
20
+ );
21
+ const STORE_PATH = join(TEST_DIR, "keys.enc");
12
22
 
13
23
  describe("CredentialBroker", () => {
14
24
  let broker: CredentialBroker;
@@ -222,3 +232,441 @@ describe("CredentialBroker", () => {
222
232
  });
223
233
  });
224
234
  });
235
+
236
+ // ---------------------------------------------------------------------------
237
+ // Behavior that reads stored secret values, exercised against the encrypted
238
+ // store backend (transient injection, multi-template serverUseById, revokeAll,
239
+ // and canonical/legacy capability-key resolution).
240
+ // ---------------------------------------------------------------------------
241
+
242
+ describe("CredentialBroker (encrypted store backend)", () => {
243
+ let broker: CredentialBroker;
244
+
245
+ beforeEach(() => {
246
+ if (existsSync(TEST_DIR)) rmSync(TEST_DIR, { recursive: true });
247
+ mkdirSync(TEST_DIR, { recursive: true });
248
+ setStorePathForTesting(STORE_PATH);
249
+ _resetBackend();
250
+ _setMetadataPath(join(TEST_DIR, "metadata.json"));
251
+ broker = new CredentialBroker();
252
+ });
253
+
254
+ afterEach(() => {
255
+ _setMetadataPath(null);
256
+ setStorePathForTesting(null);
257
+ _resetBackend();
258
+ rmSync(TEST_DIR, { recursive: true, force: true });
259
+ });
260
+
261
+ describe("transient credentials", () => {
262
+ test("consume returns transient value and deletes it", () => {
263
+ // GIVEN a credential with metadata and an injected one-time transient value
264
+ upsertCredentialMetadata("svc", "key", { allowedTools: ["tool1"] });
265
+ broker.injectTransient("svc", "key", "one-time-secret");
266
+
267
+ // WHEN the credential is authorized and consumed
268
+ const auth = broker.authorize({
269
+ service: "svc",
270
+ field: "key",
271
+ toolName: "tool1",
272
+ });
273
+ expect(auth.authorized).toBe(true);
274
+ if (!auth.authorized) return;
275
+ const result = broker.consume(auth.token.tokenId);
276
+
277
+ // THEN the transient value is returned alongside the storage key
278
+ expect(result.success).toBe(true);
279
+ expect(result.value).toBe("one-time-secret");
280
+ expect(result.storageKey).toBe(credentialKey("svc", "key"));
281
+
282
+ // AND a subsequent authorize+consume no longer has the transient value
283
+ const auth2 = broker.authorize({
284
+ service: "svc",
285
+ field: "key",
286
+ toolName: "tool1",
287
+ });
288
+ expect(auth2.authorized).toBe(true);
289
+ if (!auth2.authorized) return;
290
+ const result2 = broker.consume(auth2.token.tokenId);
291
+ expect(result2.success).toBe(true);
292
+ expect(result2.value).toBeUndefined();
293
+ });
294
+
295
+ test("browserFill uses transient value when available", async () => {
296
+ // GIVEN a credential with a transient value and no stored value
297
+ upsertCredentialMetadata("github", "token", {
298
+ allowedTools: ["browser_fill_credential"],
299
+ });
300
+ broker.injectTransient("github", "token", "transient-ghp-123");
301
+
302
+ // WHEN browserFill runs
303
+ let filledValue: string | undefined;
304
+ const result = await broker.browserFill({
305
+ service: "github",
306
+ field: "token",
307
+ toolName: "browser_fill_credential",
308
+ fill: async (v) => {
309
+ filledValue = v;
310
+ },
311
+ });
312
+
313
+ // THEN the transient value is filled
314
+ expect(result.success).toBe(true);
315
+ expect(filledValue).toBe("transient-ghp-123");
316
+ });
317
+
318
+ test("browserFill consumes transient value — second fill falls back to stored", async () => {
319
+ // GIVEN a credential with both a stored value and a transient value
320
+ upsertCredentialMetadata("github", "token", {
321
+ allowedTools: ["browser_fill_credential"],
322
+ });
323
+ await setSecureKeyAsync(credentialKey("github", "token"), "stored-value");
324
+ broker.injectTransient("github", "token", "transient-value");
325
+
326
+ // WHEN browserFill runs twice
327
+ let filled1: string | undefined;
328
+ await broker.browserFill({
329
+ service: "github",
330
+ field: "token",
331
+ toolName: "browser_fill_credential",
332
+ fill: async (v) => {
333
+ filled1 = v;
334
+ },
335
+ });
336
+ let filled2: string | undefined;
337
+ await broker.browserFill({
338
+ service: "github",
339
+ field: "token",
340
+ toolName: "browser_fill_credential",
341
+ fill: async (v) => {
342
+ filled2 = v;
343
+ },
344
+ });
345
+
346
+ // THEN the first fill uses the transient and the second falls back to stored
347
+ expect(filled1).toBe("transient-value");
348
+ expect(filled2).toBe("stored-value");
349
+ });
350
+
351
+ test("browserFill preserves transient value on fill failure", async () => {
352
+ // GIVEN a credential with a transient value
353
+ upsertCredentialMetadata("github", "token", {
354
+ allowedTools: ["browser_fill_credential"],
355
+ });
356
+ broker.injectTransient("github", "token", "transient-preserved");
357
+
358
+ // WHEN the first fill throws
359
+ const result1 = await broker.browserFill({
360
+ service: "github",
361
+ field: "token",
362
+ toolName: "browser_fill_credential",
363
+ fill: async () => {
364
+ throw new Error("Playwright timeout");
365
+ },
366
+ });
367
+ expect(result1.success).toBe(false);
368
+ let filled: string | undefined;
369
+ const result2 = await broker.browserFill({
370
+ service: "github",
371
+ field: "token",
372
+ toolName: "browser_fill_credential",
373
+ fill: async (v) => {
374
+ filled = v;
375
+ },
376
+ });
377
+
378
+ // THEN the transient value survives for the second fill
379
+ expect(result2.success).toBe(true);
380
+ expect(filled).toBe("transient-preserved");
381
+ });
382
+
383
+ test("serverUse uses transient value when available", async () => {
384
+ // GIVEN a credential with a transient value
385
+ upsertCredentialMetadata("vercel", "api_token", {
386
+ allowedTools: ["deploy"],
387
+ });
388
+ broker.injectTransient("vercel", "api_token", "transient-vercel-tok");
389
+
390
+ // WHEN serverUse runs
391
+ const result = await broker.serverUse({
392
+ service: "vercel",
393
+ field: "api_token",
394
+ toolName: "deploy",
395
+ execute: async (v) => {
396
+ expect(v).toBe("transient-vercel-tok");
397
+ return "deployed";
398
+ },
399
+ });
400
+
401
+ // THEN the transient value is used for execution
402
+ expect(result.success).toBe(true);
403
+ expect(result.result).toBe("deployed");
404
+ });
405
+
406
+ test("serverUse consumes transient — subsequent call has no value without stored key", async () => {
407
+ // GIVEN a credential with only a transient value (no stored value)
408
+ upsertCredentialMetadata("vercel", "api_token", {
409
+ allowedTools: ["deploy"],
410
+ });
411
+ broker.injectTransient("vercel", "api_token", "transient-only");
412
+
413
+ // WHEN serverUse runs twice
414
+ await broker.serverUse({
415
+ service: "vercel",
416
+ field: "api_token",
417
+ toolName: "deploy",
418
+ execute: async () => "ok",
419
+ });
420
+ const result = await broker.serverUse({
421
+ service: "vercel",
422
+ field: "api_token",
423
+ toolName: "deploy",
424
+ execute: async () => {
425
+ throw new Error("should not be called");
426
+ },
427
+ });
428
+
429
+ // THEN the second call fails because no stored value remains
430
+ expect(result.success).toBe(false);
431
+ expect(result.reason).toContain("no stored value");
432
+ });
433
+
434
+ test("injectTransient replaces previous transient for same key", () => {
435
+ // GIVEN two transient values injected for the same credential
436
+ upsertCredentialMetadata("svc", "key", { allowedTools: ["t"] });
437
+ broker.injectTransient("svc", "key", "first");
438
+ broker.injectTransient("svc", "key", "second");
439
+
440
+ // WHEN the credential is authorized and consumed
441
+ const auth = broker.authorize({
442
+ service: "svc",
443
+ field: "key",
444
+ toolName: "t",
445
+ });
446
+ if (!auth.authorized) return;
447
+ const result = broker.consume(auth.token.tokenId);
448
+
449
+ // THEN the most recent transient value wins
450
+ expect(result.value).toBe("second");
451
+ });
452
+
453
+ test("transient value for one credential does not affect another", () => {
454
+ // GIVEN a transient value injected for svcA only
455
+ upsertCredentialMetadata("svcA", "key", { allowedTools: ["t"] });
456
+ upsertCredentialMetadata("svcB", "key", { allowedTools: ["t"] });
457
+ broker.injectTransient("svcA", "key", "val-a");
458
+
459
+ // WHEN both credentials are authorized and consumed
460
+ const authB = broker.authorize({
461
+ service: "svcB",
462
+ field: "key",
463
+ toolName: "t",
464
+ });
465
+ if (!authB.authorized) return;
466
+ const resultB = broker.consume(authB.token.tokenId);
467
+ const authA = broker.authorize({
468
+ service: "svcA",
469
+ field: "key",
470
+ toolName: "t",
471
+ });
472
+ if (!authA.authorized) return;
473
+ const resultA = broker.consume(authA.token.tokenId);
474
+
475
+ // THEN only svcA carries the transient value
476
+ expect(resultB.success).toBe(true);
477
+ expect(resultB.value).toBeUndefined();
478
+ expect(resultA.value).toBe("val-a");
479
+ });
480
+ });
481
+
482
+ describe("serverUseById edge cases", () => {
483
+ test("serverUseById with multiple injection templates returns all", async () => {
484
+ // GIVEN a credential with two injection templates and a stored value
485
+ const meta = upsertCredentialMetadata("multi", "api_key", {
486
+ allowedTools: ["proxy"],
487
+ injectionTemplates: [
488
+ {
489
+ hostPattern: "*.fal.ai",
490
+ injectionType: "header",
491
+ headerName: "Authorization",
492
+ valuePrefix: "Key ",
493
+ },
494
+ {
495
+ hostPattern: "gateway.fal.ai",
496
+ injectionType: "header",
497
+ headerName: "X-Fal-Key",
498
+ },
499
+ ],
500
+ });
501
+ await setSecureKeyAsync(
502
+ credentialKey("multi", "api_key"),
503
+ "multi-secret",
504
+ );
505
+
506
+ // WHEN serverUseById resolves the credential by id
507
+ const result = await broker.serverUseById({
508
+ credentialId: meta.credentialId,
509
+ requestingTool: "proxy",
510
+ });
511
+
512
+ // THEN both injection templates are returned without leaking the secret
513
+ expect(result.success).toBe(true);
514
+ if (!result.success) return;
515
+ expect(result.injectionTemplates).toHaveLength(2);
516
+ expect(result.injectionTemplates[0].hostPattern).toBe("*.fal.ai");
517
+ expect(result.injectionTemplates[1].hostPattern).toBe("gateway.fal.ai");
518
+ expect(JSON.stringify(result)).not.toContain("multi-secret");
519
+ });
520
+ });
521
+
522
+ describe("revokeAll", () => {
523
+ test("revokeAll clears all tokens and subsequent consume fails", () => {
524
+ // GIVEN two active tokens for a credential
525
+ upsertCredentialMetadata("svc", "key", { allowedTools: ["t1", "t2"] });
526
+ const a1 = broker.authorize({
527
+ service: "svc",
528
+ field: "key",
529
+ toolName: "t1",
530
+ });
531
+ const a2 = broker.authorize({
532
+ service: "svc",
533
+ field: "key",
534
+ toolName: "t2",
535
+ });
536
+ expect(broker.activeTokenCount).toBe(2);
537
+
538
+ // WHEN revokeAll is called
539
+ broker.revokeAll();
540
+
541
+ // THEN the token count is zero and consuming either token fails
542
+ expect(broker.activeTokenCount).toBe(0);
543
+ if (a1.authorized) {
544
+ expect(broker.consume(a1.token.tokenId).success).toBe(false);
545
+ }
546
+ if (a2.authorized) {
547
+ expect(broker.consume(a2.token.tokenId).success).toBe(false);
548
+ }
549
+ });
550
+
551
+ test("revokeAll on empty broker is a no-op", () => {
552
+ // GIVEN a broker with no active tokens
553
+ expect(broker.activeTokenCount).toBe(0);
554
+
555
+ // WHEN revokeAll is called
556
+ broker.revokeAll();
557
+
558
+ // THEN the token count remains zero
559
+ expect(broker.activeTokenCount).toBe(0);
560
+ });
561
+ });
562
+
563
+ describe("canonical capability key", () => {
564
+ test("authorize succeeds with canonical key when metadata has canonical key", () => {
565
+ // GIVEN metadata allowing the canonical browser-fill capability key
566
+ upsertCredentialMetadata("github", "token", {
567
+ allowedTools: [BROWSER_FILL_CAPABILITY],
568
+ });
569
+
570
+ // WHEN authorizing with the canonical key
571
+ const result = broker.authorize({
572
+ service: "github",
573
+ field: "token",
574
+ toolName: BROWSER_FILL_CAPABILITY,
575
+ });
576
+
577
+ // THEN authorization succeeds
578
+ expect(result.authorized).toBe(true);
579
+ });
580
+
581
+ test("authorize succeeds with canonical key when metadata has legacy alias", () => {
582
+ // GIVEN metadata stored under the legacy browser_fill_credential alias
583
+ upsertCredentialMetadata("github", "token", {
584
+ allowedTools: ["browser_fill_credential"],
585
+ });
586
+
587
+ // WHEN authorizing with the canonical key
588
+ const result = broker.authorize({
589
+ service: "github",
590
+ field: "token",
591
+ toolName: BROWSER_FILL_CAPABILITY,
592
+ });
593
+
594
+ // THEN authorization succeeds
595
+ expect(result.authorized).toBe(true);
596
+ });
597
+
598
+ test("authorize succeeds with legacy alias when metadata has canonical key", () => {
599
+ // GIVEN metadata allowing the canonical capability key
600
+ upsertCredentialMetadata("github", "token", {
601
+ allowedTools: [BROWSER_FILL_CAPABILITY],
602
+ });
603
+
604
+ // WHEN authorizing with the legacy alias
605
+ const result = broker.authorize({
606
+ service: "github",
607
+ field: "token",
608
+ toolName: "browser_fill_credential",
609
+ });
610
+
611
+ // THEN authorization succeeds
612
+ expect(result.authorized).toBe(true);
613
+ });
614
+
615
+ test("serverUse with canonical key works when metadata has legacy alias", async () => {
616
+ // GIVEN metadata stored under the legacy alias with a stored value
617
+ upsertCredentialMetadata("vercel", "api_token", {
618
+ allowedTools: ["browser_fill_credential"],
619
+ });
620
+ await setSecureKeyAsync(
621
+ credentialKey("vercel", "api_token"),
622
+ "vercel-tok",
623
+ );
624
+
625
+ // WHEN serverUse runs with the canonical key
626
+ const result = await broker.serverUse({
627
+ service: "vercel",
628
+ field: "api_token",
629
+ toolName: BROWSER_FILL_CAPABILITY,
630
+ execute: async (v) => v,
631
+ });
632
+
633
+ // THEN execution succeeds with the stored value
634
+ expect(result.success).toBe(true);
635
+ expect(result.result).toBe("vercel-tok");
636
+ });
637
+
638
+ test("non-aliased tool names are unaffected by alias resolution", () => {
639
+ // GIVEN metadata allowing a non-aliased custom tool
640
+ upsertCredentialMetadata("svc", "key", {
641
+ allowedTools: ["custom_tool"],
642
+ });
643
+
644
+ // WHEN authorizing with that custom tool
645
+ const result = broker.authorize({
646
+ service: "svc",
647
+ field: "key",
648
+ toolName: "custom_tool",
649
+ });
650
+
651
+ // THEN authorization succeeds
652
+ expect(result.authorized).toBe(true);
653
+ });
654
+
655
+ test("non-aliased tool denied when only canonical key is allowed", () => {
656
+ // GIVEN metadata allowing only the canonical capability key
657
+ upsertCredentialMetadata("svc", "key", {
658
+ allowedTools: [BROWSER_FILL_CAPABILITY],
659
+ });
660
+
661
+ // WHEN authorizing with an unrelated tool
662
+ const result = broker.authorize({
663
+ service: "svc",
664
+ field: "key",
665
+ toolName: "unrelated_tool",
666
+ });
667
+
668
+ // THEN authorization is denied
669
+ expect(result.authorized).toBe(false);
670
+ });
671
+ });
672
+ });
@@ -11,27 +11,33 @@
11
11
 
12
12
  import { describe, expect, test } from "bun:test";
13
13
 
14
- import { isUntrustedTrustClass } from "../runtime/actor-trust-resolver.js";
14
+ import { resolveCapabilities } from "../runtime/capabilities.js";
15
15
 
16
16
  // ---------------------------------------------------------------------------
17
17
  // Trust class categorization (foundational for lockdown decisions)
18
18
  // ---------------------------------------------------------------------------
19
19
 
20
20
  describe("trust class categorization for CES lockdown", () => {
21
- test("guardian is not untrusted", () => {
22
- expect(isUntrustedTrustClass("guardian")).toBe(false);
21
+ test("guardian runs an unsandboxed shell", () => {
22
+ expect(resolveCapabilities("guardian").canRunUnsandboxedShell).toBe(true);
23
23
  });
24
24
 
25
- test("trusted_contact is untrusted", () => {
26
- expect(isUntrustedTrustClass("trusted_contact")).toBe(true);
25
+ test("trusted_contact shell is sandboxed", () => {
26
+ expect(resolveCapabilities("trusted_contact").canRunUnsandboxedShell).toBe(false);
27
27
  });
28
28
 
29
- test("unknown is untrusted", () => {
30
- expect(isUntrustedTrustClass("unknown")).toBe(true);
29
+ test("unverified_contact shell is sandboxed", () => {
30
+ expect(resolveCapabilities("unverified_contact").canRunUnsandboxedShell).toBe(
31
+ false,
32
+ );
31
33
  });
32
34
 
33
- test("undefined is untrusted", () => {
34
- expect(isUntrustedTrustClass(undefined)).toBe(true);
35
+ test("unknown shell is sandboxed", () => {
36
+ expect(resolveCapabilities("unknown").canRunUnsandboxedShell).toBe(false);
37
+ });
38
+
39
+ test("undefined shell is sandboxed", () => {
40
+ expect(resolveCapabilities(undefined).canRunUnsandboxedShell).toBe(false);
35
41
  });
36
42
  });
37
43
 
@@ -91,7 +97,7 @@ describe("VELLUM_UNTRUSTED_SHELL env flag", () => {
91
97
  describe("CES shell lockdown activation", () => {
92
98
  test("lockdown is active only when both flag is enabled AND actor is untrusted", () => {
93
99
  // Simulates the condition used in shell.ts:
94
- // const shellLockdownActive = isCesShellLockdownEnabled(config) && isUntrustedTrustClass(context.trustClass);
100
+ // const shellLockdownActive = isCesShellLockdownEnabled(config) && !resolveCapabilities(context.trustClass).canRunUnsandboxedShell;
95
101
  const cases: Array<{
96
102
  flagEnabled: boolean;
97
103
  trustClass: "guardian" | "trusted_contact" | "unknown";
@@ -106,7 +112,8 @@ describe("CES shell lockdown activation", () => {
106
112
  ];
107
113
 
108
114
  for (const { flagEnabled, trustClass, expected } of cases) {
109
- const active = flagEnabled && isUntrustedTrustClass(trustClass);
115
+ const active =
116
+ flagEnabled && !resolveCapabilities(trustClass).canRunUnsandboxedShell;
110
117
  expect(active).toBe(expected);
111
118
  }
112
119
  });
@@ -136,7 +136,6 @@ describe("secure tool installation is separate from credential grants", () => {
136
136
  test("manage_secure_command_tool does not share tool name with grant tools", () => {
137
137
  // The tool name must not collide with existing credential grant tools
138
138
  const grantToolNames = [
139
- "credential_store",
140
139
  "credential_grant",
141
140
  "credential_revoke",
142
141
  "credential_list",
@@ -110,6 +110,7 @@ function slackResult(
110
110
  hasAppToken: false,
111
111
  hasUserToken: false,
112
112
  connected: false,
113
+ threadMode: "mention_only",
113
114
  ...overrides,
114
115
  };
115
116
  }
@@ -138,10 +139,9 @@ describe("credentials/prompt route", () => {
138
139
 
139
140
  test("forwards usageDescription as the prompt purpose and to metadata", async () => {
140
141
  /**
141
- * The CLI `credentials prompt` command exposes `--usage-description` to
142
- * match the credential_store tool's prompt action. The route must thread
143
- * it to the secure prompt (as `purpose`, shown to the user) and persist it
144
- * to credential metadata (as `usageDescription`).
142
+ * The CLI `credentials prompt` command exposes `--usage-description`. The
143
+ * route must thread it to the secure prompt (as `purpose`, shown to the
144
+ * user) and persist it to credential metadata (as `usageDescription`).
145
145
  */
146
146
  // GIVEN the credentials/prompt route is registered
147
147
  expect(promptRoute).toBeDefined();