@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
@@ -0,0 +1,343 @@
1
+ import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
2
+ import { getConfig } from "../config/loader.js";
3
+ import { buildAssistantEvent } from "../runtime/assistant-event.js";
4
+ import { assistantEventHub } from "../runtime/assistant-event-hub.js";
5
+ import { cancelBackgroundTools } from "../tools/background-tool-registry.js";
6
+ import { getDiskUsageInfo } from "../util/disk-usage.js";
7
+ import { getLogger } from "../util/logger.js";
8
+
9
+ export const DISK_PRESSURE_THRESHOLD_PERCENT = 95;
10
+ export const DISK_PRESSURE_CHECK_INTERVAL_MS = 60_000;
11
+ export const DISK_PRESSURE_OVERRIDE_CONFIRMATION = "I understand the risks";
12
+ export const DISK_PRESSURE_BLOCKED_CAPABILITIES = [
13
+ "agent-turns",
14
+ "background-work",
15
+ "remote-ingress",
16
+ ] as const;
17
+
18
+ export type DiskPressureState = "disabled" | "ok" | "critical" | "unknown";
19
+
20
+ export type DiskPressureBlockedCapability =
21
+ (typeof DISK_PRESSURE_BLOCKED_CAPABILITIES)[number];
22
+
23
+ export interface DiskPressureStatus {
24
+ enabled: boolean;
25
+ state: DiskPressureState;
26
+ locked: boolean;
27
+ acknowledged: boolean;
28
+ overrideActive: boolean;
29
+ effectivelyLocked: boolean;
30
+ lockId: string | null;
31
+ usagePercent: number | null;
32
+ thresholdPercent: number;
33
+ path: string | null;
34
+ lastCheckedAt: string | null;
35
+ blockedCapabilities: DiskPressureBlockedCapability[];
36
+ error: string | null;
37
+ }
38
+
39
+ export type DiskPressureTransitionResult =
40
+ | { ok: true; status: DiskPressureStatus }
41
+ | {
42
+ ok: false;
43
+ reason:
44
+ | "not_locked"
45
+ | "already_acknowledged"
46
+ | "already_overridden"
47
+ | "invalid_confirmation";
48
+ message: string;
49
+ status: DiskPressureStatus;
50
+ };
51
+
52
+ interface DiskPressureGuardState {
53
+ timer: ReturnType<typeof setInterval> | null;
54
+ status: DiskPressureStatus;
55
+ }
56
+
57
+ const log = getLogger("disk-pressure-guard");
58
+
59
+ const DISABLED_STATUS: DiskPressureStatus = {
60
+ enabled: false,
61
+ state: "disabled",
62
+ locked: false,
63
+ acknowledged: false,
64
+ overrideActive: false,
65
+ effectivelyLocked: false,
66
+ lockId: null,
67
+ usagePercent: null,
68
+ thresholdPercent: DISK_PRESSURE_THRESHOLD_PERCENT,
69
+ path: null,
70
+ lastCheckedAt: null,
71
+ blockedCapabilities: [],
72
+ error: null,
73
+ };
74
+
75
+ const OPEN_STATUS: DiskPressureStatus = {
76
+ ...DISABLED_STATUS,
77
+ enabled: true,
78
+ state: "ok",
79
+ thresholdPercent: DISK_PRESSURE_THRESHOLD_PERCENT,
80
+ };
81
+
82
+ const state: DiskPressureGuardState = {
83
+ timer: null,
84
+ status: cloneStatus(DISABLED_STATUS),
85
+ };
86
+
87
+ function cloneStatus(status: DiskPressureStatus): DiskPressureStatus {
88
+ return {
89
+ ...status,
90
+ blockedCapabilities: [...status.blockedCapabilities],
91
+ };
92
+ }
93
+
94
+ function statusFingerprint(status: DiskPressureStatus): string {
95
+ const { lastCheckedAt: _lastCheckedAt, ...substantiveStatus } = status;
96
+ return JSON.stringify(substantiveStatus);
97
+ }
98
+
99
+ function publishStatusChangedIfNeeded(previous: DiskPressureStatus): void {
100
+ if (statusFingerprint(previous) === statusFingerprint(state.status)) return;
101
+ const status = cloneStatus(state.status);
102
+ assistantEventHub
103
+ .publish(
104
+ buildAssistantEvent({
105
+ type: "disk_pressure_status_changed",
106
+ status,
107
+ }),
108
+ )
109
+ .catch((err) => {
110
+ log.warn({ err }, "Failed to publish disk pressure status change");
111
+ });
112
+ }
113
+
114
+ function replaceStatus(next: DiskPressureStatus): DiskPressureStatus {
115
+ const previous = cloneStatus(state.status);
116
+ state.status = cloneStatus(next);
117
+ publishStatusChangedIfNeeded(previous);
118
+ return cloneStatus(state.status);
119
+ }
120
+
121
+ function isEnabled(): boolean {
122
+ return isAssistantFeatureFlagEnabled("safe-storage-limits", getConfig());
123
+ }
124
+
125
+ function resetToDisabled(): DiskPressureStatus {
126
+ const previous = cloneStatus(state.status);
127
+ stopDiskPressureGuard();
128
+ state.status = cloneStatus(DISABLED_STATUS);
129
+ publishStatusChangedIfNeeded(previous);
130
+ return cloneStatus(state.status);
131
+ }
132
+
133
+ function ensureEnabledStatus(): DiskPressureStatus | null {
134
+ if (!isEnabled()) return resetToDisabled();
135
+ if (!state.status.enabled) {
136
+ state.status = cloneStatus(OPEN_STATUS);
137
+ }
138
+ return null;
139
+ }
140
+
141
+ function nextLockId(): string {
142
+ return `disk-pressure-${Date.now()}`;
143
+ }
144
+
145
+ function roundPercent(value: number): number {
146
+ return Math.round(value * 100) / 100;
147
+ }
148
+
149
+ function formatError(error: unknown): string {
150
+ return error instanceof Error ? error.message : String(error);
151
+ }
152
+
153
+ function sampleFailureStatus(error: unknown): DiskPressureStatus {
154
+ const now = new Date().toISOString();
155
+ return {
156
+ ...state.status,
157
+ enabled: true,
158
+ state: "unknown",
159
+ locked: false,
160
+ acknowledged: false,
161
+ overrideActive: false,
162
+ effectivelyLocked: false,
163
+ lockId: null,
164
+ usagePercent: null,
165
+ thresholdPercent: DISK_PRESSURE_THRESHOLD_PERCENT,
166
+ path: null,
167
+ lastCheckedAt: now,
168
+ blockedCapabilities: [],
169
+ error: formatError(error),
170
+ };
171
+ }
172
+
173
+ function cancelTerminalBackgroundToolsForLock(): void {
174
+ const cancelled = cancelBackgroundTools(
175
+ (tool) => tool.toolName === "bash" || tool.toolName === "host_bash",
176
+ "disk_pressure",
177
+ );
178
+ if (cancelled.length === 0) return;
179
+ log.info(
180
+ { count: cancelled.length, ids: cancelled.map((tool) => tool.id) },
181
+ "Cancelled background terminal tools during disk pressure lock",
182
+ );
183
+ }
184
+
185
+ function rejectTransition(
186
+ reason: Exclude<DiskPressureTransitionResult, { ok: true }>["reason"],
187
+ message: string,
188
+ status: DiskPressureStatus,
189
+ ): DiskPressureTransitionResult {
190
+ return { ok: false, reason, message, status };
191
+ }
192
+
193
+ export function startDiskPressureGuard(): DiskPressureStatus {
194
+ const disabledStatus = ensureEnabledStatus();
195
+ if (disabledStatus) return disabledStatus;
196
+
197
+ if (!state.timer) {
198
+ state.timer = setInterval(() => {
199
+ void evaluateDiskPressureNow();
200
+ }, DISK_PRESSURE_CHECK_INTERVAL_MS);
201
+ (state.timer as { unref?: () => void }).unref?.();
202
+ }
203
+
204
+ return cloneStatus(state.status);
205
+ }
206
+
207
+ export function stopDiskPressureGuard(): void {
208
+ if (!state.timer) return;
209
+ clearInterval(state.timer);
210
+ state.timer = null;
211
+ }
212
+
213
+ export function evaluateDiskPressureNow(): DiskPressureStatus {
214
+ const disabledStatus = ensureEnabledStatus();
215
+ if (disabledStatus) return disabledStatus;
216
+
217
+ let usageInfo: ReturnType<typeof getDiskUsageInfo>;
218
+ try {
219
+ usageInfo = getDiskUsageInfo();
220
+ } catch (error) {
221
+ return replaceStatus(sampleFailureStatus(error));
222
+ }
223
+
224
+ if (!usageInfo || usageInfo.totalMb <= 0) {
225
+ return replaceStatus(sampleFailureStatus("Disk usage sample unavailable"));
226
+ }
227
+
228
+ const usagePercent = roundPercent(
229
+ (usageInfo.usedMb / usageInfo.totalMb) * 100,
230
+ );
231
+ const isCritical = usagePercent >= DISK_PRESSURE_THRESHOLD_PERCENT;
232
+ const lastCheckedAt = new Date().toISOString();
233
+
234
+ if (!isCritical) {
235
+ return replaceStatus({
236
+ ...OPEN_STATUS,
237
+ usagePercent,
238
+ path: usageInfo.path,
239
+ lastCheckedAt,
240
+ });
241
+ }
242
+
243
+ if (!state.status.locked) {
244
+ cancelTerminalBackgroundToolsForLock();
245
+ }
246
+
247
+ const lockId = state.status.locked ? state.status.lockId : nextLockId();
248
+ return replaceStatus({
249
+ enabled: true,
250
+ state: "critical",
251
+ locked: true,
252
+ acknowledged: state.status.locked ? state.status.acknowledged : false,
253
+ overrideActive: state.status.locked ? state.status.overrideActive : false,
254
+ effectivelyLocked: state.status.locked
255
+ ? !state.status.overrideActive
256
+ : true,
257
+ lockId,
258
+ usagePercent,
259
+ thresholdPercent: DISK_PRESSURE_THRESHOLD_PERCENT,
260
+ path: usageInfo.path,
261
+ lastCheckedAt,
262
+ blockedCapabilities: [...DISK_PRESSURE_BLOCKED_CAPABILITIES],
263
+ error: null,
264
+ });
265
+ }
266
+
267
+ export function getDiskPressureStatus(): DiskPressureStatus {
268
+ if (!isEnabled()) return cloneStatus(DISABLED_STATUS);
269
+ if (!state.status.enabled) return cloneStatus(OPEN_STATUS);
270
+ return cloneStatus(state.status);
271
+ }
272
+
273
+ export function acknowledgeDiskPressureLock(): DiskPressureTransitionResult {
274
+ const disabledStatus = ensureEnabledStatus();
275
+ const status = disabledStatus ?? cloneStatus(state.status);
276
+ if (!status.locked) {
277
+ return rejectTransition(
278
+ "not_locked",
279
+ "No disk pressure lock is active for this assistant.",
280
+ status,
281
+ );
282
+ }
283
+
284
+ if (status.acknowledged) {
285
+ return rejectTransition(
286
+ "already_acknowledged",
287
+ "The disk pressure lock has already been acknowledged.",
288
+ status,
289
+ );
290
+ }
291
+
292
+ const previous = cloneStatus(state.status);
293
+ state.status.acknowledged = true;
294
+ publishStatusChangedIfNeeded(previous);
295
+ return { ok: true, status: cloneStatus(state.status) };
296
+ }
297
+
298
+ export function overrideDiskPressureLock(
299
+ confirmation: string,
300
+ ): DiskPressureTransitionResult {
301
+ const disabledStatus = ensureEnabledStatus();
302
+ const status = disabledStatus ?? cloneStatus(state.status);
303
+ if (!status.locked) {
304
+ return rejectTransition(
305
+ "not_locked",
306
+ "No disk pressure lock is active for this assistant.",
307
+ status,
308
+ );
309
+ }
310
+
311
+ if (status.overrideActive) {
312
+ return rejectTransition(
313
+ "already_overridden",
314
+ "The disk pressure lock has already been overridden.",
315
+ status,
316
+ );
317
+ }
318
+
319
+ if (confirmation.trim() !== DISK_PRESSURE_OVERRIDE_CONFIRMATION) {
320
+ return rejectTransition(
321
+ "invalid_confirmation",
322
+ `Type "${DISK_PRESSURE_OVERRIDE_CONFIRMATION}" to resume normal assistant behavior.`,
323
+ status,
324
+ );
325
+ }
326
+
327
+ const previous = cloneStatus(state.status);
328
+ state.status.overrideActive = true;
329
+ state.status.effectivelyLocked = false;
330
+ publishStatusChangedIfNeeded(previous);
331
+ return { ok: true, status: cloneStatus(state.status) };
332
+ }
333
+
334
+ export function __resetDiskPressureGuardForTests(): void {
335
+ stopDiskPressureGuard();
336
+ state.status = cloneStatus(DISABLED_STATUS);
337
+ }
338
+
339
+ export function __getDiskPressureGuardTimerForTests(): ReturnType<
340
+ typeof setInterval
341
+ > | null {
342
+ return state.timer;
343
+ }
@@ -0,0 +1,163 @@
1
+ import type { InterfaceId } from "../channels/types.js";
2
+ import type { LLMCallSite } from "../config/schemas/llm.js";
3
+ import type { DiskPressureStatus } from "./disk-pressure-guard.js";
4
+ import type { ConversationType } from "./message-types/shared.js";
5
+ import type { TrustContext } from "./trust-context.js";
6
+
7
+ export type DiskPressureCleanupReason = "local-owner" | "guardian";
8
+
9
+ export type DiskPressureBlockReason =
10
+ | "background"
11
+ | "trusted-contact"
12
+ | "non-guardian"
13
+ | "unknown-remote";
14
+
15
+ export type DiskPressureTurnPolicyDecision =
16
+ | { action: "allow-normal" }
17
+ | { action: "allow-cleanup-mode"; reason: DiskPressureCleanupReason }
18
+ | { action: "block"; reason: DiskPressureBlockReason };
19
+
20
+ export type DiskPressureTurnTrustClass =
21
+ | TrustContext["trustClass"]
22
+ | "non_guardian"
23
+ | "non-guardian"
24
+ | (string & {});
25
+
26
+ export interface DiskPressureTurnTrustContext {
27
+ sourceChannel?: TrustContext["sourceChannel"] | (string & {});
28
+ trustClass?: DiskPressureTurnTrustClass;
29
+ }
30
+
31
+ export interface DiskPressureTurnMetadata {
32
+ conversationType?: ConversationType | (string & {}) | null;
33
+ conversationGroupId?: string | null;
34
+ conversationSource?: string | null;
35
+ callSite?: LLMCallSite | (string & {}) | null;
36
+ isInteractive?: boolean | null;
37
+ sourceChannel?: TrustContext["sourceChannel"] | (string & {}) | null;
38
+ sourceInterface?: InterfaceId | "vellum" | (string & {}) | null;
39
+ trustContext?: DiskPressureTurnTrustContext | null;
40
+ isDirectWake?: boolean | null;
41
+ }
42
+
43
+ const BACKGROUND_CONVERSATION_TYPES = new Set(["background", "scheduled"]);
44
+ const BACKGROUND_GROUP_IDS = new Set(["system:background", "system:scheduled"]);
45
+ const BACKGROUND_SOURCES = new Set([
46
+ "auto-analysis",
47
+ "background",
48
+ "compaction",
49
+ "direct",
50
+ "filing",
51
+ "heartbeat",
52
+ "memory",
53
+ "notification",
54
+ "proactive-artifact",
55
+ "reminder",
56
+ "schedule",
57
+ "task",
58
+ "update-bulletin",
59
+ ]);
60
+ const LOCAL_OWNER_INTERFACES = new Set(["macos", "web", "vellum", "cli"]);
61
+
62
+ export function classifyDiskPressureTurnPolicy(
63
+ status: DiskPressureStatus,
64
+ metadata: DiskPressureTurnMetadata,
65
+ ): DiskPressureTurnPolicyDecision {
66
+ if (!status.enabled || !status.locked || status.overrideActive) {
67
+ return { action: "allow-normal" };
68
+ }
69
+
70
+ if (!status.effectivelyLocked) {
71
+ return { action: "allow-normal" };
72
+ }
73
+
74
+ if (isBackgroundTurn(metadata)) {
75
+ return { action: "block", reason: "background" };
76
+ }
77
+
78
+ const trustClass = metadata.trustContext?.trustClass;
79
+ if (trustClass === "guardian") {
80
+ return { action: "allow-cleanup-mode", reason: "guardian" };
81
+ }
82
+
83
+ if (trustClass === "trusted_contact") {
84
+ return { action: "block", reason: "trusted-contact" };
85
+ }
86
+
87
+ if (isNonGuardianTrustClass(trustClass)) {
88
+ return { action: "block", reason: "non-guardian" };
89
+ }
90
+
91
+ if (trustClass === "unknown") {
92
+ return { action: "block", reason: "unknown-remote" };
93
+ }
94
+
95
+ if (trustClass !== undefined) {
96
+ return { action: "block", reason: "non-guardian" };
97
+ }
98
+
99
+ if (isLocalOwnerTurnWithoutTrust(metadata)) {
100
+ return { action: "allow-cleanup-mode", reason: "local-owner" };
101
+ }
102
+
103
+ return { action: "block", reason: "unknown-remote" };
104
+ }
105
+
106
+ function isBackgroundTurn(metadata: DiskPressureTurnMetadata): boolean {
107
+ if (isExplicitLocalOwnerCleanupTurn(metadata)) return false;
108
+ if (metadata.isDirectWake) return true;
109
+ if (metadata.callSite != null && metadata.callSite !== "mainAgent") {
110
+ return true;
111
+ }
112
+ if (
113
+ metadata.conversationType != null &&
114
+ BACKGROUND_CONVERSATION_TYPES.has(metadata.conversationType)
115
+ ) {
116
+ return true;
117
+ }
118
+ if (
119
+ metadata.conversationGroupId != null &&
120
+ BACKGROUND_GROUP_IDS.has(metadata.conversationGroupId)
121
+ ) {
122
+ return true;
123
+ }
124
+ return (
125
+ metadata.conversationSource != null &&
126
+ BACKGROUND_SOURCES.has(metadata.conversationSource)
127
+ );
128
+ }
129
+
130
+ function isNonGuardianTrustClass(
131
+ trustClass: DiskPressureTurnTrustClass | undefined,
132
+ ): boolean {
133
+ return trustClass === "non_guardian" || trustClass === "non-guardian";
134
+ }
135
+
136
+ function isLocalOwnerTurnWithoutTrust(
137
+ metadata: DiskPressureTurnMetadata,
138
+ ): boolean {
139
+ if (metadata.trustContext != null) return false;
140
+
141
+ const channel = metadata.sourceChannel;
142
+ const sourceInterface = metadata.sourceInterface;
143
+ if (channel !== "vellum" || sourceInterface == null) return false;
144
+ return LOCAL_OWNER_INTERFACES.has(sourceInterface);
145
+ }
146
+
147
+ function isExplicitLocalOwnerCleanupTurn(
148
+ metadata: DiskPressureTurnMetadata,
149
+ ): boolean {
150
+ if (metadata.isDirectWake !== true) return false;
151
+ const sourceInterface = metadata.sourceInterface;
152
+ if (
153
+ metadata.sourceChannel !== "vellum" ||
154
+ sourceInterface == null ||
155
+ !LOCAL_OWNER_INTERFACES.has(sourceInterface)
156
+ ) {
157
+ return false;
158
+ }
159
+ return (
160
+ metadata.trustContext == null ||
161
+ metadata.trustContext.trustClass === "guardian"
162
+ );
163
+ }
@@ -129,7 +129,6 @@ export interface ConversationCreateOptions {
129
129
  isInteractive?: boolean;
130
130
  /** Slack-only non-persisted notice injected into the active model turn. */
131
131
  slackRuntimeContextNotice?: string;
132
- memoryScopeId?: string;
133
132
  /** Channel command intent metadata (e.g. Telegram /start). */
134
133
  commandIntent?: { type: string; payload?: string; languageCode?: string };
135
134
 
@@ -430,7 +430,7 @@ async function listSkillsWithCatalog(): Promise<SlimSkillResponse[]> {
430
430
 
431
431
  // ─── Filtered skill listing ──────────────────────────────────────────────────
432
432
 
433
- export interface SkillListFilter {
433
+ interface SkillListFilter {
434
434
  origin?: string;
435
435
  kind?: string;
436
436
  q?: string;
@@ -698,7 +698,6 @@ export async function getSkill(
698
698
  // depends on `catalog-cache.ts`, which would otherwise be reachable via this
699
699
  // handler module). Re-exported here so handlers can import it alongside
700
700
  // the other skill handler exports.
701
- export type { SkillFileEntry } from "../../skills/catalog-files.js";
702
701
 
703
702
  /**
704
703
  * Returns true if `filePath` is a symlink whose resolved real path escapes
@@ -1428,7 +1427,7 @@ export async function inspectSkill(
1428
1427
  }
1429
1428
  }
1430
1429
 
1431
- export interface DraftResult {
1430
+ interface DraftResult {
1432
1431
  success: boolean;
1433
1432
  draft?: {
1434
1433
  skillId: string;
@@ -1583,7 +1582,7 @@ export async function draftSkill(params: {
1583
1582
  }
1584
1583
  }
1585
1584
 
1586
- export interface CreateSkillParams {
1585
+ interface CreateSkillParams {
1587
1586
  skillId: string;
1588
1587
  name: string;
1589
1588
  description: string;