@vellumai/assistant 0.9.0 → 0.10.0-staging.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (572) hide show
  1. package/ARCHITECTURE.md +18 -34
  2. package/bun.lock +7 -8
  3. package/docs/activation-funnel-telemetry.md +28 -22
  4. package/docs/architecture/security.md +29 -28
  5. package/docs/stt-provider-onboarding.md +3 -5
  6. package/docs/workflows-testing.md +13 -44
  7. package/docs/workflows.md +3 -5
  8. package/node_modules/@vellumai/ces-client/src/__tests__/ces-client.test.ts +47 -0
  9. package/node_modules/@vellumai/ces-client/src/rpc-client.ts +28 -5
  10. package/node_modules/@vellumai/environments/src/seeds.ts +2 -5
  11. package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +97 -0
  12. package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +10 -0
  13. package/node_modules/@vellumai/gateway-client/src/index.ts +32 -6
  14. package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +119 -0
  15. package/node_modules/@vellumai/gateway-client/src/types.ts +15 -84
  16. package/openapi.yaml +976 -63
  17. package/package.json +2 -1
  18. package/scripts/sync-llm-catalog.ts +6 -15
  19. package/scripts/sync-web-search-catalog.ts +3 -11
  20. package/src/__tests__/access-request-card-view.test.ts +98 -0
  21. package/src/__tests__/access-request-seed-content-blocks.test.ts +2 -4
  22. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +72 -32
  23. package/src/__tests__/agent-loop-compaction-strip.test.ts +241 -0
  24. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +16 -13
  25. package/src/__tests__/agent-loop-output-hooks.test.ts +69 -0
  26. package/src/__tests__/agent-loop-override-profile.test.ts +25 -0
  27. package/src/__tests__/always-loaded-tools-guard.test.ts +2 -3
  28. package/src/__tests__/app-compiler.test.ts +15 -1
  29. package/src/__tests__/app-dir-path-guard.test.ts +0 -1
  30. package/src/__tests__/assistant-feature-flag-guard.test.ts +1 -4
  31. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +0 -2
  32. package/src/__tests__/auth-fallback-events-store.test.ts +6 -14
  33. package/src/__tests__/avatar-identity-sync.test.ts +2 -27
  34. package/src/__tests__/btw-routes.test.ts +6 -8
  35. package/src/__tests__/call-pointer-messages.test.ts +28 -0
  36. package/src/__tests__/cancel-clears-processing.test.ts +89 -0
  37. package/src/__tests__/channel-approval-routes.test.ts +0 -4
  38. package/src/__tests__/channel-inbound-disk-pressure.test.ts +5 -15
  39. package/src/__tests__/checker.test.ts +0 -3
  40. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +3 -4
  41. package/src/__tests__/compactor-image-manifest-trust.test.ts +21 -1
  42. package/src/__tests__/compactor-summary-call-truncation.test.ts +223 -0
  43. package/src/__tests__/config-loader-backfill.test.ts +268 -27
  44. package/src/__tests__/config-schema.test.ts +35 -0
  45. package/src/__tests__/config-watcher.test.ts +0 -18
  46. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +2 -2
  47. package/src/__tests__/contact-store-user-file.test.ts +0 -6
  48. package/src/__tests__/contacts-tools.test.ts +29 -0
  49. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +22 -0
  50. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
  51. package/src/__tests__/conversation-agent-loop.test.ts +58 -0
  52. package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
  53. package/src/__tests__/conversation-lifecycle.test.ts +7 -9
  54. package/src/__tests__/conversation-load-history-repair.test.ts +101 -0
  55. package/src/__tests__/conversation-routes-guardian-reply.test.ts +15 -12
  56. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +6 -3
  57. package/src/__tests__/conversation-title-service.test.ts +62 -0
  58. package/src/__tests__/credential-broker.test.ts +449 -1
  59. package/src/__tests__/credential-execution-shell-lockdown.test.ts +18 -11
  60. package/src/__tests__/credential-execution-tools.test.ts +0 -1
  61. package/src/__tests__/credential-prompt-route.test.ts +4 -4
  62. package/src/__tests__/credential-routes.test.ts +360 -0
  63. package/src/__tests__/credential-security-invariants.test.ts +4 -13
  64. package/src/__tests__/disk-pressure-policy.test.ts +12 -0
  65. package/src/__tests__/disk-usage.test.ts +65 -0
  66. package/src/__tests__/dynamic-page-surface.test.ts +152 -1
  67. package/src/__tests__/fixtures/credential-security-fixtures.ts +2 -33
  68. package/src/__tests__/gateway-flag-listener.test.ts +110 -1
  69. package/src/__tests__/gateway-only-guard.test.ts +3 -7
  70. package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
  71. package/src/__tests__/guardian-card-withdrawal.test.ts +403 -0
  72. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +5 -3
  73. package/src/__tests__/guardian-grant-minting.test.ts +3 -35
  74. package/src/__tests__/guardian-routing-invariants.test.ts +64 -26
  75. package/src/__tests__/guardian-routing-state.test.ts +0 -1
  76. package/src/__tests__/headless-browser-mode.test.ts +10 -0
  77. package/src/__tests__/headless-browser-navigate.test.ts +8 -3
  78. package/src/__tests__/helpers/create-guardian-binding.ts +0 -1
  79. package/src/__tests__/host-browser-proxy.test.ts +87 -0
  80. package/src/__tests__/identity-routes.test.ts +0 -189
  81. package/src/__tests__/inbound-invite-redemption.test.ts +4 -4
  82. package/src/__tests__/injector-v3-suppression.test.ts +27 -20
  83. package/src/__tests__/internal-telemetry-routes.test.ts +6 -14
  84. package/src/__tests__/invite-redemption-service.test.ts +4 -7
  85. package/src/__tests__/llm-callsite-catalog.test.ts +5 -6
  86. package/src/__tests__/llm-catalog-parity.test.ts +30 -23
  87. package/src/__tests__/llm-resolver.test.ts +70 -24
  88. package/src/__tests__/llm-schema.test.ts +1 -0
  89. package/src/__tests__/managed-profile-guard.test.ts +163 -4
  90. package/src/__tests__/mcp-health-check.test.ts +6 -7
  91. package/src/__tests__/media-stream-server-integration.test.ts +317 -13
  92. package/src/__tests__/oauth-provider-seed-logos.test.ts +4 -6
  93. package/src/__tests__/onboarding-persona-write.test.ts +1 -1
  94. package/src/__tests__/path-policy.test.ts +34 -0
  95. package/src/__tests__/persona-resolver.test.ts +49 -14
  96. package/src/__tests__/plugin-api-model-profiles.test.ts +178 -0
  97. package/src/__tests__/plugin-api-provider.test.ts +24 -0
  98. package/src/__tests__/plugin-tool-contribution.test.ts +6 -3
  99. package/src/__tests__/post-compaction-reinjection-idempotency.test.ts +214 -0
  100. package/src/__tests__/provider-send-message-override-profile.test.ts +76 -0
  101. package/src/__tests__/reaction-persistence.test.ts +150 -29
  102. package/src/__tests__/registry.test.ts +2 -7
  103. package/src/__tests__/relay-server.test.ts +285 -0
  104. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
  105. package/src/__tests__/schedule-routes-workflow-validation.test.ts +1 -10
  106. package/src/__tests__/schedule-routes.test.ts +0 -30
  107. package/src/__tests__/schedule-tools.test.ts +2 -18
  108. package/src/__tests__/scheduler-reuse-conversation.test.ts +8 -5
  109. package/src/__tests__/skill-execute-input.test.ts +51 -1
  110. package/src/__tests__/skill-runtime-path.test.ts +2 -3
  111. package/src/__tests__/skills.test.ts +51 -0
  112. package/src/__tests__/slack-notification-approval-card.test.ts +176 -0
  113. package/src/__tests__/slack-reaction-canonical-approval.test.ts +285 -0
  114. package/src/__tests__/subagent-tools.test.ts +266 -0
  115. package/src/__tests__/surface-completion-nudge-hook.test.ts +367 -0
  116. package/src/__tests__/task-progress-nudge-hook.test.ts +1 -1
  117. package/src/__tests__/title-generate-hook.test.ts +100 -3
  118. package/src/__tests__/token-estimator-accuracy.benchmark.test.ts +1 -29
  119. package/src/__tests__/token-manager.test.ts +519 -0
  120. package/src/__tests__/tool-approval-seed-content-blocks.test.ts +1 -1
  121. package/src/__tests__/tool-audit-listener.test.ts +7 -7
  122. package/src/__tests__/tool-executor-lifecycle-events.test.ts +6 -3
  123. package/src/__tests__/tool-executor.test.ts +0 -79
  124. package/src/__tests__/trusted-contact-approval-notifier.test.ts +4 -2
  125. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +220 -3
  126. package/src/__tests__/trusted-contact-multichannel.test.ts +3 -3
  127. package/src/__tests__/trusted-contact-verification.test.ts +8 -10
  128. package/src/__tests__/twilio-routes.test.ts +81 -1
  129. package/src/__tests__/voice-invite-redemption.test.ts +2 -3
  130. package/src/__tests__/weak-open-model.test.ts +30 -0
  131. package/src/__tests__/web-search-catalog-parity.test.ts +6 -25
  132. package/src/__tests__/workspace-greetings.test.ts +152 -0
  133. package/src/__tests__/workspace-migration-105-enable-memory-v3-live-for-new-workspaces.test.ts +149 -0
  134. package/src/__tests__/workspace-migration-108-drop-balanced-economy-profile.test.ts +285 -0
  135. package/src/__tests__/workspace-migration-add-send-diagnostics.test.ts +1 -1
  136. package/src/__tests__/workspace-migration-drop-collect-usage-data.test.ts +118 -0
  137. package/src/__tests__/workspace-migration-drop-send-diagnostics.test.ts +118 -0
  138. package/src/a2a/__tests__/e2e-a2a-channel.test.ts +0 -4
  139. package/src/agent/loop.ts +49 -29
  140. package/src/api/README.md +6 -6
  141. package/src/api/events/tool-result.ts +6 -0
  142. package/src/api/events/workflow-completed.ts +53 -0
  143. package/src/api/events/workflow-leaf-finished.ts +38 -0
  144. package/src/api/events/workflow-leaf-started.ts +35 -0
  145. package/src/api/events/workflow-progress.ts +32 -0
  146. package/src/api/events/workflow-started.ts +31 -0
  147. package/src/api/index.ts +40 -0
  148. package/src/api/responses/conversation-message.ts +28 -4
  149. package/src/api/responses/home.ts +26 -4
  150. package/src/api/responses/workflow-journal.ts +53 -0
  151. package/src/approvals/guardian-card-withdrawal.ts +145 -0
  152. package/src/approvals/guardian-decision-primitive.ts +26 -3
  153. package/src/approvals/guardian-request-resolvers.ts +183 -80
  154. package/src/calls/__tests__/channel-admission-reader.test.ts +132 -0
  155. package/src/calls/__tests__/relay-setup-router.test.ts +350 -0
  156. package/src/calls/call-pointer-messages.ts +10 -4
  157. package/src/calls/channel-admission-reader.ts +104 -0
  158. package/src/calls/guardian-dispatch.ts +17 -45
  159. package/src/calls/media-stream-server.ts +84 -2
  160. package/src/calls/relay-access-wait.ts +1 -1
  161. package/src/calls/relay-server.ts +66 -0
  162. package/src/calls/relay-setup-router.ts +82 -1
  163. package/src/calls/twilio-routes.ts +17 -8
  164. package/src/calls/voice-session-bridge.ts +2 -2
  165. package/src/cli/commands/clients.ts +3 -0
  166. package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2-compare-render.test.ts +1 -1
  167. package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2.test.ts +8 -7
  168. package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v3.test.ts +5 -4
  169. package/src/cli/commands/memory/index.ts +30 -0
  170. package/src/cli/commands/{memory-v2-compare-render.ts → memory/memory-v2-compare-render.ts} +1 -1
  171. package/src/cli/commands/{memory-v2.ts → memory/memory-v2.ts} +6 -15
  172. package/src/cli/commands/{memory-v3.ts → memory/memory-v3.ts} +97 -11
  173. package/src/cli/commands/oauth/status.test.ts +36 -0
  174. package/src/cli/commands/oauth/status.ts +23 -3
  175. package/src/cli/commands/plugins.ts +197 -4
  176. package/src/cli/lib/__tests__/diff-plugin.test.ts +443 -0
  177. package/src/cli/lib/__tests__/inspect-plugin.test.ts +54 -0
  178. package/src/cli/lib/__tests__/merge-plugin-tree.test.ts +443 -0
  179. package/src/cli/lib/__tests__/plugin-surfaces.test.ts +111 -0
  180. package/src/cli/lib/__tests__/upgrade-plugin.test.ts +295 -2
  181. package/src/cli/lib/diff-plugin.ts +346 -0
  182. package/src/cli/lib/inspect-plugin.ts +12 -1
  183. package/src/cli/lib/install-from-github.ts +105 -17
  184. package/src/cli/lib/merge-plugin-tree.ts +328 -0
  185. package/src/cli/lib/plugin-fingerprint.ts +14 -0
  186. package/src/cli/lib/plugin-surfaces.ts +104 -0
  187. package/src/cli/lib/upgrade-plugin.ts +298 -10
  188. package/src/cli/program.ts +2 -6
  189. package/src/config/__tests__/sync-gated-profiles.test.ts +368 -0
  190. package/src/config/assistant-feature-flags.ts +22 -7
  191. package/src/config/bundled-skills/contacts/tools/contact-search.ts +0 -1
  192. package/src/config/bundled-skills/messaging/SKILL.md +6 -4
  193. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +9 -8
  194. package/src/config/bundled-skills/subagent/SKILL.md +4 -0
  195. package/src/config/bundled-skills/subagent/TOOLS.json +4 -0
  196. package/src/config/bundled-skills/workflows/SKILL.md +14 -8
  197. package/src/config/bundled-tool-registry.ts +2 -7
  198. package/src/config/call-site-defaults.ts +15 -2
  199. package/src/config/feature-flag-registry.json +46 -31
  200. package/src/config/inference-profile-validation.ts +26 -0
  201. package/src/config/llm-resolver.ts +3 -0
  202. package/src/config/loader.ts +4 -0
  203. package/src/config/memory-v3-gate.ts +11 -0
  204. package/src/config/profile-order.ts +28 -0
  205. package/src/config/schema.ts +8 -6
  206. package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
  207. package/src/config/schemas/call-site-catalog.ts +7 -0
  208. package/src/config/schemas/channels.ts +11 -0
  209. package/src/config/schemas/elevenlabs.ts +0 -1
  210. package/src/config/schemas/llm.ts +31 -0
  211. package/src/config/schemas/memory-lifecycle.ts +3 -7
  212. package/src/config/schemas/memory-v3.ts +6 -0
  213. package/src/config/schemas/platform.ts +0 -8
  214. package/src/config/schemas/services.ts +18 -0
  215. package/src/config/seed-inference-profiles.ts +109 -44
  216. package/src/config/skills.ts +21 -0
  217. package/src/config/sync-gated-profiles.ts +220 -0
  218. package/src/contacts/contact-store.ts +89 -106
  219. package/src/contacts/contacts-write.ts +5 -22
  220. package/src/contacts/types.ts +0 -1
  221. package/src/context/compactor.ts +88 -54
  222. package/src/context/strip-injections.ts +58 -10
  223. package/src/context/token-estimator.ts +1 -1
  224. package/src/credential-execution/process-manager.ts +55 -14
  225. package/src/credential-execution/prompted-credential.ts +2 -3
  226. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -2
  227. package/src/daemon/config-watcher.ts +0 -4
  228. package/src/daemon/conversation-agent-loop-handlers.ts +2 -0
  229. package/src/daemon/conversation-agent-loop.ts +114 -22
  230. package/src/daemon/conversation-history.ts +1 -1
  231. package/src/daemon/conversation-lifecycle.ts +3 -5
  232. package/src/daemon/conversation-process.ts +13 -5
  233. package/src/daemon/conversation-runtime-assembly.ts +13 -15
  234. package/src/daemon/conversation-slash.ts +2 -23
  235. package/src/daemon/conversation-surfaces.ts +26 -0
  236. package/src/daemon/conversation-tool-setup.ts +27 -14
  237. package/src/daemon/conversation.ts +66 -14
  238. package/src/daemon/disk-pressure-policy.ts +5 -3
  239. package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +0 -1
  240. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -1
  241. package/src/daemon/handlers/config-a2a.ts +0 -2
  242. package/src/daemon/handlers/config-channels.ts +15 -16
  243. package/src/daemon/handlers/config-slack-channel.ts +22 -3
  244. package/src/daemon/handlers/conversations.ts +107 -0
  245. package/src/daemon/host-browser-proxy.ts +41 -0
  246. package/src/daemon/lifecycle.ts +55 -27
  247. package/src/daemon/message-provenance.ts +2 -0
  248. package/src/daemon/message-types/contacts.ts +0 -1
  249. package/src/daemon/message-types/conversations.ts +3 -3
  250. package/src/daemon/message-types/sync.ts +0 -1
  251. package/src/daemon/message-types/web-activity.ts +7 -1
  252. package/src/daemon/message-types/workflows.ts +83 -1
  253. package/src/daemon/orphan-reaper.test.ts +0 -19
  254. package/src/daemon/orphan-reaper.ts +2 -24
  255. package/src/daemon/server.ts +0 -10
  256. package/src/daemon/tool-setup-types.ts +4 -0
  257. package/src/daemon/trust-context.ts +1 -1
  258. package/src/events/tool-audit-listener.ts +2 -2
  259. package/src/home/feed-source-enrichment.test.ts +151 -0
  260. package/src/home/feed-source-enrichment.ts +176 -0
  261. package/src/home/relationship-state.ts +2 -4
  262. package/src/instrument.ts +18 -6
  263. package/src/ipc/__tests__/binary-result-ipc.test.ts +81 -0
  264. package/src/ipc/__tests__/clients-list-ipc.test.ts +20 -0
  265. package/src/ipc/assistant-server.ts +37 -4
  266. package/src/ipc/gateway-flag-listener.ts +18 -2
  267. package/src/memory/__tests__/auto-analysis-enqueue.test.ts +5 -16
  268. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +7 -11
  269. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +37 -7
  270. package/src/memory/__tests__/memory-retrospective-job.test.ts +229 -401
  271. package/src/memory/__tests__/onboarding-events-store.test.ts +7 -7
  272. package/src/memory/auth-fallback-events-store.ts +2 -2
  273. package/src/memory/auto-analysis-enqueue.ts +3 -5
  274. package/src/memory/bookmark-crud.ts +1 -2
  275. package/src/memory/canonical-guardian-store.ts +39 -1
  276. package/src/memory/conversation-crud.ts +9 -4
  277. package/src/memory/conversation-key-store.ts +17 -2
  278. package/src/memory/conversation-title-service.ts +64 -7
  279. package/src/memory/db-init.ts +17 -17
  280. package/src/memory/embedding-backend.ts +38 -1
  281. package/src/memory/embedding-billing-breaker.ts +96 -0
  282. package/src/memory/jobs-store.ts +25 -13
  283. package/src/memory/jobs-worker.ts +54 -1
  284. package/src/memory/lifecycle-events-store.ts +2 -2
  285. package/src/memory/memory-retrospective-constants.ts +4 -4
  286. package/src/memory/memory-retrospective-enqueue.ts +31 -6
  287. package/src/memory/memory-retrospective-job.ts +28 -227
  288. package/src/memory/migrations/129-contact-channels-access-fields.ts +18 -9
  289. package/src/memory/migrations/131-drop-legacy-member-guardian-tables.ts +14 -2
  290. package/src/memory/migrations/289-contact-channels-unique-ext-user.ts +10 -0
  291. package/src/memory/migrations/291-contact-channels-renormalize-addresses.ts +72 -0
  292. package/src/memory/migrations/292-schedule-default-no-reuse-conversation.test.ts +67 -0
  293. package/src/memory/migrations/292-schedule-default-no-reuse-conversation.ts +25 -0
  294. package/src/memory/migrations/293-workflow-journal-leaf-tokens.ts +32 -0
  295. package/src/memory/migrations/294-drop-external-user-id.ts +31 -0
  296. package/src/memory/migrations/295-drop-approval-prompt-ts-tracker.ts +20 -0
  297. package/src/memory/migrations/296-rewrite-balanced-economy-profile-pins.test.ts +110 -0
  298. package/src/memory/migrations/296-rewrite-balanced-economy-profile-pins.ts +68 -0
  299. package/src/memory/migrations/__tests__/131-drop-legacy-member-guardian-tables.test.ts +154 -0
  300. package/src/memory/migrations/__tests__/289-contact-channels-unique-ext-user.test.ts +31 -0
  301. package/src/memory/migrations/__tests__/291-contact-channels-renormalize-addresses.test.ts +341 -0
  302. package/src/memory/migrations/__tests__/run-migrations.test.ts +52 -0
  303. package/src/memory/migrations/index.ts +6 -0
  304. package/src/memory/migrations/run-migrations.ts +41 -0
  305. package/src/memory/migrations/validate-migration-state.ts +1 -1
  306. package/src/memory/onboarding-events-store.ts +3 -3
  307. package/src/memory/schema/contacts.ts +0 -5
  308. package/src/memory/skill-loaded-events-store.test.ts +7 -15
  309. package/src/memory/skill-loaded-events-store.ts +2 -2
  310. package/src/memory/tool-executed-events-store.test.ts +7 -7
  311. package/src/memory/turn-trace-store.test.ts +736 -0
  312. package/src/memory/turn-trace-store.ts +364 -0
  313. package/src/memory/v2/__tests__/consolidation-job.test.ts +8 -0
  314. package/src/memory/v2/__tests__/skill-content.test.ts +30 -0
  315. package/src/memory/v2/consolidation-job.ts +2 -2
  316. package/src/memory/v2/skill-content.ts +25 -7
  317. package/src/memory/v2/skill-store.ts +7 -1
  318. package/src/memory/v3-eval/__tests__/eval-packets.test.ts +248 -0
  319. package/src/memory/v3-eval/eval-packets.ts +546 -0
  320. package/src/messaging/providers/slack/adapter.ts +1 -1
  321. package/src/messaging/providers/slack/api.ts +31 -0
  322. package/src/messaging/providers/slack/send.test.ts +114 -2
  323. package/src/messaging/providers/slack/send.ts +30 -7
  324. package/src/messaging/providers/slack/withdraw.test.ts +200 -0
  325. package/src/messaging/providers/slack/withdraw.ts +161 -0
  326. package/src/notifications/AGENTS.md +2 -0
  327. package/src/notifications/access-request-copy.ts +72 -59
  328. package/src/notifications/adapters/shared.ts +29 -0
  329. package/src/notifications/adapters/slack.ts +58 -103
  330. package/src/notifications/adapters/telegram.ts +2 -20
  331. package/src/notifications/approval-card-data.ts +333 -0
  332. package/src/notifications/broadcaster.ts +16 -3
  333. package/src/notifications/canonical-delivery-recorder.ts +139 -0
  334. package/src/notifications/copy-composer.ts +3 -3
  335. package/src/notifications/decision-engine.ts +4 -2
  336. package/src/notifications/destination-resolver.ts +4 -6
  337. package/src/notifications/guardian-question-mode.ts +10 -0
  338. package/src/notifications/home-feed-side-effect.ts +7 -16
  339. package/src/notifications/notification-utils.ts +19 -20
  340. package/src/notifications/signal.ts +79 -43
  341. package/src/notifications/types.ts +98 -121
  342. package/src/oauth/AGENTS.md +5 -24
  343. package/src/permissions/checker.test.ts +51 -0
  344. package/src/permissions/checker.ts +185 -26
  345. package/src/permissions/ipc-risk-types.ts +24 -0
  346. package/src/permissions/question-prompter.test.ts +27 -0
  347. package/src/permissions/question-prompter.ts +4 -0
  348. package/src/platform/client.test.ts +119 -0
  349. package/src/platform/client.ts +66 -0
  350. package/src/platform/consent-cache.test.ts +267 -0
  351. package/src/platform/consent-cache.ts +174 -0
  352. package/src/plugin-api/constants.ts +1 -1
  353. package/src/plugin-api/index.ts +33 -1
  354. package/src/plugin-api/model-profiles.ts +33 -0
  355. package/src/plugin-api/types.ts +50 -2
  356. package/src/plugins/defaults/advisor/__tests__/advisor-gate.test.ts +56 -0
  357. package/src/plugins/defaults/advisor/__tests__/advisor-state-store.test.ts +43 -0
  358. package/src/plugins/defaults/advisor/__tests__/agent-loop-integration.test.ts +137 -0
  359. package/src/plugins/defaults/advisor/__tests__/consult.test.ts +153 -0
  360. package/src/plugins/defaults/advisor/__tests__/hooks.test.ts +138 -0
  361. package/src/plugins/defaults/advisor/__tests__/transcript.test.ts +147 -0
  362. package/src/plugins/defaults/advisor/advisor-gate.ts +29 -0
  363. package/src/plugins/defaults/advisor/advisor-state-store.ts +94 -0
  364. package/src/plugins/defaults/advisor/config.ts +21 -0
  365. package/src/plugins/defaults/advisor/consult.ts +93 -0
  366. package/src/plugins/defaults/advisor/hooks/post-model-call.ts +34 -0
  367. package/src/plugins/defaults/advisor/hooks/pre-model-call.ts +30 -0
  368. package/src/plugins/defaults/advisor/hooks/user-prompt-submit.ts +19 -0
  369. package/src/plugins/defaults/advisor/package.json +14 -0
  370. package/src/plugins/defaults/advisor/steering.ts +67 -0
  371. package/src/plugins/defaults/advisor/tools/advisor.ts +65 -0
  372. package/src/plugins/defaults/advisor/transcript.ts +76 -0
  373. package/src/plugins/defaults/index.ts +60 -0
  374. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +22 -9
  375. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +2 -2
  376. package/src/plugins/defaults/memory-retrieval/tail-reinjection-strip.ts +64 -0
  377. package/src/plugins/defaults/memory-retrieval/unified-turn-context.ts +29 -21
  378. package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +1 -0
  379. package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +1 -0
  380. package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +129 -9
  381. package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +31 -4
  382. package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +77 -2
  383. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +1 -0
  384. package/src/plugins/defaults/memory-v3-shadow/injector.ts +7 -10
  385. package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +144 -11
  386. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +32 -20
  387. package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +56 -3
  388. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +23 -2
  389. package/src/plugins/defaults/surface-completion-nudge/hooks/post-model-call.ts +276 -0
  390. package/src/plugins/defaults/surface-completion-nudge/hooks/stop.ts +22 -0
  391. package/src/plugins/defaults/surface-completion-nudge/nudge-state-store.ts +46 -0
  392. package/src/plugins/defaults/surface-completion-nudge/package.json +14 -0
  393. package/src/plugins/defaults/task-progress-nudge/hooks/post-tool-use.ts +3 -13
  394. package/src/plugins/defaults/title-generate/hooks/stop.ts +56 -21
  395. package/src/prompts/persona-resolver.ts +14 -4
  396. package/src/prompts/templates/system-sections.ts +7 -2
  397. package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
  398. package/src/providers/__tests__/provider-secret-catalog.test.ts +1 -0
  399. package/src/providers/__tests__/retry-callsite.test.ts +176 -0
  400. package/src/providers/atlascloud/client.ts +85 -0
  401. package/src/providers/fetch-provider-catalog.ts +85 -0
  402. package/src/providers/inference/adapter-factory.ts +3 -0
  403. package/src/providers/model-catalog.ts +58 -0
  404. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +33 -0
  405. package/src/providers/openai/chat-completions-provider.ts +7 -0
  406. package/src/providers/openai/responses-provider.ts +10 -0
  407. package/src/providers/provider-send-message.ts +11 -3
  408. package/src/providers/retry.ts +53 -12
  409. package/src/providers/search-provider-catalog.ts +10 -0
  410. package/src/providers/weak-open-model.ts +22 -0
  411. package/src/runtime/AGENTS.md +0 -1
  412. package/src/runtime/__tests__/agent-wake.test.ts +181 -0
  413. package/src/runtime/__tests__/client-health.test.ts +44 -0
  414. package/src/runtime/access-request-helper.ts +21 -53
  415. package/src/runtime/actor-trust-resolver.ts +59 -63
  416. package/src/runtime/agent-wake.ts +52 -0
  417. package/src/runtime/assistant-event-hub.ts +18 -4
  418. package/src/runtime/auth/__tests__/route-policy.test.ts +12 -0
  419. package/src/runtime/auth/require-bound-guardian.ts +1 -4
  420. package/src/runtime/btw-sidechain.ts +3 -6
  421. package/src/runtime/capabilities.test.ts +120 -0
  422. package/src/runtime/capabilities.ts +197 -0
  423. package/src/runtime/channel-approval-types.ts +22 -45
  424. package/src/runtime/channel-invite-transports/telegram.ts +4 -4
  425. package/src/runtime/channel-retry-sweep.ts +1 -0
  426. package/src/runtime/channel-verification-service.ts +3 -3
  427. package/src/runtime/client-health.ts +26 -0
  428. package/src/runtime/confirmation-request-guardian-bridge.ts +38 -29
  429. package/src/runtime/effective-capabilities.test.ts +128 -0
  430. package/src/runtime/effective-capabilities.ts +84 -0
  431. package/src/runtime/guardian-reply-router.ts +106 -21
  432. package/src/runtime/invite-redemption-service.ts +9 -25
  433. package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +123 -0
  434. package/src/runtime/migrations/vbundle-builder.ts +49 -20
  435. package/src/runtime/pending-interactions.ts +15 -0
  436. package/src/runtime/routes/__tests__/client-routes.test.ts +13 -0
  437. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +67 -0
  438. package/src/runtime/routes/__tests__/plugins-routes.test.ts +240 -1
  439. package/src/runtime/routes/app-routes.ts +1 -1
  440. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +2 -2
  441. package/src/runtime/routes/assets/vellum-design-system.css +1959 -0
  442. package/src/runtime/routes/browser-tabs-routes.ts +9 -0
  443. package/src/runtime/routes/btw-routes.ts +1 -27
  444. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +17 -8
  445. package/src/runtime/routes/client-routes.ts +10 -0
  446. package/src/runtime/routes/contact-routes.ts +31 -8
  447. package/src/runtime/routes/conversation-compaction-routes.ts +1 -1
  448. package/src/runtime/routes/conversation-management-routes.ts +80 -1
  449. package/src/runtime/routes/conversation-query-routes.ts +68 -22
  450. package/src/runtime/routes/conversation-routes.ts +39 -14
  451. package/src/runtime/routes/credential-routes.ts +40 -16
  452. package/src/runtime/routes/empty-state-greeting-cache.ts +1 -2
  453. package/src/runtime/routes/events-routes.ts +1 -3
  454. package/src/runtime/routes/guardian-approval-interception.ts +14 -73
  455. package/src/runtime/routes/guardian-approval-prompt.ts +22 -4
  456. package/src/runtime/routes/home-feed-routes.ts +8 -3
  457. package/src/runtime/routes/identity-routes.ts +1 -296
  458. package/src/runtime/routes/inbound-message-handler.ts +214 -228
  459. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +89 -7
  460. package/src/runtime/routes/inbound-stages/admission-policy.test.ts +154 -0
  461. package/src/runtime/routes/inbound-stages/admission-policy.ts +140 -0
  462. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +3 -3
  463. package/src/runtime/routes/inbound-stages/background-dispatch.ts +11 -6
  464. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +1 -2
  465. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +1 -2
  466. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +7 -7
  467. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +47 -28
  468. package/src/runtime/routes/inbound-stages/reaction-intercept.ts +358 -0
  469. package/src/runtime/routes/index.ts +2 -0
  470. package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +8 -0
  471. package/src/runtime/routes/integrations/slack/channel.ts +36 -0
  472. package/src/runtime/routes/internal-telemetry-routes.ts +1 -1
  473. package/src/runtime/routes/mcp-auth-routes.ts +233 -41
  474. package/src/runtime/routes/memory-eval-routes.ts +87 -0
  475. package/src/runtime/routes/notification-routes.ts +122 -133
  476. package/src/runtime/routes/platform-routes.ts +2 -2
  477. package/src/runtime/routes/plugins-routes.ts +202 -3
  478. package/src/runtime/routes/schedule-routes.ts +0 -22
  479. package/src/runtime/routes/secret-routes.ts +10 -0
  480. package/src/runtime/routes/surface-action-routes.ts +2 -1
  481. package/src/runtime/routes/tool-call-question-enrichment.test.ts +146 -0
  482. package/src/runtime/routes/tool-call-question-enrichment.ts +66 -0
  483. package/src/runtime/routes/workflow-routes.test.ts +229 -44
  484. package/src/runtime/routes/workflow-routes.ts +131 -29
  485. package/src/runtime/routes/workspace-greetings.ts +55 -0
  486. package/src/runtime/sync/resource-sync-events.ts +1 -11
  487. package/src/runtime/tool-grant-request-helper.ts +18 -16
  488. package/src/runtime/trust-context-resolver.ts +8 -5
  489. package/src/schedule/inference-profile.ts +2 -14
  490. package/src/schedule/schedule-store.ts +1 -1
  491. package/src/schedule/scheduler-types.ts +5 -1
  492. package/src/security/__tests__/provider-key-env-fallback.test.ts +6 -0
  493. package/src/security/secret-patterns.ts +3 -0
  494. package/src/subagent/manager.ts +17 -4
  495. package/src/subagent/types.ts +6 -0
  496. package/src/telemetry/trace-collection-policy.test.ts +28 -0
  497. package/src/telemetry/trace-collection-policy.ts +30 -0
  498. package/src/telemetry/types.ts +89 -0
  499. package/src/telemetry/usage-telemetry-reporter.test.ts +586 -36
  500. package/src/telemetry/usage-telemetry-reporter.ts +148 -41
  501. package/src/tools/AGENTS.md +3 -3
  502. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +31 -0
  503. package/src/tools/browser/browser-execution.ts +30 -19
  504. package/src/tools/document/document-tool.ts +2 -3
  505. package/src/tools/executor.ts +5 -3
  506. package/src/tools/host-terminal/host-shell.ts +5 -4
  507. package/src/tools/memory/register.ts +2 -2
  508. package/src/tools/network/__tests__/web-fetch-firecrawl.test.ts +360 -0
  509. package/src/tools/network/__tests__/web-search.test.ts +143 -0
  510. package/src/tools/network/web-fetch.ts +372 -1
  511. package/src/tools/network/web-search-error.ts +1 -1
  512. package/src/tools/network/web-search.ts +213 -10
  513. package/src/tools/permission-checker.ts +4 -3
  514. package/src/tools/registry.ts +20 -0
  515. package/src/tools/schedule/create.ts +7 -12
  516. package/src/tools/schedule/update.ts +4 -11
  517. package/src/tools/shared/filesystem/path-policy.ts +39 -13
  518. package/src/tools/side-effects.ts +2 -17
  519. package/src/tools/skills/execute.ts +33 -0
  520. package/src/tools/subagent/spawn.ts +61 -12
  521. package/src/tools/terminal/shell.ts +10 -4
  522. package/src/tools/tool-approval-handler.ts +18 -13
  523. package/src/tools/tool-manifest.ts +0 -2
  524. package/src/tools/types.ts +9 -0
  525. package/src/tools/ui-surface/definitions.ts +64 -3
  526. package/src/tools/verification-control-plane-policy.ts +3 -1
  527. package/src/tools/workflows/run-workflow.test.ts +8 -18
  528. package/src/tools/workflows/run-workflow.ts +1 -0
  529. package/src/util/disk-usage.ts +78 -23
  530. package/src/util/platform.ts +10 -3
  531. package/src/watcher/telemetry.ts +2 -2
  532. package/src/workflows/capabilities.ts +2 -3
  533. package/src/workflows/engine.test.ts +175 -1
  534. package/src/workflows/engine.ts +82 -0
  535. package/src/workflows/journal-store.test.ts +70 -0
  536. package/src/workflows/journal-store.ts +18 -3
  537. package/src/workflows/run-manager.test.ts +171 -28
  538. package/src/workflows/run-manager.ts +66 -24
  539. package/src/workspace/migrations/105-enable-memory-v3-live-for-new-workspaces.ts +63 -0
  540. package/src/workspace/migrations/106-drop-collect-usage-data.ts +47 -0
  541. package/src/workspace/migrations/107-drop-send-diagnostics.ts +47 -0
  542. package/src/workspace/migrations/108-drop-balanced-economy-profile.ts +129 -0
  543. package/src/workspace/migrations/registry.ts +8 -0
  544. package/src/__tests__/app-control-no-global-cgevent.test.ts +0 -98
  545. package/src/__tests__/credential-security-e2e.test.ts +0 -362
  546. package/src/__tests__/credential-vault-unit.test.ts +0 -1528
  547. package/src/__tests__/credential-vault.test.ts +0 -1706
  548. package/src/__tests__/identity-intro-cache.test.ts +0 -315
  549. package/src/__tests__/secret-onetime-send.test.ts +0 -182
  550. package/src/cli/commands/__tests__/task.test.ts +0 -914
  551. package/src/cli/commands/task.ts +0 -771
  552. package/src/config/bundled-skills/personal-page/SKILL.md +0 -57
  553. package/src/config/bundled-skills/personal-page/TOOLS.json +0 -27
  554. package/src/config/bundled-skills/personal-page/tools/app-refresh.ts +0 -17
  555. package/src/config/preloaded-apps/personal-page/src/components/About.tsx +0 -22
  556. package/src/config/preloaded-apps/personal-page/src/components/App.tsx +0 -16
  557. package/src/config/preloaded-apps/personal-page/src/components/Features.tsx +0 -77
  558. package/src/config/preloaded-apps/personal-page/src/components/Hero.tsx +0 -57
  559. package/src/config/preloaded-apps/personal-page/src/components/Pending.tsx +0 -28
  560. package/src/config/preloaded-apps/personal-page/src/components/animations.tsx +0 -234
  561. package/src/config/preloaded-apps/personal-page/src/components/icons.tsx +0 -48
  562. package/src/config/preloaded-apps/personal-page/src/components/media.ts +0 -16
  563. package/src/config/preloaded-apps/personal-page/src/index.html +0 -20
  564. package/src/config/preloaded-apps/personal-page/src/main.tsx +0 -7
  565. package/src/config/preloaded-apps/personal-page/src/profile-data.ts +0 -82
  566. package/src/config/preloaded-apps/personal-page/src/styles.css +0 -759
  567. package/src/memory/__tests__/preloaded-apps.test.ts +0 -85
  568. package/src/memory/preloaded-apps.ts +0 -116
  569. package/src/notifications/tool-approval-copy.ts +0 -142
  570. package/src/runtime/routes/approval-prompt-ts-tracker.ts +0 -78
  571. package/src/runtime/routes/identity-intro-cache.ts +0 -172
  572. package/src/tools/credentials/vault.ts +0 -712
@@ -0,0 +1,368 @@
1
+ import {
2
+ existsSync,
3
+ mkdirSync,
4
+ readFileSync,
5
+ rmSync,
6
+ writeFileSync,
7
+ } from "node:fs";
8
+ import { join } from "node:path";
9
+ import {
10
+ afterAll,
11
+ afterEach,
12
+ beforeEach,
13
+ describe,
14
+ expect,
15
+ mock,
16
+ test,
17
+ } from "bun:test";
18
+
19
+ const WORKSPACE_DIR = process.env.VELLUM_WORKSPACE_DIR!;
20
+ const CONFIG_PATH = join(WORKSPACE_DIR, "config.json");
21
+
22
+ function ensureTestDir(): void {
23
+ const dirs = [
24
+ WORKSPACE_DIR,
25
+ join(WORKSPACE_DIR, "data"),
26
+ join(WORKSPACE_DIR, "data", "memory"),
27
+ join(WORKSPACE_DIR, "data", "logs"),
28
+ ];
29
+ for (const dir of dirs) {
30
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
31
+ }
32
+ }
33
+
34
+ function makeLoggerStub(): Record<string, unknown> {
35
+ const stub: Record<string, unknown> = {};
36
+ for (const m of [
37
+ "info",
38
+ "warn",
39
+ "error",
40
+ "debug",
41
+ "trace",
42
+ "fatal",
43
+ "silent",
44
+ "child",
45
+ ]) {
46
+ stub[m] = m === "child" ? () => makeLoggerStub() : () => {};
47
+ }
48
+ return stub;
49
+ }
50
+
51
+ mock.module("../../util/logger.js", () => ({
52
+ getLogger: () => makeLoggerStub(),
53
+ }));
54
+
55
+ afterAll(() => {
56
+ mock.restore();
57
+ });
58
+
59
+ import { setOverridesForTesting } from "../../__tests__/feature-flag-test-helpers.js";
60
+ import { invalidateConfigCache } from "../loader.js";
61
+ import { LLMSchema } from "../schemas/llm.js";
62
+ import { seedInferenceProfiles } from "../seed-inference-profiles.js";
63
+ import { reconcileFlagGatedProfiles } from "../sync-gated-profiles.js";
64
+
65
+ type RawConfig = {
66
+ llm: {
67
+ profiles: Record<string, Record<string, unknown>>;
68
+ profileOrder: string[];
69
+ activeProfile?: string;
70
+ advisorProfile?: string;
71
+ };
72
+ };
73
+
74
+ function writeConfig(obj: unknown): void {
75
+ writeFileSync(CONFIG_PATH, JSON.stringify(obj, null, 2) + "\n");
76
+ }
77
+
78
+ function readConfig(): RawConfig {
79
+ return JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
80
+ }
81
+
82
+ function seedBalancedConfig(): void {
83
+ writeConfig({ llm: { default: { provider: "anthropic" } } });
84
+ invalidateConfigCache();
85
+ seedInferenceProfiles({});
86
+ }
87
+
88
+ describe("reconcileFlagGatedProfiles", () => {
89
+ beforeEach(() => {
90
+ ensureTestDir();
91
+ if (existsSync(CONFIG_PATH)) rmSync(CONFIG_PATH, { force: true });
92
+ delete process.env.IS_PLATFORM;
93
+ setOverridesForTesting({});
94
+ invalidateConfigCache();
95
+ });
96
+
97
+ afterEach(() => {
98
+ delete process.env.IS_PLATFORM;
99
+ setOverridesForTesting({});
100
+ invalidateConfigCache();
101
+ });
102
+
103
+ test("flag on materializes the managed os-beta profile after balanced", () => {
104
+ process.env.IS_PLATFORM = "true";
105
+ seedBalancedConfig();
106
+ setOverridesForTesting({ "os-beta": true });
107
+
108
+ expect(reconcileFlagGatedProfiles()).toBe(true);
109
+
110
+ const raw = readConfig();
111
+ const osBeta = raw.llm.profiles["os-beta"]!;
112
+ expect(osBeta.model).toBe("accounts/fireworks/models/glm-5p2");
113
+ expect(osBeta.provider_connection).toBe("fireworks-managed");
114
+ expect(osBeta.source).toBe("managed");
115
+ expect(osBeta.label).toBe("OS Beta");
116
+
117
+ const order = raw.llm.profileOrder;
118
+ expect(order.indexOf("os-beta")).toBe(order.indexOf("balanced") + 1);
119
+ });
120
+
121
+ test("flag on in BYOK mode seeds the os-beta profile disabled", () => {
122
+ seedBalancedConfig();
123
+ setOverridesForTesting({ "os-beta": true });
124
+
125
+ expect(reconcileFlagGatedProfiles()).toBe(true);
126
+
127
+ const osBeta = readConfig().llm.profiles["os-beta"]!;
128
+ expect(osBeta.status).toBe("disabled");
129
+ expect(osBeta.label).toBe("OS Beta (Managed)");
130
+ expect(osBeta.source).toBe("managed");
131
+ });
132
+
133
+ test("flag on is idempotent across repeated runs", () => {
134
+ process.env.IS_PLATFORM = "true";
135
+ seedBalancedConfig();
136
+ setOverridesForTesting({ "os-beta": true });
137
+
138
+ expect(reconcileFlagGatedProfiles()).toBe(true);
139
+ invalidateConfigCache();
140
+ expect(reconcileFlagGatedProfiles()).toBe(false);
141
+ });
142
+
143
+ test("flag on preserves user overrides on the managed profile", () => {
144
+ process.env.IS_PLATFORM = "true";
145
+ seedBalancedConfig();
146
+ setOverridesForTesting({ "os-beta": true });
147
+ reconcileFlagGatedProfiles();
148
+
149
+ const raw = readConfig();
150
+ raw.llm.profiles["os-beta"]!.label = "My OS Beta";
151
+ raw.llm.profiles["os-beta"]!.status = "disabled";
152
+ raw.llm.profiles["os-beta"]!.advisorEnabled = true;
153
+ writeConfig(raw);
154
+ invalidateConfigCache();
155
+
156
+ reconcileFlagGatedProfiles();
157
+
158
+ const after = readConfig().llm.profiles["os-beta"]!;
159
+ expect(after.label).toBe("My OS Beta");
160
+ expect(after.status).toBe("disabled");
161
+ expect(after.advisorEnabled).toBe(true);
162
+ expect(after.model).toBe("accounts/fireworks/models/glm-5p2");
163
+ });
164
+
165
+ test("flag off removes a managed os-beta and applies fallbacks", () => {
166
+ process.env.IS_PLATFORM = "true";
167
+ seedBalancedConfig();
168
+ setOverridesForTesting({ "os-beta": true });
169
+ reconcileFlagGatedProfiles();
170
+
171
+ const raw = readConfig();
172
+ raw.llm.activeProfile = "os-beta";
173
+ raw.llm.advisorProfile = "os-beta";
174
+ writeConfig(raw);
175
+ invalidateConfigCache();
176
+
177
+ setOverridesForTesting({ "os-beta": false });
178
+ expect(reconcileFlagGatedProfiles()).toBe(true);
179
+
180
+ const after = readConfig();
181
+ expect(after.llm.profiles["os-beta"]).toBeUndefined();
182
+ expect(after.llm.profileOrder.includes("os-beta")).toBe(false);
183
+ expect(after.llm.activeProfile).toBe("balanced");
184
+ expect(after.llm.advisorProfile).toBe("quality-optimized");
185
+ });
186
+
187
+ test("flag off with no os-beta present is a no-op", () => {
188
+ process.env.IS_PLATFORM = "true";
189
+ seedBalancedConfig();
190
+ setOverridesForTesting({ "os-beta": false });
191
+
192
+ expect(reconcileFlagGatedProfiles()).toBe(false);
193
+ });
194
+
195
+ test("flag off scrubs os-beta from user mix arms, keeping >= 2-arm mixes", () => {
196
+ process.env.IS_PLATFORM = "true";
197
+ seedBalancedConfig();
198
+ setOverridesForTesting({ "os-beta": true });
199
+ reconcileFlagGatedProfiles();
200
+
201
+ const raw = readConfig();
202
+ raw.llm.profiles["my-mix"] = {
203
+ source: "user",
204
+ label: "My Mix",
205
+ mix: [
206
+ { profile: "balanced", weight: 70 },
207
+ { profile: "quality-optimized", weight: 20 },
208
+ { profile: "os-beta", weight: 30 },
209
+ ],
210
+ };
211
+ raw.llm.profileOrder.push("my-mix");
212
+ writeConfig(raw);
213
+ invalidateConfigCache();
214
+
215
+ setOverridesForTesting({ "os-beta": false });
216
+ expect(reconcileFlagGatedProfiles()).toBe(true);
217
+
218
+ const after = readConfig();
219
+ expect(after.llm.profiles["os-beta"]).toBeUndefined();
220
+ const mix = after.llm.profiles["my-mix"]!;
221
+ expect(mix.mix).toEqual([
222
+ { profile: "balanced", weight: 70 },
223
+ { profile: "quality-optimized", weight: 20 },
224
+ ]);
225
+ expect(mix.source).toBe("user");
226
+ expect(mix.label).toBe("My Mix");
227
+
228
+ invalidateConfigCache();
229
+ expect(reconcileFlagGatedProfiles()).toBe(false);
230
+ });
231
+
232
+ test("flag off removes a two-arm mix that loses os-beta and repoints refs", () => {
233
+ process.env.IS_PLATFORM = "true";
234
+ seedBalancedConfig();
235
+ setOverridesForTesting({ "os-beta": true });
236
+ reconcileFlagGatedProfiles();
237
+
238
+ const raw = readConfig();
239
+ raw.llm.profiles["experiment"] = {
240
+ source: "user",
241
+ label: "Experiment",
242
+ mix: [
243
+ { profile: "balanced", weight: 50 },
244
+ { profile: "os-beta", weight: 50 },
245
+ ],
246
+ };
247
+ raw.llm.profileOrder.push("experiment");
248
+ raw.llm.activeProfile = "experiment";
249
+ raw.llm.advisorProfile = "os-beta";
250
+ (raw.llm as Record<string, unknown>).callSites = {
251
+ mainAgent: { profile: "experiment" },
252
+ };
253
+ writeConfig(raw);
254
+ invalidateConfigCache();
255
+
256
+ setOverridesForTesting({ "os-beta": false });
257
+ expect(reconcileFlagGatedProfiles()).toBe(true);
258
+
259
+ const after = readConfig();
260
+ expect(after.llm.profiles["os-beta"]).toBeUndefined();
261
+ expect(after.llm.profiles["experiment"]).toBeUndefined();
262
+ expect(after.llm.profileOrder.includes("os-beta")).toBe(false);
263
+ expect(after.llm.profileOrder.includes("experiment")).toBe(false);
264
+ expect(after.llm.activeProfile).toBe("balanced");
265
+ expect(after.llm.advisorProfile).toBe("quality-optimized");
266
+ expect(
267
+ (
268
+ after.llm as unknown as Record<
269
+ string,
270
+ Record<string, Record<string, unknown>>
271
+ >
272
+ ).callSites.mainAgent.profile,
273
+ ).toBeUndefined();
274
+
275
+ expect(LLMSchema.safeParse(after.llm).success).toBe(true);
276
+ });
277
+
278
+ test("flag off shortens a three-arm mix to two surviving arms", () => {
279
+ process.env.IS_PLATFORM = "true";
280
+ seedBalancedConfig();
281
+ setOverridesForTesting({ "os-beta": true });
282
+ reconcileFlagGatedProfiles();
283
+
284
+ const raw = readConfig();
285
+ raw.llm.profiles["blend"] = {
286
+ source: "user",
287
+ label: "Blend",
288
+ mix: [
289
+ { profile: "balanced", weight: 40 },
290
+ { profile: "os-beta", weight: 30 },
291
+ { profile: "quality-optimized", weight: 30 },
292
+ ],
293
+ };
294
+ raw.llm.profileOrder.push("blend");
295
+ writeConfig(raw);
296
+ invalidateConfigCache();
297
+
298
+ setOverridesForTesting({ "os-beta": false });
299
+ expect(reconcileFlagGatedProfiles()).toBe(true);
300
+
301
+ const after = readConfig();
302
+ expect(after.llm.profiles["os-beta"]).toBeUndefined();
303
+ expect(after.llm.profiles["blend"]!.mix).toEqual([
304
+ { profile: "balanced", weight: 40 },
305
+ { profile: "quality-optimized", weight: 30 },
306
+ ]);
307
+
308
+ expect(LLMSchema.safeParse(after.llm).success).toBe(true);
309
+ });
310
+
311
+ test("flag off clears a call-site profile reference to os-beta", () => {
312
+ process.env.IS_PLATFORM = "true";
313
+ seedBalancedConfig();
314
+ setOverridesForTesting({ "os-beta": true });
315
+ reconcileFlagGatedProfiles();
316
+
317
+ const raw = readConfig();
318
+ (raw.llm as Record<string, unknown>).callSites = {
319
+ advisor: { profile: "os-beta", temperature: 0.3 },
320
+ };
321
+ writeConfig(raw);
322
+ invalidateConfigCache();
323
+
324
+ setOverridesForTesting({ "os-beta": false });
325
+ expect(reconcileFlagGatedProfiles()).toBe(true);
326
+
327
+ const after = readConfig();
328
+ const advisor = (
329
+ after.llm as unknown as Record<
330
+ string,
331
+ Record<string, Record<string, unknown>>
332
+ >
333
+ ).callSites.advisor;
334
+ expect(advisor.profile).toBeUndefined();
335
+ expect(advisor.temperature).toBe(0.3);
336
+
337
+ expect(LLMSchema.safeParse(after.llm).success).toBe(true);
338
+ });
339
+
340
+ test("a user-owned os-beta profile is never touched", () => {
341
+ process.env.IS_PLATFORM = "true";
342
+ writeConfig({
343
+ llm: {
344
+ default: { provider: "anthropic" },
345
+ profiles: {
346
+ "os-beta": {
347
+ source: "user",
348
+ label: "Mine",
349
+ provider: "anthropic",
350
+ model: "claude-x",
351
+ provider_connection: "anthropic-personal",
352
+ },
353
+ },
354
+ profileOrder: ["os-beta"],
355
+ },
356
+ });
357
+ invalidateConfigCache();
358
+ const before = readFileSync(CONFIG_PATH, "utf-8");
359
+
360
+ setOverridesForTesting({ "os-beta": true });
361
+ expect(reconcileFlagGatedProfiles()).toBe(false);
362
+ expect(readFileSync(CONFIG_PATH, "utf-8")).toBe(before);
363
+
364
+ setOverridesForTesting({ "os-beta": false });
365
+ expect(reconcileFlagGatedProfiles()).toBe(false);
366
+ expect(readFileSync(CONFIG_PATH, "utf-8")).toBe(before);
367
+ });
368
+ });
@@ -103,7 +103,11 @@ function parseRegistryToDefaults(parsed: unknown): FeatureFlagDefaultsRegistry {
103
103
  const entry = flag as Record<string, unknown>;
104
104
  if (entry.scope !== "assistant" && entry.scope !== "both") continue;
105
105
  if (typeof entry.key !== "string") continue;
106
- if (typeof entry.defaultEnabled !== "boolean" && typeof entry.defaultEnabled !== "string") continue;
106
+ if (
107
+ typeof entry.defaultEnabled !== "boolean" &&
108
+ typeof entry.defaultEnabled !== "string"
109
+ )
110
+ continue;
107
111
 
108
112
  result[entry.key as string] = {
109
113
  defaultEnabled: entry.defaultEnabled,
@@ -178,6 +182,12 @@ const DEFAULT_INIT_RETRY_BACKOFFS_MS: readonly number[] = [
178
182
  * tests preseed flag state via `setOverridesForTesting()` (in
179
183
  * `__tests__/feature-flag-test-helpers.ts`) without the gateway IPC call
180
184
  * clobbering their setup.
185
+ *
186
+ * Resolves `true` when the override cache is populated from the gateway and
187
+ * `false` when the cache is left unset (exhausted retries / unreachable
188
+ * gateway). Callers that mutate persisted state from flag values gate that
189
+ * work on a `true` result so a failed fetch never resolves a flag to its
190
+ * registry default and drops user state.
181
191
  */
182
192
  export async function initFeatureFlagOverrides(options?: {
183
193
  retryBackoffsMs?: readonly number[];
@@ -188,8 +198,8 @@ export async function initFeatureFlagOverrides(options?: {
188
198
  * instead of blocking startup.
189
199
  */
190
200
  callTimeoutMs?: number;
191
- }): Promise<void> {
192
- if (isCachedFromGateway()) return;
201
+ }): Promise<boolean> {
202
+ if (isCachedFromGateway()) return true;
193
203
 
194
204
  const backoffs = options?.retryBackoffsMs ?? DEFAULT_INIT_RETRY_BACKOFFS_MS;
195
205
  const callTimeoutMs = options?.callTimeoutMs;
@@ -205,7 +215,7 @@ export async function initFeatureFlagOverrides(options?: {
205
215
  // Re-check after the wait: a concurrent caller (e.g. a test using
206
216
  // `setOverridesForTesting`) may have populated the cache while we
207
217
  // were sleeping. Bail out so we don't clobber their setup.
208
- if (isCachedFromGateway()) return;
218
+ if (isCachedFromGateway()) return true;
209
219
  }
210
220
 
211
221
  const gatewayOverrides = await fetchOverridesFromGateway(callTimeoutMs);
@@ -217,7 +227,7 @@ export async function initFeatureFlagOverrides(options?: {
217
227
  "Feature flag overrides loaded from gateway after retry",
218
228
  );
219
229
  }
220
- return;
230
+ return true;
221
231
  }
222
232
  }
223
233
 
@@ -230,6 +240,7 @@ export async function initFeatureFlagOverrides(options?: {
230
240
  "Feature flag overrides empty after all retries; falling back to registry defaults and fail-closed undeclared flags",
231
241
  );
232
242
  }
243
+ return false;
233
244
  }
234
245
 
235
246
  /**
@@ -262,10 +273,14 @@ export function clearFeatureFlagOverridesCache(): void {
262
273
  * retries (the gateway is known to be up because it just pushed an event).
263
274
  * Called by the gateway flag listener when a `feature_flags_changed` event
264
275
  * arrives.
276
+ *
277
+ * Resolves `true` when the cache was repopulated from the gateway, `false`
278
+ * when the fetch came back empty/failed — callers gate persisted-state
279
+ * reconciliation on a `true` result.
265
280
  */
266
- export async function refreshOverridesFromGateway(): Promise<void> {
281
+ export async function refreshOverridesFromGateway(): Promise<boolean> {
267
282
  clearFeatureFlagOverridesCache();
268
- await initFeatureFlagOverrides({ retryBackoffsMs: [] });
283
+ return initFeatureFlagOverrides({ retryBackoffsMs: [] });
269
284
  }
270
285
 
271
286
  // ---------------------------------------------------------------------------
@@ -18,7 +18,6 @@ function formatContactSummary(c: ContactWithChannels): string {
18
18
  .map((ch) => {
19
19
  let s = `${ch.type}:${ch.address}${ch.isPrimary ? "*" : ""}`;
20
20
  const extras: string[] = [];
21
- if (ch.externalUserId) extras.push(`userId: ${ch.externalUserId}`);
22
21
  if (ch.externalChatId) extras.push(`chatId: ${ch.externalChatId}`);
23
22
  if (extras.length > 0) s += ` (${extras.join(", ")})`;
24
23
  return s;
@@ -28,6 +28,8 @@ When the user mentions "email" - sending, reading, checking, decluttering, draft
28
28
 
29
29
  Do not offer the assistant's own email as an option unless the user specifically asks. If Gmail and Outlook are not connected, guide them through setup.
30
30
 
31
+ Reading, searching, or summarizing the user's inbox is a **messaging task** — use the messaging tools (or the Gmail connection flow below if nothing is connected). Never run `assistant channels` commands for a mailbox request: channels are the assistant's own inbound delivery routes, not the user's mailbox, and inspecting them sends you down the wrong path.
32
+
31
33
  When a platform is connected (auth test succeeds), always use the messaging API tools for that platform. Never fall back to browser automation, shell commands (bash, curl), or any other approach for operations that messaging tools can handle. The messaging tools handle authentication internally - never try to access tokens or call APIs directly. Browser automation is only appropriate for initial credential setup (OAuth consent screens), not for day-to-day messaging operations.
32
34
 
33
35
  **Exception: Slack.** Slack messaging should use the Slack Web API directly via CLI, not messaging tools. See the **slack** skill for details.
@@ -50,13 +52,13 @@ When the user asks to "connect my email", "set up email", "manage my email", or
50
52
 
51
53
  ### Gmail
52
54
 
53
- 1. **Try connecting directly first.** Run `assistant oauth status google`. This will show whether or not the user had previously connected their google account. If so, they are ready to go.
54
- 2. **If no connections are found:** Call `skill_load` with `skill: "vellum-oauth-integrations"`. The skill will evaluate whether managed or your-own mode is appropriate and guide the user accordingly.
55
+ 1. **Check the connection.** Run `assistant oauth status google`. If a connection exists, the user is ready to go proceed with their request.
56
+ 2. **If no connections are found, render the connect button in one step:** call `ui_show` with `surface_type: "oauth_connect"` and `data.providerKey: "google"`. That surface is always available — do **not** run `assistant channels`, `oauth providers get`, or load `vellum-oauth-integrations` just to display the button, and do **not** fall back to `assistant oauth connect`. Only load `vellum-oauth-integrations` when the managed-vs-your-own-credentials decision genuinely needs handling (e.g. a BYOK setup where the managed connect surface isn't available).
55
57
 
56
58
  ### Outlook
57
59
 
58
- 1. **Try connecting directly first.** Run `assistant oauth status outlook`. This will show whether the user has previously connected their Outlook account.
59
- 2. **If no connections are found:** Call `skill_load` with `skill: "vellum-oauth-integrations"`. The skill will evaluate whether managed or your-own mode is appropriate and guide the user accordingly.
60
+ 1. **Check the connection.** Run `assistant oauth status outlook`. If a connection exists, the user is ready to go — proceed with their request.
61
+ 2. **If no connections are found, render the connect button in one step:** call `ui_show` with `surface_type: "oauth_connect"` and `data.providerKey: "outlook"`. The same rules as Gmail apply — don't probe further or load a setup skill just to show the button; only load `vellum-oauth-integrations` when a managed-vs-your-own-credentials decision genuinely needs handling.
60
62
 
61
63
  ### Slack
62
64
 
@@ -1,3 +1,4 @@
1
+ import { isArchiveBySenderAuthorized } from "../../../../runtime/effective-capabilities.js";
1
2
  import type {
2
3
  ToolContext,
3
4
  ToolExecutionResult,
@@ -8,14 +9,14 @@ export async function run(
8
9
  input: Record<string, unknown>,
9
10
  context: ToolContext,
10
11
  ): Promise<ToolExecutionResult> {
11
- const userApproved =
12
- input.user_approved === true && context.trustClass === "guardian";
13
- if (
14
- !context.triggeredBySurfaceAction &&
15
- !context.batchAuthorizedByTask &&
16
- !context.approvedViaPrompt &&
17
- !userApproved
18
- ) {
12
+ const authorized = isArchiveBySenderAuthorized({
13
+ trustClass: context.trustClass,
14
+ triggeredBySurfaceAction: context.triggeredBySurfaceAction,
15
+ batchAuthorizedByTask: context.batchAuthorizedByTask,
16
+ approvedViaPrompt: context.approvedViaPrompt,
17
+ userApproved: input.user_approved === true,
18
+ });
19
+ if (!authorized) {
19
20
  return err(
20
21
  "This tool requires either a surface action or a scheduled task run with this tool in required_tools. Present results in a selection table with action buttons and wait for the user to click before proceeding.",
21
22
  );
@@ -71,6 +71,10 @@ Only the parent conversation that spawned a subagent can interact with it (check
71
71
 
72
72
  Set `send_result_to_user: false` when spawning a subagent whose result is for internal processing only. The parent will still be notified on completion, but the notification will instruct it to read the result without presenting it to the user.
73
73
 
74
+ ## Inference Profile
75
+
76
+ Set `inference_profile` to an `llm.profiles` key when a subagent should run under a specific model profile. When omitted, the subagent inherits the parent turn's active profile if one exists; otherwise it uses the `subagentSpawn` call site's default model selection.
77
+
74
78
  ## Fork Mode
75
79
 
76
80
  Forks are sub-agents that inherit the parent's full context -- messages, system prompt, and memory -- sharing the KV cache for near-free context inheritance. Use forks when the task benefits from knowing what you've been discussing; use a regular sub-agent when the task is self-contained.
@@ -39,6 +39,10 @@
39
39
  "investigator"
40
40
  ],
41
41
  "description": "Agent specialization that controls tool access. 'researcher': read-only (web, files, memory). 'coder': file and bash access. 'planner': read-only analysis. 'investigator': root-cause analysis — debugging, log forensics, tracing behavior across many files; has bash for read-only investigation (grep/find/log inspection) and returns a compact root-cause report. 'general': full access (default). Ignored when fork: true (forks always use general)."
42
+ },
43
+ "inference_profile": {
44
+ "type": "string",
45
+ "description": "Optional llm.profiles key this subagent should run under. When omitted, the subagent inherits the parent turn's profile when one is active; otherwise it uses the subagentSpawn call site's default model selection."
42
46
  }
43
47
  },
44
48
  "required": ["label", "objective"]
@@ -1,19 +1,22 @@
1
1
  ---
2
2
  name: workflows
3
- description: Author and run autonomous multi-agent workflows that fan work across parallel leaf agents
3
+ description: Delegate a big or high-stakes job to a fleet of parallel subagents, orchestrated deterministically; runs unattended and reports back
4
4
  compatibility: "Designed for Vellum personal assistants"
5
5
  metadata:
6
6
  emoji: "⚙️"
7
7
  vellum:
8
8
  display-name: "Workflows"
9
9
  category: "system"
10
- feature-flag: "workflows"
10
+ always-candidate: true
11
11
  activation-hints:
12
- - "A task decomposes into many similar sub-tasks that can run concurrently (score every item, extract a field from each of many documents, draft-then-verify a batch)"
13
- - "You want fan-out orchestrated deterministically and the result reported back when the whole run finishes"
12
+ - "Batch apply one operation to each of MANY items (score / rate / rank / classify / extract / summarize each of a large set)"
13
+ - "Comprehensive coverage exhaustively sweep, audit, or find EVERY instance across a large surface"
14
+ - "Research & synthesize — gather across many sources or pages and combine into one answer"
15
+ - "Confidence — generate several independent attempts and judge them, or adversarially verify findings before trusting the result"
16
+ - "Scale — work too large to finish well in one inline pass"
14
17
  avoid-when:
15
- - "The task is a single tool call or a quick lookup do it inline"
16
- - "The work needs interactive, conversational back-and-forth rather than unattended fan-out"
18
+ - "A single inline answer, a quick lookup, or a small one-off"
19
+ - "Interactive, conversational back-and-forth rather than unattended fan-out"
17
20
  ---
18
21
 
19
22
  A workflow is a short JS/TS script you author that runs in a sandbox and fans work
@@ -22,8 +25,11 @@ one with `run_workflow` (inline `script` OR saved `name`, exactly one). It retur
22
25
  `runId` immediately; the run is asynchronous and you are notified in this
23
26
  conversation when it completes — **do NOT poll**.
24
27
 
25
- Reach for one when a task decomposes into many similar small sub-tasks that can run
26
- concurrently. For a single task or a quick lookup, do it inline.
28
+ Reach for one when a job is too big, too parallel, or too important for one inline
29
+ pass. That is more than batch/map-reduce over many items it also covers exhaustively
30
+ sweeping or auditing a large surface, researching across many sources and synthesizing,
31
+ and generating several independent attempts to judge or adversarially verify before
32
+ trusting the result. For a single task or a quick lookup, do it inline.
27
33
 
28
34
  ## The script model
29
35
 
@@ -24,7 +24,7 @@ import * as appCreate from "./bundled-skills/app-builder/tools/app-create.js";
24
24
  import * as appDelete from "./bundled-skills/app-builder/tools/app-delete.js";
25
25
  import * as appGenerateIcon from "./bundled-skills/app-builder/tools/app-generate-icon.js";
26
26
  import * as appList from "./bundled-skills/app-builder/tools/app-list.js";
27
- import * as appBuilder_appRefresh from "./bundled-skills/app-builder/tools/app-refresh.js";
27
+ import * as appRefresh from "./bundled-skills/app-builder/tools/app-refresh.js";
28
28
  import * as appUpdate from "./bundled-skills/app-builder/tools/app-update.js";
29
29
  // ── app-control ────────────────────────────────────────────────────────────────
30
30
  import * as appControlClick from "./bundled-skills/app-control/tools/app-control-click.js";
@@ -88,8 +88,6 @@ import * as messagingRead from "./bundled-skills/messaging/tools/messaging-read.
88
88
  import * as messagingSearch from "./bundled-skills/messaging/tools/messaging-search.js";
89
89
  import * as messagingSend from "./bundled-skills/messaging/tools/messaging-send.js";
90
90
  import * as messagingSenderDigest from "./bundled-skills/messaging/tools/messaging-sender-digest.js";
91
- // ── personal-page ──────────────────────────────────────────────────────────────
92
- import * as personalPage_appRefresh from "./bundled-skills/personal-page/tools/app-refresh.js";
93
91
  // ── phone-calls ────────────────────────────────────────────────────────────────
94
92
  import * as callEnd from "./bundled-skills/phone-calls/tools/call-end.js";
95
93
  import * as callStart from "./bundled-skills/phone-calls/tools/call-start.js";
@@ -148,7 +146,7 @@ export const bundledToolRegistry = new Map<string, SkillToolScript>([
148
146
  ["app-builder:tools/app-create.ts", appCreate],
149
147
  ["app-builder:tools/app-update.ts", appUpdate],
150
148
  ["app-builder:tools/app-delete.ts", appDelete],
151
- ["app-builder:tools/app-refresh.ts", appBuilder_appRefresh],
149
+ ["app-builder:tools/app-refresh.ts", appRefresh],
152
150
  ["app-builder:tools/app-generate-icon.ts", appGenerateIcon],
153
151
  ["app-builder:tools/app-list.ts", appList],
154
152
 
@@ -228,9 +226,6 @@ export const bundledToolRegistry = new Map<string, SkillToolScript>([
228
226
  ["messaging:tools/messaging-sender-digest.ts", messagingSenderDigest],
229
227
  ["messaging:tools/messaging-archive-by-sender.ts", messagingArchiveBySender],
230
228
 
231
- // personal-page
232
- ["personal-page:tools/app-refresh.ts", personalPage_appRefresh],
233
-
234
229
  // phone-calls
235
230
  ["phone-calls:tools/call-start.ts", callStart],
236
231
  ["phone-calls:tools/call-status.ts", callStatus],
@@ -1,7 +1,13 @@
1
1
  import { type LLMCallSite } from "./schemas/llm.js";
2
2
 
3
3
  type CallSiteDefaultConfig = {
4
- profile: string;
4
+ /**
5
+ * Named profile the call site resolves to. Omit to inherit the workspace
6
+ * default config (`llm.default`, with the active profile applied) — used for
7
+ * call sites that must resolve to a credentialed provider on every install
8
+ * rather than pinning a profile that may be unavailable.
9
+ */
10
+ profile?: string;
5
11
  maxTokens?: number;
6
12
  effort?: "none" | "low" | "medium" | "high" | "xhigh" | "max";
7
13
  temperature?: number | null;
@@ -63,6 +69,9 @@ export const CALL_SITE_DEFAULTS: Record<LLMCallSite, CallSiteDefaultConfig> = {
63
69
  meetConsentMonitor: { profile: "cost-optimized" },
64
70
  meetChatOpportunity: { profile: "cost-optimized" },
65
71
  inference: { profile: "cost-optimized" },
72
+ // The advisor consults the strongest managed profile by default; a workspace
73
+ // overrides this via `llm.advisorProfile` (which floats above this).
74
+ advisor: { profile: "quality-optimized" },
66
75
 
67
76
  heartbeatAgent: {
68
77
  profile: "cost-optimized",
@@ -125,8 +134,12 @@ export const CALL_SITE_DEFAULTS: Record<LLMCallSite, CallSiteDefaultConfig> = {
125
134
  thinking: { enabled: false },
126
135
  disableCache: true,
127
136
  },
137
+ // Anonymous and schema leaves inherit the workspace default config (no pinned
138
+ // profile) so they always resolve to a credentialed provider. Pinning a
139
+ // managed profile like `cost-optimized` breaks BYOK installs where the managed
140
+ // profiles are uncredentialed. A per-leaf `profile` option or a `workflowLeaf`
141
+ // call-site override still takes precedence for cost control.
128
142
  workflowLeaf: {
129
- profile: "cost-optimized",
130
143
  effort: "low",
131
144
  thinking: { enabled: false },
132
145
  },