@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
package/ARCHITECTURE.md CHANGED
@@ -21,6 +21,20 @@ This document owns assistant-runtime architecture details. The repo-level archit
21
21
  - Voice calls mirror the same prompt contract: `CallController` receives guardian context on setup and refreshes it immediately after successful voice challenge verification, so the first post-verification turn is grounded as `actor_role: guardian`.
22
22
  - Voice-specific behavior (DTMF/speech verification flow, relay state machine) remains voice-local; only actor-role resolution is shared.
23
23
 
24
+ ### Safe Storage Limits
25
+
26
+ Safe storage limits are gated by the assistant feature flag `safe-storage-limits`, default off. When the flag is off, the disk pressure guard reports a disabled status and no runtime path blocks work, injects cleanup guidance, or changes tool access.
27
+
28
+ **Disk pressure state:** `src/daemon/disk-pressure-guard.ts` samples workspace storage usage every 60 seconds through `src/util/disk-usage.ts`. At or above the 95% critical threshold it creates an in-memory lock with `lockId`, usage snapshot, `acknowledged`, `overrideActive`, `effectivelyLocked`, and the blocked capabilities `agent-turns`, `background-work`, and `remote-ingress`. The lock clears when usage drops below the threshold or the process restarts. `acknowledgeDiskPressureLock()` only lets the guardian enter cleanup mode; `overrideDiskPressureLock()` requires the exact phrase `I understand the risks` and disables the effective lock while usage remains critical.
29
+
30
+ **Runtime API and events:** `src/runtime/routes/disk-pressure-routes.ts` exposes `GET /v1/disk-pressure/status`, `POST /v1/disk-pressure/acknowledge`, and `POST /v1/disk-pressure/override`. Route auth policies require normal runtime protection, and `disk_pressure_status_changed` events are emitted when the status changes so clients can update live.
31
+
32
+ **Turn policy:** `src/daemon/disk-pressure-policy.ts` classifies turns before the main agent loop. Local guardian/owner turns are allowed in cleanup mode; trusted contacts, non-guardian actors, unknown remote senders, background conversations, direct wakes, and non-main LLM call sites are blocked while `effectivelyLocked` is true. Blocked turns emit terminal conversation errors rather than reaching the provider.
33
+
34
+ **Background work:** Heartbeats, scheduled tasks, filing work, retry sweeps, and background tool completions call `src/daemon/disk-pressure-background-gate.ts` before starting work. While effectively locked they skip the wake or job and log throttled disk-pressure fields.
35
+
36
+ **Prompt and tools:** Cleanup-mode turns carry `diskPressureContext` through runtime assembly and receive the `<disk_pressure_warning>` injector in `src/plugins/defaults/injectors.ts`. The instruction tells the assistant to warn first, focus only on freeing storage, inspect before deleting, ask for deletion approval, and explain that background processes and trusted-contact messages are blocked. Tool setup marks the turn as cleanup mode; `src/tools/tool-approval-handler.ts` rejects non-cleanup-safe tools, and foreground shell inspection remains available while background `bash` and `host_bash` modes are rejected. When a new lock is created, active background terminal tools are cancelled with reason `disk_pressure`.
37
+
24
38
  ### Single-Header JWT Auth Model
25
39
 
26
40
  All HTTP API requests use a single `Authorization: Bearer <jwt>` header for authentication. The JWT carries identity, permissions, and policy versioning in a unified token.
@@ -966,6 +980,7 @@ The daemon emits two distinct error message types via SSE:
966
980
  | -------------------------------- | ----------------------------------------------------------------------- | --------- |
967
981
  | `PROVIDER_NETWORK` | Unable to reach the LLM provider (connection refused, timeout, DNS) | Yes |
968
982
  | `PROVIDER_RATE_LIMIT` | LLM provider rate-limited the request (HTTP 429) | Yes |
983
+ | `MANAGED_USAGE_LIMIT` | Vellum managed inference usage limit or quota was exceeded (HTTP 429) | Yes |
969
984
  | `PROVIDER_API` | Provider returned a server error (5xx) or retryable 4xx | Yes |
970
985
  | `PROVIDER_BILLING` | Invalid/expired API key or insufficient credits (HTTP 401, billing 4xx) | No |
971
986
  | `CONTEXT_TOO_LARGE` | Request exceeds the model's context window (HTTP 413, token limit) | No |
@@ -980,7 +995,7 @@ The daemon classifies errors via `classifyConversationError()` in `conversation-
980
995
 
981
996
  Classification uses a two-tier strategy:
982
997
 
983
- 1. **Structured provider errors**: If the error is a `ProviderError` with a `statusCode`, the status code determines the category deterministically — `413` maps to `CONTEXT_TOO_LARGE` (not retryable), `401` maps to `PROVIDER_BILLING` (not retryable, invalid/expired key), `429` maps to `PROVIDER_RATE_LIMIT` (retryable), `5xx` to `PROVIDER_API` (retryable), other `4xx` to `PROVIDER_API` (retryable) unless a message pattern matches a more specific non-retryable category (context-too-large, billing/auth).
998
+ 1. **Structured provider errors**: If the error is a `ProviderError` with a `statusCode`, the status code determines the category deterministically — `413` maps to `CONTEXT_TOO_LARGE` (not retryable), `401` maps to `PROVIDER_BILLING` (not retryable, invalid/expired key), `429` maps to `MANAGED_USAGE_LIMIT` when the provider is routed through the managed proxy or the payload matches a Vellum managed quota/limit response, otherwise `PROVIDER_RATE_LIMIT` (retryable), `5xx` to `PROVIDER_API` (retryable), other `4xx` to `PROVIDER_API` (retryable) unless a message pattern matches a more specific non-retryable category (context-too-large, billing/auth).
984
999
  2. **Regex fallback**: For non-provider errors or `ProviderError` without a status code, regex pattern matching against the error message detects network failures, rate limits, and API errors. Phase-specific overrides handle regeneration contexts.
985
1000
 
986
1001
  Debug details are capped at 4,000 characters to prevent oversized payloads.
@@ -472,7 +472,7 @@ The Anthropic provider places `cache_control: { type: 'ephemeral' }` on the **la
472
472
 
473
473
  The session injects a unified `<turn_context>` block into every user message, giving the model awareness of the current timestamp (with timezone), interface, channel, and actor identity. This replaces the former separate `<temporal_context>`, `<inbound_actor_context>`, and per-channel turn context blocks. The unified block persists in conversation history so the assistant retains temporal and actor grounding across turns. Legacy blocks from pre-change history are stripped for backward compatibility.
474
474
 
475
- The `current_time:` field format is: `2026-04-02 (Wednesday) 14:30:00 -05:00 (America/Chicago)` — date, weekday name, local time, UTC offset, and IANA timezone name.
475
+ The `current_time:` field format is: `2026-04-02 (Wednesday) 14:30:00 -05:00 (America/Chicago)` — date, weekday name, local time, UTC offset, and IANA timezone name. The timestamp is grounded in the user's effective timezone, not UTC, so a message sent at 10pm local time is represented as 10pm for date/time reasoning.
476
476
 
477
477
  ### Per-turn flow
478
478
 
@@ -492,7 +492,10 @@ graph TB
492
492
 
493
493
  - **Fresh each turn**: `buildUnifiedTurnContextBlock()` is called at the start of every agent loop invocation, ensuring the model always sees the current timestamp even in long-running conversations.
494
494
  - **Clock source invariant**: Absolute time (`now`) always comes from the assistant host clock (`Date.now()`), never from channel/client clocks.
495
- - **Timezone precedence**: If `ui.userTimezone` is configured, turn context uses it for local-date interpretation. Otherwise it falls back to memory-stored timezone, then assistant host timezone.
495
+ - **Timezone precedence**: Turn context resolves the effective timezone in this order: explicit runtime override for tests/legacy callers, manual `ui.userTimezone`, current turn `clientTimezone`, persisted `ui.detectedTimezone`, then assistant host timezone. The host clock still supplies the absolute instant; this cascade only selects the local timezone used to render `current_time`.
496
+ - **Manual override semantics**: `ui.userTimezone` is a historical config path, but it is runtime-affecting, not purely presentational. When set, it is authoritative for `current_time` across all clients until the user clears or changes it.
497
+ - **Device timezone semantics**: `clientTimezone` is the timezone reported with the active message for this turn. `ui.detectedTimezone` is the last device-detected timezone persisted by a client and is only used when there is no manual override and the current message does not carry a client timezone.
498
+ - **Timezone mismatch guidance**: When `ui.userTimezone` differs from the current device timezone (`clientTimezone`, or `ui.detectedTimezone` when no current client value exists), `<turn_context>` also includes `configured_user_timezone`, `client_device_timezone`, and `timezone_update_available`. The last line tells the assistant that, after explicit user confirmation, it can persist the device timezone with `assistant config set ui.userTimezone "<IANA zone>"`. This gives the assistant a natural-language path to fix stale manual overrides without adding a dedicated tool.
496
499
  - **Timezone-aware**: Uses `Intl.DateTimeFormat` APIs for DST-safe date arithmetic and timezone validation/canonicalization.
497
500
  - **Persists in history**: The `<turn_context>` block persists in conversation history. Legacy `<temporal_context>`, `<inbound_actor_context>`, and separate channel context blocks from pre-change history are stripped for backward compatibility.
498
501
  - **Retry paths**: Turn context is included in all `applyRuntimeInjections` call sites (main path, compact retry, media-trim retry).
@@ -62,13 +62,22 @@ const CONNECT_TIMEOUT_MS = 3_000;
62
62
  * Designed for CLI and daemon startup where we need a single RPC call
63
63
  * without leaving open handles. Returns `undefined` on any failure
64
64
  * (socket not found, timeout, parse error) so callers can fall back.
65
+ *
66
+ * @param timeoutMs - Optional override for both the connect and call
67
+ * timeouts. When omitted, defaults to the module constants
68
+ * (CONNECT_TIMEOUT_MS / DEFAULT_CALL_TIMEOUT_MS). Pass a small value
69
+ * (e.g. 200) for opportunistic CLI checks where a slow/absent gateway
70
+ * should fail fast rather than block startup.
65
71
  */
66
72
  export async function ipcCall(
67
73
  socketPath: string,
68
74
  method: string,
69
75
  params?: Record<string, unknown>,
70
76
  log: Logger = noopLogger,
77
+ timeoutMs?: number,
71
78
  ): Promise<unknown> {
79
+ const connectTimeoutMs = timeoutMs ?? CONNECT_TIMEOUT_MS;
80
+ const callTimeoutMs = timeoutMs ?? DEFAULT_CALL_TIMEOUT_MS;
72
81
  return new Promise<unknown>((resolve) => {
73
82
  let settled = false;
74
83
  let callTimer: ReturnType<typeof setTimeout> | undefined;
@@ -84,11 +93,11 @@ export async function ipcCall(
84
93
 
85
94
  const connectTimer = setTimeout(() => {
86
95
  log.warn(
87
- { method, socketPath, timeoutMs: CONNECT_TIMEOUT_MS },
96
+ { method, socketPath, timeoutMs: connectTimeoutMs },
88
97
  "IPC connect timed out",
89
98
  );
90
99
  finish(undefined);
91
- }, CONNECT_TIMEOUT_MS);
100
+ }, connectTimeoutMs);
92
101
 
93
102
  const socket: Socket = connect(socketPath);
94
103
  socket.unref();
@@ -103,11 +112,11 @@ export async function ipcCall(
103
112
 
104
113
  callTimer = setTimeout(() => {
105
114
  log.warn(
106
- { method, socketPath, timeoutMs: DEFAULT_CALL_TIMEOUT_MS },
115
+ { method, socketPath, timeoutMs: callTimeoutMs },
107
116
  "IPC call timed out waiting for response",
108
117
  );
109
118
  finish(undefined);
110
- }, DEFAULT_CALL_TIMEOUT_MS);
119
+ }, callTimeoutMs);
111
120
 
112
121
  socket.on("data", (chunk) => {
113
122
  buffer += chunk.toString();
@@ -84,12 +84,3 @@ export function formatSseFrame(event: AssistantEvent): string {
84
84
  export function formatSseHeartbeat(): string {
85
85
  return ": heartbeat\n\n";
86
86
  }
87
-
88
- /**
89
- * Format a keep-alive as both an SSE comment (for proxy keepalive) and a
90
- * data-bearing event (so fetch-based SSE clients that cannot observe comment
91
- * lines can still detect heartbeats for disconnect watchdogs).
92
- */
93
- export function formatSseHeartbeatWithData(): string {
94
- return `${formatSseHeartbeat()}event: assistant_event\ndata: ${JSON.stringify({ type: "heartbeat" })}\n\n`;
95
- }
@@ -4,8 +4,6 @@ import {
4
4
  buildSlackUserLabelMap,
5
5
  extractSlackUserMentionIds,
6
6
  renderSlackTextForModel,
7
- stripLeadingSlackMentionFallback,
8
- stripLeadingSlackUserMention,
9
7
  } from "./index.js";
10
8
 
11
9
  describe("extractSlackUserMentionIds", () => {
@@ -16,34 +14,6 @@ describe("extractSlackUserMentionIds", () => {
16
14
  });
17
15
  });
18
16
 
19
- describe("stripLeadingSlackUserMention", () => {
20
- test("strips only leading mentions for the exact bot ID", () => {
21
- expect(stripLeadingSlackUserMention("<@U111> <@U222> hi", "U111")).toBe(
22
- "<@U222> hi"
23
- );
24
- });
25
-
26
- test("strips repeated leading mentions for the exact bot ID", () => {
27
- expect(stripLeadingSlackUserMention(" <@U111> <@U111> hi", "U111")).toBe(
28
- "hi"
29
- );
30
- });
31
-
32
- test("preserves text when the leading mention is a different user", () => {
33
- expect(stripLeadingSlackUserMention("<@U222> hi <@U111>", "U111")).toBe(
34
- "<@U222> hi <@U111>"
35
- );
36
- });
37
- });
38
-
39
- describe("stripLeadingSlackMentionFallback", () => {
40
- test("strips only the first leading Slack user mention", () => {
41
- expect(stripLeadingSlackMentionFallback(" <@U111> <@U222> hi")).toBe(
42
- "<@U222> hi"
43
- );
44
- });
45
- });
46
-
47
17
  describe("renderSlackTextForModel", () => {
48
18
  test("renders resolved user mentions", () => {
49
19
  expect(
@@ -123,19 +93,32 @@ describe("renderSlackTextForModel", () => {
123
93
  });
124
94
 
125
95
  describe("buildSlackUserLabelMap", () => {
126
- test("dedupes mentioned users across text inputs and ignores configured IDs", async () => {
96
+ test("dedupes mentioned users across text inputs and resolves them in parallel", async () => {
127
97
  const resolved: string[] = [];
128
98
  const labels = await buildSlackUserLabelMap(
129
99
  ["<@U123> hi <@U999>", undefined, "<@U123> and <@W456>"],
130
100
  async (userId) => {
131
101
  resolved.push(userId);
102
+ if (userId === "U999") return "Charlie";
132
103
  return userId === "W456" ? "Bob" : "Alice";
133
- },
134
- { ignoredUserIds: ["U999"] }
104
+ }
105
+ );
106
+
107
+ expect(resolved.sort()).toEqual(["U123", "U999", "W456"]);
108
+ expect(labels).toEqual({ U123: "Alice", U999: "Charlie", W456: "Bob" });
109
+ });
110
+
111
+ test("resolves bot and human user mentions together", async () => {
112
+ const labels = await buildSlackUserLabelMap(
113
+ ["<@UBOT> can you help <@ULEO> with the deploy?"],
114
+ async (userId) => {
115
+ if (userId === "UBOT") return "vex";
116
+ if (userId === "ULEO") return "leo";
117
+ return undefined;
118
+ }
135
119
  );
136
120
 
137
- expect(resolved).toEqual(["U123", "W456"]);
138
- expect(labels).toEqual({ U123: "Alice", W456: "Bob" });
121
+ expect(labels).toEqual({ UBOT: "vex", ULEO: "leo" });
139
122
  });
140
123
 
141
124
  test("omits unresolved labels and labels equal to the Slack user ID", async () => {
@@ -5,12 +5,7 @@ export interface RenderSlackTextOptions {
5
5
  channelFallbackLabel?: string;
6
6
  }
7
7
 
8
- export interface BuildSlackUserLabelMapOptions {
9
- ignoredUserIds?: Iterable<string | undefined>;
10
- }
11
-
12
8
  const SLACK_USER_MENTION_RE = /<@([UW][A-Z0-9]+)>/g;
13
- const LEADING_SLACK_USER_MENTION_RE = /^\s*<@[UW][A-Z0-9]+>\s*/;
14
9
 
15
10
  export function extractSlackUserMentionIds(text: string): string[] {
16
11
  const seen = new Set<string>();
@@ -27,30 +22,6 @@ export function extractSlackUserMentionIds(text: string): string[] {
27
22
  return ids;
28
23
  }
29
24
 
30
- export function stripLeadingSlackUserMention(
31
- text: string,
32
- userId: string
33
- ): string {
34
- if (!isSlackUserId(userId)) {
35
- return text;
36
- }
37
-
38
- const mention = `<@${userId}>`;
39
- let stripped = text;
40
-
41
- while (true) {
42
- const next = stripLeadingExactToken(stripped, mention);
43
- if (next === stripped) {
44
- return stripped;
45
- }
46
- stripped = next;
47
- }
48
- }
49
-
50
- export function stripLeadingSlackMentionFallback(text: string): string {
51
- return text.replace(LEADING_SLACK_USER_MENTION_RE, "");
52
- }
53
-
54
25
  export function renderSlackTextForModel(
55
26
  text: string,
56
27
  options: RenderSlackTextOptions = {}
@@ -78,21 +49,15 @@ export function renderSlackTextForModel(
78
49
 
79
50
  export async function buildSlackUserLabelMap(
80
51
  texts: Iterable<string | undefined>,
81
- resolveLabel: (userId: string) => Promise<string | undefined | null>,
82
- options: BuildSlackUserLabelMapOptions = {}
52
+ resolveLabel: (userId: string) => Promise<string | undefined | null>
83
53
  ): Promise<Record<string, string>> {
84
- const ignored = new Set(
85
- [...(options.ignoredUserIds ?? [])].filter(
86
- (id): id is string => typeof id === "string" && id.length > 0
87
- )
88
- );
89
54
  const ids: string[] = [];
90
55
  const seen = new Set<string>();
91
56
 
92
57
  for (const text of texts) {
93
58
  if (!text) continue;
94
59
  for (const id of extractSlackUserMentionIds(text)) {
95
- if (ignored.has(id) || seen.has(id)) continue;
60
+ if (seen.has(id)) continue;
96
61
  seen.add(id);
97
62
  ids.push(id);
98
63
  }
@@ -215,17 +180,6 @@ function sanitizeOptionalLabel(label: string | undefined): string | undefined {
215
180
  .trim();
216
181
  }
217
182
 
218
- function stripLeadingExactToken(text: string, token: string): string {
219
- const leadingWhitespaceLength = text.length - text.trimStart().length;
220
- const afterWhitespace = text.slice(leadingWhitespaceLength);
221
-
222
- if (!afterWhitespace.startsWith(token)) {
223
- return text;
224
- }
225
-
226
- return afterWhitespace.slice(token.length).trimStart();
227
- }
228
-
229
183
  function isSlackUserId(value: string): boolean {
230
184
  return /^[UW][A-Z0-9]+$/.test(value);
231
185
  }