@vellumai/assistant 0.9.0 → 0.10.0-dev.202606192226.8ed8a6a

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 (624) hide show
  1. package/ARCHITECTURE.md +19 -35
  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 +1128 -119
  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__/agent-loop-pushes-post-hook-prompt.test.ts +306 -0
  28. package/src/__tests__/always-loaded-tools-guard.test.ts +2 -3
  29. package/src/__tests__/app-compiler.test.ts +15 -1
  30. package/src/__tests__/app-dir-path-guard.test.ts +0 -1
  31. package/src/__tests__/approval-cascade.test.ts +6 -0
  32. package/src/__tests__/approval-routes-http.test.ts +128 -0
  33. package/src/__tests__/assistant-feature-flag-guard.test.ts +1 -4
  34. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +0 -2
  35. package/src/__tests__/auth-fallback-events-store.test.ts +6 -14
  36. package/src/__tests__/avatar-identity-sync.test.ts +2 -27
  37. package/src/__tests__/btw-routes.test.ts +6 -8
  38. package/src/__tests__/call-pointer-messages.test.ts +28 -0
  39. package/src/__tests__/cancel-clears-processing.test.ts +89 -0
  40. package/src/__tests__/channel-approval-routes.test.ts +0 -4
  41. package/src/__tests__/channel-inbound-disk-pressure.test.ts +5 -15
  42. package/src/__tests__/checker.test.ts +0 -3
  43. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +3 -4
  44. package/src/__tests__/compaction-events.test.ts +6 -0
  45. package/src/__tests__/compactor-image-manifest-trust.test.ts +21 -1
  46. package/src/__tests__/compactor-summary-call-truncation.test.ts +223 -0
  47. package/src/__tests__/config-loader-backfill.test.ts +268 -27
  48. package/src/__tests__/config-schema.test.ts +35 -0
  49. package/src/__tests__/config-watcher.test.ts +0 -18
  50. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +2 -2
  51. package/src/__tests__/contact-store-user-file.test.ts +0 -6
  52. package/src/__tests__/contacts-tools.test.ts +29 -0
  53. package/src/__tests__/conversation-abort-tool-results.test.ts +6 -0
  54. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +22 -0
  55. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
  56. package/src/__tests__/conversation-agent-loop.test.ts +58 -0
  57. package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
  58. package/src/__tests__/conversation-confirmation-signals.test.ts +6 -0
  59. package/src/__tests__/conversation-lifecycle.test.ts +7 -9
  60. package/src/__tests__/conversation-load-history-repair.test.ts +101 -0
  61. package/src/__tests__/conversation-process-callsite.test.ts +6 -0
  62. package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
  63. package/src/__tests__/conversation-queue.test.ts +6 -0
  64. package/src/__tests__/conversation-routes-guardian-reply.test.ts +15 -12
  65. package/src/__tests__/conversation-slash-queue.test.ts +6 -0
  66. package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
  67. package/src/__tests__/conversation-speed-override.test.ts +6 -0
  68. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +6 -3
  69. package/src/__tests__/conversation-title-service.test.ts +62 -0
  70. package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -0
  71. package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
  72. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -0
  73. package/src/__tests__/credential-broker.test.ts +449 -1
  74. package/src/__tests__/credential-execution-shell-lockdown.test.ts +18 -11
  75. package/src/__tests__/credential-execution-tools.test.ts +0 -1
  76. package/src/__tests__/credential-prompt-route.test.ts +4 -4
  77. package/src/__tests__/credential-routes.test.ts +360 -0
  78. package/src/__tests__/credential-security-invariants.test.ts +4 -13
  79. package/src/__tests__/disk-pressure-policy.test.ts +12 -0
  80. package/src/__tests__/disk-pressure-tools.test.ts +41 -1
  81. package/src/__tests__/disk-usage.test.ts +65 -0
  82. package/src/__tests__/document-tool-security.test.ts +9 -6
  83. package/src/__tests__/document-update-default-surface.test.ts +202 -0
  84. package/src/__tests__/dynamic-page-surface.test.ts +152 -1
  85. package/src/__tests__/fixtures/credential-security-fixtures.ts +2 -33
  86. package/src/__tests__/gateway-flag-listener.test.ts +110 -1
  87. package/src/__tests__/gateway-only-guard.test.ts +3 -7
  88. package/src/__tests__/gemini-count-tokens.test.ts +70 -0
  89. package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
  90. package/src/__tests__/guardian-card-withdrawal.test.ts +403 -0
  91. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +5 -3
  92. package/src/__tests__/guardian-grant-minting.test.ts +3 -35
  93. package/src/__tests__/guardian-routing-invariants.test.ts +64 -26
  94. package/src/__tests__/guardian-routing-state.test.ts +0 -1
  95. package/src/__tests__/headless-browser-mode.test.ts +10 -0
  96. package/src/__tests__/headless-browser-navigate.test.ts +8 -3
  97. package/src/__tests__/helpers/create-guardian-binding.ts +0 -1
  98. package/src/__tests__/host-browser-proxy.test.ts +87 -0
  99. package/src/__tests__/identity-routes.test.ts +0 -189
  100. package/src/__tests__/inbound-invite-redemption.test.ts +4 -4
  101. package/src/__tests__/injector-disk-pressure.test.ts +10 -5
  102. package/src/__tests__/injector-v3-suppression.test.ts +27 -20
  103. package/src/__tests__/internal-telemetry-routes.test.ts +6 -14
  104. package/src/__tests__/invite-redemption-service.test.ts +4 -7
  105. package/src/__tests__/llm-callsite-catalog.test.ts +5 -6
  106. package/src/__tests__/llm-catalog-parity.test.ts +30 -23
  107. package/src/__tests__/llm-resolver.test.ts +70 -24
  108. package/src/__tests__/llm-schema.test.ts +1 -0
  109. package/src/__tests__/managed-profile-guard.test.ts +163 -4
  110. package/src/__tests__/mcp-health-check.test.ts +6 -7
  111. package/src/__tests__/media-stream-server-integration.test.ts +317 -13
  112. package/src/__tests__/oauth-provider-seed-logos.test.ts +4 -6
  113. package/src/__tests__/onboarding-persona-write.test.ts +1 -1
  114. package/src/__tests__/path-policy.test.ts +34 -0
  115. package/src/__tests__/persona-resolver.test.ts +49 -14
  116. package/src/__tests__/plugin-api-model-profiles.test.ts +178 -0
  117. package/src/__tests__/plugin-api-provider.test.ts +24 -0
  118. package/src/__tests__/plugin-tool-contribution.test.ts +6 -3
  119. package/src/__tests__/post-compaction-reinjection-idempotency.test.ts +214 -0
  120. package/src/__tests__/provider-send-message-override-profile.test.ts +76 -0
  121. package/src/__tests__/reaction-persistence.test.ts +150 -29
  122. package/src/__tests__/registry.test.ts +2 -7
  123. package/src/__tests__/relay-server.test.ts +285 -0
  124. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
  125. package/src/__tests__/schedule-routes-workflow-validation.test.ts +1 -10
  126. package/src/__tests__/schedule-routes.test.ts +0 -30
  127. package/src/__tests__/schedule-tools.test.ts +2 -18
  128. package/src/__tests__/scheduler-reuse-conversation.test.ts +8 -5
  129. package/src/__tests__/secret-response-routing.test.ts +35 -0
  130. package/src/__tests__/secret-routes-platform-proxy.test.ts +16 -2
  131. package/src/__tests__/skill-execute-input.test.ts +177 -1
  132. package/src/__tests__/skill-load-tool.test.ts +72 -0
  133. package/src/__tests__/skill-runtime-path.test.ts +2 -3
  134. package/src/__tests__/skills.test.ts +51 -0
  135. package/src/__tests__/slack-notification-approval-card.test.ts +176 -0
  136. package/src/__tests__/slack-reaction-canonical-approval.test.ts +285 -0
  137. package/src/__tests__/subagent-tools.test.ts +266 -0
  138. package/src/__tests__/surface-completion-nudge-hook.test.ts +367 -0
  139. package/src/__tests__/system-storage-cleanup-skill.test.ts +56 -0
  140. package/src/__tests__/task-progress-nudge-hook.test.ts +1 -1
  141. package/src/__tests__/title-generate-hook.test.ts +100 -3
  142. package/src/__tests__/token-estimator-accuracy.benchmark.test.ts +1 -29
  143. package/src/__tests__/token-manager.test.ts +519 -0
  144. package/src/__tests__/tool-approval-seed-content-blocks.test.ts +1 -1
  145. package/src/__tests__/tool-audit-listener.test.ts +7 -7
  146. package/src/__tests__/tool-executor-lifecycle-events.test.ts +6 -3
  147. package/src/__tests__/tool-executor.test.ts +0 -79
  148. package/src/__tests__/trusted-contact-approval-notifier.test.ts +4 -2
  149. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +220 -3
  150. package/src/__tests__/trusted-contact-multichannel.test.ts +3 -3
  151. package/src/__tests__/trusted-contact-verification.test.ts +8 -10
  152. package/src/__tests__/twilio-routes.test.ts +81 -1
  153. package/src/__tests__/voice-invite-redemption.test.ts +2 -3
  154. package/src/__tests__/weak-open-model.test.ts +30 -0
  155. package/src/__tests__/web-search-catalog-parity.test.ts +6 -25
  156. package/src/__tests__/workspace-greetings.test.ts +152 -0
  157. package/src/__tests__/workspace-migration-105-enable-memory-v3-live-for-new-workspaces.test.ts +149 -0
  158. package/src/__tests__/workspace-migration-108-drop-balanced-economy-profile.test.ts +285 -0
  159. package/src/__tests__/workspace-migration-add-send-diagnostics.test.ts +1 -1
  160. package/src/__tests__/workspace-migration-drop-collect-usage-data.test.ts +118 -0
  161. package/src/__tests__/workspace-migration-drop-send-diagnostics.test.ts +118 -0
  162. package/src/a2a/__tests__/e2e-a2a-channel.test.ts +0 -4
  163. package/src/agent/loop.ts +75 -29
  164. package/src/api/README.md +6 -6
  165. package/src/api/events/tool-result.ts +6 -0
  166. package/src/api/events/workflow-completed.ts +53 -0
  167. package/src/api/events/workflow-leaf-finished.ts +38 -0
  168. package/src/api/events/workflow-leaf-started.ts +35 -0
  169. package/src/api/events/workflow-progress.ts +32 -0
  170. package/src/api/events/workflow-started.ts +31 -0
  171. package/src/api/index.ts +40 -0
  172. package/src/api/responses/conversation-message.ts +28 -4
  173. package/src/api/responses/home.ts +26 -4
  174. package/src/api/responses/workflow-journal.ts +53 -0
  175. package/src/approvals/guardian-card-withdrawal.ts +145 -0
  176. package/src/approvals/guardian-decision-primitive.ts +26 -3
  177. package/src/approvals/guardian-request-resolvers.ts +183 -80
  178. package/src/calls/__tests__/channel-admission-reader.test.ts +132 -0
  179. package/src/calls/__tests__/relay-setup-router.test.ts +350 -0
  180. package/src/calls/call-pointer-messages.ts +10 -4
  181. package/src/calls/channel-admission-reader.ts +104 -0
  182. package/src/calls/guardian-dispatch.ts +17 -45
  183. package/src/calls/media-stream-server.ts +84 -2
  184. package/src/calls/relay-access-wait.ts +1 -1
  185. package/src/calls/relay-server.ts +66 -0
  186. package/src/calls/relay-setup-router.ts +82 -1
  187. package/src/calls/twilio-routes.ts +17 -8
  188. package/src/calls/voice-session-bridge.ts +2 -2
  189. package/src/cli/commands/clients.ts +3 -0
  190. package/src/cli/commands/db/status.ts +37 -3
  191. package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2-compare-render.test.ts +1 -1
  192. package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2.test.ts +8 -7
  193. package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v3.test.ts +5 -4
  194. package/src/cli/commands/memory/index.ts +30 -0
  195. package/src/cli/commands/{memory-v2-compare-render.ts → memory/memory-v2-compare-render.ts} +1 -1
  196. package/src/cli/commands/{memory-v2.ts → memory/memory-v2.ts} +6 -15
  197. package/src/cli/commands/{memory-v3.ts → memory/memory-v3.ts} +97 -11
  198. package/src/cli/commands/oauth/status.test.ts +36 -0
  199. package/src/cli/commands/oauth/status.ts +23 -3
  200. package/src/cli/commands/plugins.ts +400 -14
  201. package/src/cli/lib/__tests__/diff-plugin.test.ts +443 -0
  202. package/src/cli/lib/__tests__/inspect-plugin.test.ts +54 -0
  203. package/src/cli/lib/__tests__/install-from-github.test.ts +31 -0
  204. package/src/cli/lib/__tests__/merge-plugin-tree.test.ts +443 -0
  205. package/src/cli/lib/__tests__/plugin-pin-history.test.ts +162 -0
  206. package/src/cli/lib/__tests__/plugin-surfaces.test.ts +111 -0
  207. package/src/cli/lib/__tests__/upgrade-plugin.test.ts +295 -2
  208. package/src/cli/lib/diff-plugin.ts +346 -0
  209. package/src/cli/lib/inspect-plugin.ts +12 -1
  210. package/src/cli/lib/install-from-github.ts +128 -19
  211. package/src/cli/lib/merge-plugin-tree.ts +328 -0
  212. package/src/cli/lib/plugin-fingerprint.ts +14 -0
  213. package/src/cli/lib/plugin-marketplace.ts +11 -0
  214. package/src/cli/lib/plugin-pin-history.ts +257 -0
  215. package/src/cli/lib/plugin-surfaces.ts +104 -0
  216. package/src/cli/lib/upgrade-plugin.ts +298 -10
  217. package/src/cli/program.ts +2 -6
  218. package/src/config/__tests__/sync-gated-profiles.test.ts +368 -0
  219. package/src/config/assistant-feature-flags.ts +22 -7
  220. package/src/config/bundled-skills/contacts/tools/contact-search.ts +0 -1
  221. package/src/config/bundled-skills/document-editor/SKILL.md +3 -3
  222. package/src/config/bundled-skills/document-editor/TOOLS.json +2 -2
  223. package/src/config/bundled-skills/messaging/SKILL.md +6 -4
  224. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +9 -8
  225. package/src/config/bundled-skills/subagent/SKILL.md +4 -0
  226. package/src/config/bundled-skills/subagent/TOOLS.json +4 -0
  227. package/src/config/bundled-skills/system-storage-cleanup/SKILL.md +74 -0
  228. package/src/config/bundled-skills/workflows/SKILL.md +14 -8
  229. package/src/config/bundled-tool-registry.ts +2 -7
  230. package/src/config/call-site-defaults.ts +15 -2
  231. package/src/config/feature-flag-registry.json +46 -31
  232. package/src/config/inference-profile-validation.ts +26 -0
  233. package/src/config/llm-resolver.ts +3 -0
  234. package/src/config/loader.ts +4 -0
  235. package/src/config/memory-v3-gate.ts +11 -0
  236. package/src/config/profile-order.ts +28 -0
  237. package/src/config/schema.ts +8 -6
  238. package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
  239. package/src/config/schemas/call-site-catalog.ts +7 -0
  240. package/src/config/schemas/channels.ts +11 -0
  241. package/src/config/schemas/elevenlabs.ts +0 -1
  242. package/src/config/schemas/llm.ts +31 -0
  243. package/src/config/schemas/memory-lifecycle.ts +3 -7
  244. package/src/config/schemas/memory-v3.ts +6 -0
  245. package/src/config/schemas/platform.ts +0 -8
  246. package/src/config/schemas/services.ts +18 -0
  247. package/src/config/seed-inference-profiles.ts +109 -44
  248. package/src/config/skills.ts +21 -0
  249. package/src/config/sync-gated-profiles.ts +220 -0
  250. package/src/contacts/contact-store.ts +89 -106
  251. package/src/contacts/contacts-write.ts +5 -22
  252. package/src/contacts/types.ts +0 -1
  253. package/src/context/compactor.ts +88 -54
  254. package/src/context/strip-injections.ts +58 -10
  255. package/src/context/token-estimator.ts +1 -1
  256. package/src/credential-execution/process-manager.ts +55 -14
  257. package/src/credential-execution/prompted-credential.ts +2 -3
  258. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -2
  259. package/src/daemon/__tests__/conversation-tool-setup.test.ts +44 -0
  260. package/src/daemon/config-watcher.ts +0 -4
  261. package/src/daemon/conversation-agent-loop-handlers.ts +2 -0
  262. package/src/daemon/conversation-agent-loop.ts +114 -22
  263. package/src/daemon/conversation-history.ts +1 -1
  264. package/src/daemon/conversation-lifecycle.ts +3 -5
  265. package/src/daemon/conversation-process.ts +13 -5
  266. package/src/daemon/conversation-runtime-assembly.ts +13 -15
  267. package/src/daemon/conversation-slash.ts +2 -23
  268. package/src/daemon/conversation-surfaces.ts +26 -0
  269. package/src/daemon/conversation-tool-setup.ts +53 -19
  270. package/src/daemon/conversation.ts +131 -20
  271. package/src/daemon/disk-pressure-policy.ts +5 -3
  272. package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +0 -1
  273. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -1
  274. package/src/daemon/handlers/config-a2a.ts +0 -2
  275. package/src/daemon/handlers/config-channels.ts +15 -16
  276. package/src/daemon/handlers/config-slack-channel.ts +22 -3
  277. package/src/daemon/handlers/conversations.ts +107 -0
  278. package/src/daemon/host-browser-proxy.ts +41 -0
  279. package/src/daemon/lifecycle.ts +55 -27
  280. package/src/daemon/memory-v2-startup.test.ts +131 -0
  281. package/src/daemon/memory-v2-startup.ts +100 -1
  282. package/src/daemon/message-provenance.ts +2 -0
  283. package/src/daemon/message-types/contacts.ts +0 -1
  284. package/src/daemon/message-types/conversations.ts +3 -3
  285. package/src/daemon/message-types/sync.ts +0 -1
  286. package/src/daemon/message-types/web-activity.ts +7 -1
  287. package/src/daemon/message-types/workflows.ts +83 -1
  288. package/src/daemon/orphan-reaper.test.ts +0 -19
  289. package/src/daemon/orphan-reaper.ts +2 -24
  290. package/src/daemon/server.ts +0 -10
  291. package/src/daemon/tool-setup-types.ts +4 -0
  292. package/src/daemon/trust-context.ts +1 -1
  293. package/src/daemon/wake-conversation-ops.ts +1 -0
  294. package/src/events/tool-audit-listener.ts +2 -2
  295. package/src/home/feed-source-enrichment.test.ts +151 -0
  296. package/src/home/feed-source-enrichment.ts +176 -0
  297. package/src/home/relationship-state.ts +2 -4
  298. package/src/instrument.ts +18 -6
  299. package/src/ipc/__tests__/binary-result-ipc.test.ts +81 -0
  300. package/src/ipc/__tests__/clients-list-ipc.test.ts +20 -0
  301. package/src/ipc/assistant-server.ts +37 -4
  302. package/src/ipc/gateway-flag-listener.ts +18 -2
  303. package/src/memory/__tests__/auto-analysis-enqueue.test.ts +5 -16
  304. package/src/memory/__tests__/db-logs-attach.test.ts +122 -0
  305. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +7 -11
  306. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +37 -7
  307. package/src/memory/__tests__/memory-retrospective-job.test.ts +229 -401
  308. package/src/memory/__tests__/onboarding-events-store.test.ts +7 -7
  309. package/src/memory/auth-fallback-events-store.ts +2 -2
  310. package/src/memory/auto-analysis-enqueue.ts +3 -5
  311. package/src/memory/bookmark-crud.ts +1 -2
  312. package/src/memory/canonical-guardian-store.ts +39 -1
  313. package/src/memory/conversation-crud.ts +9 -4
  314. package/src/memory/conversation-key-store.ts +17 -2
  315. package/src/memory/conversation-title-service.ts +64 -7
  316. package/src/memory/db-async-query.ts +20 -2
  317. package/src/memory/db-connection.ts +49 -5
  318. package/src/memory/db-init.ts +17 -17
  319. package/src/memory/embedding-backend.ts +38 -1
  320. package/src/memory/embedding-billing-breaker.ts +96 -0
  321. package/src/memory/jobs-store.ts +25 -13
  322. package/src/memory/jobs-worker.ts +54 -1
  323. package/src/memory/lifecycle-events-store.ts +2 -2
  324. package/src/memory/memory-retrospective-constants.ts +4 -4
  325. package/src/memory/memory-retrospective-enqueue.ts +31 -6
  326. package/src/memory/memory-retrospective-job.ts +28 -227
  327. package/src/memory/migrations/129-contact-channels-access-fields.ts +18 -9
  328. package/src/memory/migrations/131-drop-legacy-member-guardian-tables.ts +14 -2
  329. package/src/memory/migrations/289-contact-channels-unique-ext-user.ts +10 -0
  330. package/src/memory/migrations/291-contact-channels-renormalize-addresses.ts +72 -0
  331. package/src/memory/migrations/292-schedule-default-no-reuse-conversation.test.ts +67 -0
  332. package/src/memory/migrations/292-schedule-default-no-reuse-conversation.ts +25 -0
  333. package/src/memory/migrations/293-workflow-journal-leaf-tokens.ts +32 -0
  334. package/src/memory/migrations/294-drop-external-user-id.ts +31 -0
  335. package/src/memory/migrations/295-drop-approval-prompt-ts-tracker.ts +20 -0
  336. package/src/memory/migrations/296-rewrite-balanced-economy-profile-pins.test.ts +110 -0
  337. package/src/memory/migrations/296-rewrite-balanced-economy-profile-pins.ts +68 -0
  338. package/src/memory/migrations/__tests__/131-drop-legacy-member-guardian-tables.test.ts +154 -0
  339. package/src/memory/migrations/__tests__/289-contact-channels-unique-ext-user.test.ts +31 -0
  340. package/src/memory/migrations/__tests__/291-contact-channels-renormalize-addresses.test.ts +341 -0
  341. package/src/memory/migrations/__tests__/run-migrations.test.ts +52 -0
  342. package/src/memory/migrations/index.ts +6 -0
  343. package/src/memory/migrations/run-migrations.ts +41 -0
  344. package/src/memory/migrations/validate-migration-state.ts +1 -1
  345. package/src/memory/onboarding-events-store.ts +3 -3
  346. package/src/memory/schema/contacts.ts +0 -5
  347. package/src/memory/skill-loaded-events-store.test.ts +7 -15
  348. package/src/memory/skill-loaded-events-store.ts +2 -2
  349. package/src/memory/tool-executed-events-store.test.ts +7 -7
  350. package/src/memory/turn-trace-store.test.ts +736 -0
  351. package/src/memory/turn-trace-store.ts +364 -0
  352. package/src/memory/v2/__tests__/consolidation-job.test.ts +8 -0
  353. package/src/memory/v2/__tests__/skill-content.test.ts +30 -0
  354. package/src/memory/v2/consolidation-job.ts +2 -2
  355. package/src/memory/v2/skill-content.ts +25 -7
  356. package/src/memory/v2/skill-store.ts +7 -1
  357. package/src/memory/v3-eval/__tests__/eval-packets.test.ts +248 -0
  358. package/src/memory/v3-eval/eval-packets.ts +546 -0
  359. package/src/messaging/providers/slack/adapter.ts +1 -1
  360. package/src/messaging/providers/slack/api.ts +31 -0
  361. package/src/messaging/providers/slack/send.test.ts +114 -2
  362. package/src/messaging/providers/slack/send.ts +30 -7
  363. package/src/messaging/providers/slack/withdraw.test.ts +200 -0
  364. package/src/messaging/providers/slack/withdraw.ts +161 -0
  365. package/src/notifications/AGENTS.md +2 -0
  366. package/src/notifications/access-request-copy.ts +72 -59
  367. package/src/notifications/adapters/shared.ts +29 -0
  368. package/src/notifications/adapters/slack.ts +58 -103
  369. package/src/notifications/adapters/telegram.ts +2 -20
  370. package/src/notifications/approval-card-data.ts +333 -0
  371. package/src/notifications/broadcaster.ts +16 -3
  372. package/src/notifications/canonical-delivery-recorder.ts +139 -0
  373. package/src/notifications/copy-composer.ts +3 -3
  374. package/src/notifications/decision-engine.ts +4 -2
  375. package/src/notifications/destination-resolver.ts +4 -6
  376. package/src/notifications/guardian-question-mode.ts +10 -0
  377. package/src/notifications/home-feed-side-effect.ts +7 -16
  378. package/src/notifications/notification-utils.ts +19 -20
  379. package/src/notifications/signal.ts +79 -43
  380. package/src/notifications/types.ts +98 -121
  381. package/src/oauth/AGENTS.md +5 -24
  382. package/src/permissions/checker.test.ts +51 -0
  383. package/src/permissions/checker.ts +185 -26
  384. package/src/permissions/ipc-risk-types.ts +24 -0
  385. package/src/permissions/question-prompter.test.ts +27 -0
  386. package/src/permissions/question-prompter.ts +4 -0
  387. package/src/permissions/secret-prompter.ts +15 -1
  388. package/src/platform/client.test.ts +119 -0
  389. package/src/platform/client.ts +66 -0
  390. package/src/platform/consent-cache.test.ts +267 -0
  391. package/src/platform/consent-cache.ts +174 -0
  392. package/src/plugin-api/constants.ts +1 -1
  393. package/src/plugin-api/index.ts +33 -1
  394. package/src/plugin-api/model-profiles.ts +33 -0
  395. package/src/plugin-api/types.ts +50 -2
  396. package/src/plugins/defaults/advisor/__tests__/advisor-gate.test.ts +56 -0
  397. package/src/plugins/defaults/advisor/__tests__/advisor-state-store.test.ts +43 -0
  398. package/src/plugins/defaults/advisor/__tests__/agent-loop-integration.test.ts +137 -0
  399. package/src/plugins/defaults/advisor/__tests__/consult.test.ts +153 -0
  400. package/src/plugins/defaults/advisor/__tests__/hooks.test.ts +138 -0
  401. package/src/plugins/defaults/advisor/__tests__/transcript.test.ts +147 -0
  402. package/src/plugins/defaults/advisor/advisor-gate.ts +29 -0
  403. package/src/plugins/defaults/advisor/advisor-state-store.ts +94 -0
  404. package/src/plugins/defaults/advisor/config.ts +21 -0
  405. package/src/plugins/defaults/advisor/consult.ts +93 -0
  406. package/src/plugins/defaults/advisor/hooks/post-model-call.ts +34 -0
  407. package/src/plugins/defaults/advisor/hooks/pre-model-call.ts +30 -0
  408. package/src/plugins/defaults/advisor/hooks/user-prompt-submit.ts +19 -0
  409. package/src/plugins/defaults/advisor/package.json +14 -0
  410. package/src/plugins/defaults/advisor/steering.ts +67 -0
  411. package/src/plugins/defaults/advisor/tools/advisor.ts +65 -0
  412. package/src/plugins/defaults/advisor/transcript.ts +76 -0
  413. package/src/plugins/defaults/compaction/window-manager.ts +18 -0
  414. package/src/plugins/defaults/index.ts +60 -0
  415. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +22 -9
  416. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +2 -2
  417. package/src/plugins/defaults/memory-retrieval/injectors.ts +4 -4
  418. package/src/plugins/defaults/memory-retrieval/tail-reinjection-strip.ts +64 -0
  419. package/src/plugins/defaults/memory-retrieval/unified-turn-context.ts +29 -21
  420. package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +1 -0
  421. package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +1 -0
  422. package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +129 -9
  423. package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +31 -4
  424. package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +77 -2
  425. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +1 -0
  426. package/src/plugins/defaults/memory-v3-shadow/injector.ts +7 -10
  427. package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +144 -11
  428. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +32 -20
  429. package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +56 -3
  430. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +23 -2
  431. package/src/plugins/defaults/surface-completion-nudge/hooks/post-model-call.ts +276 -0
  432. package/src/plugins/defaults/surface-completion-nudge/hooks/stop.ts +22 -0
  433. package/src/plugins/defaults/surface-completion-nudge/nudge-state-store.ts +46 -0
  434. package/src/plugins/defaults/surface-completion-nudge/package.json +14 -0
  435. package/src/plugins/defaults/task-progress-nudge/hooks/post-tool-use.ts +3 -13
  436. package/src/plugins/defaults/title-generate/hooks/stop.ts +56 -21
  437. package/src/prompts/persona-resolver.ts +14 -4
  438. package/src/prompts/templates/system-sections.ts +7 -2
  439. package/src/providers/__tests__/count-tokens-forwarding.test.ts +98 -0
  440. package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
  441. package/src/providers/__tests__/provider-secret-catalog.test.ts +1 -0
  442. package/src/providers/__tests__/retry-callsite.test.ts +176 -0
  443. package/src/providers/anthropic/client.ts +230 -175
  444. package/src/providers/atlascloud/client.ts +85 -0
  445. package/src/providers/call-site-routing.ts +10 -0
  446. package/src/providers/fetch-provider-catalog.ts +85 -0
  447. package/src/providers/gemini/client.ts +43 -0
  448. package/src/providers/inference/adapter-factory.ts +3 -0
  449. package/src/providers/model-catalog.ts +58 -0
  450. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +33 -0
  451. package/src/providers/openai/chat-completions-provider.ts +7 -0
  452. package/src/providers/openai/responses-provider.ts +10 -0
  453. package/src/providers/provider-send-message.ts +11 -3
  454. package/src/providers/ratelimit.ts +9 -0
  455. package/src/providers/retry.ts +62 -12
  456. package/src/providers/search-provider-catalog.ts +10 -0
  457. package/src/providers/types.ts +16 -0
  458. package/src/providers/usage-tracking.ts +7 -0
  459. package/src/providers/weak-open-model.ts +22 -0
  460. package/src/runtime/AGENTS.md +0 -1
  461. package/src/runtime/__tests__/agent-wake.test.ts +227 -0
  462. package/src/runtime/__tests__/client-health.test.ts +44 -0
  463. package/src/runtime/access-request-helper.ts +21 -53
  464. package/src/runtime/actor-trust-resolver.ts +59 -63
  465. package/src/runtime/agent-wake.ts +71 -0
  466. package/src/runtime/assistant-event-hub.ts +18 -4
  467. package/src/runtime/auth/__tests__/route-policy.test.ts +12 -0
  468. package/src/runtime/auth/require-bound-guardian.ts +1 -4
  469. package/src/runtime/btw-sidechain.ts +3 -6
  470. package/src/runtime/capabilities.test.ts +120 -0
  471. package/src/runtime/capabilities.ts +197 -0
  472. package/src/runtime/channel-approval-types.ts +22 -45
  473. package/src/runtime/channel-invite-transports/telegram.ts +4 -4
  474. package/src/runtime/channel-retry-sweep.ts +1 -0
  475. package/src/runtime/channel-verification-service.ts +3 -3
  476. package/src/runtime/client-health.ts +26 -0
  477. package/src/runtime/confirmation-request-guardian-bridge.ts +38 -29
  478. package/src/runtime/effective-capabilities.test.ts +128 -0
  479. package/src/runtime/effective-capabilities.ts +84 -0
  480. package/src/runtime/guardian-reply-router.ts +106 -21
  481. package/src/runtime/invite-redemption-service.ts +9 -25
  482. package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +126 -0
  483. package/src/runtime/migrations/vbundle-builder.ts +49 -20
  484. package/src/runtime/pending-interactions.ts +35 -0
  485. package/src/runtime/routes/__tests__/client-routes.test.ts +13 -0
  486. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +67 -0
  487. package/src/runtime/routes/__tests__/plugins-routes.test.ts +383 -1
  488. package/src/runtime/routes/app-routes.ts +1 -1
  489. package/src/runtime/routes/approval-routes.ts +40 -9
  490. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +2 -2
  491. package/src/runtime/routes/assets/vellum-design-system.css +1959 -0
  492. package/src/runtime/routes/browser-tabs-routes.ts +9 -0
  493. package/src/runtime/routes/btw-routes.ts +1 -27
  494. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +17 -8
  495. package/src/runtime/routes/client-routes.ts +10 -0
  496. package/src/runtime/routes/contact-routes.ts +31 -8
  497. package/src/runtime/routes/conversation-compaction-routes.ts +1 -1
  498. package/src/runtime/routes/conversation-management-routes.ts +80 -1
  499. package/src/runtime/routes/conversation-query-routes.ts +68 -22
  500. package/src/runtime/routes/conversation-routes.ts +39 -14
  501. package/src/runtime/routes/credential-routes.ts +40 -16
  502. package/src/runtime/routes/empty-state-greeting-cache.ts +1 -2
  503. package/src/runtime/routes/events-routes.ts +1 -3
  504. package/src/runtime/routes/guardian-approval-interception.ts +14 -73
  505. package/src/runtime/routes/guardian-approval-prompt.ts +22 -4
  506. package/src/runtime/routes/home-feed-routes.ts +8 -3
  507. package/src/runtime/routes/identity-routes.ts +1 -296
  508. package/src/runtime/routes/inbound-message-handler.ts +214 -228
  509. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +89 -7
  510. package/src/runtime/routes/inbound-stages/admission-policy.test.ts +154 -0
  511. package/src/runtime/routes/inbound-stages/admission-policy.ts +140 -0
  512. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +3 -3
  513. package/src/runtime/routes/inbound-stages/background-dispatch.ts +11 -6
  514. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +1 -2
  515. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +1 -2
  516. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +7 -7
  517. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +47 -28
  518. package/src/runtime/routes/inbound-stages/reaction-intercept.ts +358 -0
  519. package/src/runtime/routes/index.ts +2 -0
  520. package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +8 -0
  521. package/src/runtime/routes/integrations/slack/channel.ts +36 -0
  522. package/src/runtime/routes/internal-telemetry-routes.ts +1 -1
  523. package/src/runtime/routes/mcp-auth-routes.ts +233 -41
  524. package/src/runtime/routes/memory-eval-routes.ts +87 -0
  525. package/src/runtime/routes/notification-routes.ts +122 -133
  526. package/src/runtime/routes/platform-routes.ts +2 -2
  527. package/src/runtime/routes/plugins-routes.ts +366 -11
  528. package/src/runtime/routes/schedule-routes.ts +0 -22
  529. package/src/runtime/routes/secret-routes.ts +15 -0
  530. package/src/runtime/routes/surface-action-routes.ts +2 -1
  531. package/src/runtime/routes/tool-call-question-enrichment.test.ts +146 -0
  532. package/src/runtime/routes/tool-call-question-enrichment.ts +66 -0
  533. package/src/runtime/routes/workflow-routes.test.ts +229 -44
  534. package/src/runtime/routes/workflow-routes.ts +131 -29
  535. package/src/runtime/routes/workspace-greetings.ts +55 -0
  536. package/src/runtime/sync/resource-sync-events.ts +1 -11
  537. package/src/runtime/tool-grant-request-helper.ts +18 -16
  538. package/src/runtime/trust-context-resolver.ts +8 -5
  539. package/src/schedule/inference-profile.ts +2 -14
  540. package/src/schedule/schedule-store.ts +1 -1
  541. package/src/schedule/scheduler-types.ts +5 -1
  542. package/src/security/__tests__/provider-key-env-fallback.test.ts +6 -0
  543. package/src/security/secret-patterns.ts +3 -0
  544. package/src/subagent/manager.ts +17 -4
  545. package/src/subagent/types.ts +6 -0
  546. package/src/telemetry/trace-collection-policy.test.ts +28 -0
  547. package/src/telemetry/trace-collection-policy.ts +30 -0
  548. package/src/telemetry/types.ts +89 -0
  549. package/src/telemetry/usage-telemetry-reporter.test.ts +586 -36
  550. package/src/telemetry/usage-telemetry-reporter.ts +148 -41
  551. package/src/tools/AGENTS.md +3 -3
  552. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +31 -0
  553. package/src/tools/browser/browser-execution.ts +30 -19
  554. package/src/tools/document/document-tool.ts +30 -6
  555. package/src/tools/executor.ts +5 -3
  556. package/src/tools/host-terminal/host-shell.ts +5 -4
  557. package/src/tools/memory/register.ts +2 -2
  558. package/src/tools/network/__tests__/web-fetch-firecrawl.test.ts +360 -0
  559. package/src/tools/network/__tests__/web-search.test.ts +143 -0
  560. package/src/tools/network/web-fetch.ts +372 -1
  561. package/src/tools/network/web-search-error.ts +1 -1
  562. package/src/tools/network/web-search.ts +213 -10
  563. package/src/tools/permission-checker.ts +4 -3
  564. package/src/tools/registry.ts +20 -0
  565. package/src/tools/schedule/create.ts +7 -12
  566. package/src/tools/schedule/update.ts +4 -11
  567. package/src/tools/shared/filesystem/path-policy.ts +39 -13
  568. package/src/tools/side-effects.ts +2 -17
  569. package/src/tools/skills/execute.ts +99 -2
  570. package/src/tools/skills/load.ts +43 -2
  571. package/src/tools/subagent/spawn.ts +64 -15
  572. package/src/tools/terminal/shell.ts +10 -4
  573. package/src/tools/tool-approval-handler.ts +18 -13
  574. package/src/tools/tool-manifest.ts +0 -2
  575. package/src/tools/types.ts +10 -0
  576. package/src/tools/ui-surface/definitions.ts +64 -3
  577. package/src/tools/verification-control-plane-policy.ts +3 -1
  578. package/src/tools/workflows/run-workflow.test.ts +8 -18
  579. package/src/tools/workflows/run-workflow.ts +1 -0
  580. package/src/util/disk-usage.ts +78 -23
  581. package/src/util/logs-db-path.ts +22 -0
  582. package/src/util/platform.ts +10 -3
  583. package/src/watcher/telemetry.ts +2 -2
  584. package/src/workflows/capabilities.ts +2 -3
  585. package/src/workflows/engine.test.ts +175 -1
  586. package/src/workflows/engine.ts +82 -0
  587. package/src/workflows/journal-store.test.ts +70 -0
  588. package/src/workflows/journal-store.ts +18 -3
  589. package/src/workflows/run-manager.test.ts +171 -28
  590. package/src/workflows/run-manager.ts +66 -24
  591. package/src/workspace/migrations/105-enable-memory-v3-live-for-new-workspaces.ts +63 -0
  592. package/src/workspace/migrations/106-drop-collect-usage-data.ts +47 -0
  593. package/src/workspace/migrations/107-drop-send-diagnostics.ts +47 -0
  594. package/src/workspace/migrations/108-drop-balanced-economy-profile.ts +129 -0
  595. package/src/workspace/migrations/registry.ts +8 -0
  596. package/src/__tests__/app-control-no-global-cgevent.test.ts +0 -98
  597. package/src/__tests__/credential-security-e2e.test.ts +0 -362
  598. package/src/__tests__/credential-vault-unit.test.ts +0 -1528
  599. package/src/__tests__/credential-vault.test.ts +0 -1706
  600. package/src/__tests__/identity-intro-cache.test.ts +0 -315
  601. package/src/__tests__/secret-onetime-send.test.ts +0 -182
  602. package/src/cli/commands/__tests__/task.test.ts +0 -914
  603. package/src/cli/commands/task.ts +0 -771
  604. package/src/config/bundled-skills/personal-page/SKILL.md +0 -57
  605. package/src/config/bundled-skills/personal-page/TOOLS.json +0 -27
  606. package/src/config/bundled-skills/personal-page/tools/app-refresh.ts +0 -17
  607. package/src/config/preloaded-apps/personal-page/src/components/About.tsx +0 -22
  608. package/src/config/preloaded-apps/personal-page/src/components/App.tsx +0 -16
  609. package/src/config/preloaded-apps/personal-page/src/components/Features.tsx +0 -77
  610. package/src/config/preloaded-apps/personal-page/src/components/Hero.tsx +0 -57
  611. package/src/config/preloaded-apps/personal-page/src/components/Pending.tsx +0 -28
  612. package/src/config/preloaded-apps/personal-page/src/components/animations.tsx +0 -234
  613. package/src/config/preloaded-apps/personal-page/src/components/icons.tsx +0 -48
  614. package/src/config/preloaded-apps/personal-page/src/components/media.ts +0 -16
  615. package/src/config/preloaded-apps/personal-page/src/index.html +0 -20
  616. package/src/config/preloaded-apps/personal-page/src/main.tsx +0 -7
  617. package/src/config/preloaded-apps/personal-page/src/profile-data.ts +0 -82
  618. package/src/config/preloaded-apps/personal-page/src/styles.css +0 -759
  619. package/src/memory/__tests__/preloaded-apps.test.ts +0 -85
  620. package/src/memory/preloaded-apps.ts +0 -116
  621. package/src/notifications/tool-approval-copy.ts +0 -142
  622. package/src/runtime/routes/approval-prompt-ts-tracker.ts +0 -78
  623. package/src/runtime/routes/identity-intro-cache.ts +0 -172
  624. package/src/tools/credentials/vault.ts +0 -712
@@ -1,14 +1,14 @@
1
1
  /**
2
- * Verifies that the `memory-v3-live` cache-anchor signal surfaces on every
3
- * `SendMessageOptions.config` the loop emits. When the flag is on, the latest
2
+ * Verifies that the memory-v3-live cache-anchor signal surfaces on every
3
+ * `SendMessageOptions.config` the loop emits. When v3-live is on, the latest
4
4
  * user message carries a volatile `<memory>` block, so the loop sets
5
5
  * `providerConfig.mutableLatestUserMessage` to tell the provider to anchor its
6
6
  * long-TTL cache breakpoint on the most recent STABLE message instead.
7
7
  *
8
- * The loop reads the flag directly where it assembles `providerConfig`, so the
9
- * signal is sourced from the flag rather than a run option. When the flag is
10
- * off the field is omitted (not `false`/`undefined`) so the wire stays
11
- * byte-identical to today.
8
+ * The loop reads `config.memory.v3.live` directly where it assembles
9
+ * `providerConfig`, so the signal is sourced from config rather than a run
10
+ * option. When v3-live is off the field is omitted (not `false`/`undefined`) so
11
+ * the wire stays byte-identical to today.
12
12
  */
13
13
 
14
14
  import { afterEach, describe, expect, mock, test } from "bun:test";
@@ -19,11 +19,14 @@ mock.module("../util/logger.js", () => ({
19
19
  getLogger: () => makeMockLogger(),
20
20
  }));
21
21
 
22
+ // AgentLoop reads the v3-live gate (`config.memory.v3.live`) via
23
+ // `isMemoryV3Live` to decide the cache-anchor signal; drive it per-test.
24
+ let memoryV3LiveSlot = false;
25
+ mock.module("../config/memory-v3-gate.js", () => ({
26
+ isMemoryV3Live: () => memoryV3LiveSlot,
27
+ }));
28
+
22
29
  import { AgentLoop } from "../agent/loop.js";
23
- import {
24
- clearCachedOverrides,
25
- setCachedOverrides,
26
- } from "../config/feature-flag-cache.js";
27
30
  import type {
28
31
  Message,
29
32
  Provider,
@@ -82,12 +85,12 @@ function makeRecordingProvider(responses: ProviderResponse[]): {
82
85
 
83
86
  describe("AgentLoop.run — mutableLatestUserMessage from memory-v3-live", () => {
84
87
  afterEach(() => {
85
- clearCachedOverrides();
88
+ memoryV3LiveSlot = false;
86
89
  });
87
90
 
88
91
  test("sets mutableLatestUserMessage on every LLM call when memory-v3-live is on (multi-turn)", async () => {
89
92
  // GIVEN memory-v3-live is enabled
90
- setCachedOverrides({ "memory-v3-live": true }, { fromGateway: true });
93
+ memoryV3LiveSlot = true;
91
94
 
92
95
  // AND a provider that records the config of each LLM call across a tool round-trip
93
96
  const { provider, configs } = makeRecordingProvider([
@@ -131,7 +134,7 @@ describe("AgentLoop.run — mutableLatestUserMessage from memory-v3-live", () =>
131
134
 
132
135
  test("omits mutableLatestUserMessage when memory-v3-live is off (flag-off byte-identity)", async () => {
133
136
  // GIVEN memory-v3-live is off (no override; registry default is false)
134
- clearCachedOverrides();
137
+ memoryV3LiveSlot = false;
135
138
 
136
139
  // AND a provider that records the config of each LLM call
137
140
  const { provider, configs } = makeRecordingProvider([textResponse("hi")]);
@@ -365,6 +365,75 @@ describe("agent loop output hooks", () => {
365
365
  expect(calls[0].systemPrompt).toContain("[EDITED]");
366
366
  });
367
367
 
368
+ test("pre-model-call routes the call to the hook's chosen inference profile", async () => {
369
+ // GIVEN a hook that selects an inference profile for the user-facing call
370
+ registerOutputHookPlugin({
371
+ preModelCall: (ctx) => {
372
+ if (ctx.callSite !== "mainAgent") return;
373
+ ctx.modelProfile = "fast-profile";
374
+ },
375
+ });
376
+ const { provider, calls } = createMockProvider([textResponse("hi")]);
377
+ const loop = new AgentLoop({
378
+ provider: provider,
379
+ systemPrompt: "system",
380
+ conversationId: "test-conversation",
381
+ });
382
+
383
+ // WHEN the loop issues the user-facing provider call
384
+ await loop.run({
385
+ requestId: "test-request",
386
+ messages: [userMessage],
387
+ onEvent: collect([]),
388
+ callSite: "mainAgent",
389
+ trust: { sourceChannel: "vellum", trustClass: "unknown" },
390
+ });
391
+
392
+ // THEN the provider call carries the hook's profile as the override
393
+ expect(calls[0].options?.config?.overrideProfile).toBe("fast-profile");
394
+ });
395
+
396
+ test("pre-model-call seeds modelProfile from the resolved override and clearing it drops the override", async () => {
397
+ // GIVEN a hook that observes the seeded override and then clears it
398
+ let seeded: string | null | undefined;
399
+ registerOutputHookPlugin({
400
+ preModelCall: (ctx) => {
401
+ seeded = ctx.modelProfile;
402
+ ctx.modelProfile = null;
403
+ },
404
+ });
405
+ const { provider, calls } = createMockProvider([textResponse("hi")]);
406
+ const loop = new AgentLoop({
407
+ provider: provider,
408
+ systemPrompt: "system",
409
+ conversationId: "test-conversation",
410
+ });
411
+
412
+ // WHEN the loop runs with an ad-hoc override profile
413
+ await loop.run({
414
+ requestId: "test-request",
415
+ messages: [userMessage],
416
+ onEvent: collect([]),
417
+ callSite: "mainAgent",
418
+ overrideProfile: "seed-profile",
419
+ trust: { sourceChannel: "vellum", trustClass: "unknown" },
420
+ });
421
+
422
+ // THEN the hook saw the loop's resolved override
423
+ expect(seeded).toBe("seed-profile");
424
+ // AND clearing it sends no override on the provider call
425
+ expect(calls[0].options?.config?.overrideProfile).toBeUndefined();
426
+ });
427
+
428
+ // Context-window sizing and overflow recovery read the profile resolved
429
+ // before the hook runs, so a hook routing to a smaller-window profile does
430
+ // not resize the budget gate for that call. Tracked for a follow-up that
431
+ // resolves the routed profile ahead of the context-sizing gate.
432
+ test.todo(
433
+ "pre-model-call routing resizes the context-window budget for the routed profile",
434
+ () => {},
435
+ );
436
+
368
437
  test("fail-open: a hook that mutates in place AND then throws cannot corrupt the persisted content", async () => {
369
438
  // The hook mutates the array it receives before throwing. If the loop
370
439
  // handed the hook the real `assistantMessage.content` array, the
@@ -195,6 +195,7 @@ interface CapturedRunAgentLoopOptions {
195
195
  titleText?: string;
196
196
  callSite?: string;
197
197
  overrideProfile?: string;
198
+ forceOverrideProfile?: boolean;
198
199
  }
199
200
 
200
201
  const capturedRunAgentLoopOptions: CapturedRunAgentLoopOptions[] = [];
@@ -323,6 +324,29 @@ describe("SubagentManager.spawn — overrideProfile inheritance", () => {
323
324
  const captured = capturedRunAgentLoopOptions[0];
324
325
  expect(captured.callSite).toBe("subagentSpawn");
325
326
  expect(captured.overrideProfile).toBe("fast");
327
+ expect("forceOverrideProfile" in captured).toBe(false);
328
+ });
329
+
330
+ test("forwards forced overrideProfile from SubagentConfig into runAgentLoop", async () => {
331
+ capturedRunAgentLoopOptions.length = 0;
332
+
333
+ const manager = new SubagentManager();
334
+ await manager.spawn(
335
+ {
336
+ parentConversationId: "parent-forced",
337
+ label: "child",
338
+ objective: "do the thing",
339
+ overrideProfile: "fast",
340
+ forceOverrideProfile: true,
341
+ },
342
+ () => {},
343
+ );
344
+
345
+ expect(capturedRunAgentLoopOptions).toHaveLength(1);
346
+ const captured = capturedRunAgentLoopOptions[0];
347
+ expect(captured.callSite).toBe("subagentSpawn");
348
+ expect(captured.overrideProfile).toBe("fast");
349
+ expect(captured.forceOverrideProfile).toBe(true);
326
350
  });
327
351
 
328
352
  test("omits overrideProfile when SubagentConfig does not set it", async () => {
@@ -344,6 +368,7 @@ describe("SubagentManager.spawn — overrideProfile inheritance", () => {
344
368
  // Field must be absent rather than carrying `undefined`, mirroring the
345
369
  // agent loop's "field omitted when unset" contract.
346
370
  expect("overrideProfile" in captured).toBe(false);
371
+ expect("forceOverrideProfile" in captured).toBe(false);
347
372
  });
348
373
  });
349
374
 
@@ -0,0 +1,306 @@
1
+ /**
2
+ * Tests for the `system_prompt_changed` event emitted by AgentLoop when the
3
+ * `pre-model-call` hook chain mutates the system prompt.
4
+ *
5
+ * The event fires whenever the post-hook `systemPrompt` differs from the
6
+ * value the loop handed the hook (compared against `providerOptions.systemPrompt`,
7
+ * not the context object — which the hook may mutate in place).
8
+ */
9
+
10
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
11
+
12
+ // ── Stub pipes ──────────────────────────────────────────────────────
13
+ // Same logger-stub shape as the rest of the test suite — pino pulls are
14
+ // agent-loop-time too, but we silence them so the test stays deterministic.
15
+ mock.module("../util/logger.js", () => ({
16
+ getLogger: () =>
17
+ new Proxy({} as Record<string, unknown>, { get: () => () => {} }),
18
+ }));
19
+
20
+ // Mock plugin pipeline. Two modes:
21
+ // - return mode (default): returns `hookResponse` as the hook result.
22
+ // - in-place mode: mutates ctx.systemPrompt directly and returns the same
23
+ // object, simulating a hook that edits the context without returning a
24
+ // new value — the scenario that requires comparing against
25
+ // providerOptions.systemPrompt, not preModelCtx.systemPrompt.
26
+ type PreModelCallCtx = {
27
+ conversationId: string;
28
+ callSite: string | null;
29
+ systemPrompt: string | null;
30
+ modelProfile: string | null;
31
+ deferAssistantOutput: boolean;
32
+ logger: unknown;
33
+ };
34
+ let hookResponse: PreModelCallCtx = {
35
+ conversationId: "test-conv",
36
+ callSite: "mainAgent",
37
+ systemPrompt:
38
+ "BASELINE-PROMPT\n\n<!-- advisor:steering -->\nAPPENDED-FROM-HOOK",
39
+ modelProfile: null,
40
+ deferAssistantOutput: false,
41
+ logger: {},
42
+ };
43
+ let hookMutatesInPlace = false;
44
+ mock.module("../plugins/pipeline.js", () => ({
45
+ runHook: async (
46
+ _hook: unknown,
47
+ ctx: PreModelCallCtx,
48
+ ): Promise<PreModelCallCtx> => {
49
+ if (hookMutatesInPlace) {
50
+ ctx.systemPrompt = hookResponse.systemPrompt;
51
+ return ctx;
52
+ }
53
+ return hookResponse;
54
+ },
55
+ }));
56
+
57
+ // Minimal `getConfig` so the loop's defaults/loader path doesn't trip.
58
+ let mockLlmConfig: Record<string, unknown> = {};
59
+ mock.module("../config/loader.js", () => ({
60
+ getConfig: () => ({ llm: mockLlmConfig }),
61
+ }));
62
+
63
+ import type { AgentEvent } from "../agent/loop.js";
64
+ import { AgentLoop } from "../agent/loop.js";
65
+ import { LLMSchema } from "../config/schemas/llm.js";
66
+ import type { TrustContext } from "../daemon/trust-context.js";
67
+ import type {
68
+ Message,
69
+ Provider,
70
+ ProviderResponse,
71
+ SendMessageOptions,
72
+ } from "../providers/types.js";
73
+
74
+ const userMessage: Message = {
75
+ role: "user",
76
+ content: [{ type: "text", text: "hi" }],
77
+ };
78
+
79
+ const trust: TrustContext = {
80
+ sourceChannel: "vellum",
81
+ trustClass: "guardian",
82
+ };
83
+
84
+ function setLlmConfig(raw: unknown): void {
85
+ mockLlmConfig = LLMSchema.parse(raw) as Record<string, unknown>;
86
+ }
87
+
88
+ beforeEach(() => {
89
+ mockLlmConfig = LLMSchema.parse({}) as Record<string, unknown>;
90
+ hookMutatesInPlace = false;
91
+ hookResponse = {
92
+ conversationId: "test-conv",
93
+ callSite: "mainAgent",
94
+ systemPrompt:
95
+ "BASELINE-PROMPT\n\n<!-- advisor:steering -->\nAPPENDED-FROM-HOOK",
96
+ modelProfile: null,
97
+ deferAssistantOutput: false,
98
+ logger: {},
99
+ };
100
+ });
101
+
102
+ /**
103
+ * Provider that records the system prompt it sees on every send and short-
104
+ * circuits the turn after one call. We don't need streaming for verifying
105
+ * prompt pushback.
106
+ */
107
+ function makeRecordingProvider(): {
108
+ provider: Provider;
109
+ capturedSystemPrompts: () => string[];
110
+ } {
111
+ const captured: string[] = [];
112
+ let callCount = 0;
113
+ const provider: Provider = {
114
+ name: "anthropic",
115
+ async sendMessage(
116
+ _messages: Message[],
117
+ options?: SendMessageOptions,
118
+ ): Promise<ProviderResponse> {
119
+ if (options?.systemPrompt !== undefined) {
120
+ captured.push(options.systemPrompt);
121
+ }
122
+ callCount += 1;
123
+ return {
124
+ content: [{ type: "text", text: callCount === 1 ? "done" : "..." }],
125
+ model: "mock-model",
126
+ usage: { inputTokens: 1, outputTokens: 1 },
127
+ stopReason: "end_turn",
128
+ };
129
+ },
130
+ };
131
+ return { provider, capturedSystemPrompts: () => captured };
132
+ }
133
+
134
+ describe("AgentLoop system_prompt_changed event", () => {
135
+ test("fires when the hook mutates the prompt on mainAgent", async () => {
136
+ setLlmConfig({
137
+ default: { provider: "anthropic", model: "mock-model" },
138
+ });
139
+
140
+ const mutatedPrompt = "BASELINE\n\n<!-- advisor:steering -->";
141
+ hookResponse = {
142
+ conversationId: "test-conv",
143
+ callSite: "mainAgent",
144
+ systemPrompt: mutatedPrompt,
145
+ modelProfile: null,
146
+ deferAssistantOutput: false,
147
+ logger: {},
148
+ };
149
+
150
+ const { provider } = makeRecordingProvider();
151
+ const events: AgentEvent[] = [];
152
+
153
+ const loop = new AgentLoop({
154
+ provider,
155
+ systemPrompt: "BASELINE",
156
+ config: {},
157
+ conversationId: "test-conv",
158
+ });
159
+
160
+ await loop.run({
161
+ requestId: "test-request",
162
+ messages: [userMessage],
163
+ onEvent: (e) => {
164
+ events.push(e);
165
+ },
166
+ trust,
167
+ callSite: "mainAgent",
168
+ });
169
+
170
+ const changedEvents = events.filter(
171
+ (e) => e.type === "system_prompt_changed",
172
+ );
173
+ expect(changedEvents).toHaveLength(1);
174
+ expect(changedEvents[0].systemPrompt).toBe(mutatedPrompt);
175
+ });
176
+
177
+ test("fires on non-mainAgent call sites too", async () => {
178
+ setLlmConfig({
179
+ default: { provider: "anthropic", model: "mock-model" },
180
+ });
181
+
182
+ hookResponse = {
183
+ conversationId: "test-conv",
184
+ callSite: "subagentSpawn",
185
+ systemPrompt: "MUTATED-BY-HOOK",
186
+ modelProfile: null,
187
+ deferAssistantOutput: false,
188
+ logger: {},
189
+ };
190
+
191
+ const { provider } = makeRecordingProvider();
192
+ const events: AgentEvent[] = [];
193
+
194
+ const loop = new AgentLoop({
195
+ provider,
196
+ systemPrompt: "BASELINE",
197
+ config: {},
198
+ conversationId: "test-conv",
199
+ });
200
+
201
+ await loop.run({
202
+ requestId: "test-request",
203
+ messages: [userMessage],
204
+ onEvent: (e) => {
205
+ events.push(e);
206
+ },
207
+ trust,
208
+ callSite: "subagentSpawn",
209
+ });
210
+
211
+ const changedEvents = events.filter(
212
+ (e) => e.type === "system_prompt_changed",
213
+ );
214
+ expect(changedEvents).toHaveLength(1);
215
+ expect(changedEvents[0].systemPrompt).toBe("MUTATED-BY-HOOK");
216
+ });
217
+
218
+ test("does not fire when hook returns the same prompt", async () => {
219
+ setLlmConfig({
220
+ default: { provider: "anthropic", model: "mock-model" },
221
+ });
222
+
223
+ hookResponse = {
224
+ conversationId: "test-conv",
225
+ callSite: "mainAgent",
226
+ systemPrompt: "SAME-PROMPT",
227
+ modelProfile: null,
228
+ deferAssistantOutput: false,
229
+ logger: {},
230
+ };
231
+
232
+ const { provider } = makeRecordingProvider();
233
+ const events: AgentEvent[] = [];
234
+
235
+ const loop = new AgentLoop({
236
+ provider,
237
+ systemPrompt: "SAME-PROMPT",
238
+ config: {},
239
+ conversationId: "test-conv",
240
+ });
241
+
242
+ await loop.run({
243
+ requestId: "test-request",
244
+ messages: [userMessage],
245
+ onEvent: (e) => {
246
+ events.push(e);
247
+ },
248
+ trust,
249
+ callSite: "mainAgent",
250
+ });
251
+
252
+ const changedEvents = events.filter(
253
+ (e) => e.type === "system_prompt_changed",
254
+ );
255
+ expect(changedEvents).toHaveLength(0);
256
+ });
257
+
258
+ test("fires when the hook mutates ctx.systemPrompt in place", async () => {
259
+ setLlmConfig({
260
+ default: { provider: "anthropic", model: "mock-model" },
261
+ });
262
+
263
+ // In-place mode: the mock mutates ctx.systemPrompt directly and
264
+ // returns the same object reference. The old comparison against
265
+ // preModelCtx.systemPrompt would miss this because preModelCtx IS
266
+ // the mutated object. Comparing against providerOptions.systemPrompt
267
+ // (captured pre-hook) catches it.
268
+ hookMutatesInPlace = true;
269
+ hookResponse = {
270
+ conversationId: "test-conv",
271
+ callSite: "mainAgent",
272
+ systemPrompt: "BASELINE\n\n<!-- advisor:steering -->",
273
+ modelProfile: null,
274
+ deferAssistantOutput: false,
275
+ logger: {},
276
+ };
277
+
278
+ const { provider } = makeRecordingProvider();
279
+ const events: AgentEvent[] = [];
280
+
281
+ const loop = new AgentLoop({
282
+ provider,
283
+ systemPrompt: "BASELINE",
284
+ config: {},
285
+ conversationId: "test-conv",
286
+ });
287
+
288
+ await loop.run({
289
+ requestId: "test-request",
290
+ messages: [userMessage],
291
+ onEvent: (e) => {
292
+ events.push(e);
293
+ },
294
+ trust,
295
+ callSite: "mainAgent",
296
+ });
297
+
298
+ const changedEvents = events.filter(
299
+ (e) => e.type === "system_prompt_changed",
300
+ );
301
+ expect(changedEvents).toHaveLength(1);
302
+ expect(changedEvents[0].systemPrompt).toBe(
303
+ "BASELINE\n\n<!-- advisor:steering -->",
304
+ );
305
+ });
306
+ });
@@ -28,7 +28,7 @@ afterAll(() => {
28
28
  });
29
29
 
30
30
  describe("always-loaded tool count", () => {
31
- test("should be exactly 11 with recall occupying the existing slot", async () => {
31
+ test("should be exactly 10 with recall occupying the existing slot", async () => {
32
32
  await initializeTools();
33
33
  const allDefs = getAllToolDefinitions();
34
34
 
@@ -52,7 +52,6 @@ describe("always-loaded tool count", () => {
52
52
  // path would allow unchecked host command execution.
53
53
  const expectedNames = [
54
54
  "bash",
55
- "credential_store",
56
55
  "file_edit",
57
56
  "file_read",
58
57
  "file_write",
@@ -66,6 +65,6 @@ describe("always-loaded tool count", () => {
66
65
 
67
66
  expect(activeNames).toEqual(expectedNames);
68
67
  expect(activeNames.filter((name) => name === "recall")).toHaveLength(1);
69
- expect(activeTools.length).toBe(11);
68
+ expect(activeTools.length).toBe(10);
70
69
  });
71
70
  });
@@ -2,9 +2,17 @@ import { existsSync } from "node:fs";
2
2
  import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
- import { afterAll, beforeAll, describe, expect, test } from "bun:test";
5
+ import {
6
+ afterAll,
7
+ beforeAll,
8
+ describe,
9
+ expect,
10
+ setDefaultTimeout,
11
+ test,
12
+ } from "bun:test";
6
13
 
7
14
  import { compileApp } from "../bundler/app-compiler.js";
15
+ import { ensureCompilerTools } from "../bundler/compiler-tools.js";
8
16
  import {
9
17
  ALLOWED_PACKAGES,
10
18
  getCacheDir,
@@ -19,8 +27,14 @@ import {
19
27
 
20
28
  let tempDir: string;
21
29
 
30
+ // Compiler-tool download (esbuild + preact from npm) can take 10s+ on a cold
31
+ // CI cache. Raise the file-level default so beforeAll isn't killed mid-install.
32
+ // Each test file runs in its own process, so this doesn't leak.
33
+ setDefaultTimeout(30_000);
34
+
22
35
  beforeAll(async () => {
23
36
  tempDir = await mkdtemp(join(tmpdir(), "app-compiler-test-"));
37
+ await ensureCompilerTools();
24
38
  });
25
39
 
26
40
  afterAll(async () => {
@@ -20,7 +20,6 @@ const ALLOWLIST = new Set([
20
20
  "assistant/src/memory/app-git-service.ts", // uses getAppsDir for git repo root, not per-app paths
21
21
  "assistant/src/daemon/app-source-watcher.ts", // uses getAppsDir for recursive fs.watch root, not per-app paths
22
22
  "assistant/src/tools/filesystem/write.ts", // uses getAppsDir as an exemption root for the artifact-HTML guard, not per-app paths
23
- "assistant/src/memory/preloaded-apps.ts", // seeds fixed-slug apps (id === dirName by construction) and writes the definition JSON, which app-store has no fixed-id helper for
24
23
  ]);
25
24
 
26
25
  function isTestFile(filePath: string): boolean {
@@ -170,6 +170,12 @@ mock.module("../memory/retriever.js", () => ({
170
170
 
171
171
  mock.module("../plugins/defaults/compaction/window-manager.js", () => ({
172
172
  ContextWindowManager: class {
173
+ estimateInputTokens() {
174
+ return 0;
175
+ }
176
+ get tokenCountInputs() {
177
+ return { systemPrompt: "", tools: undefined };
178
+ }
173
179
  constructor() {}
174
180
  updateConfig() {}
175
181
  shouldCompact() {