@vellumai/assistant 0.7.2 → 0.8.0

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 (424) hide show
  1. package/ARCHITECTURE.md +45 -29
  2. package/Dockerfile +1 -0
  3. package/__tests__/permissions/gateway-threshold-reader.test.ts +236 -9
  4. package/bun.lock +3 -0
  5. package/docs/architecture/memory.md +5 -2
  6. package/knip.json +1 -0
  7. package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +13 -4
  8. package/node_modules/@vellumai/ipc-server-utils/bun.lock +24 -0
  9. package/node_modules/@vellumai/ipc-server-utils/package.json +18 -0
  10. package/node_modules/@vellumai/ipc-server-utils/src/index.ts +6 -0
  11. package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.test.ts +430 -0
  12. package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.ts +221 -0
  13. package/node_modules/@vellumai/ipc-server-utils/tsconfig.json +20 -0
  14. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -9
  15. package/node_modules/@vellumai/slack-text/src/index.test.ts +18 -35
  16. package/node_modules/@vellumai/slack-text/src/index.ts +2 -48
  17. package/openapi.yaml +470 -25
  18. package/package.json +3 -1
  19. package/src/__tests__/annotate-risk-options.test.ts +291 -0
  20. package/src/__tests__/app-control-flow.test.ts +21 -11
  21. package/src/__tests__/approval-cascade.test.ts +8 -16
  22. package/src/__tests__/approval-routes-http.test.ts +6 -0
  23. package/src/__tests__/assistant-event-hub.test.ts +48 -0
  24. package/src/__tests__/assistant-event.test.ts +0 -10
  25. package/src/__tests__/assistant-events-sse-hardening.test.ts +2 -7
  26. package/src/__tests__/assistant-feature-flags-integration.test.ts +18 -0
  27. package/src/__tests__/auto-analysis-end-to-end.test.ts +48 -0
  28. package/src/__tests__/background-workers-disk-pressure.test.ts +268 -0
  29. package/src/__tests__/call-constants.test.ts +10 -1
  30. package/src/__tests__/call-controller.test.ts +127 -0
  31. package/src/__tests__/call-conversation-messages.test.ts +8 -2
  32. package/src/__tests__/channel-inbound-disk-pressure.test.ts +537 -0
  33. package/src/__tests__/channel-readiness-service.test.ts +4 -2
  34. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +58 -28
  35. package/src/__tests__/config-loader-backfill.test.ts +379 -0
  36. package/src/__tests__/config-loader-platform-defaults.test.ts +284 -1
  37. package/src/__tests__/config-schema.test.ts +1 -0
  38. package/src/__tests__/config-watcher-cleanup-throttle.test.ts +18 -9
  39. package/src/__tests__/config-watcher.test.ts +140 -69
  40. package/src/__tests__/context-search-agent-runner.test.ts +61 -3
  41. package/src/__tests__/context-search-conversations-source.test.ts +0 -24
  42. package/src/__tests__/context-search-fanout.test.ts +0 -1
  43. package/src/__tests__/context-search-memory-source.test.ts +6 -33
  44. package/src/__tests__/context-search-memory-v2-source.test.ts +0 -2
  45. package/src/__tests__/context-search-pkb-source.test.ts +12 -7
  46. package/src/__tests__/context-search-workspace-source.test.ts +0 -1
  47. package/src/__tests__/conversation-abort-tool-results.test.ts +1 -0
  48. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +223 -0
  49. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -1
  50. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -1
  51. package/src/__tests__/conversation-agent-loop.test.ts +457 -8
  52. package/src/__tests__/conversation-confirmation-signals.test.ts +5 -13
  53. package/src/__tests__/conversation-error.test.ts +150 -3
  54. package/src/__tests__/conversation-init.benchmark.test.ts +1 -1
  55. package/src/__tests__/conversation-process-callsite.test.ts +38 -0
  56. package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -0
  57. package/src/__tests__/conversation-runtime-assembly.test.ts +74 -0
  58. package/src/__tests__/conversation-slash-unknown.test.ts +1 -0
  59. package/src/__tests__/conversation-speed-override.test.ts +0 -3
  60. package/src/__tests__/conversation-store.test.ts +0 -18
  61. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +170 -9
  62. package/src/__tests__/conversation-surfaces-app-control.test.ts +15 -4
  63. package/src/__tests__/conversation-surfaces-data-persist.test.ts +476 -0
  64. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +61 -5
  65. package/src/__tests__/conversation-workspace-injection.test.ts +1 -1
  66. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -1
  67. package/src/__tests__/credentials-cli.test.ts +7 -0
  68. package/src/__tests__/cu-unified-flow.test.ts +176 -10
  69. package/src/__tests__/date-context.test.ts +164 -2
  70. package/src/__tests__/disk-pressure-guard.test.ts +262 -0
  71. package/src/__tests__/disk-pressure-lifecycle.test.ts +168 -0
  72. package/src/__tests__/disk-pressure-policy.test.ts +241 -0
  73. package/src/__tests__/disk-pressure-routes.test.ts +379 -0
  74. package/src/__tests__/disk-pressure-tools.test.ts +277 -0
  75. package/src/__tests__/disk-usage.test.ts +150 -0
  76. package/src/__tests__/events-client-registration.test.ts +52 -0
  77. package/src/__tests__/events-dev-bypass-actor.test.ts +162 -0
  78. package/src/__tests__/file-write-tool.test.ts +4 -10
  79. package/src/__tests__/filing-service.test.ts +2 -20
  80. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +10 -26
  81. package/src/__tests__/heartbeat-disk-pressure.test.ts +183 -0
  82. package/src/__tests__/heartbeat-service.test.ts +260 -11
  83. package/src/__tests__/host-app-control-proxy.test.ts +195 -25
  84. package/src/__tests__/host-bash-proxy.test.ts +227 -34
  85. package/src/__tests__/host-bash-routes.test.ts +178 -13
  86. package/src/__tests__/host-cu-proxy.test.ts +210 -3
  87. package/src/__tests__/host-cu-routes-targeted.test.ts +141 -12
  88. package/src/__tests__/host-file-proxy-targeted.test.ts +48 -9
  89. package/src/__tests__/host-file-proxy.test.ts +268 -6
  90. package/src/__tests__/host-file-routes-targeted.test.ts +175 -17
  91. package/src/__tests__/host-transfer-proxy-targeted.test.ts +408 -59
  92. package/src/__tests__/host-transfer-routes-targeted.test.ts +232 -17
  93. package/src/__tests__/http-user-message-parity.test.ts +107 -1
  94. package/src/__tests__/injector-chain.test.ts +36 -16
  95. package/src/__tests__/injector-disk-pressure.test.ts +224 -0
  96. package/src/__tests__/injector-pkb-v2-silenced.test.ts +10 -7
  97. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +154 -67
  98. package/src/__tests__/managed-profile-guard.test.ts +18 -0
  99. package/src/__tests__/mcp-abort-signal.test.ts +130 -0
  100. package/src/__tests__/memory-admin-recall.test.ts +3 -11
  101. package/src/__tests__/memory-retrieval-pipeline.test.ts +22 -1
  102. package/src/__tests__/normalize-onboarding.test.ts +180 -0
  103. package/src/__tests__/notification-decision-fallback.test.ts +91 -0
  104. package/src/__tests__/notification-decision-strategy.test.ts +22 -0
  105. package/src/__tests__/oauth-cli.test.ts +121 -0
  106. package/src/__tests__/oauth-connect-routes.test.ts +316 -0
  107. package/src/__tests__/oauth-provider-seed-logos.test.ts +24 -2
  108. package/src/__tests__/onboarding-persona-write.test.ts +308 -0
  109. package/src/__tests__/openai-provider.test.ts +45 -8
  110. package/src/__tests__/persist-onboarding-artifacts.test.ts +44 -64
  111. package/src/__tests__/platform-callback-registration.test.ts +21 -4
  112. package/src/__tests__/platform.test.ts +2 -1
  113. package/src/__tests__/playbook-execution.test.ts +0 -43
  114. package/src/__tests__/plugin-tool-contribution.test.ts +47 -0
  115. package/src/__tests__/prechat-onboarding-contract.test.ts +214 -27
  116. package/src/__tests__/provider-tool-name.test.ts +23 -0
  117. package/src/__tests__/relay-server.test.ts +60 -5
  118. package/src/__tests__/runtime-events-sse.test.ts +4 -8
  119. package/src/__tests__/scheduler-disk-pressure.test.ts +148 -0
  120. package/src/__tests__/secret-ingress-http.test.ts +0 -1
  121. package/src/__tests__/secret-prompt-log-hygiene.test.ts +7 -5
  122. package/src/__tests__/secret-prompter-channel-fallback.test.ts +7 -5
  123. package/src/__tests__/secret-response-routing.test.ts +7 -5
  124. package/src/__tests__/server-history-render.test.ts +82 -0
  125. package/src/__tests__/skill-include-graph.test.ts +31 -0
  126. package/src/__tests__/skill-load-tool.test.ts +44 -16
  127. package/src/__tests__/skills.test.ts +39 -0
  128. package/src/__tests__/suggestion-routes.test.ts +46 -0
  129. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -42
  130. package/src/__tests__/tool-executor.test.ts +155 -0
  131. package/src/__tests__/twilio-validation.test.ts +2 -2
  132. package/src/__tests__/voice-session-bridge.test.ts +3 -0
  133. package/src/__tests__/workspace-migration-065-bump-stale-heartbeat-interval.test.ts +122 -0
  134. package/src/__tests__/workspace-migration-066-seed-heartbeat-callsite-cost-default.test.ts +285 -0
  135. package/src/__tests__/workspace-migration-068-release-notes-local-timezone.test.ts +90 -0
  136. package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +120 -0
  137. package/src/__tests__/workspace-migration-071-remove-safe-storage-release-note.test.ts +206 -0
  138. package/src/__tests__/workspace-migration-safe-storage-limits-release.test.ts +78 -0
  139. package/src/agent/loop.ts +11 -0
  140. package/src/approvals/guardian-request-resolvers.ts +3 -32
  141. package/src/backup/snapshot-lock.ts +2 -27
  142. package/src/bundler/compiler-tools.ts +3 -2
  143. package/src/calls/call-constants.ts +5 -8
  144. package/src/calls/call-controller.ts +130 -67
  145. package/src/calls/call-conversation-messages.ts +46 -10
  146. package/src/calls/relay-server.ts +7 -1
  147. package/src/calls/voice-session-bridge.ts +1 -1
  148. package/src/cli/commands/__tests__/webhooks.test.ts +0 -4
  149. package/src/cli/commands/bash.ts +35 -108
  150. package/src/cli/commands/contacts.ts +64 -25
  151. package/src/cli/commands/credentials.ts +56 -0
  152. package/src/cli/commands/memory-v2.ts +11 -10
  153. package/src/cli/commands/oauth/__tests__/connect.test.ts +401 -219
  154. package/src/cli/commands/oauth/connect.ts +124 -40
  155. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -3
  156. package/src/cli/commands/platform/__tests__/connect.test.ts +7 -1
  157. package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -1
  158. package/src/cli/commands/platform/__tests__/status.test.ts +103 -6
  159. package/src/cli/commands/platform/index.ts +16 -7
  160. package/src/cli/commands/status.ts +57 -0
  161. package/src/cli/program.ts +4 -2
  162. package/src/config/assistant-feature-flags.ts +13 -3
  163. package/src/config/bundled-skills/app-builder/SKILL.md +1 -3
  164. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +4 -3
  165. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +13 -7
  166. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +2 -2
  167. package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +2 -2
  168. package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +2 -2
  169. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +2 -2
  170. package/src/config/env.ts +0 -8
  171. package/src/config/feature-flag-registry.json +13 -5
  172. package/src/config/loader.ts +199 -27
  173. package/src/config/schemas/__tests__/memory-v2.test.ts +10 -5
  174. package/src/config/schemas/call-site-catalog.ts +14 -0
  175. package/src/config/schemas/channels.ts +0 -5
  176. package/src/config/schemas/heartbeat.ts +1 -1
  177. package/src/config/schemas/llm.ts +2 -0
  178. package/src/config/schemas/memory-lifecycle.ts +13 -0
  179. package/src/config/schemas/memory-v2.ts +76 -12
  180. package/src/config/schemas/platform.ts +43 -3
  181. package/src/config/schemas/services.ts +28 -0
  182. package/src/config/seed-inference-profiles.ts +230 -33
  183. package/src/contacts/contact-store.ts +0 -25
  184. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +32 -0
  185. package/src/daemon/__tests__/conversation-tool-setup.test.ts +86 -25
  186. package/src/daemon/assistant-attachments.ts +4 -4
  187. package/src/daemon/config-watcher.ts +85 -57
  188. package/src/daemon/conversation-agent-loop-handlers.ts +38 -0
  189. package/src/daemon/conversation-agent-loop.ts +183 -43
  190. package/src/daemon/conversation-error.ts +87 -15
  191. package/src/daemon/conversation-lifecycle.ts +22 -10
  192. package/src/daemon/conversation-process.ts +8 -0
  193. package/src/daemon/conversation-runtime-assembly.ts +26 -0
  194. package/src/daemon/conversation-store.ts +2 -2
  195. package/src/daemon/conversation-surfaces.ts +211 -29
  196. package/src/daemon/conversation-tool-setup.ts +66 -19
  197. package/src/daemon/conversation.ts +18 -23
  198. package/src/daemon/date-context.ts +71 -22
  199. package/src/daemon/disk-pressure-background-gate.ts +73 -0
  200. package/src/daemon/disk-pressure-guard.ts +343 -0
  201. package/src/daemon/disk-pressure-policy.ts +163 -0
  202. package/src/daemon/handlers/shared.ts +26 -1
  203. package/src/daemon/handlers/skills.ts +3 -4
  204. package/src/daemon/host-app-control-proxy.ts +137 -41
  205. package/src/daemon/host-bash-proxy.ts +47 -22
  206. package/src/daemon/host-browser-proxy.ts +1 -1
  207. package/src/daemon/host-cu-proxy.ts +50 -4
  208. package/src/daemon/host-file-proxy.ts +44 -8
  209. package/src/daemon/host-transfer-proxy.ts +97 -6
  210. package/src/daemon/lifecycle.ts +167 -101
  211. package/src/daemon/meet-host-supervisor.ts +4 -4
  212. package/src/daemon/meet-manifest-loader.ts +0 -1
  213. package/src/daemon/memory-v2-startup.ts +66 -15
  214. package/src/daemon/message-protocol.ts +3 -0
  215. package/src/daemon/message-types/conversations.ts +4 -0
  216. package/src/daemon/message-types/disk-pressure.ts +9 -0
  217. package/src/daemon/message-types/messages.ts +22 -1
  218. package/src/daemon/profiler-run-store.ts +5 -5
  219. package/src/daemon/tool-setup-types.ts +2 -2
  220. package/src/documents/document-store.ts +119 -0
  221. package/src/filing/filing-service.ts +29 -5
  222. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +9 -16
  223. package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +36 -0
  224. package/src/heartbeat/heartbeat-run-store.ts +13 -0
  225. package/src/heartbeat/heartbeat-service.ts +205 -31
  226. package/src/home/feed-scheduler.ts +18 -0
  227. package/src/inbound/platform-callback-registration.ts +8 -15
  228. package/src/ipc/__tests__/clients-list-ipc.test.ts +169 -0
  229. package/src/ipc/assistant-server.ts +149 -38
  230. package/src/ipc/gateway-client.ts +37 -3
  231. package/src/ipc/skill-server.ts +99 -42
  232. package/src/live-voice/live-voice-archive.ts +4 -4
  233. package/src/live-voice/protocol.ts +5 -7
  234. package/src/media/image-service.ts +1 -7
  235. package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +21 -13
  236. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +34 -51
  237. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +0 -6
  238. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +272 -0
  239. package/src/memory/admin.ts +5 -9
  240. package/src/memory/context-search/agent-runner.ts +19 -2
  241. package/src/memory/context-search/sources/conversations.ts +2 -11
  242. package/src/memory/context-search/sources/memory-v2.ts +1 -16
  243. package/src/memory/context-search/sources/memory.ts +2 -3
  244. package/src/memory/context-search/sources/pkb.ts +2 -3
  245. package/src/memory/context-search/types.ts +0 -1
  246. package/src/memory/conversation-crud.ts +4 -12
  247. package/src/memory/db-init.ts +2 -0
  248. package/src/memory/embedding-runtime-manager.ts +119 -5
  249. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +136 -82
  250. package/src/memory/graph/__tests__/handle-remember-v2.test.ts +11 -26
  251. package/src/memory/graph/conversation-graph-memory.ts +72 -61
  252. package/src/memory/graph/extraction.ts +1 -3
  253. package/src/memory/graph/graph-search.test.ts +11 -67
  254. package/src/memory/graph/graph-search.ts +4 -24
  255. package/src/memory/graph/retriever.test.ts +12 -1
  256. package/src/memory/graph/retriever.ts +10 -15
  257. package/src/memory/graph/tool-handlers.ts +3 -4
  258. package/src/memory/graph/tools.ts +4 -4
  259. package/src/memory/indexer.ts +53 -45
  260. package/src/memory/job-handlers/backfill.ts +2 -11
  261. package/src/memory/job-handlers/cleanup.ts +43 -0
  262. package/src/memory/job-handlers/embedding.ts +6 -8
  263. package/src/memory/job-handlers/summarization.ts +2 -7
  264. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +116 -0
  265. package/src/memory/jobs/embed-concept-page.ts +223 -87
  266. package/src/memory/jobs-store.ts +48 -0
  267. package/src/memory/jobs-worker.ts +85 -43
  268. package/src/memory/memory-v2-activation-log-store.ts +32 -14
  269. package/src/memory/memory-v2-concept-frequency.ts +169 -0
  270. package/src/memory/migrations/239-trace-events-created-at-index.ts +18 -0
  271. package/src/memory/migrations/index.ts +1 -0
  272. package/src/memory/pkb/pkb-search.test.ts +7 -0
  273. package/src/memory/pkb/pkb-search.ts +4 -5
  274. package/src/memory/qdrant-client.ts +3 -13
  275. package/src/memory/rerank-local.ts +374 -0
  276. package/src/memory/search/semantic.ts +10 -72
  277. package/src/memory/trace-event-store.ts +1 -17
  278. package/src/memory/v2/__tests__/activation.test.ts +346 -255
  279. package/src/memory/v2/__tests__/consolidation-job.test.ts +61 -40
  280. package/src/memory/v2/__tests__/injection.test.ts +297 -190
  281. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +61 -2
  282. package/src/memory/v2/__tests__/qdrant.test.ts +326 -9
  283. package/src/memory/v2/__tests__/reranker.test.ts +338 -0
  284. package/src/memory/v2/__tests__/sim.test.ts +113 -196
  285. package/src/memory/v2/__tests__/skill-store.test.ts +71 -65
  286. package/src/memory/v2/__tests__/static-context.test.ts +77 -14
  287. package/src/memory/v2/__tests__/sweep-job.test.ts +19 -33
  288. package/src/memory/v2/activation.ts +149 -156
  289. package/src/memory/v2/consolidation-job.ts +69 -20
  290. package/src/memory/v2/injection.ts +75 -68
  291. package/src/memory/v2/page-store.ts +39 -0
  292. package/src/memory/v2/prompts/consolidation.ts +41 -1
  293. package/src/memory/v2/qdrant.ts +306 -46
  294. package/src/memory/v2/reranker.ts +177 -0
  295. package/src/memory/v2/sim.ts +77 -110
  296. package/src/memory/v2/skill-content.ts +4 -3
  297. package/src/memory/v2/skill-store.ts +82 -59
  298. package/src/memory/v2/static-context.ts +26 -8
  299. package/src/memory/v2/sweep-job.ts +5 -6
  300. package/src/memory/v2/types.ts +17 -10
  301. package/src/notifications/copy-composer.ts +47 -0
  302. package/src/notifications/decision-engine.ts +46 -0
  303. package/src/notifications/signal.ts +4 -0
  304. package/src/oauth/AGENTS.md +3 -1
  305. package/src/oauth/__tests__/oauth-connect-state.test.ts +137 -0
  306. package/src/oauth/connect-orchestrator.ts +2 -0
  307. package/src/oauth/connection-resolver.test.ts +66 -1
  308. package/src/oauth/connection-resolver.ts +55 -1
  309. package/src/oauth/oauth-connect-state.ts +77 -0
  310. package/src/oauth/seed-providers.ts +58 -1
  311. package/src/permissions/gateway-threshold-reader.ts +116 -8
  312. package/src/permissions/prompter.ts +86 -96
  313. package/src/permissions/secret-prompter.ts +31 -31
  314. package/src/plugins/defaults/injectors.ts +36 -4
  315. package/src/plugins/defaults/memory-retrieval.ts +5 -6
  316. package/src/plugins/types.ts +7 -0
  317. package/src/proactive-artifact/aux-message-injector.ts +74 -0
  318. package/src/proactive-artifact/decision.test.ts +226 -0
  319. package/src/proactive-artifact/decision.ts +165 -0
  320. package/src/proactive-artifact/index.ts +7 -0
  321. package/src/proactive-artifact/job.test.ts +914 -0
  322. package/src/proactive-artifact/job.ts +366 -0
  323. package/src/proactive-artifact/message-copy.ts +58 -0
  324. package/src/proactive-artifact/trigger-state.test.ts +277 -0
  325. package/src/proactive-artifact/trigger-state.ts +119 -0
  326. package/src/prompts/normalize-onboarding.ts +80 -0
  327. package/src/prompts/persona-resolver.ts +101 -9
  328. package/src/prompts/system-prompt.ts +21 -7
  329. package/src/prompts/templates/BOOTSTRAP.md +13 -5
  330. package/src/prompts/templates/SOUL.md +13 -28
  331. package/src/providers/__tests__/retry-callsite.test.ts +222 -1
  332. package/src/providers/model-intents.ts +7 -0
  333. package/src/providers/openrouter/client.ts +8 -0
  334. package/src/providers/retry.ts +50 -0
  335. package/src/providers/types.ts +1 -0
  336. package/src/runtime/__tests__/agent-wake.test.ts +456 -3
  337. package/src/runtime/agent-wake.ts +238 -100
  338. package/src/runtime/assistant-event-hub.ts +36 -6
  339. package/src/runtime/assistant-event.ts +0 -1
  340. package/src/runtime/auth/__tests__/route-policy.test.ts +64 -0
  341. package/src/runtime/auth/route-policy.ts +15 -1
  342. package/src/runtime/auth/same-actor.ts +216 -0
  343. package/src/runtime/channel-approvals.ts +3 -2
  344. package/src/runtime/channel-retry-sweep.ts +65 -1
  345. package/src/runtime/local-actor-identity.ts +52 -11
  346. package/src/runtime/pending-interactions.ts +27 -15
  347. package/src/runtime/routes/__tests__/client-routes.test.ts +155 -0
  348. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +0 -5
  349. package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +1 -1
  350. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +147 -0
  351. package/src/runtime/routes/approval-routes.ts +7 -3
  352. package/src/runtime/routes/client-routes.ts +20 -2
  353. package/src/runtime/routes/consolidation-routes.ts +8 -9
  354. package/src/runtime/routes/contact-routes.ts +0 -25
  355. package/src/runtime/routes/conversation-query-routes.ts +44 -1
  356. package/src/runtime/routes/conversation-routes.ts +35 -26
  357. package/src/runtime/routes/debug-bash-routes.ts +165 -0
  358. package/src/runtime/routes/disk-pressure-routes.ts +121 -0
  359. package/src/runtime/routes/document-pdf-renderer.ts +6 -2
  360. package/src/runtime/routes/documents-routes.ts +2 -75
  361. package/src/runtime/routes/events-routes.ts +41 -9
  362. package/src/runtime/routes/filing-routes.ts +2 -3
  363. package/src/runtime/routes/host-bash-routes.ts +23 -3
  364. package/src/runtime/routes/host-cu-routes.ts +33 -6
  365. package/src/runtime/routes/host-file-routes.ts +32 -6
  366. package/src/runtime/routes/host-transfer-routes.ts +79 -16
  367. package/src/runtime/routes/identity-routes.ts +7 -138
  368. package/src/runtime/routes/inbound-message-handler.ts +77 -12
  369. package/src/runtime/routes/index.ts +6 -0
  370. package/src/runtime/routes/memory-item-routes.test.ts +37 -17
  371. package/src/runtime/routes/memory-item-routes.ts +5 -6
  372. package/src/runtime/routes/memory-v2-routes.ts +136 -17
  373. package/src/runtime/routes/oauth-connect-routes.ts +153 -0
  374. package/src/runtime/verification-outbound-actions.ts +4 -4
  375. package/src/schedule/run-script.ts +37 -5
  376. package/src/schedule/scheduler.ts +20 -1
  377. package/src/security/encrypted-store.ts +2 -0
  378. package/src/security/secure-keys.ts +55 -0
  379. package/src/skills/include-graph.ts +35 -13
  380. package/src/skills/remote-skill-policy.ts +4 -10
  381. package/src/subagent/index.ts +1 -7
  382. package/src/subagent/manager.ts +1 -15
  383. package/src/tasks/task-runner.ts +0 -1
  384. package/src/tasks/task-store.ts +0 -3
  385. package/src/tools/background-tool-registry.ts +17 -3
  386. package/src/tools/document/document-tool.ts +20 -0
  387. package/src/tools/executor.ts +18 -2
  388. package/src/tools/host-filesystem/edit.test.ts +151 -0
  389. package/src/tools/host-filesystem/edit.ts +43 -1
  390. package/src/tools/host-filesystem/read.test.ts +129 -0
  391. package/src/tools/host-filesystem/read.ts +43 -1
  392. package/src/tools/host-filesystem/transfer.test.ts +127 -2
  393. package/src/tools/host-filesystem/transfer.ts +56 -11
  394. package/src/tools/host-filesystem/write.test.ts +134 -0
  395. package/src/tools/host-filesystem/write.ts +43 -1
  396. package/src/tools/host-terminal/host-shell.ts +13 -6
  397. package/src/tools/mcp/mcp-tool-factory.ts +2 -1
  398. package/src/tools/memory/register.test.ts +14 -9
  399. package/src/tools/memory/register.ts +1 -2
  400. package/src/tools/permission-checker.ts +15 -0
  401. package/src/tools/provider-tool-name.ts +28 -0
  402. package/src/tools/registry.ts +30 -9
  403. package/src/tools/skills/load.ts +24 -20
  404. package/src/tools/terminal/shell.ts +9 -1
  405. package/src/tools/tool-approval-handler.ts +31 -6
  406. package/src/tools/tool-name-aliases.ts +19 -0
  407. package/src/tools/types.ts +43 -3
  408. package/src/tts/provider-catalog.ts +3 -5
  409. package/src/util/disk-usage.ts +138 -0
  410. package/src/util/platform.ts +21 -11
  411. package/src/util/process-liveness.ts +26 -0
  412. package/src/workspace/heartbeat-service.ts +19 -0
  413. package/src/workspace/migrations/065-bump-stale-heartbeat-interval.ts +60 -0
  414. package/src/workspace/migrations/066-seed-heartbeat-callsite-cost-default.ts +146 -0
  415. package/src/workspace/migrations/067-release-notes-safe-storage-limits.ts +14 -0
  416. package/src/workspace/migrations/068-release-notes-local-timezone.ts +65 -0
  417. package/src/workspace/migrations/069-seed-onboarding-threads.ts +28 -0
  418. package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +31 -0
  419. package/src/workspace/migrations/071-remove-safe-storage-release-note.ts +111 -0
  420. package/src/workspace/migrations/registry.ts +14 -0
  421. package/src/__tests__/conversation-tool-setup-memory-scope.test.ts +0 -167
  422. package/src/memory/v2/__tests__/skill-qdrant.test.ts +0 -657
  423. package/src/memory/v2/skill-qdrant.ts +0 -404
  424. package/src/signals/bash.ts +0 -198
@@ -179,9 +179,17 @@ class HostShellTool implements Tool {
179
179
  };
180
180
  }
181
181
  const background = input.background === true;
182
+ if (background && context.diskPressureCleanupModeActive === true) {
183
+ return {
184
+ content:
185
+ "Error: background host shell commands are not available during disk pressure cleanup mode.",
186
+ isError: true,
187
+ };
188
+ }
182
189
 
183
190
  const targetClientId =
184
- typeof input.target_client_id === "string" && input.target_client_id !== ""
191
+ typeof input.target_client_id === "string" &&
192
+ input.target_client_id !== ""
185
193
  ? input.target_client_id
186
194
  : undefined;
187
195
 
@@ -236,10 +244,7 @@ class HostShellTool implements Tool {
236
244
  // guard both targetClientId != null guards above are bypassed, and the
237
245
  // code falls through to local daemon execution — silently running commands
238
246
  // inside the Docker container instead of on the intended host machine.
239
- if (
240
- targetClientId != null &&
241
- !HostBashProxy.instance.isAvailable()
242
- ) {
247
+ if (targetClientId != null && !HostBashProxy.instance.isAvailable()) {
243
248
  return {
244
249
  content: `Error: target client "${targetClientId}" is no longer connected. The specified client may have disconnected since the tool was called. Run \`assistant clients list --capability host_bash\` to see currently connected clients.`,
245
250
  isError: true,
@@ -287,6 +292,7 @@ class HostShellTool implements Tool {
287
292
  },
288
293
  context.conversationId,
289
294
  abortController.signal,
295
+ context.sourceActorPrincipalId,
290
296
  );
291
297
 
292
298
  proxyPromise
@@ -315,7 +321,7 @@ class HostShellTool implements Tool {
315
321
  conversationId: context.conversationId,
316
322
  command,
317
323
  startedAt: Date.now(),
318
- cancel: () => abortController.abort(),
324
+ cancel: (reason?: string) => abortController.abort(reason),
319
325
  });
320
326
 
321
327
  return {
@@ -334,6 +340,7 @@ class HostShellTool implements Tool {
334
340
  },
335
341
  context.conversationId,
336
342
  context.signal,
343
+ context.sourceActorPrincipalId,
337
344
  );
338
345
  }
339
346
 
@@ -2,6 +2,7 @@ import type { McpServerConfig } from "../../config/schemas/mcp.js";
2
2
  import type { McpServerManager } from "../../mcp/manager.js";
3
3
  import { RiskLevel } from "../../permissions/types.js";
4
4
  import type { ToolDefinition } from "../../providers/types.js";
5
+ import { toProviderSafeToolName } from "../provider-tool-name.js";
5
6
  import { schemaDefinesProperty } from "../schema-transforms.js";
6
7
  import type { Tool, ToolContext, ToolExecutionResult } from "../types.js";
7
8
 
@@ -16,7 +17,7 @@ const riskMap: Record<string, RiskLevel> = {
16
17
  * and with core/skill tools.
17
18
  */
18
19
  function mcpToolName(serverId: string, toolName: string): string {
19
- return `mcp__${serverId}__${toolName}`;
20
+ return toProviderSafeToolName(`mcp__${serverId}__${toolName}`);
20
21
  }
21
22
 
22
23
  export interface McpToolMetadata {
@@ -14,6 +14,14 @@ import {
14
14
  import { PKB_WORKSPACE_SCOPE } from "../../memory/pkb/types.js";
15
15
  import type { ToolContext } from "../types.js";
16
16
 
17
+ // This test exercises v1 PKB re-index enqueue. `config.memory.v2.enabled`
18
+ // (default `true`) makes the enqueue path skipped — force it off so the
19
+ // v1 PKB index path stays under test.
20
+ mock.module("../../config/loader.js", () => ({
21
+ getConfig: () => ({ memory: { v2: { enabled: false } } }),
22
+ loadConfig: () => ({ memory: { v2: { enabled: false } } }),
23
+ }));
24
+
17
25
  let tmpWorkspace: string;
18
26
  let previousWorkspaceEnv: string | undefined;
19
27
 
@@ -175,7 +183,7 @@ describe("recallTool.execute", () => {
175
183
  max_results: 4,
176
184
  depth: "deep",
177
185
  },
178
- makeContext({ memoryScopeId: "scope-filter" }),
186
+ makeContext(),
179
187
  );
180
188
 
181
189
  expect(result).toEqual({
@@ -196,7 +204,7 @@ describe("recallTool.execute", () => {
196
204
 
197
205
  const result = await recallTool.execute(
198
206
  { query: "fallback search", sources: ["workspace"], depth: "fast" },
199
- makeContext({ memoryScopeId: "scope-fallback" }),
207
+ makeContext(),
200
208
  );
201
209
 
202
210
  expect(result).toEqual({
@@ -205,7 +213,7 @@ describe("recallTool.execute", () => {
205
213
  });
206
214
  });
207
215
 
208
- test("propagates tool context and defaults missing memory scope", async () => {
216
+ test("propagates tool context", async () => {
209
217
  const controller = new AbortController();
210
218
 
211
219
  await recallTool.execute(
@@ -221,7 +229,6 @@ describe("recallTool.execute", () => {
221
229
  expect(recallCalls[0]?.context).toEqual({
222
230
  workingDir: "/workspace/project",
223
231
  conversationId: "conv-context",
224
- memoryScopeId: "default",
225
232
  config: getConfig(),
226
233
  signal: controller.signal,
227
234
  });
@@ -275,9 +282,7 @@ describe("rememberTool.execute — PKB re-index enqueue", () => {
275
282
  test("enqueues re-index jobs for both buffer and daily archive paths", async () => {
276
283
  const result = await rememberTool.execute(
277
284
  { content: "index me please" },
278
- // Passes a non-default per-conversation scopeId to prove the PKB
279
- // enqueue ignores it and pins to PKB_WORKSPACE_SCOPE instead.
280
- makeContext({ memoryScopeId: "scope-enqueue" }),
285
+ makeContext(),
281
286
  );
282
287
  expect(result.isError).toBe(false);
283
288
 
@@ -308,7 +313,7 @@ describe("rememberTool.execute — PKB re-index enqueue", () => {
308
313
  test("does not enqueue when content is empty (write was skipped)", async () => {
309
314
  const result = await rememberTool.execute(
310
315
  { content: " " },
311
- makeContext({ memoryScopeId: "scope-empty" }),
316
+ makeContext(),
312
317
  );
313
318
  expect(result.isError).toBe(true);
314
319
  expect(enqueueCalls).toHaveLength(0);
@@ -319,7 +324,7 @@ describe("rememberTool.execute — PKB re-index enqueue", () => {
319
324
 
320
325
  const result = await rememberTool.execute(
321
326
  { content: "enqueue will throw" },
322
- makeContext({ memoryScopeId: "scope-throw" }),
327
+ makeContext(),
323
328
  );
324
329
 
325
330
  // Remember call succeeded despite enqueue throwing for each write.
@@ -34,7 +34,7 @@ class RememberTool implements Tool {
34
34
  const result = handleRemember(
35
35
  typedInput,
36
36
  context.conversationId,
37
- context.memoryScopeId ?? "default",
37
+ "default",
38
38
  getConfig(),
39
39
  );
40
40
  return {
@@ -73,7 +73,6 @@ class RecallTool implements Tool {
73
73
  const result = await runAgenticRecall(input as unknown as RecallInput, {
74
74
  workingDir: context.workingDir,
75
75
  conversationId: context.conversationId,
76
- memoryScopeId: context.memoryScopeId ?? "default",
77
76
  config,
78
77
  signal: context.signal,
79
78
  });
@@ -32,6 +32,11 @@ export type PermissionDecision =
32
32
  riskLevel: string;
33
33
  riskReason: string;
34
34
  riskScopeOptions: Array<{ pattern: string; label: string }>;
35
+ riskAllowlistOptions?: Array<{
36
+ label: string;
37
+ description: string;
38
+ pattern: string;
39
+ }>;
35
40
  riskDirectoryScopeOptions?: Array<{ scope: string; label: string }>;
36
41
  isContainerized?: boolean;
37
42
  };
@@ -51,6 +56,11 @@ export type PermissionDecision =
51
56
  riskLevel: string;
52
57
  riskReason: string;
53
58
  riskScopeOptions: Array<{ pattern: string; label: string }>;
59
+ riskAllowlistOptions?: Array<{
60
+ label: string;
61
+ description: string;
62
+ pattern: string;
63
+ }>;
54
64
  riskDirectoryScopeOptions?: Array<{ scope: string; label: string }>;
55
65
  isContainerized?: boolean;
56
66
  };
@@ -111,7 +121,12 @@ export class PermissionChecker {
111
121
  ? {
112
122
  riskLevel: cachedAssessment.riskLevel,
113
123
  riskReason: cachedAssessment.reason,
124
+ // Display ladder (regex patterns — internal only, not for save).
114
125
  riskScopeOptions: cachedAssessment.scopeOptions,
126
+ // Save ladder (Minimatch globs — what the gateway matches against).
127
+ // Populated for classifiers that produce allowlist options
128
+ // (bash, file, skill); undefined otherwise.
129
+ riskAllowlistOptions: cachedAssessment.allowlistOptions,
115
130
  riskDirectoryScopeOptions: cachedAssessment.directoryScopeOptions,
116
131
  isContainerized: getIsContainerized(),
117
132
  }
@@ -0,0 +1,28 @@
1
+ import { createHash } from "node:crypto";
2
+
3
+ const PROVIDER_TOOL_NAME_MAX_LENGTH = 64;
4
+ const PROVIDER_TOOL_NAME_RE = /^[a-zA-Z0-9_-]{1,64}$/;
5
+ const HASH_LENGTH = 12;
6
+
7
+ export function isProviderSafeToolName(name: string): boolean {
8
+ return PROVIDER_TOOL_NAME_RE.test(name);
9
+ }
10
+
11
+ export function toProviderSafeToolName(rawName: string): string {
12
+ const trimmed = rawName.trim();
13
+ if (isProviderSafeToolName(rawName)) {
14
+ return rawName;
15
+ }
16
+
17
+ const hash = createHash("sha256")
18
+ .update(rawName)
19
+ .digest("hex")
20
+ .slice(0, HASH_LENGTH);
21
+ const suffix = `__${hash}`;
22
+ const maxBaseLength = PROVIDER_TOOL_NAME_MAX_LENGTH - suffix.length;
23
+ const sanitized =
24
+ trimmed.replace(/[^a-zA-Z0-9_-]+/g, "_").replace(/^_+|_+$/g, "") || "tool";
25
+ const base = sanitized.slice(0, maxBaseLength).replace(/_+$/g, "") || "tool";
26
+
27
+ return `${base}${suffix}`;
28
+ }
@@ -8,6 +8,7 @@ import { hostFileReadTool } from "./host-filesystem/read.js";
8
8
  import { hostFileTransferTool } from "./host-filesystem/transfer.js";
9
9
  import { hostFileWriteTool } from "./host-filesystem/write.js";
10
10
  import { hostShellTool } from "./host-terminal/host-shell.js";
11
+ import { toProviderSafeToolName } from "./provider-tool-name.js";
11
12
  import { registerSystemTools } from "./system/register.js";
12
13
  import type { Tool } from "./types.js";
13
14
  import { allUiSurfaceTools } from "./ui-surface/definitions.js";
@@ -75,6 +76,24 @@ const skillRefCount = new Map<string, number>();
75
76
  // separate and covers the case of two extensions choosing the same tool name.
76
77
  const pluginRefCount = new Map<string, number>();
77
78
 
79
+ function withProviderSafeToolName(tool: Tool): Tool {
80
+ const safeName = toProviderSafeToolName(tool.name);
81
+ if (safeName === tool.name) {
82
+ return tool;
83
+ }
84
+
85
+ return {
86
+ ...tool,
87
+ name: safeName,
88
+ getDefinition(): ToolDefinition {
89
+ return {
90
+ ...tool.getDefinition(),
91
+ name: safeName,
92
+ };
93
+ },
94
+ };
95
+ }
96
+
78
97
  export function registerTool(tool: Tool): void {
79
98
  const existing = tools.get(tool.name);
80
99
  if (existing) {
@@ -176,15 +195,17 @@ export function registerPluginTools(
176
195
  pluginName: string,
177
196
  newTools: Tool[],
178
197
  ): Tool[] {
179
- const stamped: Tool[] = newTools.map((tool) => ({
180
- ...tool,
181
- origin: "plugin" as const,
182
- ownerPluginId: pluginName,
183
- ownerSkillId: undefined,
184
- ownerMcpServerId: undefined,
185
- ownerSkillBundled: undefined,
186
- ownerSkillVersionHash: undefined,
187
- }));
198
+ const stamped: Tool[] = newTools.map((tool) =>
199
+ withProviderSafeToolName({
200
+ ...tool,
201
+ origin: "plugin" as const,
202
+ ownerPluginId: pluginName,
203
+ ownerSkillId: undefined,
204
+ ownerMcpServerId: undefined,
205
+ ownerSkillBundled: undefined,
206
+ ownerSkillVersionHash: undefined,
207
+ }),
208
+ );
188
209
 
189
210
  const accepted: Tool[] = [];
190
211
  for (const tool of stamped) {
@@ -19,7 +19,7 @@ import {
19
19
  import {
20
20
  collectAllMissing,
21
21
  indexCatalogById,
22
- validateIncludes,
22
+ validateIncludeCycles,
23
23
  } from "../../skills/include-graph.js";
24
24
  import { renderInlineCommands } from "../../skills/inline-command-render.js";
25
25
  import { parseToolManifestFile } from "../../skills/tool-manifest.js";
@@ -204,6 +204,7 @@ export class SkillLoadTool implements Tool {
204
204
 
205
205
  // Load catalog for include validation and child metadata output
206
206
  let catalogIndex: Map<string, SkillSummary> | undefined;
207
+ let missingIncludedSkillIds: string[] = [];
207
208
  if (skill.includes && skill.includes.length > 0) {
208
209
  let catalog = loadSkillCatalog();
209
210
  catalogIndex = indexCatalogById(catalog);
@@ -260,19 +261,13 @@ export class SkillLoadTool implements Tool {
260
261
  catalogIndex = indexCatalogById(catalog);
261
262
  }
262
263
 
263
- // Validate (fail-closed - catches genuinely missing deps + cycles)
264
- const validation = validateIncludes(skill.id, catalogIndex);
264
+ missingIncludedSkillIds = [...collectAllMissing(skill.id, catalogIndex)];
265
+
266
+ // Validate cycles fail closed. Missing includes are advisory: the parent
267
+ // skill should still load so the assistant can decide whether to search
268
+ // for and install the suggested dependency.
269
+ const validation = validateIncludeCycles(skill.id, catalogIndex);
265
270
  if (!validation.ok) {
266
- if (validation.error === "missing") {
267
- return {
268
- content: `Error: skill "${skill.id}" includes "${
269
- validation.missingChildId
270
- }" which was not found (referenced by "${
271
- validation.parentId
272
- }" via path: ${validation.path.join(" → ")})`,
273
- isError: true,
274
- };
275
- }
276
271
  if (validation.error === "cycle") {
277
272
  return {
278
273
  content: `Error: skill "${
@@ -283,10 +278,6 @@ export class SkillLoadTool implements Tool {
283
278
  isError: true,
284
279
  };
285
280
  }
286
- return {
287
- content: `Error: skill "${skill.id}" has an invalid include graph`,
288
- isError: true,
289
- };
290
281
  }
291
282
  }
292
283
 
@@ -444,13 +435,25 @@ export class SkillLoadTool implements Tool {
444
435
  }
445
436
  }
446
437
  }
447
- immediateChildrenSection = `Included Skills (immediate):\n${childLines.join(
448
- "\n",
449
- )}`;
438
+ immediateChildrenSection =
439
+ childLines.length > 0
440
+ ? `Included Skills (immediate):\n${childLines.join("\n")}`
441
+ : "Included Skills (immediate): none";
450
442
  } else {
451
443
  immediateChildrenSection = "Included Skills (immediate): none";
452
444
  }
453
445
 
446
+ const missingIncludesSection =
447
+ missingIncludedSkillIds.length > 0
448
+ ? [
449
+ "Suggested Included Skills (not loaded):",
450
+ ...missingIncludedSkillIds.map(
451
+ (id) =>
452
+ ` - ${id}: not installed or unavailable. If this task needs it, search for and install this skill, then load it.`,
453
+ ),
454
+ ].join("\n")
455
+ : undefined;
456
+
454
457
  let versionHash: string | undefined;
455
458
  try {
456
459
  versionHash = computeSkillVersionHash(skill.directoryPath);
@@ -512,6 +515,7 @@ export class SkillLoadTool implements Tool {
512
515
  : []),
513
516
  ...includedBodies.flatMap((b) => [b, ""]),
514
517
  immediateChildrenSection,
518
+ ...(missingIncludesSection ? [missingIncludesSection] : []),
515
519
  "",
516
520
  `<loaded_skill id="${skill.id}"${versionAttr} />`,
517
521
  ...includeMarkers,
@@ -111,6 +111,15 @@ class ShellTool implements Tool {
111
111
  return { content: "Error: command contains null bytes", isError: true };
112
112
  }
113
113
 
114
+ const background = input.background === true;
115
+ if (background && context.diskPressureCleanupModeActive === true) {
116
+ return {
117
+ content:
118
+ "Error: background shell commands are not available during disk pressure cleanup mode.",
119
+ isError: true,
120
+ };
121
+ }
122
+
114
123
  const config = getConfig();
115
124
  const shellLockdownActive =
116
125
  isCesShellLockdownEnabled(config) &&
@@ -276,7 +285,6 @@ class ShellTool implements Tool {
276
285
  // Background mode: spawn and return immediately. The process output is
277
286
  // delivered to the conversation as a wake when the process exits.
278
287
  // -----------------------------------------------------------------------
279
- const background = input.background === true;
280
288
  if (background) {
281
289
  // Check the registry limit BEFORE spawning so we never leak an
282
290
  // untracked process when the registry is full.
@@ -13,12 +13,13 @@ import { getLogger } from "../util/logger.js";
13
13
  import { getAllTools, getTool } from "./registry.js";
14
14
  import { isSideEffectTool } from "./side-effects.js";
15
15
  import { summarizeToolInput } from "./tool-input-summary.js";
16
- import type {
17
- ExecutionTarget,
18
- Tool,
19
- ToolContext,
20
- ToolExecutionResult,
21
- ToolLifecycleEvent,
16
+ import {
17
+ type ExecutionTarget,
18
+ isDiskPressureCleanupToolName,
19
+ type Tool,
20
+ type ToolContext,
21
+ type ToolExecutionResult,
22
+ type ToolLifecycleEvent,
22
23
  } from "./types.js";
23
24
  import { enforceVerificationControlPlanePolicy } from "./verification-control-plane-policy.js";
24
25
 
@@ -309,6 +310,30 @@ export class ToolApprovalHandler {
309
310
  };
310
311
  }
311
312
 
313
+ if (
314
+ context.diskPressureCleanupModeActive === true &&
315
+ !isDiskPressureCleanupToolName(name)
316
+ ) {
317
+ const msg = `Tool "${name}" is not available during disk pressure cleanup mode.`;
318
+ const durationMs = Date.now() - startTime;
319
+ emitLifecycleEvent({
320
+ type: "error",
321
+ toolName: name,
322
+ executionTarget,
323
+ input,
324
+ workingDir: context.workingDir,
325
+ conversationId: context.conversationId,
326
+ requestId: context.requestId,
327
+ riskLevel,
328
+ decision: "error",
329
+ durationMs,
330
+ errorMessage: msg,
331
+ isExpected: true,
332
+ errorCategory: "tool_failure",
333
+ });
334
+ return { allowed: false, result: { content: msg, isError: true } };
335
+ }
336
+
312
337
  // Gate tools not active for the current turn
313
338
  if (context.allowedToolNames && !context.allowedToolNames.has(name)) {
314
339
  const msg = `Tool "${name}" is not currently active. Load the skill that provides this tool first.`;
@@ -0,0 +1,19 @@
1
+ const TOOL_NAME_ALIASES = new Map<string, string>([
2
+ ["create_app", "app_create"],
3
+ ]);
4
+
5
+ /**
6
+ * Resolve high-confidence compatibility aliases before active-tool gating.
7
+ * Keep this list narrow: aliases should only cover observed model drift where
8
+ * the canonical target is active for the turn.
9
+ */
10
+ export function resolveToolNameAlias(
11
+ name: string,
12
+ allowedToolNames?: ReadonlySet<string>,
13
+ ): string {
14
+ if (allowedToolNames?.has(name)) return name;
15
+ const canonical = TOOL_NAME_ALIASES.get(name);
16
+ if (!canonical) return name;
17
+ if (allowedToolNames && !allowedToolNames.has(canonical)) return name;
18
+ return canonical;
19
+ }
@@ -18,6 +18,20 @@ import type { SecretPromptResult } from "../permissions/secret-prompter.js";
18
18
  import type { ContentBlock } from "../providers/types.js";
19
19
  import type { TrustClass } from "../runtime/actor-trust-resolver.js";
20
20
 
21
+ export const DISK_PRESSURE_CLEANUP_TOOL_NAMES: ReadonlySet<string> = new Set([
22
+ "bash",
23
+ "host_bash",
24
+ "file_read",
25
+ "file_list",
26
+ "host_file_read",
27
+ "background_tool_list",
28
+ "background_tool_cancel",
29
+ ]);
30
+
31
+ export function isDiskPressureCleanupToolName(name: string): boolean {
32
+ return DISK_PRESSURE_CLEANUP_TOOL_NAMES.has(name);
33
+ }
34
+
21
35
  // ---------------------------------------------------------------------------
22
36
  // Re-exports + concrete overlays for types that live in
23
37
  // @vellumai/skill-host-contracts.
@@ -101,8 +115,26 @@ export interface ToolExecutionResult {
101
115
  riskThreshold?: string;
102
116
  /** Whether the daemon is running in a containerized (Docker) environment. */
103
117
  isContainerized?: boolean;
104
- /** Scope options ladder for the rule editor (narrowest to broadest). */
118
+ /**
119
+ * Display-only ladder of scope option labels for the rule editor
120
+ * (narrowest to broadest). The `pattern` field here is a regex-style
121
+ * descriptor used internally by the daemon and is NOT a valid trust
122
+ * rule pattern. Use `riskAllowlistOptions` for the pattern that gets
123
+ * saved as a trust rule.
124
+ */
105
125
  riskScopeOptions?: Array<{ pattern: string; label: string }>;
126
+ /**
127
+ * Allowlist options for the rule editor save path (narrowest to
128
+ * broadest). Each `pattern` is a Minimatch-glob compatible string
129
+ * (e.g. raw command for exact match, `action:<program>` for command
130
+ * wildcards) — what the gateway actually matches against. Mirrors
131
+ * the `allowlistOptions` field on `ConfirmationRequest` SSE events.
132
+ */
133
+ riskAllowlistOptions?: Array<{
134
+ label: string;
135
+ description: string;
136
+ pattern: string;
137
+ }>;
106
138
  /** Directory scope ladder for the rule editor (narrowest to broadest). */
107
139
  riskDirectoryScopeOptions?: Array<{ scope: string; label: string }>;
108
140
  /**
@@ -177,6 +209,8 @@ export interface ToolContext {
177
209
  proxyToolResolver?: ProxyToolResolver;
178
210
  /** When set, only tools in this set may execute. Tools outside the set are blocked with an error. */
179
211
  allowedToolNames?: Set<string>;
212
+ /** True when this turn is restricted to storage cleanup-safe tools. */
213
+ diskPressureCleanupModeActive?: boolean;
180
214
  /** Prompt the user for a secret value via native SecureField UI. */
181
215
  requestSecret?: (params: {
182
216
  service: string;
@@ -192,8 +226,6 @@ export interface ToolContext {
192
226
  sendToClient?: (msg: { type: string; [key: string]: unknown }) => void;
193
227
  /** True when an interactive client is connected (not just a no-op callback). */
194
228
  isInteractive?: boolean;
195
- /** Memory scope ID from the conversation's memory policy, so memory tools can target the correct scope. */
196
- memoryScopeId?: string;
197
229
  /** When true, tools with side effects should always prompt for confirmation. */
198
230
  forcePromptSideEffects?: boolean;
199
231
  /**
@@ -268,6 +300,14 @@ export interface ToolContext {
268
300
  * `executeSubagentSpawn` in tools/subagent/spawn.ts.
269
301
  */
270
302
  overrideProfile?: string;
303
+ /**
304
+ * Canonical principal ID of the actor on whose behalf this tool invocation
305
+ * is running. Sourced from `conversation.trustContext.guardianPrincipalId`.
306
+ * Used by host proxies to bind cross-client targeted execution to the same
307
+ * authenticated user identity. May be undefined for legacy/internal flows
308
+ * with no resolved actor identity.
309
+ */
310
+ sourceActorPrincipalId?: string;
271
311
  }
272
312
 
273
313
  export interface Tool {
@@ -13,8 +13,6 @@
13
13
 
14
14
  import type { TtsCallMode, TtsProviderId } from "./types.js";
15
15
 
16
- export type { TtsCallMode } from "./types.js";
17
-
18
16
  // ---------------------------------------------------------------------------
19
17
  // Catalog entry model
20
18
  // ---------------------------------------------------------------------------
@@ -22,7 +20,7 @@ export type { TtsCallMode } from "./types.js";
22
20
  /**
23
21
  * Metadata about a secret (API key / credential) required by a provider.
24
22
  */
25
- export interface TtsProviderSecretRequirement {
23
+ interface TtsProviderSecretRequirement {
26
24
  /**
27
25
  * The key used to retrieve this secret from the secure credential store.
28
26
  *
@@ -49,7 +47,7 @@ export interface TtsProviderSecretRequirement {
49
47
  * These describe static, provider-wide traits — they do not change based
50
48
  * on runtime configuration or per-request parameters.
51
49
  */
52
- export interface TtsProviderCatalogCapabilities {
50
+ interface TtsProviderCatalogCapabilities {
53
51
  /** Whether the provider supports chunk-level streaming synthesis. */
54
52
  readonly supportsStreaming: boolean;
55
53
 
@@ -64,7 +62,7 @@ export interface TtsProviderCatalogCapabilities {
64
62
  * metadata level — identity, display name, telephony call mode,
65
63
  * capabilities, and secret requirements.
66
64
  */
67
- export interface TtsProviderCatalogEntry {
65
+ interface TtsProviderCatalogEntry {
68
66
  /** Unique provider identifier matching {@link TtsProviderId}. */
69
67
  readonly id: TtsProviderId;
70
68