@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
@@ -151,6 +151,13 @@ function applyTransportMetadata(
151
151
  *
152
152
  * Handles provider setup, rate limiting, system prompt, memory policy,
153
153
  * and conversation hydration.
154
+ *
155
+ * The in-memory Conversation snapshots the tool registry at construction.
156
+ * An empty snapshot is an empty tool list on the wire for the life of the
157
+ * instance, so the create path initializes the registry before that
158
+ * constructor runs. A hit in `findConversation` already has its snapshot.
159
+ * `initializeTools` is idempotent: a process that already initialized at
160
+ * boot awaits the settled promise.
154
161
  */
155
162
  export async function getOrCreateConversation(
156
163
  conversationId: string,
@@ -228,6 +235,9 @@ export async function getOrCreateConversation(
228
235
  const systemPrompt = await resolveInitialSystemPrompt(storedOptions);
229
236
  const maxTokens = storedOptions?.maxResponseTokens;
230
237
 
238
+ const { initializeTools } = await import("../tools/registry.js");
239
+ await initializeTools();
240
+
231
241
  const newConversation = new Conversation(
232
242
  conversationId,
233
243
  provider,
@@ -85,6 +85,8 @@ import type {
85
85
  } from "./message-protocol.js";
86
86
  import { INTERACTIVE_SURFACE_TYPES } from "./message-protocol.js";
87
87
  import { isRowVisibleToUntrustedActor } from "./message-provenance.js";
88
+ import type { TrustContext } from "./trust-context-types.js";
89
+ import { restingTrust } from "./trust-context-types.js";
88
90
  export {
89
91
  buildSurfaceShowPair,
90
92
  type CurrentTurnSurface,
@@ -1904,7 +1906,13 @@ export async function handleSurfaceAction(
1904
1906
  // reconstruct the same-user binding for host proxies (CU / app-control),
1905
1907
  // mirroring the normal message path.
1906
1908
  sourceActorPrincipalId?: string,
1909
+ // Trust of the actor committing this action, resolved by the route from the
1910
+ // verified requester. Passed rather than read back off the conversation so a
1911
+ // click that lands mid-turn is attributed to its clicker instead of to
1912
+ // whoever occupies the resting slot.
1913
+ requesterTrustContext?: TrustContext,
1907
1914
  ): Promise<SurfaceActionResult> {
1915
+ const actionTrustContext = requesterTrustContext ?? restingTrust(ctx);
1908
1916
  // ── Standalone surface interception ──────────────────────────────
1909
1917
  // Daemon-driven surfaces (from `requestInteractiveUi`) register a
1910
1918
  // pending entry in `pendingStandaloneSurfaces`. When the user clicks
@@ -2050,7 +2058,7 @@ export async function handleSurfaceAction(
2050
2058
  // `await` resolves as soon as the conversation is created + titled +
2051
2059
  // published to the event hub. The HTTP POST /v1/surface-actions
2052
2060
  // response returns promptly — the seed turn runs in the background.
2053
- const originTrustContext = ctx.trustContext;
2061
+ const originTrustContext = actionTrustContext;
2054
2062
  const { conversationId } = await launchConversation({
2055
2063
  title,
2056
2064
  seedPrompt,
@@ -2069,14 +2077,11 @@ export async function handleSurfaceAction(
2069
2077
  return { accepted: true, conversationId };
2070
2078
  }
2071
2079
 
2072
- // Trust of the actor committing THIS action. `POST /v1/surface-actions`
2073
- // stamps the verified requester's trust onto the conversation before
2074
- // dispatching here, and `loadFromDb` derives the live history filter from
2075
- // the same value, so the completion path's persisted read stays scoped to
2076
- // exactly what this actor's live view would have held. Unresolvable trust
2077
- // fails closed to the untrusted filter.
2080
+ // Trust of the actor committing THIS action, so the completion path's
2081
+ // persisted read stays scoped to exactly what this actor's live view would
2082
+ // have held. Unresolvable trust fails closed to the untrusted filter.
2078
2083
  const requesterCanAccessMemory = resolveCapabilities(
2079
- ctx.trustContext?.trustClass,
2084
+ actionTrustContext?.trustClass,
2080
2085
  ).canAccessMemory;
2081
2086
 
2082
2087
  const pending = ctx.pendingSurfaceActions.get(surfaceId);
@@ -2222,6 +2227,7 @@ export async function handleSurfaceAction(
2222
2227
  activeSurfaceId: surfaceId,
2223
2228
  displayContent,
2224
2229
  sourceActorPrincipalId,
2230
+ trustContext: actionTrustContext,
2225
2231
  isInteractive: SURFACE_ACTION_TURN_IS_INTERACTIVE,
2226
2232
  // Rides the metadata bag rather than a typed option: the queue
2227
2233
  // round-trips `metadata` but not `PersistMessageOptions`.
@@ -2285,6 +2291,9 @@ export async function handleSurfaceAction(
2285
2291
  activeSurfaceId: surfaceId,
2286
2292
  displayContent,
2287
2293
  sourceActorPrincipalId,
2294
+ // Reached only when `enqueueMessage` declined to queue: the click is
2295
+ // starting this turn, so it is the actor the run belongs to.
2296
+ trustContext: actionTrustContext,
2288
2297
  isInteractive: SURFACE_ACTION_TURN_IS_INTERACTIVE,
2289
2298
  scripted: isSyntheticSurfaceActionContent(content),
2290
2299
  })
@@ -2472,6 +2481,7 @@ export async function handleSurfaceAction(
2472
2481
  activeSurfaceId: surfaceId,
2473
2482
  displayContent,
2474
2483
  sourceActorPrincipalId,
2484
+ trustContext: actionTrustContext,
2475
2485
  isInteractive: SURFACE_ACTION_TURN_IS_INTERACTIVE,
2476
2486
  // Rides the metadata bag rather than a typed option: the queue
2477
2487
  // round-trips `metadata` but not `PersistMessageOptions`.
@@ -2545,6 +2555,9 @@ export async function handleSurfaceAction(
2545
2555
  activeSurfaceId: surfaceId,
2546
2556
  displayContent,
2547
2557
  sourceActorPrincipalId,
2558
+ // Same as the history-restored branch: the enqueue declined, so this
2559
+ // click is the turn about to run.
2560
+ trustContext: actionTrustContext,
2548
2561
  isInteractive: SURFACE_ACTION_TURN_IS_INTERACTIVE,
2549
2562
  scripted: isSyntheticSurfaceActionContent(content),
2550
2563
  })
@@ -1119,11 +1119,10 @@ export class Conversation {
1119
1119
  preStrippedCount = boundary === -1 ? slicedDbMessages.length : boundary;
1120
1120
  }
1121
1121
 
1122
- // The injection-time personal-memory gate, so background/local
1123
- // conversations (sourceChannel `undefined` or `"vellum"`) can rehydrate
1124
- // the persisted v2 static memory block. The shared helper folds in the
1125
- // HTTP-auth-disabled dev bypass so rehydration and injection agree on the
1126
- // effective trust class.
1122
+ // The injection-time personal-memory gate, so rehydration of the persisted
1123
+ // blocks admits exactly the actors injection would. The shared helper folds
1124
+ // in the HTTP-auth-disabled dev bypass, so a turn with no bound actor
1125
+ // resolves the same way on both paths.
1127
1126
  const personalMemoryAllowed = isPersonalMemoryAllowed(this.trustContext);
1128
1127
  // Pruned v3 card slugs, read lazily on the first row that carries a v3
1129
1128
  // block (most conversations carry none, so most loads never query). The
@@ -1513,11 +1512,12 @@ export class Conversation {
1513
1512
 
1514
1513
  async ensureActorScopedHistory(): Promise<void> {
1515
1514
  const currentTrustClass = this.trustContext?.trustClass;
1516
- // `loadFromDb` gates personal-memory rehydration on `sourceChannel` too
1517
- // (via `isPersonalMemoryAllowed`), so a same-trust-class reuse from a
1518
- // different channel (e.g. internal `vellum` → remote channel) must also
1519
- // trigger a reload. Otherwise stale personal-memory blocks can leak to
1520
- // an untrusted remote turn, or be hidden when they should be present.
1515
+ // Tracked alongside the trust class because `loadFromDb` gates
1516
+ // personal-memory rehydration on `isPersonalMemoryAllowed`, which folds in
1517
+ // the disabled-auth elevation of an unbound actor: two contexts can share a
1518
+ // trust class and still differ here. A reuse that changes the answer has to
1519
+ // reload, or stale personal-memory blocks persist into a turn that must not
1520
+ // see them, or stay stripped from one that should.
1521
1521
  const currentPersonalMemoryAllowed = isPersonalMemoryAllowed(
1522
1522
  this.trustContext,
1523
1523
  );
@@ -2829,6 +2829,7 @@ export class Conversation {
2829
2829
  actionId: string,
2830
2830
  data?: Record<string, unknown>,
2831
2831
  sourceActorPrincipalId?: string,
2832
+ requesterTrustContext?: TrustContext,
2832
2833
  ): Promise<SurfaceActionResult> {
2833
2834
  return handleSurfaceActionImpl(
2834
2835
  this,
@@ -2836,6 +2837,7 @@ export class Conversation {
2836
2837
  actionId,
2837
2838
  data,
2838
2839
  sourceActorPrincipalId,
2840
+ requesterTrustContext,
2839
2841
  );
2840
2842
  }
2841
2843
 
@@ -98,6 +98,7 @@ import {
98
98
  registerMessagingProviders,
99
99
  registerWatcherProviders,
100
100
  } from "./providers-setup.js";
101
+ import { startResourcePressureGuardForLifecycle } from "./resource-pressure-guard-lifecycle.js";
101
102
  import { installShutdownHandlers } from "./shutdown-handlers.js";
102
103
  import { broadcastDaemonStatus } from "./status.js";
103
104
 
@@ -197,8 +198,10 @@ export async function runDaemon(): Promise<void> {
197
198
  }
198
199
  }
199
200
 
200
- // Start the runtime HTTP server early so /healthz answers ASAP. A bind
201
- // failure is non-fatal — the daemon falls back to IPC-only operation.
201
+ // Start the runtime HTTP server early so /healthz answers ASAP. Throws on
202
+ // EADDRINUSE to abort startup: another process holds the port every HTTP
203
+ // client (and the gateway's /v1/* proxy) targets, so an IPC-only daemon
204
+ // would look healthy while all HTTP traffic 502s.
202
205
  await startRuntimeHttpServer();
203
206
 
204
207
  // Warms the configured-probe cache (credential reads only, no DB). Fired
@@ -700,6 +703,7 @@ export async function runDaemon(): Promise<void> {
700
703
 
701
704
  startUsageTelemetryReporter();
702
705
  startDiskPressureGuardForLifecycle();
706
+ startResourcePressureGuardForLifecycle();
703
707
  startOrphanReaper();
704
708
  startEventLoopWatchdog();
705
709
 
@@ -48,18 +48,16 @@ interface BaseTransportMetadata {
48
48
  }
49
49
 
50
50
  /**
51
- * Transport metadata for interfaces that support the full desktop host-proxy
52
- * set (see `HostProxyInterfaceId` / `supportsHostProxy`). Carries the host
51
+ * Transport metadata for interfaces that support desktop host-proxy tools
52
+ * (see `HostProxyInterfaceId` / `supportsHostProxy`). Carries the host
53
53
  * environment fields the client reports so the `<workspace>` block renders
54
54
  * the user's actual machine rather than a containerized daemon's own OS.
55
55
  *
56
- * Today this variant is populated only by the macOS client, but the shape
57
- * is capability-keyed (not interface-name-keyed) so future host-capable
58
- * clients (e.g. a native Linux or Windows desktop) get the same treatment
59
- * automatically when added to `HostProxyInterfaceId`.
56
+ * The shape is capability-keyed so each native desktop client gets the same
57
+ * host-environment treatment through `HostProxyInterfaceId`.
60
58
  */
61
59
  export interface HostProxyTransportMetadata extends BaseTransportMetadata {
62
- /** Interface identifier — restricted to interfaces that support host proxies. */
60
+ /** Interface identifier restricted to interfaces that support host proxies. */
63
61
  interfaceId: HostProxyInterfaceId;
64
62
  /** Home directory of the user on the host machine (e.g. `NSHomeDirectory()`). */
65
63
  hostHomeDir?: string;
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Log-field builder for provider rejections that carry no actionable
3
+ * classification of their own (unclassified 4xx).
4
+ *
5
+ * The extracted fields on `ProviderError` (`apiErrorCode`, `message`) drop the
6
+ * detail an operator needs to find the offending request: which request field,
7
+ * which message, which byte pattern. The verbatim upstream body carries it, so
8
+ * it rides the log record, bounded so a large provider error page cannot flood
9
+ * the log stream.
10
+ */
11
+
12
+ import { ProviderError } from "../util/errors.js";
13
+ import { redactLogString } from "../util/log-redact.js";
14
+
15
+ /**
16
+ * Ceiling for the logged upstream body. Bodies are already capped at 16 KiB
17
+ * when captured (`providers/openai/api-error-normalization.ts`); this second,
18
+ * tighter bound is what a log record carries.
19
+ */
20
+ export const MAX_LOGGED_UPSTREAM_BODY_CHARS = 4096;
21
+
22
+ /**
23
+ * Upstream error codes whose message names the offending request content part,
24
+ * e.g. `Invalid 'input[191].content[1].text': string too long`. Kept narrow:
25
+ * codes outside this set have no such pointer, so parsing their message would
26
+ * only produce coincidental matches.
27
+ */
28
+ const CONTENT_PART_POINTER_CODES = new Set([
29
+ "string_above_max_length",
30
+ "invalid_body",
31
+ ]);
32
+
33
+ /**
34
+ * Positional pointer into the request payload. `input[N]` is the Responses API
35
+ * shape, `messages[N]` the Chat Completions shape; both index the request's
36
+ * message array in send order, so `N` is an offset into the conversation
37
+ * history that produced the request.
38
+ */
39
+ const CONTENT_PART_POINTER = /\b(?:input|messages)\[(\d+)\]\.content\[(\d+)\]/i;
40
+
41
+ export interface ProviderRejectionLogFields {
42
+ /** Verbatim upstream non-2xx body, truncated to the logged ceiling. */
43
+ upstreamErrorBody: string | null;
44
+ /** True when the body was cut to fit the ceiling. */
45
+ upstreamErrorBodyTruncated?: boolean;
46
+ apiErrorCode?: string;
47
+ apiErrorType?: string;
48
+ apiErrorParam?: string;
49
+ requestId?: string;
50
+ /** Index of the offending message within the request's message array. */
51
+ offendingMessageIndex?: number;
52
+ /** Index of the offending content part within that message. */
53
+ offendingContentIndex?: number;
54
+ }
55
+
56
+ /**
57
+ * Extract the offending `input[N].content[M]` coordinates from an upstream
58
+ * error message, for the codes that carry such a pointer.
59
+ */
60
+ function parseContentPartPointer(
61
+ error: ProviderError,
62
+ ): Pick<
63
+ ProviderRejectionLogFields,
64
+ "offendingMessageIndex" | "offendingContentIndex"
65
+ > {
66
+ const code = error.apiErrorCode?.toLowerCase();
67
+ if (!code || !CONTENT_PART_POINTER_CODES.has(code)) {
68
+ return {};
69
+ }
70
+ const match = CONTENT_PART_POINTER.exec(
71
+ `${error.message} ${error.rawBody ?? ""}`,
72
+ );
73
+ if (!match) {
74
+ return {};
75
+ }
76
+ const messageIndex = Number(match[1]);
77
+ const contentIndex = Number(match[2]);
78
+ if (
79
+ !Number.isSafeInteger(messageIndex) ||
80
+ !Number.isSafeInteger(contentIndex)
81
+ ) {
82
+ return {};
83
+ }
84
+ return {
85
+ offendingMessageIndex: messageIndex,
86
+ offendingContentIndex: contentIndex,
87
+ };
88
+ }
89
+
90
+ /** Diagnostic fields describing what the provider actually rejected. */
91
+ export function buildProviderRejectionLogFields(
92
+ error: Error,
93
+ ): ProviderRejectionLogFields {
94
+ if (!(error instanceof ProviderError)) {
95
+ return { upstreamErrorBody: null };
96
+ }
97
+
98
+ // The body is arbitrary upstream text under a custom field name, so it is
99
+ // outside the reach of the pino `err`/`req`/`res` serializers and is scrubbed
100
+ // here before it reaches the record.
101
+ const rawBody =
102
+ error.rawBody === undefined ? undefined : redactLogString(error.rawBody);
103
+ const truncated =
104
+ rawBody !== undefined && rawBody.length > MAX_LOGGED_UPSTREAM_BODY_CHARS;
105
+
106
+ return {
107
+ upstreamErrorBody:
108
+ rawBody === undefined
109
+ ? null
110
+ : rawBody.slice(0, MAX_LOGGED_UPSTREAM_BODY_CHARS),
111
+ ...(truncated ? { upstreamErrorBodyTruncated: true } : {}),
112
+ ...(error.apiErrorCode !== undefined
113
+ ? { apiErrorCode: error.apiErrorCode }
114
+ : {}),
115
+ ...(error.apiErrorType !== undefined
116
+ ? { apiErrorType: error.apiErrorType }
117
+ : {}),
118
+ ...(error.apiErrorParam !== undefined
119
+ ? { apiErrorParam: error.apiErrorParam }
120
+ : {}),
121
+ ...(error.requestId !== undefined ? { requestId: error.requestId } : {}),
122
+ ...parseContentPartPointer(error),
123
+ };
124
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Resource-pressure guard wiring for the daemon lifecycle.
3
+ *
4
+ * Starts the guard at boot and defers the first sample onto a macrotask so it
5
+ * never blocks startup, and stops the guard (cancelling any pending deferred
6
+ * sample) on shutdown. When the guard is disabled (non-platform), no deferred
7
+ * sample is scheduled.
8
+ */
9
+ import { getLogger } from "../util/logger.js";
10
+ import {
11
+ evaluateResourcePressureNow,
12
+ startResourcePressureGuard,
13
+ stopResourcePressureGuard,
14
+ } from "./resource-pressure-guard.js";
15
+
16
+ const log = getLogger("resource-pressure-guard-lifecycle");
17
+
18
+ let resourcePressureStartupSampleTimer: ReturnType<typeof setTimeout> | null =
19
+ null;
20
+
21
+ function runDeferredResourcePressureStartupSample(): void {
22
+ resourcePressureStartupSampleTimer = null;
23
+ try {
24
+ const status = evaluateResourcePressureNow();
25
+ if (status.error) {
26
+ log.warn(
27
+ { error: status.error },
28
+ "Resource pressure guard sample failed during startup, continuing",
29
+ );
30
+ }
31
+ } catch (err) {
32
+ log.warn(
33
+ { err },
34
+ "Resource pressure guard failed during startup, continuing",
35
+ );
36
+ }
37
+ }
38
+
39
+ export function startResourcePressureGuardForLifecycle(): void {
40
+ try {
41
+ const startedStatus = startResourcePressureGuard();
42
+ if (!startedStatus.enabled) {
43
+ return;
44
+ }
45
+ if (!resourcePressureStartupSampleTimer) {
46
+ resourcePressureStartupSampleTimer = setTimeout(
47
+ runDeferredResourcePressureStartupSample,
48
+ 0,
49
+ );
50
+ (resourcePressureStartupSampleTimer as { unref?: () => void }).unref?.();
51
+ }
52
+ } catch (err) {
53
+ log.warn(
54
+ { err },
55
+ "Resource pressure guard failed during startup, continuing",
56
+ );
57
+ }
58
+ }
59
+
60
+ export function stopResourcePressureGuardForLifecycle(): void {
61
+ if (resourcePressureStartupSampleTimer) {
62
+ clearTimeout(resourcePressureStartupSampleTimer);
63
+ resourcePressureStartupSampleTimer = null;
64
+ }
65
+ stopResourcePressureGuard();
66
+ }