@vellumai/assistant 0.11.4 → 0.11.5-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 (367) hide show
  1. package/AGENTS.md +2 -2
  2. package/ARCHITECTURE.md +29 -4
  3. package/README.md +1 -1
  4. package/docs/architecture/memory.md +17 -5
  5. package/docs/architecture/security.md +96 -152
  6. package/docs/guardian-request-flow.md +13 -2
  7. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +1 -0
  8. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/url-normalization.test.ts +135 -0
  9. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  10. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -0
  11. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +1 -0
  12. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/url-normalization.test.ts +135 -0
  13. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  14. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -0
  15. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +166 -1
  16. package/node_modules/@vellumai/gateway-client/src/http-delivery.ts +7 -14
  17. package/node_modules/@vellumai/gateway-client/src/index.ts +2 -0
  18. package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +29 -31
  19. package/node_modules/@vellumai/service-contracts/package.json +1 -0
  20. package/node_modules/@vellumai/service-contracts/src/__tests__/url-normalization.test.ts +135 -0
  21. package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  22. package/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -0
  23. package/openapi.yaml +193 -3
  24. package/package.json +1 -1
  25. package/src/__tests__/anthropic-provider.test.ts +10 -3
  26. package/src/__tests__/approval-interception-trust-gates.test.ts +40 -0
  27. package/src/__tests__/background-workers-disk-pressure.test.ts +1 -1
  28. package/src/__tests__/channel-approval-routes.test.ts +4 -0
  29. package/src/__tests__/channel-inbound-disk-pressure.test.ts +5 -6
  30. package/src/__tests__/channel-reply-delivery.test.ts +26 -13
  31. package/src/__tests__/checker.test.ts +20 -314
  32. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +6 -2
  33. package/src/__tests__/client-os-metadata-persistence.test.ts +16 -0
  34. package/src/__tests__/compactor-retained-image-validation.test.ts +142 -0
  35. package/src/__tests__/config-loader-backfill.test.ts +19 -10
  36. package/src/__tests__/container-cpu-sampler.test.ts +153 -0
  37. package/src/__tests__/context-search-memory-v2-source.test.ts +0 -1
  38. package/src/__tests__/conversation-attachments.test.ts +0 -1
  39. package/src/__tests__/conversation-error.test.ts +17 -0
  40. package/src/__tests__/conversation-lifecycle.test.ts +20 -26
  41. package/src/__tests__/conversation-pairing.test.ts +186 -0
  42. package/src/__tests__/conversation-runtime-assembly.test.ts +21 -2
  43. package/src/__tests__/credential-broker-server-use.test.ts +24 -5
  44. package/src/__tests__/credential-routes.test.ts +22 -3
  45. package/src/__tests__/credential-security-invariants.test.ts +2 -1
  46. package/src/__tests__/daemon-credential-client.test.ts +88 -0
  47. package/src/__tests__/default-plugin-names-guard.test.ts +12 -1
  48. package/src/__tests__/dm-backfill.test.ts +63 -0
  49. package/src/__tests__/dynamic-skill-background-guard.test.ts +0 -2
  50. package/src/__tests__/edit-propagation.test.ts +107 -4
  51. package/src/__tests__/events-client-registration.test.ts +28 -0
  52. package/src/__tests__/file-write-tool.test.ts +4 -2
  53. package/src/__tests__/guardian-prompt-notice-privacy.test.ts +133 -0
  54. package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +143 -97
  55. package/src/__tests__/helpers/gateway-classify-mock.ts +27 -6
  56. package/src/__tests__/host-proxy-interface.test.ts +11 -1
  57. package/src/__tests__/host-shell-tool.test.ts +23 -4
  58. package/src/__tests__/image-conversion.test.ts +143 -1
  59. package/src/__tests__/inline-skill-load-permissions.test.ts +47 -36
  60. package/src/__tests__/input-repairs.test.ts +207 -0
  61. package/src/__tests__/live-workspace-guard.test.ts +75 -0
  62. package/src/__tests__/managed-profile-guard.test.ts +4 -2
  63. package/src/__tests__/mcp-abort-signal.test.ts +1 -1
  64. package/src/__tests__/mcp-client-auth.test.ts +1 -1
  65. package/src/__tests__/mcp-tool-annotations-risk.test.ts +1 -1
  66. package/src/__tests__/media-resolve-image-validation.test.ts +310 -0
  67. package/src/__tests__/mtime-cache.test.ts +2 -0
  68. package/src/__tests__/notification-vellum-adapter.test.ts +124 -1
  69. package/src/__tests__/openai-provider.test.ts +22 -0
  70. package/src/__tests__/personal-memory-auth-bypass.test.ts +22 -6
  71. package/src/__tests__/platform-bash-auto-approve.test.ts +0 -4
  72. package/src/__tests__/platform.test.ts +16 -1
  73. package/src/__tests__/plugin-api-resolve-credential.test.ts +22 -13
  74. package/src/__tests__/plugin-api-shim.test.ts +5 -0
  75. package/src/__tests__/plugin-api-store-credential.test.ts +268 -0
  76. package/src/__tests__/plugin-config-data-migration.test.ts +8 -1
  77. package/src/__tests__/plugin-disabled-state.test.ts +2 -0
  78. package/src/__tests__/plugin-effective-enabled-set.test.ts +55 -3
  79. package/src/__tests__/plugin-execution-context.test.ts +73 -0
  80. package/src/__tests__/plugin-import-boundary-guard.test.ts +0 -1
  81. package/src/__tests__/plugin-import-boundary-reverse-guard.test.ts +0 -1
  82. package/src/__tests__/reaction-persistence.test.ts +200 -7
  83. package/src/__tests__/require-fresh-approval.test.ts +0 -4
  84. package/src/__tests__/resource-pressure-guard.test.ts +428 -0
  85. package/src/__tests__/resource-pressure-routes.test.ts +113 -0
  86. package/src/__tests__/risk-classification-boundary-guard.test.ts +115 -0
  87. package/src/__tests__/run-conversation-turn-persistence.test.ts +27 -1
  88. package/src/__tests__/secret-routes-platform-proxy.test.ts +7 -0
  89. package/src/__tests__/skill-tool-factory.test.ts +161 -0
  90. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -1
  91. package/src/__tests__/tool-executor-lifecycle-events.test.ts +132 -5
  92. package/src/__tests__/tool-executor.test.ts +63 -38
  93. package/src/__tests__/tool-policy.test.ts +97 -1
  94. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +7 -4
  95. package/src/__tests__/user-plugin-loader.test.ts +2 -0
  96. package/src/__tests__/validate-input.test.ts +243 -7
  97. package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
  98. package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -0
  99. package/src/__tests__/voice-session-bridge.test.ts +42 -0
  100. package/src/acp/__tests__/acp-claude-oauth.test.ts +97 -29
  101. package/src/acp/__tests__/prepare-agent-env.test.ts +376 -153
  102. package/src/acp/acp-claude-oauth.ts +38 -21
  103. package/src/acp/prepare-agent-env.ts +146 -55
  104. package/src/agent/loop-tool-dedup.test.ts +161 -0
  105. package/src/agent/loop.ts +68 -22
  106. package/src/api/constants/app-tools.ts +34 -0
  107. package/src/api/events/resource-pressure-status-changed.ts +53 -0
  108. package/src/api/index.ts +19 -0
  109. package/src/api/responses/resource-pressure-status.ts +25 -0
  110. package/src/approvals/guardian-channel-delivery.ts +70 -6
  111. package/src/approvals/guardian-request-resolvers.ts +32 -66
  112. package/src/calls/__tests__/voice-session-bridge.test.ts +114 -0
  113. package/src/calls/voice-session-bridge.ts +60 -6
  114. package/src/channels/__tests__/message-audience.test.ts +49 -0
  115. package/src/channels/__tests__/types.test.ts +17 -3
  116. package/src/channels/message-audience.ts +40 -0
  117. package/src/channels/types.ts +16 -12
  118. package/src/cli/__tests__/catalog-search-help.test.ts +50 -0
  119. package/src/cli/commands/__tests__/channel-verification-sessions.test.ts +31 -0
  120. package/src/cli/commands/__tests__/conversations-search.test.ts +289 -0
  121. package/src/cli/commands/__tests__/conversations-slack.test.ts +1 -0
  122. package/src/cli/commands/__tests__/inference-providers.test.ts +68 -0
  123. package/src/cli/commands/__tests__/keys.test.ts +89 -8
  124. package/src/cli/commands/__tests__/plugins.test.ts +57 -1
  125. package/src/cli/commands/channel-verification-sessions.help.ts +11 -9
  126. package/src/cli/commands/channel-verification-sessions.ts +11 -21
  127. package/src/cli/commands/conversations.help.ts +34 -0
  128. package/src/cli/commands/conversations.ts +125 -0
  129. package/src/cli/commands/inference-providers.ts +9 -4
  130. package/src/cli/commands/inference.help.ts +9 -4
  131. package/src/cli/commands/keys.help.ts +13 -1
  132. package/src/cli/commands/keys.ts +26 -15
  133. package/src/cli/commands/memory/__tests__/memory-v2.test.ts +57 -7
  134. package/src/cli/commands/memory/index.help.ts +41 -27
  135. package/src/cli/commands/memory/index.ts +2 -0
  136. package/src/cli/commands/memory/memory-v2.ts +58 -54
  137. package/src/cli/commands/memory/memory-validate.ts +18 -0
  138. package/src/cli/commands/monitoring.ts +1 -0
  139. package/src/cli/commands/plugins.help.ts +28 -31
  140. package/src/cli/commands/plugins.ts +10 -0
  141. package/src/cli/commands/skills.help.ts +13 -16
  142. package/src/cli/commands/trust.ts +3 -14
  143. package/src/cli/lib/__tests__/install-from-github.test.ts +38 -0
  144. package/src/cli/lib/__tests__/merge-plugin-tree.test.ts +34 -0
  145. package/src/cli/lib/__tests__/plugin-surfaces.test.ts +32 -1
  146. package/src/cli/lib/__tests__/toggle-plugin.test.ts +2 -1
  147. package/src/cli/lib/__tests__/upgrade-plugin.test.ts +64 -0
  148. package/src/cli/lib/bundled-marketplace.json +13 -0
  149. package/src/cli/lib/daemon-credential-client.ts +25 -3
  150. package/src/cli/lib/install-from-github.ts +35 -24
  151. package/src/cli/lib/merge-plugin-tree.ts +22 -4
  152. package/src/cli/lib/plugin-surfaces.ts +27 -0
  153. package/src/config/__tests__/balanced-model-experiment.test.ts +7 -7
  154. package/src/config/__tests__/default-profile-catalog.test.ts +3 -3
  155. package/src/config/default-profile-catalog.ts +5 -6
  156. package/src/config/feature-flag-registry.json +32 -32
  157. package/src/config/webhook-routing.ts +8 -0
  158. package/src/context/compactor.ts +31 -2
  159. package/src/daemon/__tests__/provider-rejection-log-fields.test.ts +272 -0
  160. package/src/daemon/conversation-agent-loop-handlers.ts +4 -1
  161. package/src/daemon/conversation-error.ts +13 -0
  162. package/src/daemon/conversation-messaging.ts +22 -2
  163. package/src/daemon/conversation-process.ts +11 -0
  164. package/src/daemon/conversation-store.ts +10 -0
  165. package/src/daemon/conversation-surfaces.ts +21 -8
  166. package/src/daemon/conversation.ts +12 -10
  167. package/src/daemon/lifecycle.ts +6 -2
  168. package/src/daemon/message-types/conversations.ts +5 -7
  169. package/src/daemon/provider-rejection-log-fields.ts +124 -0
  170. package/src/daemon/resource-pressure-guard-lifecycle.ts +66 -0
  171. package/src/daemon/resource-pressure-guard.ts +387 -0
  172. package/src/daemon/shutdown-handlers.ts +2 -0
  173. package/src/daemon/startup-error.ts +16 -0
  174. package/src/daemon/trust-context.ts +14 -10
  175. package/src/daemon/unsendable-image-notice.ts +76 -0
  176. package/src/hooks/registry.ts +65 -51
  177. package/src/ipc/__tests__/socket-path.test.ts +15 -7
  178. package/src/ipc/gateway-client.test.ts +1 -1
  179. package/src/ipc/gateway-client.ts +14 -21
  180. package/src/ipc/socket-cleanup.ts +2 -11
  181. package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +1 -1
  182. package/src/messaging/provider-message-metadata.ts +128 -0
  183. package/src/messaging/providers/__tests__/transport-dispatch.test.ts +116 -68
  184. package/src/messaging/providers/channel-transport.ts +90 -13
  185. package/src/messaging/providers/discord/send.ts +16 -0
  186. package/src/messaging/providers/discord/transport.ts +11 -1
  187. package/src/messaging/providers/index.ts +109 -16
  188. package/src/messaging/providers/slack/message-metadata.ts +45 -0
  189. package/src/messaging/providers/slack/render-transcript.ts +1 -4
  190. package/src/messaging/providers/slack/send.test.ts +6 -9
  191. package/src/messaging/providers/slack/send.ts +40 -28
  192. package/src/messaging/providers/slack/transport.ts +22 -26
  193. package/src/messaging/providers/telegram-bot/send.test.ts +2 -8
  194. package/src/messaging/providers/telegram-bot/transport.ts +3 -6
  195. package/src/messaging/read-provider-metadata.test.ts +157 -0
  196. package/src/messaging/read-provider-metadata.ts +51 -0
  197. package/src/notifications/__tests__/assistant-reply-producer.test.ts +94 -0
  198. package/src/notifications/__tests__/edit-notification.test.ts +174 -2
  199. package/src/notifications/__tests__/home-feed-side-effect.test.ts +536 -4
  200. package/src/notifications/adapters/macos.ts +55 -0
  201. package/src/notifications/adapters/slack.ts +10 -5
  202. package/src/notifications/assistant-reply-producer.ts +37 -4
  203. package/src/notifications/conversation-pairing.ts +111 -21
  204. package/src/notifications/edit-notification.ts +38 -8
  205. package/src/notifications/emit-signal.ts +12 -14
  206. package/src/notifications/home-feed-side-effect.ts +218 -15
  207. package/src/notifications/types.ts +5 -0
  208. package/src/permissions/AGENTS.md +16 -0
  209. package/src/permissions/checker.test.ts +75 -122
  210. package/src/permissions/checker.ts +44 -560
  211. package/src/permissions/confirmation-guardian-request.test.ts +28 -3
  212. package/src/permissions/confirmation-guardian-request.ts +5 -1
  213. package/src/persistence/conversation-crud.ts +23 -20
  214. package/src/persistence/conversation-queries.ts +14 -1
  215. package/src/persistence/conversation-types.ts +22 -0
  216. package/src/persistence/delivery-crud.ts +122 -15
  217. package/src/plugin-api/__tests__/import-graph-partial-mock.test.ts +67 -0
  218. package/src/plugin-api/conversation-turn.ts +27 -0
  219. package/src/plugin-api/credential-scope.test.ts +15 -0
  220. package/src/plugin-api/credential-scope.ts +14 -0
  221. package/src/plugin-api/index.ts +19 -1
  222. package/src/plugin-api/resolve-credential.ts +15 -10
  223. package/src/plugin-api/store-credential.ts +148 -0
  224. package/src/plugin-api/system-card.ts +36 -0
  225. package/src/plugin-api/vision-support.test.ts +82 -0
  226. package/src/plugin-api/vision-support.ts +14 -2
  227. package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +361 -110
  228. package/src/plugins/defaults/image-fallback/__tests__/vision-recovery.test.ts +4 -0
  229. package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +58 -0
  230. package/src/plugins/defaults/image-fallback/src/caption-blocks.ts +64 -23
  231. package/src/plugins/defaults/image-recovery/detect.ts +24 -1
  232. package/src/plugins/defaults/main.ts +15 -0
  233. package/src/plugins/defaults/memory/AGENTS.md +11 -3
  234. package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +0 -1
  235. package/src/plugins/defaults/memory/graph-topology/pending-buffer.ts +9 -12
  236. package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +1 -1
  237. package/src/plugins/defaults/memory/src/memory-v2-routes.ts +12 -10
  238. package/src/plugins/defaults/memory/substrate/__tests__/consolidation-job.test.ts +114 -0
  239. package/src/plugins/defaults/memory/substrate/__tests__/consolidation-prompt-flag-gating-guard.test.ts +8 -0
  240. package/src/plugins/defaults/memory/substrate/__tests__/edge-index.test.ts +0 -30
  241. package/src/plugins/defaults/memory/substrate/__tests__/ingest.test.ts +73 -1
  242. package/src/plugins/defaults/memory/substrate/__tests__/page-index.test.ts +37 -0
  243. package/src/plugins/defaults/memory/substrate/__tests__/page-links.test.ts +208 -0
  244. package/src/plugins/defaults/memory/substrate/__tests__/prompts-consolidation.test.ts +158 -1
  245. package/src/plugins/defaults/memory/substrate/__tests__/static-context.test.ts +1 -61
  246. package/src/plugins/defaults/memory/substrate/consolidation-job.ts +68 -6
  247. package/src/plugins/defaults/memory/substrate/edge-index.ts +0 -31
  248. package/src/plugins/defaults/memory/substrate/ingest.ts +59 -0
  249. package/src/plugins/defaults/memory/substrate/page-index.ts +35 -8
  250. package/src/plugins/defaults/memory/substrate/page-links.ts +133 -0
  251. package/src/plugins/defaults/memory/substrate/page-store.ts +10 -0
  252. package/src/plugins/defaults/memory/substrate/prompts/consolidation.ts +124 -34
  253. package/src/plugins/defaults/memory/substrate/static-context.ts +0 -29
  254. package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +3 -1
  255. package/src/plugins/defaults/memory/v3/card.ts +9 -9
  256. package/src/plugins/defaults/memory/v3/core-set.test.ts +7 -0
  257. package/src/plugins/defaults/memory/v3/core-set.ts +5 -1
  258. package/src/plugins/defaults/memory/v3/edge.ts +13 -57
  259. package/src/plugins/mtime-cache.ts +1 -1
  260. package/src/plugins/pipeline.ts +14 -7
  261. package/src/plugins/plugin-execution-context.ts +35 -11
  262. package/src/plugins/plugin-tree-walk.ts +63 -4
  263. package/src/providers/anthropic/__tests__/pause-turn-continuation.test.ts +170 -0
  264. package/src/providers/anthropic/client.ts +332 -241
  265. package/src/providers/connection-resolution.ts +2 -1
  266. package/src/providers/content-blocks.ts +22 -0
  267. package/src/providers/gemini/client.ts +5 -2
  268. package/src/providers/inference/__tests__/adapter-factory-litellm.test.ts +47 -1
  269. package/src/providers/inference/__tests__/adapter-factory-ollama.test.ts +83 -0
  270. package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +98 -1
  271. package/src/providers/inference/__tests__/base-url-route-validation.test.ts +38 -0
  272. package/src/providers/inference/__tests__/base-url-security.test.ts +10 -0
  273. package/src/providers/inference/__tests__/connections-ollama.test.ts +90 -0
  274. package/src/providers/inference/__tests__/missing-credential-guard.test.ts +117 -0
  275. package/src/providers/inference/adapter-factory.ts +33 -2
  276. package/src/providers/inference/auth.ts +13 -2
  277. package/src/providers/inference/credential-usage.ts +37 -0
  278. package/src/providers/inference/missing-credential-guard.ts +110 -0
  279. package/src/providers/inference/resolve-auth.ts +7 -7
  280. package/src/providers/media-resolve.ts +176 -15
  281. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +576 -46
  282. package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +125 -2
  283. package/src/providers/openai/chat-completions-provider.ts +322 -42
  284. package/src/routes/route-host-protocol.ts +7 -0
  285. package/src/routes/worker.ts +31 -10
  286. package/src/runtime/AGENTS.md +35 -0
  287. package/src/runtime/__tests__/runtime-http-port-collision.test.ts +131 -0
  288. package/src/runtime/__tests__/web-presence.test.ts +234 -0
  289. package/src/runtime/assistant-event-hub.ts +38 -0
  290. package/src/runtime/channel-reply-delivery.ts +54 -31
  291. package/src/runtime/channel-retry-sweep.ts +6 -4
  292. package/src/runtime/effective-capabilities.test.ts +19 -0
  293. package/src/runtime/effective-capabilities.ts +25 -0
  294. package/src/runtime/guardian-reply-router.ts +6 -2
  295. package/src/runtime/http-errors.ts +1 -0
  296. package/src/runtime/http-server.ts +20 -5
  297. package/src/runtime/routes/__tests__/client-routes.test.ts +150 -0
  298. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +133 -0
  299. package/src/runtime/routes/__tests__/credential-delete-in-use.test.ts +155 -0
  300. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +52 -1
  301. package/src/runtime/routes/__tests__/monitoring-routes.test.ts +1 -0
  302. package/src/runtime/routes/__tests__/pending-interactions-route.test.ts +175 -0
  303. package/src/runtime/routes/__tests__/plugins-routes.test.ts +88 -35
  304. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +55 -6
  305. package/src/runtime/routes/__tests__/system-card-turn-termination.test.ts +107 -0
  306. package/src/runtime/routes/__tests__/user-route-dispatcher-host.test.ts +52 -1
  307. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +75 -4
  308. package/src/runtime/routes/approval-routes.ts +37 -4
  309. package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +16 -22
  310. package/src/runtime/routes/canned-message-complete.ts +68 -29
  311. package/src/runtime/routes/client-routes.ts +113 -0
  312. package/src/runtime/routes/conversation-list-routes.ts +22 -7
  313. package/src/runtime/routes/conversation-management-routes.ts +15 -9
  314. package/src/runtime/routes/conversation-routes.ts +36 -22
  315. package/src/runtime/routes/credential-in-use.ts +85 -0
  316. package/src/runtime/routes/credential-routes.ts +55 -85
  317. package/src/runtime/routes/guardian-approval-interception.ts +22 -22
  318. package/src/runtime/routes/guardian-approval-reply-helpers.ts +14 -12
  319. package/src/runtime/routes/identity-routes.ts +5 -121
  320. package/src/runtime/routes/inbound-message-handler.ts +71 -27
  321. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +16 -17
  322. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +77 -50
  323. package/src/runtime/routes/inbound-stages/background-dispatch.ts +61 -97
  324. package/src/runtime/routes/inbound-stages/edit-intercept.ts +101 -77
  325. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +17 -8
  326. package/src/runtime/routes/inbound-stages/reaction-intercept.test.ts +91 -7
  327. package/src/runtime/routes/inbound-stages/reaction-intercept.ts +72 -70
  328. package/src/runtime/routes/index.ts +2 -0
  329. package/src/runtime/routes/inference-provider-connection-routes.ts +9 -7
  330. package/src/runtime/routes/monitoring-routes.ts +9 -1
  331. package/src/runtime/routes/plugins-routes.ts +17 -5
  332. package/src/runtime/routes/resource-pressure-routes.ts +22 -0
  333. package/src/runtime/routes/secret-routes.ts +39 -8
  334. package/src/runtime/routes/settings-routes.ts +6 -6
  335. package/src/runtime/routes/surface-action-routes.ts +20 -19
  336. package/src/runtime/routes/user-route-dispatcher.ts +31 -2
  337. package/src/runtime/routes/user-route-resolution.ts +18 -1
  338. package/src/runtime/slack-reply-session.test.ts +23 -13
  339. package/src/runtime/slack-reply-session.ts +38 -55
  340. package/src/runtime/web-presence.ts +90 -0
  341. package/src/skills/validate-input.ts +177 -40
  342. package/src/subagent/__tests__/consult-context-gating.test.ts +6 -10
  343. package/src/subagent/consult-context.ts +7 -23
  344. package/src/tools/credentials/broker.ts +24 -79
  345. package/src/tools/credentials/ref-parse.ts +35 -0
  346. package/src/tools/credentials/resolve.ts +4 -10
  347. package/src/tools/credentials/store.ts +168 -0
  348. package/src/tools/credentials/tool-policy.ts +67 -0
  349. package/src/tools/executor.ts +53 -15
  350. package/src/tools/network/__tests__/web-search.test.ts +41 -1
  351. package/src/tools/network/url-safety.ts +9 -16
  352. package/src/tools/network/web-search.ts +21 -3
  353. package/src/tools/permission-checker.ts +43 -52
  354. package/src/tools/schema-transforms.ts +40 -5
  355. package/src/tools/shared/input-repairs.ts +160 -0
  356. package/src/tools/skills/skill-tool-factory.ts +18 -4
  357. package/src/tools/subagent/spawn.ts +0 -1
  358. package/src/tools/tool-approval-handler.ts +16 -10
  359. package/src/tools/tool-types.ts +26 -13
  360. package/src/tools/types.ts +6 -6
  361. package/src/util/__tests__/cgroup-memory.test.ts +3 -0
  362. package/src/util/cgroup-memory.ts +3 -0
  363. package/src/util/container-cpu-sampler.ts +250 -0
  364. package/src/util/image-conversion.ts +178 -14
  365. package/src/util/platform.ts +93 -10
  366. package/src/permissions/ipc-risk-types.ts +0 -143
  367. package/src/permissions/risk-types.ts +0 -76
@@ -18,9 +18,7 @@ mock.module("../permissions/checker.js", () => ({
18
18
  isDynamicSkillLoadInvocation: () => false,
19
19
  classifyRisk: async () => ({ level: "low" }),
20
20
  check: async () => ({ decision: "allow", reason: "allowed" }),
21
- generateAllowlistOptions: () => [],
22
21
  generateScopeOptions: () => [],
23
- getCachedAssessment: () => undefined,
24
22
  }));
25
23
 
26
24
  mock.module("../persistence/conversation-crud.js", () => ({
@@ -135,6 +135,8 @@ function createMockSession(opts?: {
135
135
  };
136
136
  },
137
137
  handleSecretResponse: () => {},
138
+ // The image-bearing profile pin reads the leg's history.
139
+ getMessages: () => [],
138
140
  runAgentLoop: async (
139
141
  _content: string,
140
142
  _messageId: string,
@@ -74,6 +74,8 @@ function makeStreamingSession(events: AssistantEvent[]): Conversation {
74
74
  }
75
75
  },
76
76
  handleConfirmationResponse: () => {},
77
+ // The image-bearing profile pin reads the leg's history.
78
+ getMessages: () => [],
77
79
  abort: () => {},
78
80
  } as unknown as Conversation;
79
81
  }
@@ -133,6 +135,8 @@ function makePersistingStreamingSession(
133
135
  },
134
136
  handleConfirmationResponse: () => {},
135
137
  abort: () => {},
138
+ // The image-bearing profile pin reads the leg's history.
139
+ getMessages: () => [],
136
140
  } as unknown as Conversation &
137
141
  PersistUserMessageContext & {
138
142
  callSessionId?: string;
@@ -263,6 +267,8 @@ describe("voice-session-bridge", () => {
263
267
  abort: () => {
264
268
  abortCalled = true;
265
269
  },
270
+ // The image-bearing profile pin reads the leg's history.
271
+ getMessages: () => [],
266
272
  } as unknown as Conversation;
267
273
 
268
274
  injectDeps(() => session);
@@ -302,6 +308,8 @@ describe("voice-session-bridge", () => {
302
308
  onEvent(event);
303
309
  }
304
310
  },
311
+ // The image-bearing profile pin reads the leg's history.
312
+ getMessages: () => [],
305
313
  } as unknown as Conversation;
306
314
 
307
315
  injectDeps(() => session);
@@ -348,6 +356,8 @@ describe("voice-session-bridge", () => {
348
356
  onEvent(event);
349
357
  }
350
358
  },
359
+ // The image-bearing profile pin reads the leg's history.
360
+ getMessages: () => [],
351
361
  } as unknown as Conversation;
352
362
 
353
363
  injectDeps(() => session);
@@ -393,6 +403,8 @@ describe("voice-session-bridge", () => {
393
403
  abort: () => {
394
404
  abortCalled = true;
395
405
  },
406
+ // The image-bearing profile pin reads the leg's history.
407
+ getMessages: () => [],
396
408
  } as unknown as Conversation;
397
409
 
398
410
  injectDeps(() => session);
@@ -430,6 +442,8 @@ describe("voice-session-bridge", () => {
430
442
  setTurnChannelContext: (ctx: unknown) => {
431
443
  capturedTurnChannelContext = ctx;
432
444
  },
445
+ // The image-bearing profile pin reads the leg's history.
446
+ getMessages: () => [],
433
447
  } as unknown as Conversation;
434
448
 
435
449
  injectDeps(() => session);
@@ -586,6 +600,8 @@ describe("voice-session-bridge", () => {
586
600
  capturedTrustContext = ctx;
587
601
  }
588
602
  },
603
+ // The image-bearing profile pin reads the leg's history.
604
+ getMessages: () => [],
589
605
  } as unknown as Conversation;
590
606
 
591
607
  injectDeps(() => session);
@@ -629,6 +645,8 @@ describe("voice-session-bridge", () => {
629
645
  capturedPrompt = prompt;
630
646
  }
631
647
  },
648
+ // The image-bearing profile pin reads the leg's history.
649
+ getMessages: () => [],
632
650
  } as unknown as Conversation;
633
651
 
634
652
  injectDeps(() => session);
@@ -690,6 +708,8 @@ describe("voice-session-bridge", () => {
690
708
  capturedPrompt = prompt;
691
709
  }
692
710
  },
711
+ // The image-bearing profile pin reads the leg's history.
712
+ getMessages: () => [],
693
713
  } as unknown as Conversation;
694
714
 
695
715
  injectDeps(() => session);
@@ -782,6 +802,8 @@ describe("voice-session-bridge", () => {
782
802
  });
783
803
  },
784
804
  abort: () => {},
805
+ // The image-bearing profile pin reads the leg's history.
806
+ getMessages: () => [],
785
807
  } as unknown as Conversation;
786
808
 
787
809
  injectDeps(() => session);
@@ -870,6 +892,8 @@ describe("voice-session-bridge", () => {
870
892
  });
871
893
  },
872
894
  abort: () => {},
895
+ // The image-bearing profile pin reads the leg's history.
896
+ getMessages: () => [],
873
897
  } as unknown as Conversation;
874
898
 
875
899
  injectDeps(() => session);
@@ -946,6 +970,8 @@ describe("voice-session-bridge", () => {
946
970
  handleConfirmationCalls.push({ requestId, decision });
947
971
  },
948
972
  abort: () => {},
973
+ // The image-bearing profile pin reads the leg's history.
974
+ getMessages: () => [],
949
975
  } as unknown as Conversation;
950
976
 
951
977
  injectDeps(() => session);
@@ -1014,6 +1040,8 @@ describe("voice-session-bridge", () => {
1014
1040
  handleConfirmationCalls.push({ requestId, decision });
1015
1041
  },
1016
1042
  abort: () => {},
1043
+ // The image-bearing profile pin reads the leg's history.
1044
+ getMessages: () => [],
1017
1045
  } as unknown as Conversation;
1018
1046
 
1019
1047
  injectDeps(() => session);
@@ -1080,6 +1108,8 @@ describe("voice-session-bridge", () => {
1080
1108
  handleConfirmationCalls.push({ requestId, decision });
1081
1109
  },
1082
1110
  abort: () => {},
1111
+ // The image-bearing profile pin reads the leg's history.
1112
+ getMessages: () => [],
1083
1113
  } as unknown as Conversation;
1084
1114
 
1085
1115
  injectDeps(() => session);
@@ -1164,6 +1194,8 @@ describe("voice-session-bridge", () => {
1164
1194
  } as AssistantEvent);
1165
1195
  },
1166
1196
  abort: () => {},
1197
+ // The image-bearing profile pin reads the leg's history.
1198
+ getMessages: () => [],
1167
1199
  } as unknown as Conversation;
1168
1200
  }
1169
1201
 
@@ -1303,6 +1335,8 @@ describe("voice-session-bridge", () => {
1303
1335
  handleSecretCalls.push({ requestId, value, delivery });
1304
1336
  },
1305
1337
  abort: () => {},
1338
+ // The image-bearing profile pin reads the leg's history.
1339
+ getMessages: () => [],
1306
1340
  } as unknown as Conversation;
1307
1341
 
1308
1342
  injectDeps(() => session);
@@ -1354,6 +1388,8 @@ describe("voice-session-bridge", () => {
1354
1388
  runAgentLoop: async () => {},
1355
1389
  handleConfirmationResponse: () => {},
1356
1390
  abort: () => {},
1391
+ // The image-bearing profile pin reads the leg's history.
1392
+ getMessages: () => [],
1357
1393
  } as unknown as Conversation & { forcePromptSideEffects: boolean };
1358
1394
 
1359
1395
  injectDeps(() => session);
@@ -1413,6 +1449,8 @@ describe("voice-session-bridge", () => {
1413
1449
  runAgentLoop: async () => {},
1414
1450
  handleConfirmationResponse: () => {},
1415
1451
  abort: () => {},
1452
+ // The image-bearing profile pin reads the leg's history.
1453
+ getMessages: () => [],
1416
1454
  } as unknown as Conversation & {
1417
1455
  forcePromptSideEffects: boolean;
1418
1456
  callSessionId?: string;
@@ -1479,6 +1517,8 @@ describe("voice-session-bridge", () => {
1479
1517
  runAgentLoop: async () => {},
1480
1518
  handleConfirmationResponse: () => {},
1481
1519
  abort: () => {},
1520
+ // The image-bearing profile pin reads the leg's history.
1521
+ getMessages: () => [],
1482
1522
  } as unknown as Conversation & {
1483
1523
  forcePromptSideEffects: boolean;
1484
1524
  callSessionId?: string;
@@ -1540,6 +1580,8 @@ describe("voice-session-bridge", () => {
1540
1580
  abort: () => {
1541
1581
  abortCalled = true;
1542
1582
  },
1583
+ // The image-bearing profile pin reads the leg's history.
1584
+ getMessages: () => [],
1543
1585
  } as unknown as Conversation;
1544
1586
 
1545
1587
  injectDeps(() => session);
@@ -1,13 +1,21 @@
1
1
  /**
2
2
  * Tests for the Claude OAuth config + capture/store helpers.
3
3
  *
4
- * The store helper reaches into secure-keys and the ACP credential policy, so
5
- * we mock both (wired BEFORE importing the module under test via dynamic
6
- * import) and assert the vault write targets `credential/acp/claude_oauth_token`
7
- * and throws when the backend rejects the write.
4
+ * The store helper reaches into secure-keys, so we mock that (wired BEFORE
5
+ * importing the module under test via dynamic import) and assert the vault
6
+ * write targets `credential/acp/claude_oauth_token` and throws when the backend
7
+ * rejects the write.
8
+ *
9
+ * The ACP credential policy is NOT mocked: `hasAcpClaudeToken` has to answer
10
+ * exactly what the spawn-time broker read would, so it is exercised against the
11
+ * real metadata store (pointed at a temp dir) and the real policy evaluation.
8
12
  */
9
13
 
10
- import { beforeEach, describe, expect, mock, test } from "bun:test";
14
+ import { randomBytes } from "node:crypto";
15
+ import { mkdirSync, rmSync } from "node:fs";
16
+ import { tmpdir } from "node:os";
17
+ import { join } from "node:path";
18
+ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
11
19
 
12
20
  // ---------------------------------------------------------------------------
13
21
  // Mocks — wired BEFORE importing the module via dynamic import.
@@ -19,20 +27,17 @@ const setSecureKeyAsync = mock(
19
27
  async (_account: string, _value: string) => storeReturn,
20
28
  );
21
29
  const getSecureKeyAsync = mock(async (_account: string) => getReturn);
22
- const grantAcpSpawnPolicy = mock(
23
- (_field: string, _usageDescription: string) => {},
24
- );
25
- let spawnCanRead = true;
26
- const acpSpawnCanReadCredential = mock((_field: string) => spawnCanRead);
27
30
 
28
31
  mock.module("../../security/secure-keys.js", () => ({
29
32
  setSecureKeyAsync,
30
33
  getSecureKeyAsync,
31
34
  }));
32
- mock.module("../prepare-agent-env.js", () => ({
33
- grantAcpSpawnPolicy,
34
- acpSpawnCanReadCredential,
35
- }));
35
+
36
+ const { _setMetadataPath, getCredentialMetadata, upsertCredentialMetadata } =
37
+ await import("../../tools/credentials/metadata-store.js");
38
+
39
+ const { acpSpawnCredentialDenialReason } =
40
+ await import("../prepare-agent-env.js");
36
41
 
37
42
  const {
38
43
  CLAUDE_OAUTH_CONFIG,
@@ -43,14 +48,31 @@ const {
43
48
  hasAcpClaudeToken,
44
49
  } = await import("../acp-claude-oauth.js");
45
50
 
51
+ const ACP_SERVICE = "acp";
52
+ const OAUTH_FIELD = "claude_oauth_token";
53
+ const ACP_SPAWN_TOOL = "acp_spawn";
54
+
55
+ const TEST_DIR = join(
56
+ tmpdir(),
57
+ `vellum-acp-claude-oauth-test-${randomBytes(4).toString("hex")}`,
58
+ );
59
+
60
+ function oauthMetadata() {
61
+ return getCredentialMetadata(ACP_SERVICE, OAUTH_FIELD);
62
+ }
63
+
46
64
  beforeEach(() => {
65
+ mkdirSync(TEST_DIR, { recursive: true });
66
+ _setMetadataPath(join(TEST_DIR, "metadata.json"));
47
67
  storeReturn = true;
48
68
  getReturn = undefined;
49
- spawnCanRead = true;
50
69
  setSecureKeyAsync.mockClear();
51
70
  getSecureKeyAsync.mockClear();
52
- grantAcpSpawnPolicy.mockClear();
53
- acpSpawnCanReadCredential.mockClear();
71
+ });
72
+
73
+ afterEach(() => {
74
+ _setMetadataPath(null);
75
+ rmSync(TEST_DIR, { recursive: true, force: true });
54
76
  });
55
77
 
56
78
  // ---------------------------------------------------------------------------
@@ -149,7 +171,7 @@ describe("parseManualClaudeCode", () => {
149
171
  // ---------------------------------------------------------------------------
150
172
 
151
173
  describe("storeAcpClaudeToken", () => {
152
- test("writes the token and force-grants the acp_spawn policy (repairs a denied policy)", async () => {
174
+ test("writes the token to the acp/claude_oauth_token vault field", async () => {
153
175
  await storeAcpClaudeToken("sk-ant-oat-token");
154
176
 
155
177
  expect(setSecureKeyAsync).toHaveBeenCalledTimes(1);
@@ -157,10 +179,25 @@ describe("storeAcpClaudeToken", () => {
157
179
  "credential/acp/claude_oauth_token",
158
180
  "sk-ant-oat-token",
159
181
  );
160
- // grant (union), not merely ensure (preserve) — so an explicit Connect
161
- // repairs a credential whose allowedTools omitted acp_spawn.
162
- expect(grantAcpSpawnPolicy).toHaveBeenCalledTimes(1);
163
- expect(grantAcpSpawnPolicy.mock.calls[0][0]).toBe("claude_oauth_token");
182
+ });
183
+
184
+ test("takes a domain-restricted credential from not-connected to connected", async () => {
185
+ // Invariant: when the vault holds a usable token whose domain policy
186
+ // makes the spawn read fail, the status check keeps the Connect card
187
+ // offered, and completing Connect repairs the policy so the retry after
188
+ // a successful sign-in succeeds. The per-shape repair details are covered
189
+ // by the repairAcpSpawnPolicy suite in prepare-agent-env.test.ts.
190
+ upsertCredentialMetadata(ACP_SERVICE, OAUTH_FIELD, {
191
+ allowedTools: [ACP_SPAWN_TOOL],
192
+ allowedDomains: ["api.anthropic.com"],
193
+ });
194
+ getReturn = "sk-ant-oat-token";
195
+ expect(await hasAcpClaudeToken()).toBe(false);
196
+
197
+ await storeAcpClaudeToken("sk-ant-oat-token");
198
+
199
+ expect(await hasAcpClaudeToken()).toBe(true);
200
+ expect(acpSpawnCredentialDenialReason(OAUTH_FIELD)).toBeUndefined();
164
201
  });
165
202
 
166
203
  test("throws when the secure store rejects the write", async () => {
@@ -169,7 +206,7 @@ describe("storeAcpClaudeToken", () => {
169
206
  await expect(storeAcpClaudeToken("sk-ant-oat-token")).rejects.toThrow(
170
207
  /Failed to store/,
171
208
  );
172
- expect(grantAcpSpawnPolicy).not.toHaveBeenCalled();
209
+ expect(oauthMetadata()).toBeUndefined();
173
210
  });
174
211
  });
175
212
 
@@ -202,13 +239,44 @@ describe("hasAcpClaudeToken", () => {
202
239
  expect(await hasAcpClaudeToken()).toBe(false);
203
240
  });
204
241
 
205
- test("reports false when the spawn policy can't read the token (denied allowedTools)", async () => {
206
- // A valid OAuth token is stored, but an explicit `allowedTools` that omits
207
- // `acp_spawn` means the broker denies the spawn read. Reporting "connected"
208
- // would self-dismiss the card and trap the user in a missing-token loop, so
209
- // it stays not-connected to keep the repair CTA visible.
242
+ test("reports true for metadata with an empty allowedTools (the spawn would grant acp_spawn)", async () => {
243
+ // One allow-state case: the full policy matrix is guarded by the parity
244
+ // suite in prepare-agent-env.test.ts and the tool-policy unit tests.
245
+ upsertCredentialMetadata(ACP_SERVICE, OAUTH_FIELD, { allowedTools: [] });
210
246
  getReturn = "sk-ant-oat-token";
211
- spawnCanRead = false;
247
+
248
+ expect(await hasAcpClaudeToken()).toBe(true);
249
+ });
250
+
251
+ test("reports false for a domain-restricted credential the broker refuses server-side", async () => {
252
+ // acp_spawn is allowed, but a non-empty allowedDomains scopes the credential
253
+ // to browser fills, so every spawn read is denied. The status check has to
254
+ // see that too, otherwise the Connect card self-dismisses while acp_spawn
255
+ // keeps failing with the missing-token marker.
256
+ upsertCredentialMetadata(ACP_SERVICE, OAUTH_FIELD, {
257
+ allowedTools: [ACP_SPAWN_TOOL],
258
+ allowedDomains: ["api.anthropic.com"],
259
+ });
260
+ getReturn = "sk-ant-oat-token";
261
+
212
262
  expect(await hasAcpClaudeToken()).toBe(false);
213
263
  });
264
+
265
+ test("writes nothing to the metadata store (the status route is a GET)", async () => {
266
+ upsertCredentialMetadata(ACP_SERVICE, OAUTH_FIELD, { allowedTools: [] });
267
+ getReturn = "sk-ant-oat-token";
268
+ const before = oauthMetadata();
269
+
270
+ await hasAcpClaudeToken();
271
+
272
+ expect(oauthMetadata()).toEqual(before);
273
+ });
274
+
275
+ test("creates no metadata when there is none to begin with", async () => {
276
+ getReturn = "sk-ant-oat-token";
277
+
278
+ await hasAcpClaudeToken();
279
+
280
+ expect(oauthMetadata()).toBeUndefined();
281
+ });
214
282
  });