@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
@@ -171,9 +171,9 @@ mock.module("../tools/network/url-safety.js", () => ({
171
171
  // ── ipcClassifyRisk mock ─────────────────────────────────────────────────────
172
172
  // This is the core mock — all classification goes through this.
173
173
 
174
- import type { ClassificationResult } from "./ipc-risk-types.js";
174
+ import type { ClassifyRiskIpcResponse } from "@vellumai/gateway-client";
175
175
 
176
- let mockIpcClassifyRiskResult: ClassificationResult | undefined;
176
+ let mockIpcClassifyRiskResult: ClassifyRiskIpcResponse | undefined;
177
177
  let lastClassifyRiskParams: Record<string, unknown> | undefined;
178
178
 
179
179
  mock.module("../ipc/gateway-client.js", () => ({
@@ -204,9 +204,7 @@ import type { Tool, ToolContext } from "../tools/types.js";
204
204
  import {
205
205
  check,
206
206
  classifyRisk,
207
- generateAllowlistOptions,
208
207
  generateScopeOptions,
209
- getCachedAssessment,
210
208
  isInstalledStaticSkillLoad,
211
209
  } from "./checker.js";
212
210
  import { RiskLevel } from "./types.js";
@@ -352,36 +350,9 @@ describe("Permission Checker (gateway IPC)", () => {
352
350
  expect(lastClassifyRiskParams?.resolvedWorkingDir).toBeUndefined();
353
351
  });
354
352
 
355
- test("caches results for identical inputs", async () => {
356
- mockIpcClassifyRiskResult = {
357
- risk: "low",
358
- reason: "Cached test",
359
- matchType: "registry",
360
- scopeOptions: [],
361
- };
362
-
363
- // First call
364
- const result1 = await classifyRisk("file_read", { path: "/tmp/a.txt" });
365
- expect(result1.level).toBe(RiskLevel.Low);
366
-
367
- // Change the mock to verify cache is used
368
- mockIpcClassifyRiskResult = {
369
- risk: "high",
370
- reason: "Should not see this",
371
- matchType: "registry",
372
- scopeOptions: [],
373
- };
374
-
375
- // Second call with same inputs should return cached result
376
- const result2 = await classifyRisk("file_read", { path: "/tmp/a.txt" });
377
- expect(result2.level).toBe(RiskLevel.Low);
378
- expect(result2.reason).toBe("Cached test");
379
- });
380
-
381
- test("file-tool cache misses when a symlink target is retargeted", async () => {
382
- // File risk depends on filesystem state: the cache key folds in the
383
- // symlink-resolved target, so the same raw input must NOT return a stale
384
- // cached result after the symlink is pointed somewhere new.
353
+ test("a retargeted symlink is reflected on the next classification of the same raw input", async () => {
354
+ // File risk depends on filesystem state; nothing in the daemon memoises
355
+ // a classification, so re-pointing the symlink changes the answer.
385
356
  const dir = mkdtempSync(join(tmpdir(), "risk-cache-symlink-"));
386
357
  try {
387
358
  const benign = join(dir, "benign.txt");
@@ -411,7 +382,7 @@ describe("Permission Checker (gateway IPC)", () => {
411
382
  scopeOptions: [],
412
383
  };
413
384
  const second = await classifyRisk("file_read", { path: link });
414
- // Cache must have missed and re-classified against the new target.
385
+ // Re-classified against the new target.
415
386
  expect(second.level).toBe(RiskLevel.High);
416
387
  expect(second.reason).toBe("now sensitive");
417
388
  } finally {
@@ -427,12 +398,8 @@ describe("Permission Checker (gateway IPC)", () => {
427
398
  scopeOptions: [],
428
399
  commandCandidates: ["ls -la", "action:ls"],
429
400
  };
430
- // Use unique command to avoid cache hits from other tests
431
401
  const result = await classifyRisk("bash", { command: "ls -la" });
432
- expect((result as any).commandCandidates).toEqual([
433
- "ls -la",
434
- "action:ls",
435
- ]);
402
+ expect(result.commandCandidates).toEqual(["ls -la", "action:ls"]);
436
403
  });
437
404
 
438
405
  test("preserves sandboxAutoApprove from gateway response", async () => {
@@ -443,9 +410,8 @@ describe("Permission Checker (gateway IPC)", () => {
443
410
  scopeOptions: [],
444
411
  sandboxAutoApprove: true,
445
412
  };
446
- // Use unique command to avoid cache hits
447
413
  const result = await classifyRisk("bash", { command: "pwd" });
448
- expect((result as any).sandboxAutoApprove).toBe(true);
414
+ expect(result.sandboxAutoApprove).toBe(true);
449
415
  });
450
416
 
451
417
  test("overrides sandboxAutoApprove when symlink escape detected", async () => {
@@ -461,7 +427,7 @@ describe("Permission Checker (gateway IPC)", () => {
461
427
  const result = await classifyRisk("bash", {
462
428
  command: "cat /workspace/escape/passwd",
463
429
  });
464
- expect((result as any).sandboxAutoApprove).toBe(false);
430
+ expect(result.sandboxAutoApprove).toBe(false);
465
431
  mockIsPathWithinWorkspaceRoot = true;
466
432
  });
467
433
 
@@ -478,7 +444,7 @@ describe("Permission Checker (gateway IPC)", () => {
478
444
  const result = await classifyRisk("bash", {
479
445
  command: "cat /workspace/file.txt",
480
446
  });
481
- expect((result as any).sandboxAutoApprove).toBe(true);
447
+ expect(result.sandboxAutoApprove).toBe(true);
482
448
  });
483
449
 
484
450
  test("overrides sandboxAutoApprove when any path arg escapes", async () => {
@@ -494,7 +460,7 @@ describe("Permission Checker (gateway IPC)", () => {
494
460
  const result = await classifyRisk("bash", {
495
461
  command: "cat /workspace/safe.txt && cat /workspace/escape/passwd",
496
462
  });
497
- expect((result as any).sandboxAutoApprove).toBe(false);
463
+ expect(result.sandboxAutoApprove).toBe(false);
498
464
  mockIsPathWithinWorkspaceRoot = true;
499
465
  });
500
466
 
@@ -509,11 +475,11 @@ describe("Permission Checker (gateway IPC)", () => {
509
475
  // No sandboxPathArgs — e.g. older gateway that doesn't send them
510
476
  };
511
477
  const result = await classifyRisk("bash", { command: "ls" });
512
- expect((result as any).sandboxAutoApprove).toBe(true);
478
+ expect(result.sandboxAutoApprove).toBe(true);
513
479
  mockIsPathWithinWorkspaceRoot = true;
514
480
  });
515
481
 
516
- test("cache hit re-runs symlink escape check after symlink retargeted", async () => {
482
+ test("the symlink escape check runs on every classification, so a retargeted symlink revokes sandbox auto-approve", async () => {
517
483
  // First call: path args within workspace → sandboxAutoApprove true.
518
484
  mockIsPathWithinWorkspaceRoot = true;
519
485
  mockIpcClassifyRiskResult = {
@@ -527,16 +493,15 @@ describe("Permission Checker (gateway IPC)", () => {
527
493
  const first = await classifyRisk("bash", {
528
494
  command: "cat /workspace/escape/secret42.bin",
529
495
  });
530
- expect((first as any).sandboxAutoApprove).toBe(true);
496
+ expect(first.sandboxAutoApprove).toBe(true);
531
497
 
532
- // Second call with the same command: cache hit, but symlink now
533
- // resolves outside workspace. The cache hit must re-run the check
534
- // and override sandboxAutoApprove to false.
498
+ // Second call with the same command: the symlink now resolves outside
499
+ // the workspace, so sandboxAutoApprove is revoked.
535
500
  mockIsPathWithinWorkspaceRoot = false;
536
501
  const second = await classifyRisk("bash", {
537
502
  command: "cat /workspace/escape/secret42.bin",
538
503
  });
539
- expect((second as any).sandboxAutoApprove).toBe(false);
504
+ expect(second.sandboxAutoApprove).toBe(false);
540
505
  mockIsPathWithinWorkspaceRoot = true;
541
506
  });
542
507
 
@@ -556,9 +521,8 @@ describe("Permission Checker (gateway IPC)", () => {
556
521
  scopeOptions: [],
557
522
  allowlistOptions: mockOptions,
558
523
  };
559
- // Use unique command to avoid cache hits
560
524
  const result = await classifyRisk("bash", { command: "date" });
561
- expect((result as any).allowlistOptions).toEqual(mockOptions);
525
+ expect(result.allowlistOptions).toEqual(mockOptions);
562
526
  });
563
527
  });
564
528
 
@@ -1215,10 +1179,10 @@ describe("Permission Checker (gateway IPC)", () => {
1215
1179
  });
1216
1180
  });
1217
1181
 
1218
- // ── generateAllowlistOptions ──────────────────────────────────────────────
1182
+ // ── allowlist ladder ──────────────────────────────────────────────────────
1219
1183
 
1220
- describe("generateAllowlistOptions", () => {
1221
- test("returns gateway-provided options from assessment cache", async () => {
1184
+ describe("allowlist ladder", () => {
1185
+ test("is the gateway's, carried through unchanged", async () => {
1222
1186
  const mockOptions = [
1223
1187
  { label: "wc -l", description: "Exact command", pattern: "wc -l" },
1224
1188
  {
@@ -1235,37 +1199,27 @@ describe("Permission Checker (gateway IPC)", () => {
1235
1199
  allowlistOptions: mockOptions,
1236
1200
  };
1237
1201
 
1238
- // First classify to populate the cache
1239
- await classifyRisk("bash", { command: "wc -l" });
1240
-
1241
- // Then generate options should use cached assessment
1242
- const options = await generateAllowlistOptions("bash", {
1243
- command: "wc -l",
1244
- });
1245
- expect(options).toEqual(mockOptions);
1202
+ const classification = await classifyRisk("bash", { command: "wc -l" });
1203
+ expect(classification.allowlistOptions).toEqual(mockOptions);
1246
1204
  });
1247
1205
 
1248
- test("falls back to per-tool strategy for file tools without cached options", async () => {
1249
- const options = await generateAllowlistOptions("file_read", {
1250
- path: "/tmp/foo.txt",
1251
- });
1252
- // Should get file-specific options (exact path, directory wildcards, etc.)
1253
- expect(options.length).toBeGreaterThan(0);
1254
- expect(options[0].pattern).toContain("file_read:");
1255
- });
1206
+ test("is absent when the classifier produced none", async () => {
1207
+ mockIpcClassifyRiskResult = {
1208
+ risk: "low",
1209
+ reason: "no ladder",
1210
+ matchType: "registry",
1211
+ scopeOptions: [],
1212
+ };
1256
1213
 
1257
- test("returns default option for unknown tools", async () => {
1258
- const options = await generateAllowlistOptions("custom_tool", {});
1259
- expect(options).toEqual([
1260
- { label: "*", description: "Everything", pattern: "*" },
1261
- ]);
1214
+ const classification = await classifyRisk("custom_tool", {});
1215
+ expect(classification.allowlistOptions).toBeUndefined();
1262
1216
  });
1263
1217
  });
1264
1218
 
1265
- // ── getCachedAssessment ───────────────────────────────────────────────────
1219
+ // ── classifyRisk carries the gateway's assessment fields ──────────────────
1266
1220
 
1267
- describe("getCachedAssessment", () => {
1268
- test("returns cached assessment after classifyRisk call", async () => {
1221
+ describe("classifyRisk assessment fields", () => {
1222
+ test("carries reason, matchType and allowlistOptions from the gateway result", async () => {
1269
1223
  mockIpcClassifyRiskResult = {
1270
1224
  risk: "low",
1271
1225
  reason: "Test assessment",
@@ -1276,21 +1230,37 @@ describe("Permission Checker (gateway IPC)", () => {
1276
1230
  ],
1277
1231
  };
1278
1232
 
1279
- await classifyRisk("bash", { command: "echo test" });
1280
-
1281
- const assessment = getCachedAssessment("bash", { command: "echo test" });
1282
- expect(assessment).toBeDefined();
1283
- expect(assessment!.riskLevel).toBe("low");
1284
- expect(assessment!.reason).toBe("Test assessment");
1285
- expect(assessment!.allowlistOptions).toHaveLength(1);
1233
+ const classification = await classifyRisk("bash", {
1234
+ command: "echo test",
1235
+ });
1236
+ expect(classification.level).toBe(RiskLevel.Low);
1237
+ expect(classification.reason).toBe("Test assessment");
1238
+ expect(classification.matchType).toBe("registry");
1239
+ expect(classification.allowlistOptions).toHaveLength(1);
1286
1240
  });
1287
1241
 
1288
- test("returns undefined for uncached tool invocations", () => {
1289
- const assessment = getCachedAssessment("bash", { command: "not-cached" });
1290
- expect(assessment).toBeUndefined();
1242
+ test("is not memoised: a changed gateway answer for the same input is returned", async () => {
1243
+ mockIpcClassifyRiskResult = {
1244
+ risk: "low",
1245
+ reason: "before the rule",
1246
+ matchType: "registry",
1247
+ scopeOptions: [],
1248
+ };
1249
+ const before = await classifyRisk("bash", { command: "curl example" });
1250
+ expect(before.level).toBe(RiskLevel.Low);
1251
+
1252
+ mockIpcClassifyRiskResult = {
1253
+ risk: "high",
1254
+ reason: "after the rule",
1255
+ matchType: "user_rule",
1256
+ scopeOptions: [],
1257
+ };
1258
+ const after = await classifyRisk("bash", { command: "curl example" });
1259
+ expect(after.level).toBe(RiskLevel.High);
1260
+ expect(after.matchType).toBe("user_rule");
1291
1261
  });
1292
1262
 
1293
- test("preserves scopeOptions from gateway result in cached assessment", async () => {
1263
+ test("preserves scopeOptions from the gateway result", async () => {
1294
1264
  mockIpcClassifyRiskResult = {
1295
1265
  risk: "low",
1296
1266
  reason: "Registry match",
@@ -1302,22 +1272,16 @@ describe("Permission Checker (gateway IPC)", () => {
1302
1272
  allowlistOptions: [],
1303
1273
  };
1304
1274
 
1305
- await classifyRisk("bash", { command: "echo hello" });
1306
-
1307
- const assessment = getCachedAssessment("bash", { command: "echo hello" });
1308
- expect(assessment).toBeDefined();
1309
- expect(assessment!.scopeOptions).toHaveLength(2);
1310
- expect(assessment!.scopeOptions[0]).toEqual({
1311
- pattern: "echo *",
1312
- label: "only 'echo' commands",
1313
- });
1314
- expect(assessment!.scopeOptions[1]).toEqual({
1315
- pattern: ".*",
1316
- label: "everywhere",
1275
+ const classification = await classifyRisk("bash", {
1276
+ command: "echo hello",
1317
1277
  });
1278
+ expect(classification.scopeOptions).toEqual([
1279
+ { pattern: "echo *", label: "only 'echo' commands" },
1280
+ { pattern: ".*", label: "everywhere" },
1281
+ ]);
1318
1282
  });
1319
1283
 
1320
- test("preserves directoryScopeOptions from gateway result in cached assessment", async () => {
1284
+ test("preserves directoryScopeOptions from the gateway result", async () => {
1321
1285
  mockIpcClassifyRiskResult = {
1322
1286
  risk: "medium",
1323
1287
  reason: "Filesystem write",
@@ -1331,25 +1295,14 @@ describe("Permission Checker (gateway IPC)", () => {
1331
1295
  ],
1332
1296
  };
1333
1297
 
1334
- await classifyRisk("file_write", { path: "/workspace/scratch/out.txt" });
1335
-
1336
- const assessment = getCachedAssessment("file_write", {
1298
+ const classification = await classifyRisk("file_write", {
1337
1299
  path: "/workspace/scratch/out.txt",
1338
1300
  });
1339
- expect(assessment).toBeDefined();
1340
- expect(assessment!.directoryScopeOptions).toHaveLength(3);
1341
- expect(assessment!.directoryScopeOptions![0]).toEqual({
1342
- scope: "/workspace/scratch/*",
1343
- label: "In scratch/",
1344
- });
1345
- expect(assessment!.directoryScopeOptions![1]).toEqual({
1346
- scope: "/workspace/*",
1347
- label: "In workspace/",
1348
- });
1349
- expect(assessment!.directoryScopeOptions![2]).toEqual({
1350
- scope: "everywhere",
1351
- label: "everywhere",
1352
- });
1301
+ expect(classification.directoryScopeOptions).toEqual([
1302
+ { scope: "/workspace/scratch/*", label: "In scratch/" },
1303
+ { scope: "/workspace/*", label: "In workspace/" },
1304
+ { scope: "everywhere", label: "everywhere" },
1305
+ ]);
1353
1306
  });
1354
1307
  });
1355
1308