@vellumai/assistant 0.7.2 → 0.7.3

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 (347) hide show
  1. package/ARCHITECTURE.md +16 -1
  2. package/docs/architecture/memory.md +5 -2
  3. package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +13 -4
  4. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -9
  5. package/node_modules/@vellumai/slack-text/src/index.test.ts +18 -35
  6. package/node_modules/@vellumai/slack-text/src/index.ts +2 -48
  7. package/openapi.yaml +449 -22
  8. package/package.json +1 -1
  9. package/src/__tests__/app-control-flow.test.ts +21 -11
  10. package/src/__tests__/assistant-event-hub.test.ts +48 -0
  11. package/src/__tests__/assistant-event.test.ts +0 -10
  12. package/src/__tests__/assistant-events-sse-hardening.test.ts +2 -7
  13. package/src/__tests__/assistant-feature-flags-integration.test.ts +18 -0
  14. package/src/__tests__/auto-analysis-end-to-end.test.ts +62 -1
  15. package/src/__tests__/background-workers-disk-pressure.test.ts +268 -0
  16. package/src/__tests__/call-conversation-messages.test.ts +8 -2
  17. package/src/__tests__/channel-inbound-disk-pressure.test.ts +537 -0
  18. package/src/__tests__/channel-readiness-service.test.ts +4 -2
  19. package/src/__tests__/config-loader-backfill.test.ts +379 -0
  20. package/src/__tests__/config-schema.test.ts +1 -0
  21. package/src/__tests__/config-watcher-cleanup-throttle.test.ts +18 -9
  22. package/src/__tests__/config-watcher.test.ts +140 -69
  23. package/src/__tests__/context-search-agent-runner.test.ts +61 -3
  24. package/src/__tests__/context-search-conversations-source.test.ts +0 -24
  25. package/src/__tests__/context-search-fanout.test.ts +0 -1
  26. package/src/__tests__/context-search-memory-source.test.ts +3 -7
  27. package/src/__tests__/context-search-memory-v2-source.test.ts +0 -2
  28. package/src/__tests__/context-search-pkb-source.test.ts +0 -1
  29. package/src/__tests__/context-search-workspace-source.test.ts +0 -1
  30. package/src/__tests__/conversation-abort-tool-results.test.ts +6 -0
  31. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +223 -0
  32. package/src/__tests__/conversation-agent-loop.test.ts +454 -5
  33. package/src/__tests__/conversation-error.test.ts +150 -3
  34. package/src/__tests__/conversation-process-callsite.test.ts +43 -0
  35. package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
  36. package/src/__tests__/conversation-runtime-assembly.test.ts +65 -0
  37. package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
  38. package/src/__tests__/conversation-speed-override.test.ts +0 -3
  39. package/src/__tests__/conversation-store.test.ts +0 -18
  40. package/src/__tests__/conversation-surfaces-app-control.test.ts +15 -4
  41. package/src/__tests__/conversation-surfaces-data-persist.test.ts +404 -0
  42. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +2 -5
  43. package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
  44. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -0
  45. package/src/__tests__/credentials-cli.test.ts +7 -0
  46. package/src/__tests__/cu-unified-flow.test.ts +176 -10
  47. package/src/__tests__/date-context.test.ts +164 -2
  48. package/src/__tests__/disk-pressure-guard.test.ts +262 -0
  49. package/src/__tests__/disk-pressure-lifecycle.test.ts +168 -0
  50. package/src/__tests__/disk-pressure-policy.test.ts +241 -0
  51. package/src/__tests__/disk-pressure-routes.test.ts +379 -0
  52. package/src/__tests__/disk-pressure-tools.test.ts +277 -0
  53. package/src/__tests__/disk-usage.test.ts +150 -0
  54. package/src/__tests__/events-client-registration.test.ts +52 -0
  55. package/src/__tests__/events-dev-bypass-actor.test.ts +162 -0
  56. package/src/__tests__/file-write-tool.test.ts +4 -10
  57. package/src/__tests__/filing-service.test.ts +3 -4
  58. package/src/__tests__/heartbeat-disk-pressure.test.ts +183 -0
  59. package/src/__tests__/heartbeat-service.test.ts +260 -11
  60. package/src/__tests__/host-app-control-proxy.test.ts +195 -25
  61. package/src/__tests__/host-bash-proxy.test.ts +227 -34
  62. package/src/__tests__/host-bash-routes.test.ts +178 -13
  63. package/src/__tests__/host-cu-proxy.test.ts +210 -3
  64. package/src/__tests__/host-cu-routes-targeted.test.ts +141 -12
  65. package/src/__tests__/host-file-proxy-targeted.test.ts +48 -9
  66. package/src/__tests__/host-file-proxy.test.ts +268 -6
  67. package/src/__tests__/host-file-routes-targeted.test.ts +175 -17
  68. package/src/__tests__/host-transfer-proxy-targeted.test.ts +408 -59
  69. package/src/__tests__/host-transfer-routes-targeted.test.ts +232 -17
  70. package/src/__tests__/http-user-message-parity.test.ts +107 -1
  71. package/src/__tests__/injector-chain.test.ts +18 -6
  72. package/src/__tests__/injector-disk-pressure.test.ts +224 -0
  73. package/src/__tests__/managed-profile-guard.test.ts +18 -0
  74. package/src/__tests__/mcp-abort-signal.test.ts +130 -0
  75. package/src/__tests__/memory-admin-recall.test.ts +3 -11
  76. package/src/__tests__/memory-retrieval-pipeline.test.ts +22 -1
  77. package/src/__tests__/normalize-onboarding.test.ts +180 -0
  78. package/src/__tests__/oauth-connect-routes.test.ts +316 -0
  79. package/src/__tests__/oauth-provider-seed-logos.test.ts +24 -2
  80. package/src/__tests__/onboarding-persona-write.test.ts +308 -0
  81. package/src/__tests__/openai-provider.test.ts +45 -8
  82. package/src/__tests__/persist-onboarding-artifacts.test.ts +44 -64
  83. package/src/__tests__/platform-callback-registration.test.ts +21 -4
  84. package/src/__tests__/platform.test.ts +2 -1
  85. package/src/__tests__/playbook-execution.test.ts +0 -43
  86. package/src/__tests__/plugin-tool-contribution.test.ts +47 -0
  87. package/src/__tests__/prechat-onboarding-contract.test.ts +214 -27
  88. package/src/__tests__/provider-tool-name.test.ts +23 -0
  89. package/src/__tests__/relay-server.test.ts +15 -4
  90. package/src/__tests__/runtime-events-sse.test.ts +4 -8
  91. package/src/__tests__/scheduler-disk-pressure.test.ts +148 -0
  92. package/src/__tests__/secret-ingress-http.test.ts +0 -1
  93. package/src/__tests__/suggestion-routes.test.ts +46 -0
  94. package/src/__tests__/twilio-validation.test.ts +2 -2
  95. package/src/__tests__/workspace-migration-065-bump-stale-heartbeat-interval.test.ts +122 -0
  96. package/src/__tests__/workspace-migration-066-seed-heartbeat-callsite-cost-default.test.ts +285 -0
  97. package/src/__tests__/workspace-migration-068-release-notes-local-timezone.test.ts +90 -0
  98. package/src/__tests__/workspace-migration-safe-storage-limits-release.test.ts +90 -0
  99. package/src/approvals/guardian-decision-primitive.ts +13 -0
  100. package/src/approvals/guardian-request-resolvers.ts +16 -17
  101. package/src/backup/snapshot-lock.ts +2 -27
  102. package/src/bundler/compiler-tools.ts +3 -2
  103. package/src/calls/call-conversation-messages.ts +46 -10
  104. package/src/cli/commands/__tests__/webhooks.test.ts +0 -4
  105. package/src/cli/commands/bash.ts +35 -108
  106. package/src/cli/commands/contacts.ts +64 -25
  107. package/src/cli/commands/credentials.ts +56 -0
  108. package/src/cli/commands/memory-v2.ts +7 -6
  109. package/src/cli/commands/oauth/__tests__/connect.test.ts +437 -1
  110. package/src/cli/commands/oauth/connect.ts +127 -1
  111. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -3
  112. package/src/cli/commands/platform/__tests__/connect.test.ts +7 -1
  113. package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -1
  114. package/src/cli/commands/platform/__tests__/status.test.ts +103 -6
  115. package/src/cli/commands/platform/index.ts +16 -7
  116. package/src/cli/commands/status.ts +57 -0
  117. package/src/cli/program.ts +4 -2
  118. package/src/config/assistant-feature-flags.ts +13 -3
  119. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +4 -3
  120. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +13 -7
  121. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +2 -2
  122. package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +2 -2
  123. package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +2 -2
  124. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +2 -2
  125. package/src/config/env.ts +0 -8
  126. package/src/config/feature-flag-registry.json +27 -3
  127. package/src/config/loader.ts +127 -8
  128. package/src/config/schemas/__tests__/memory-v2.test.ts +10 -5
  129. package/src/config/schemas/call-site-catalog.ts +14 -0
  130. package/src/config/schemas/channels.ts +0 -5
  131. package/src/config/schemas/heartbeat.ts +1 -1
  132. package/src/config/schemas/llm.ts +2 -0
  133. package/src/config/schemas/memory-lifecycle.ts +13 -0
  134. package/src/config/schemas/memory-v2.ts +75 -11
  135. package/src/config/schemas/platform.ts +43 -3
  136. package/src/config/schemas/services.ts +28 -0
  137. package/src/config/seed-inference-profiles.ts +230 -33
  138. package/src/contacts/contact-store.ts +0 -25
  139. package/src/daemon/__tests__/conversation-tool-setup.test.ts +86 -25
  140. package/src/daemon/assistant-attachments.ts +4 -4
  141. package/src/daemon/config-watcher.ts +85 -57
  142. package/src/daemon/conversation-agent-loop-handlers.ts +6 -0
  143. package/src/daemon/conversation-agent-loop.ts +170 -33
  144. package/src/daemon/conversation-error.ts +87 -15
  145. package/src/daemon/conversation-lifecycle.ts +1 -3
  146. package/src/daemon/conversation-process.ts +8 -0
  147. package/src/daemon/conversation-runtime-assembly.ts +26 -0
  148. package/src/daemon/conversation-store.ts +2 -2
  149. package/src/daemon/conversation-surfaces.ts +195 -15
  150. package/src/daemon/conversation-tool-setup.ts +57 -14
  151. package/src/daemon/conversation.ts +17 -22
  152. package/src/daemon/date-context.ts +71 -22
  153. package/src/daemon/disk-pressure-background-gate.ts +73 -0
  154. package/src/daemon/disk-pressure-guard.ts +343 -0
  155. package/src/daemon/disk-pressure-policy.ts +163 -0
  156. package/src/daemon/handlers/shared.ts +0 -1
  157. package/src/daemon/handlers/skills.ts +3 -4
  158. package/src/daemon/host-app-control-proxy.ts +137 -41
  159. package/src/daemon/host-bash-proxy.ts +46 -21
  160. package/src/daemon/host-cu-proxy.ts +49 -3
  161. package/src/daemon/host-file-proxy.ts +43 -7
  162. package/src/daemon/host-transfer-proxy.ts +95 -4
  163. package/src/daemon/lifecycle.ts +79 -28
  164. package/src/daemon/meet-host-supervisor.ts +4 -4
  165. package/src/daemon/meet-manifest-loader.ts +0 -1
  166. package/src/daemon/memory-v2-startup.ts +14 -4
  167. package/src/daemon/message-protocol.ts +3 -0
  168. package/src/daemon/message-types/conversations.ts +4 -0
  169. package/src/daemon/message-types/disk-pressure.ts +9 -0
  170. package/src/daemon/message-types/messages.ts +3 -0
  171. package/src/daemon/profiler-run-store.ts +5 -5
  172. package/src/daemon/tool-setup-types.ts +2 -2
  173. package/src/documents/document-store.ts +85 -0
  174. package/src/filing/filing-service.ts +30 -5
  175. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +9 -16
  176. package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +36 -0
  177. package/src/heartbeat/heartbeat-run-store.ts +13 -0
  178. package/src/heartbeat/heartbeat-service.ts +205 -31
  179. package/src/home/feed-scheduler.ts +18 -0
  180. package/src/inbound/platform-callback-registration.ts +8 -15
  181. package/src/ipc/__tests__/clients-list-ipc.test.ts +169 -0
  182. package/src/ipc/assistant-server.ts +56 -2
  183. package/src/ipc/gateway-client.ts +37 -3
  184. package/src/live-voice/live-voice-archive.ts +4 -4
  185. package/src/live-voice/protocol.ts +5 -7
  186. package/src/media/image-service.ts +1 -7
  187. package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +21 -13
  188. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +52 -22
  189. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +0 -6
  190. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +272 -0
  191. package/src/memory/admin.ts +5 -9
  192. package/src/memory/context-search/agent-runner.ts +19 -2
  193. package/src/memory/context-search/sources/conversations.ts +2 -11
  194. package/src/memory/context-search/sources/memory-v2.ts +5 -4
  195. package/src/memory/context-search/sources/memory.ts +0 -1
  196. package/src/memory/context-search/types.ts +0 -1
  197. package/src/memory/conversation-crud.ts +4 -12
  198. package/src/memory/db-init.ts +2 -0
  199. package/src/memory/embedding-runtime-manager.ts +119 -5
  200. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +32 -21
  201. package/src/memory/graph/conversation-graph-memory.ts +42 -54
  202. package/src/memory/graph/extraction.ts +1 -3
  203. package/src/memory/graph/graph-search.test.ts +10 -67
  204. package/src/memory/graph/graph-search.ts +1 -20
  205. package/src/memory/graph/retriever.test.ts +6 -0
  206. package/src/memory/graph/retriever.ts +6 -10
  207. package/src/memory/indexer.ts +54 -45
  208. package/src/memory/job-handlers/backfill.ts +2 -11
  209. package/src/memory/job-handlers/cleanup.ts +43 -0
  210. package/src/memory/job-handlers/embedding.ts +6 -8
  211. package/src/memory/job-handlers/summarization.ts +2 -7
  212. package/src/memory/jobs-store.ts +48 -0
  213. package/src/memory/jobs-worker.ts +81 -43
  214. package/src/memory/memory-v2-activation-log-store.ts +32 -14
  215. package/src/memory/memory-v2-concept-frequency.ts +169 -0
  216. package/src/memory/migrations/239-trace-events-created-at-index.ts +18 -0
  217. package/src/memory/migrations/index.ts +1 -0
  218. package/src/memory/pkb/pkb-search.test.ts +6 -0
  219. package/src/memory/qdrant-client.ts +0 -13
  220. package/src/memory/rerank-local.ts +374 -0
  221. package/src/memory/search/semantic.ts +6 -67
  222. package/src/memory/trace-event-store.ts +1 -17
  223. package/src/memory/v2/__tests__/activation.test.ts +311 -250
  224. package/src/memory/v2/__tests__/consolidation-job.test.ts +40 -8
  225. package/src/memory/v2/__tests__/injection.test.ts +157 -167
  226. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +61 -2
  227. package/src/memory/v2/__tests__/qdrant.test.ts +16 -0
  228. package/src/memory/v2/__tests__/reranker.test.ts +338 -0
  229. package/src/memory/v2/__tests__/sim.test.ts +5 -199
  230. package/src/memory/v2/__tests__/skill-store.test.ts +71 -65
  231. package/src/memory/v2/__tests__/static-context.test.ts +76 -1
  232. package/src/memory/v2/activation.ts +149 -156
  233. package/src/memory/v2/consolidation-job.ts +62 -12
  234. package/src/memory/v2/injection.ts +47 -60
  235. package/src/memory/v2/prompts/consolidation.ts +36 -1
  236. package/src/memory/v2/qdrant.ts +99 -0
  237. package/src/memory/v2/reranker.ts +177 -0
  238. package/src/memory/v2/sim.ts +10 -84
  239. package/src/memory/v2/skill-content.ts +4 -3
  240. package/src/memory/v2/skill-store.ts +82 -59
  241. package/src/memory/v2/static-context.ts +22 -0
  242. package/src/memory/v2/types.ts +10 -10
  243. package/src/notifications/copy-composer.ts +13 -0
  244. package/src/notifications/signal.ts +4 -0
  245. package/src/oauth/AGENTS.md +3 -1
  246. package/src/oauth/__tests__/oauth-connect-state.test.ts +137 -0
  247. package/src/oauth/connect-orchestrator.ts +2 -0
  248. package/src/oauth/connection-resolver.test.ts +66 -1
  249. package/src/oauth/connection-resolver.ts +55 -1
  250. package/src/oauth/oauth-connect-state.ts +77 -0
  251. package/src/oauth/seed-providers.ts +58 -1
  252. package/src/plugins/defaults/injectors.ts +35 -2
  253. package/src/plugins/defaults/memory-retrieval.ts +5 -6
  254. package/src/plugins/types.ts +7 -0
  255. package/src/proactive-artifact/aux-message-injector.ts +74 -0
  256. package/src/proactive-artifact/decision.test.ts +226 -0
  257. package/src/proactive-artifact/decision.ts +165 -0
  258. package/src/proactive-artifact/index.ts +7 -0
  259. package/src/proactive-artifact/job.test.ts +867 -0
  260. package/src/proactive-artifact/job.ts +352 -0
  261. package/src/proactive-artifact/message-copy.ts +41 -0
  262. package/src/proactive-artifact/trigger-state.test.ts +277 -0
  263. package/src/proactive-artifact/trigger-state.ts +119 -0
  264. package/src/prompts/normalize-onboarding.ts +80 -0
  265. package/src/prompts/persona-resolver.ts +101 -9
  266. package/src/prompts/system-prompt.ts +21 -7
  267. package/src/prompts/templates/BOOTSTRAP.md +13 -5
  268. package/src/providers/__tests__/retry-callsite.test.ts +222 -1
  269. package/src/providers/model-intents.ts +7 -0
  270. package/src/providers/openrouter/client.ts +8 -0
  271. package/src/providers/retry.ts +50 -0
  272. package/src/providers/types.ts +1 -0
  273. package/src/runtime/__tests__/agent-wake.test.ts +456 -3
  274. package/src/runtime/agent-wake.ts +238 -100
  275. package/src/runtime/assistant-event-hub.ts +36 -6
  276. package/src/runtime/assistant-event.ts +0 -1
  277. package/src/runtime/auth/__tests__/route-policy.test.ts +64 -0
  278. package/src/runtime/auth/route-policy.ts +14 -1
  279. package/src/runtime/auth/same-actor.ts +216 -0
  280. package/src/runtime/channel-retry-sweep.ts +65 -1
  281. package/src/runtime/guardian-reply-router.ts +10 -0
  282. package/src/runtime/local-actor-identity.ts +52 -11
  283. package/src/runtime/pending-interactions.ts +8 -0
  284. package/src/runtime/routes/__tests__/client-routes.test.ts +155 -0
  285. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +0 -5
  286. package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +1 -1
  287. package/src/runtime/routes/client-routes.ts +20 -2
  288. package/src/runtime/routes/contact-routes.ts +0 -25
  289. package/src/runtime/routes/conversation-routes.ts +35 -26
  290. package/src/runtime/routes/debug-bash-routes.ts +163 -0
  291. package/src/runtime/routes/disk-pressure-routes.ts +121 -0
  292. package/src/runtime/routes/document-pdf-renderer.ts +6 -2
  293. package/src/runtime/routes/documents-routes.ts +2 -75
  294. package/src/runtime/routes/events-routes.ts +41 -9
  295. package/src/runtime/routes/host-bash-routes.ts +23 -3
  296. package/src/runtime/routes/host-cu-routes.ts +33 -6
  297. package/src/runtime/routes/host-file-routes.ts +32 -6
  298. package/src/runtime/routes/host-transfer-routes.ts +79 -16
  299. package/src/runtime/routes/identity-routes.ts +7 -138
  300. package/src/runtime/routes/inbound-message-handler.ts +77 -12
  301. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +3 -0
  302. package/src/runtime/routes/index.ts +6 -0
  303. package/src/runtime/routes/memory-item-routes.test.ts +41 -15
  304. package/src/runtime/routes/memory-v2-routes.ts +33 -0
  305. package/src/runtime/routes/oauth-connect-routes.ts +153 -0
  306. package/src/runtime/verification-outbound-actions.ts +4 -4
  307. package/src/schedule/run-script.ts +37 -5
  308. package/src/schedule/scheduler.ts +20 -1
  309. package/src/security/encrypted-store.ts +2 -0
  310. package/src/security/secure-keys.ts +55 -0
  311. package/src/skills/remote-skill-policy.ts +4 -10
  312. package/src/subagent/index.ts +1 -7
  313. package/src/subagent/manager.ts +1 -15
  314. package/src/tasks/task-runner.ts +0 -1
  315. package/src/tasks/task-store.ts +0 -3
  316. package/src/tools/background-tool-registry.ts +17 -3
  317. package/src/tools/host-filesystem/edit.test.ts +151 -0
  318. package/src/tools/host-filesystem/edit.ts +43 -1
  319. package/src/tools/host-filesystem/read.test.ts +129 -0
  320. package/src/tools/host-filesystem/read.ts +43 -1
  321. package/src/tools/host-filesystem/transfer.test.ts +127 -2
  322. package/src/tools/host-filesystem/transfer.ts +56 -11
  323. package/src/tools/host-filesystem/write.test.ts +134 -0
  324. package/src/tools/host-filesystem/write.ts +43 -1
  325. package/src/tools/host-terminal/host-shell.ts +13 -6
  326. package/src/tools/mcp/mcp-tool-factory.ts +2 -1
  327. package/src/tools/memory/register.test.ts +12 -9
  328. package/src/tools/memory/register.ts +1 -2
  329. package/src/tools/provider-tool-name.ts +28 -0
  330. package/src/tools/registry.ts +30 -9
  331. package/src/tools/terminal/shell.ts +9 -1
  332. package/src/tools/tool-approval-handler.ts +31 -6
  333. package/src/tools/types.ts +24 -2
  334. package/src/tts/provider-catalog.ts +3 -5
  335. package/src/util/disk-usage.ts +138 -0
  336. package/src/util/platform.ts +21 -11
  337. package/src/util/process-liveness.ts +26 -0
  338. package/src/workspace/heartbeat-service.ts +19 -0
  339. package/src/workspace/migrations/065-bump-stale-heartbeat-interval.ts +60 -0
  340. package/src/workspace/migrations/066-seed-heartbeat-callsite-cost-default.ts +146 -0
  341. package/src/workspace/migrations/067-release-notes-safe-storage-limits.ts +72 -0
  342. package/src/workspace/migrations/068-release-notes-local-timezone.ts +65 -0
  343. package/src/workspace/migrations/registry.ts +8 -0
  344. package/src/__tests__/conversation-tool-setup-memory-scope.test.ts +0 -167
  345. package/src/memory/v2/__tests__/skill-qdrant.test.ts +0 -657
  346. package/src/memory/v2/skill-qdrant.ts +0 -404
  347. package/src/signals/bash.ts +0 -198
@@ -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) {
@@ -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.`;
@@ -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.
@@ -177,6 +191,8 @@ export interface ToolContext {
177
191
  proxyToolResolver?: ProxyToolResolver;
178
192
  /** When set, only tools in this set may execute. Tools outside the set are blocked with an error. */
179
193
  allowedToolNames?: Set<string>;
194
+ /** True when this turn is restricted to storage cleanup-safe tools. */
195
+ diskPressureCleanupModeActive?: boolean;
180
196
  /** Prompt the user for a secret value via native SecureField UI. */
181
197
  requestSecret?: (params: {
182
198
  service: string;
@@ -192,8 +208,6 @@ export interface ToolContext {
192
208
  sendToClient?: (msg: { type: string; [key: string]: unknown }) => void;
193
209
  /** True when an interactive client is connected (not just a no-op callback). */
194
210
  isInteractive?: boolean;
195
- /** Memory scope ID from the conversation's memory policy, so memory tools can target the correct scope. */
196
- memoryScopeId?: string;
197
211
  /** When true, tools with side effects should always prompt for confirmation. */
198
212
  forcePromptSideEffects?: boolean;
199
213
  /**
@@ -268,6 +282,14 @@ export interface ToolContext {
268
282
  * `executeSubagentSpawn` in tools/subagent/spawn.ts.
269
283
  */
270
284
  overrideProfile?: string;
285
+ /**
286
+ * Canonical principal ID of the actor on whose behalf this tool invocation
287
+ * is running. Sourced from `conversation.trustContext.guardianPrincipalId`.
288
+ * Used by host proxies to bind cross-client targeted execution to the same
289
+ * authenticated user identity. May be undefined for legacy/internal flows
290
+ * with no resolved actor identity.
291
+ */
292
+ sourceActorPrincipalId?: string;
271
293
  }
272
294
 
273
295
  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
 
@@ -0,0 +1,138 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { existsSync, statfsSync } from "node:fs";
3
+
4
+ import { getMinikubeStorageSize } from "../config/env-registry.js";
5
+ import { getWorkspaceDir } from "./platform.js";
6
+
7
+ export interface DiskUsageInfo {
8
+ path: string;
9
+ totalMb: number;
10
+ usedMb: number;
11
+ freeMb: number;
12
+ }
13
+
14
+ /**
15
+ * Measure the on-disk usage of one or more directory paths using `du -sb`.
16
+ * Returns the sum of all paths in bytes, or null on failure.
17
+ */
18
+ function getDirectorySizeBytes(paths: string[]): number | null {
19
+ try {
20
+ const existing = paths.filter((p) => existsSync(p));
21
+ if (existing.length === 0) return null;
22
+ const result = spawnSync("du", ["-sb", ...existing], {
23
+ encoding: "utf-8",
24
+ timeout: 30_000,
25
+ });
26
+ if (result.status !== 0) return null;
27
+ let total = 0;
28
+ for (const line of result.stdout.trim().split("\n")) {
29
+ const size = parseInt(line.split("\t")[0], 10);
30
+ if (!isNaN(size) && size > 0) total += size;
31
+ }
32
+ return total > 0 ? total : null;
33
+ } catch {
34
+ return null;
35
+ }
36
+ }
37
+
38
+ const DU_CACHE_TTL_MS = 60_000;
39
+ let duCacheValue: number | null = null;
40
+ let duCacheTime = 0;
41
+ let duCachePaths: string | null = null;
42
+
43
+ function getCachedDirectorySizeBytes(paths: string[]): number | null {
44
+ const key = paths.join("\0");
45
+ const now = Date.now();
46
+ if (duCachePaths === key && now - duCacheTime < DU_CACHE_TTL_MS) {
47
+ return duCacheValue;
48
+ }
49
+ duCacheValue = getDirectorySizeBytes(paths);
50
+ duCacheTime = now;
51
+ duCachePaths = key;
52
+ return duCacheValue;
53
+ }
54
+
55
+ export function __resetDiskUsageCacheForTests(): void {
56
+ duCacheValue = null;
57
+ duCacheTime = 0;
58
+ duCachePaths = null;
59
+ }
60
+
61
+ export function getDiskUsageInfo(): DiskUsageInfo | null {
62
+ try {
63
+ const wsDir = getWorkspaceDir();
64
+ const diskPath = existsSync(wsDir) ? wsDir : "/";
65
+ const stats = statfsSync(diskPath);
66
+ const fsTotalBytes = stats.bsize * stats.blocks;
67
+ const fsFreeBytes = stats.bsize * stats.bavail;
68
+ const bytesToMb = (b: number) =>
69
+ Math.round((b / (1024 * 1024)) * 100) / 100;
70
+
71
+ // Minikube mode: the platform passes the PVC storage size so we can
72
+ // report accurate capacity. On hostPath-backed PVCs statfsSync reports
73
+ // the host's entire filesystem rather than the PVC. Detect this by
74
+ // comparing filesystem size against PVC size — if the filesystem is
75
+ // larger, measure actual directory usage with `du` instead.
76
+ const storageSizeRaw = getMinikubeStorageSize();
77
+ if (storageSizeRaw) {
78
+ const pvcTotalBytes = parseK8sMemoryBytes(storageSizeRaw);
79
+ if (pvcTotalBytes !== null && fsTotalBytes > pvcTotalBytes * 1.1) {
80
+ const volumePaths = [diskPath];
81
+ if (diskPath !== "/data" && existsSync("/data")) {
82
+ volumePaths.push("/data");
83
+ }
84
+ const usedBytes = getCachedDirectorySizeBytes(volumePaths);
85
+ if (usedBytes !== null) {
86
+ return {
87
+ path: diskPath,
88
+ totalMb: bytesToMb(pvcTotalBytes),
89
+ usedMb: bytesToMb(usedBytes),
90
+ freeMb: bytesToMb(Math.max(0, pvcTotalBytes - usedBytes)),
91
+ };
92
+ }
93
+ }
94
+ }
95
+
96
+ return {
97
+ path: diskPath,
98
+ totalMb: bytesToMb(fsTotalBytes),
99
+ usedMb: bytesToMb(fsTotalBytes - fsFreeBytes),
100
+ freeMb: bytesToMb(fsFreeBytes),
101
+ };
102
+ } catch {
103
+ return null;
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Parse a Kubernetes-style memory string (e.g. "3Gi", "512Mi", "1G") into bytes.
109
+ * Returns null if the value is not a recognized format.
110
+ */
111
+ export function parseK8sMemoryBytes(value: string): number | null {
112
+ const match = value
113
+ .trim()
114
+ .match(/^(\d+(?:\.\d+)?)\s*(Ki|Mi|Gi|Ti|Pi|Ei|k|M|G|T|P|E|m)?$/);
115
+ if (!match) return null;
116
+ const num = parseFloat(match[1]);
117
+ const unit = match[2] ?? "";
118
+ const multipliers: Record<string, number> = {
119
+ "": 1,
120
+ m: 1e-3,
121
+ k: 1e3,
122
+ M: 1e6,
123
+ G: 1e9,
124
+ T: 1e12,
125
+ P: 1e15,
126
+ E: 1e18,
127
+ Ki: 1024,
128
+ Mi: 1024 ** 2,
129
+ Gi: 1024 ** 3,
130
+ Ti: 1024 ** 4,
131
+ Pi: 1024 ** 5,
132
+ Ei: 1024 ** 6,
133
+ };
134
+ const mult = multipliers[unit];
135
+ if (mult === undefined) return null;
136
+ const bytes = Math.round(num * mult);
137
+ return bytes > 0 ? bytes : null;
138
+ }
@@ -7,14 +7,25 @@ import { getWorkspaceDirOverride } from "../config/env-registry.js";
7
7
  /**
8
8
  * The daemon's root data directory (`~/.vellum`).
9
9
  *
10
- * Multi-instance path relocation is handled by the CLI when spawning the
11
- * daemon (via `VELLUM_WORKSPACE_DIR` and `GATEWAY_SECURITY_DIR`); the
12
- * assistant itself never reads an env var for this.
10
+ * Used as a fallback when `VELLUM_WORKSPACE_DIR` is not set, and as a
11
+ * stable constant for paths (like `.env`) that intentionally live at the
12
+ * host home directory regardless of workspace relocation.
13
13
  */
14
14
  const VELLUM_ROOT = join(homedir(), ".vellum");
15
15
 
16
- /** Returns the daemon's root data directory (`~/.vellum`). */
16
+ /**
17
+ * Returns the Vellum root directory.
18
+ *
19
+ * Resolution order (mirrors workspace/migrations/utils.ts):
20
+ * 1. Parent of VELLUM_WORKSPACE_DIR — e.g. /data/.vellum/workspace → /data/.vellum
21
+ * 2. If that parent is "/" (workspace at top level), fall back to ~/.vellum
22
+ */
17
23
  export function vellumRoot(): string {
24
+ const override = getWorkspaceDirOverride();
25
+ if (override) {
26
+ const parent = dirname(override);
27
+ if (parent !== "/") return parent;
28
+ }
18
29
  return VELLUM_ROOT;
19
30
  }
20
31
 
@@ -160,17 +171,16 @@ export function getHistoryPath(): string {
160
171
  }
161
172
 
162
173
  /**
163
- * Returns the protected directory (~/.vellum/protected). Security-sensitive
164
- * files — trust rules, encrypted credential store, signing keys, feature-flag
165
- * overrides, device approval lists — live here.
174
+ * Returns the protected directory. Security-sensitive files — trust rules,
175
+ * encrypted credential store, signing keys, feature-flag overrides, device
176
+ * approval lists — live here.
166
177
  *
167
178
  * This directory is:
168
- * - Outside the workspace
169
179
  * - Outside the sandbox write boundary (tools cannot modify it)
170
180
  * - Skipped in containerized mode (credentials via CES, trust via gateway)
171
181
  */
172
182
  export function getProtectedDir(): string {
173
- return join(VELLUM_ROOT, "protected");
183
+ return join(vellumRoot(), "protected");
174
184
  }
175
185
 
176
186
  /** Returns ~/.vellum/workspace/signals — the directory for IPC signal files. */
@@ -204,7 +214,7 @@ export function getBinDir(): string {
204
214
 
205
215
  /** Returns the path to the dot-env file (~/.vellum/.env). Stays at root because it contains secrets. */
206
216
  export function getDotEnvPath(): string {
207
- return join(VELLUM_ROOT, ".env");
217
+ return join(vellumRoot(), ".env");
208
218
  }
209
219
 
210
220
  /** Returns the path to the embed-worker PID file (~/.vellum/workspace/embed-worker.pid). */
@@ -368,7 +378,7 @@ export function getBundledBunPath(): string | undefined {
368
378
  }
369
379
 
370
380
  export function ensureDataDir(): void {
371
- const root = VELLUM_ROOT;
381
+ const root = vellumRoot();
372
382
  const workspace = getWorkspaceDir();
373
383
  const wsData = join(workspace, "data");
374
384
  const dirs = [
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Cross-process liveness probe shared by file-locking helpers.
3
+ *
4
+ * Uses `kill(pid, 0)`, which sends no signal but probes the OS for whether a
5
+ * process exists and whether the caller has permission to signal it. Returns
6
+ * `false` for obviously invalid PIDs and for any error indicating the process
7
+ * is gone (most commonly ESRCH). Returns `true` for ESRCH-negative results
8
+ * (process exists) and for EPERM (process exists but is owned by another user
9
+ * — still alive, still must not be taken over).
10
+ */
11
+
12
+ import { kill } from "node:process";
13
+
14
+ export function isProcessAlive(pid: number): boolean {
15
+ if (!Number.isInteger(pid) || pid <= 0) return false;
16
+ try {
17
+ kill(pid, 0);
18
+ return true;
19
+ } catch (err) {
20
+ const code = (err as NodeJS.ErrnoException).code;
21
+ // EPERM means the PID exists but we cannot signal it — treat as alive so
22
+ // we don't accidentally take over another user's lock.
23
+ if (code === "EPERM") return true;
24
+ return false;
25
+ }
26
+ }
@@ -1,3 +1,8 @@
1
+ import {
2
+ checkDiskPressureBackgroundGate,
3
+ diskPressureBackgroundSkipLogFields,
4
+ shouldLogDiskPressureBackgroundSkip,
5
+ } from "../daemon/disk-pressure-background-gate.js";
1
6
  import { getLogger } from "../util/logger.js";
2
7
  import { getEnrichmentService } from "./commit-message-enrichment-service.js";
3
8
  import {
@@ -137,6 +142,20 @@ export class WorkspaceHeartbeatService {
137
142
  return { checked: 0, committed: 0, skipped: 0, failed: 0 };
138
143
  }
139
144
 
145
+ const diskPressureGate = checkDiskPressureBackgroundGate("background-work");
146
+ if (diskPressureGate.action === "skip") {
147
+ if (shouldLogDiskPressureBackgroundSkip("workspace-heartbeat")) {
148
+ log.warn(
149
+ {
150
+ source: "workspace-heartbeat",
151
+ ...diskPressureBackgroundSkipLogFields(diskPressureGate),
152
+ },
153
+ "Workspace heartbeat skipped during disk pressure cleanup mode",
154
+ );
155
+ }
156
+ return { checked: 0, committed: 0, skipped: 0, failed: 0 };
157
+ }
158
+
140
159
  const doCheck = async (): Promise<HeartbeatCheckResult> => {
141
160
  const result: HeartbeatCheckResult = {
142
161
  checked: 0,
@@ -0,0 +1,60 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
4
+ import type { WorkspaceMigration } from "./types.js";
5
+
6
+ const THIRTY_MINUTES_MS = 30 * 60 * 1000;
7
+ const LEGACY_DEFAULT_INTERVALS_MS = new Set([
8
+ 3 * 60 * 60 * 1000,
9
+ 6 * 60 * 60 * 1000,
10
+ ]);
11
+
12
+ /**
13
+ * Bump stale baked heartbeat defaults to 30 minutes.
14
+ *
15
+ * Older first-launch config files materialized the then-current heartbeat
16
+ * default into `config.json`, so changing the schema default alone would not
17
+ * affect existing default users. A workspace could have intentionally selected
18
+ * one of these exact intervals; product intent is still to move legacy 3h/6h
19
+ * heartbeat schedules to the 30-minute default, and those users can reset the
20
+ * interval after upgrade.
21
+ */
22
+ export const bumpStaleHeartbeatIntervalMigration: WorkspaceMigration = {
23
+ id: "065-bump-stale-heartbeat-interval",
24
+ description:
25
+ "Bump legacy heartbeat.intervalMs defaults of 3h/6h to the current 30-minute default",
26
+ run(workspaceDir: string): void {
27
+ const configPath = join(workspaceDir, "config.json");
28
+ if (!existsSync(configPath)) return;
29
+
30
+ let config: Record<string, unknown>;
31
+ try {
32
+ const raw = JSON.parse(readFileSync(configPath, "utf-8"));
33
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return;
34
+ config = raw as Record<string, unknown>;
35
+ } catch {
36
+ return;
37
+ }
38
+
39
+ const heartbeat = config.heartbeat;
40
+ if (!heartbeat || typeof heartbeat !== "object" || Array.isArray(heartbeat))
41
+ return;
42
+
43
+ const heartbeatConfig = heartbeat as Record<string, unknown>;
44
+ const intervalMs = heartbeatConfig.intervalMs;
45
+ if (
46
+ typeof intervalMs !== "number" ||
47
+ !LEGACY_DEFAULT_INTERVALS_MS.has(intervalMs)
48
+ ) {
49
+ return;
50
+ }
51
+
52
+ heartbeatConfig.intervalMs = THIRTY_MINUTES_MS;
53
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
54
+ },
55
+ down(_workspaceDir: string): void {
56
+ // Forward-only: the stale value may have been a schema-default artifact,
57
+ // while 30 minutes may also have been explicitly configured later. Without
58
+ // per-workspace state we cannot safely distinguish those cases.
59
+ },
60
+ };