@vellumai/assistant 0.7.2 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (424) hide show
  1. package/ARCHITECTURE.md +45 -29
  2. package/Dockerfile +1 -0
  3. package/__tests__/permissions/gateway-threshold-reader.test.ts +236 -9
  4. package/bun.lock +3 -0
  5. package/docs/architecture/memory.md +5 -2
  6. package/knip.json +1 -0
  7. package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +13 -4
  8. package/node_modules/@vellumai/ipc-server-utils/bun.lock +24 -0
  9. package/node_modules/@vellumai/ipc-server-utils/package.json +18 -0
  10. package/node_modules/@vellumai/ipc-server-utils/src/index.ts +6 -0
  11. package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.test.ts +430 -0
  12. package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.ts +221 -0
  13. package/node_modules/@vellumai/ipc-server-utils/tsconfig.json +20 -0
  14. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -9
  15. package/node_modules/@vellumai/slack-text/src/index.test.ts +18 -35
  16. package/node_modules/@vellumai/slack-text/src/index.ts +2 -48
  17. package/openapi.yaml +470 -25
  18. package/package.json +3 -1
  19. package/src/__tests__/annotate-risk-options.test.ts +291 -0
  20. package/src/__tests__/app-control-flow.test.ts +21 -11
  21. package/src/__tests__/approval-cascade.test.ts +8 -16
  22. package/src/__tests__/approval-routes-http.test.ts +6 -0
  23. package/src/__tests__/assistant-event-hub.test.ts +48 -0
  24. package/src/__tests__/assistant-event.test.ts +0 -10
  25. package/src/__tests__/assistant-events-sse-hardening.test.ts +2 -7
  26. package/src/__tests__/assistant-feature-flags-integration.test.ts +18 -0
  27. package/src/__tests__/auto-analysis-end-to-end.test.ts +48 -0
  28. package/src/__tests__/background-workers-disk-pressure.test.ts +268 -0
  29. package/src/__tests__/call-constants.test.ts +10 -1
  30. package/src/__tests__/call-controller.test.ts +127 -0
  31. package/src/__tests__/call-conversation-messages.test.ts +8 -2
  32. package/src/__tests__/channel-inbound-disk-pressure.test.ts +537 -0
  33. package/src/__tests__/channel-readiness-service.test.ts +4 -2
  34. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +58 -28
  35. package/src/__tests__/config-loader-backfill.test.ts +379 -0
  36. package/src/__tests__/config-loader-platform-defaults.test.ts +284 -1
  37. package/src/__tests__/config-schema.test.ts +1 -0
  38. package/src/__tests__/config-watcher-cleanup-throttle.test.ts +18 -9
  39. package/src/__tests__/config-watcher.test.ts +140 -69
  40. package/src/__tests__/context-search-agent-runner.test.ts +61 -3
  41. package/src/__tests__/context-search-conversations-source.test.ts +0 -24
  42. package/src/__tests__/context-search-fanout.test.ts +0 -1
  43. package/src/__tests__/context-search-memory-source.test.ts +6 -33
  44. package/src/__tests__/context-search-memory-v2-source.test.ts +0 -2
  45. package/src/__tests__/context-search-pkb-source.test.ts +12 -7
  46. package/src/__tests__/context-search-workspace-source.test.ts +0 -1
  47. package/src/__tests__/conversation-abort-tool-results.test.ts +1 -0
  48. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +223 -0
  49. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -1
  50. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -1
  51. package/src/__tests__/conversation-agent-loop.test.ts +457 -8
  52. package/src/__tests__/conversation-confirmation-signals.test.ts +5 -13
  53. package/src/__tests__/conversation-error.test.ts +150 -3
  54. package/src/__tests__/conversation-init.benchmark.test.ts +1 -1
  55. package/src/__tests__/conversation-process-callsite.test.ts +38 -0
  56. package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -0
  57. package/src/__tests__/conversation-runtime-assembly.test.ts +74 -0
  58. package/src/__tests__/conversation-slash-unknown.test.ts +1 -0
  59. package/src/__tests__/conversation-speed-override.test.ts +0 -3
  60. package/src/__tests__/conversation-store.test.ts +0 -18
  61. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +170 -9
  62. package/src/__tests__/conversation-surfaces-app-control.test.ts +15 -4
  63. package/src/__tests__/conversation-surfaces-data-persist.test.ts +476 -0
  64. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +61 -5
  65. package/src/__tests__/conversation-workspace-injection.test.ts +1 -1
  66. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -1
  67. package/src/__tests__/credentials-cli.test.ts +7 -0
  68. package/src/__tests__/cu-unified-flow.test.ts +176 -10
  69. package/src/__tests__/date-context.test.ts +164 -2
  70. package/src/__tests__/disk-pressure-guard.test.ts +262 -0
  71. package/src/__tests__/disk-pressure-lifecycle.test.ts +168 -0
  72. package/src/__tests__/disk-pressure-policy.test.ts +241 -0
  73. package/src/__tests__/disk-pressure-routes.test.ts +379 -0
  74. package/src/__tests__/disk-pressure-tools.test.ts +277 -0
  75. package/src/__tests__/disk-usage.test.ts +150 -0
  76. package/src/__tests__/events-client-registration.test.ts +52 -0
  77. package/src/__tests__/events-dev-bypass-actor.test.ts +162 -0
  78. package/src/__tests__/file-write-tool.test.ts +4 -10
  79. package/src/__tests__/filing-service.test.ts +2 -20
  80. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +10 -26
  81. package/src/__tests__/heartbeat-disk-pressure.test.ts +183 -0
  82. package/src/__tests__/heartbeat-service.test.ts +260 -11
  83. package/src/__tests__/host-app-control-proxy.test.ts +195 -25
  84. package/src/__tests__/host-bash-proxy.test.ts +227 -34
  85. package/src/__tests__/host-bash-routes.test.ts +178 -13
  86. package/src/__tests__/host-cu-proxy.test.ts +210 -3
  87. package/src/__tests__/host-cu-routes-targeted.test.ts +141 -12
  88. package/src/__tests__/host-file-proxy-targeted.test.ts +48 -9
  89. package/src/__tests__/host-file-proxy.test.ts +268 -6
  90. package/src/__tests__/host-file-routes-targeted.test.ts +175 -17
  91. package/src/__tests__/host-transfer-proxy-targeted.test.ts +408 -59
  92. package/src/__tests__/host-transfer-routes-targeted.test.ts +232 -17
  93. package/src/__tests__/http-user-message-parity.test.ts +107 -1
  94. package/src/__tests__/injector-chain.test.ts +36 -16
  95. package/src/__tests__/injector-disk-pressure.test.ts +224 -0
  96. package/src/__tests__/injector-pkb-v2-silenced.test.ts +10 -7
  97. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +154 -67
  98. package/src/__tests__/managed-profile-guard.test.ts +18 -0
  99. package/src/__tests__/mcp-abort-signal.test.ts +130 -0
  100. package/src/__tests__/memory-admin-recall.test.ts +3 -11
  101. package/src/__tests__/memory-retrieval-pipeline.test.ts +22 -1
  102. package/src/__tests__/normalize-onboarding.test.ts +180 -0
  103. package/src/__tests__/notification-decision-fallback.test.ts +91 -0
  104. package/src/__tests__/notification-decision-strategy.test.ts +22 -0
  105. package/src/__tests__/oauth-cli.test.ts +121 -0
  106. package/src/__tests__/oauth-connect-routes.test.ts +316 -0
  107. package/src/__tests__/oauth-provider-seed-logos.test.ts +24 -2
  108. package/src/__tests__/onboarding-persona-write.test.ts +308 -0
  109. package/src/__tests__/openai-provider.test.ts +45 -8
  110. package/src/__tests__/persist-onboarding-artifacts.test.ts +44 -64
  111. package/src/__tests__/platform-callback-registration.test.ts +21 -4
  112. package/src/__tests__/platform.test.ts +2 -1
  113. package/src/__tests__/playbook-execution.test.ts +0 -43
  114. package/src/__tests__/plugin-tool-contribution.test.ts +47 -0
  115. package/src/__tests__/prechat-onboarding-contract.test.ts +214 -27
  116. package/src/__tests__/provider-tool-name.test.ts +23 -0
  117. package/src/__tests__/relay-server.test.ts +60 -5
  118. package/src/__tests__/runtime-events-sse.test.ts +4 -8
  119. package/src/__tests__/scheduler-disk-pressure.test.ts +148 -0
  120. package/src/__tests__/secret-ingress-http.test.ts +0 -1
  121. package/src/__tests__/secret-prompt-log-hygiene.test.ts +7 -5
  122. package/src/__tests__/secret-prompter-channel-fallback.test.ts +7 -5
  123. package/src/__tests__/secret-response-routing.test.ts +7 -5
  124. package/src/__tests__/server-history-render.test.ts +82 -0
  125. package/src/__tests__/skill-include-graph.test.ts +31 -0
  126. package/src/__tests__/skill-load-tool.test.ts +44 -16
  127. package/src/__tests__/skills.test.ts +39 -0
  128. package/src/__tests__/suggestion-routes.test.ts +46 -0
  129. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -42
  130. package/src/__tests__/tool-executor.test.ts +155 -0
  131. package/src/__tests__/twilio-validation.test.ts +2 -2
  132. package/src/__tests__/voice-session-bridge.test.ts +3 -0
  133. package/src/__tests__/workspace-migration-065-bump-stale-heartbeat-interval.test.ts +122 -0
  134. package/src/__tests__/workspace-migration-066-seed-heartbeat-callsite-cost-default.test.ts +285 -0
  135. package/src/__tests__/workspace-migration-068-release-notes-local-timezone.test.ts +90 -0
  136. package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +120 -0
  137. package/src/__tests__/workspace-migration-071-remove-safe-storage-release-note.test.ts +206 -0
  138. package/src/__tests__/workspace-migration-safe-storage-limits-release.test.ts +78 -0
  139. package/src/agent/loop.ts +11 -0
  140. package/src/approvals/guardian-request-resolvers.ts +3 -32
  141. package/src/backup/snapshot-lock.ts +2 -27
  142. package/src/bundler/compiler-tools.ts +3 -2
  143. package/src/calls/call-constants.ts +5 -8
  144. package/src/calls/call-controller.ts +130 -67
  145. package/src/calls/call-conversation-messages.ts +46 -10
  146. package/src/calls/relay-server.ts +7 -1
  147. package/src/calls/voice-session-bridge.ts +1 -1
  148. package/src/cli/commands/__tests__/webhooks.test.ts +0 -4
  149. package/src/cli/commands/bash.ts +35 -108
  150. package/src/cli/commands/contacts.ts +64 -25
  151. package/src/cli/commands/credentials.ts +56 -0
  152. package/src/cli/commands/memory-v2.ts +11 -10
  153. package/src/cli/commands/oauth/__tests__/connect.test.ts +401 -219
  154. package/src/cli/commands/oauth/connect.ts +124 -40
  155. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -3
  156. package/src/cli/commands/platform/__tests__/connect.test.ts +7 -1
  157. package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -1
  158. package/src/cli/commands/platform/__tests__/status.test.ts +103 -6
  159. package/src/cli/commands/platform/index.ts +16 -7
  160. package/src/cli/commands/status.ts +57 -0
  161. package/src/cli/program.ts +4 -2
  162. package/src/config/assistant-feature-flags.ts +13 -3
  163. package/src/config/bundled-skills/app-builder/SKILL.md +1 -3
  164. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +4 -3
  165. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +13 -7
  166. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +2 -2
  167. package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +2 -2
  168. package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +2 -2
  169. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +2 -2
  170. package/src/config/env.ts +0 -8
  171. package/src/config/feature-flag-registry.json +13 -5
  172. package/src/config/loader.ts +199 -27
  173. package/src/config/schemas/__tests__/memory-v2.test.ts +10 -5
  174. package/src/config/schemas/call-site-catalog.ts +14 -0
  175. package/src/config/schemas/channels.ts +0 -5
  176. package/src/config/schemas/heartbeat.ts +1 -1
  177. package/src/config/schemas/llm.ts +2 -0
  178. package/src/config/schemas/memory-lifecycle.ts +13 -0
  179. package/src/config/schemas/memory-v2.ts +76 -12
  180. package/src/config/schemas/platform.ts +43 -3
  181. package/src/config/schemas/services.ts +28 -0
  182. package/src/config/seed-inference-profiles.ts +230 -33
  183. package/src/contacts/contact-store.ts +0 -25
  184. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +32 -0
  185. package/src/daemon/__tests__/conversation-tool-setup.test.ts +86 -25
  186. package/src/daemon/assistant-attachments.ts +4 -4
  187. package/src/daemon/config-watcher.ts +85 -57
  188. package/src/daemon/conversation-agent-loop-handlers.ts +38 -0
  189. package/src/daemon/conversation-agent-loop.ts +183 -43
  190. package/src/daemon/conversation-error.ts +87 -15
  191. package/src/daemon/conversation-lifecycle.ts +22 -10
  192. package/src/daemon/conversation-process.ts +8 -0
  193. package/src/daemon/conversation-runtime-assembly.ts +26 -0
  194. package/src/daemon/conversation-store.ts +2 -2
  195. package/src/daemon/conversation-surfaces.ts +211 -29
  196. package/src/daemon/conversation-tool-setup.ts +66 -19
  197. package/src/daemon/conversation.ts +18 -23
  198. package/src/daemon/date-context.ts +71 -22
  199. package/src/daemon/disk-pressure-background-gate.ts +73 -0
  200. package/src/daemon/disk-pressure-guard.ts +343 -0
  201. package/src/daemon/disk-pressure-policy.ts +163 -0
  202. package/src/daemon/handlers/shared.ts +26 -1
  203. package/src/daemon/handlers/skills.ts +3 -4
  204. package/src/daemon/host-app-control-proxy.ts +137 -41
  205. package/src/daemon/host-bash-proxy.ts +47 -22
  206. package/src/daemon/host-browser-proxy.ts +1 -1
  207. package/src/daemon/host-cu-proxy.ts +50 -4
  208. package/src/daemon/host-file-proxy.ts +44 -8
  209. package/src/daemon/host-transfer-proxy.ts +97 -6
  210. package/src/daemon/lifecycle.ts +167 -101
  211. package/src/daemon/meet-host-supervisor.ts +4 -4
  212. package/src/daemon/meet-manifest-loader.ts +0 -1
  213. package/src/daemon/memory-v2-startup.ts +66 -15
  214. package/src/daemon/message-protocol.ts +3 -0
  215. package/src/daemon/message-types/conversations.ts +4 -0
  216. package/src/daemon/message-types/disk-pressure.ts +9 -0
  217. package/src/daemon/message-types/messages.ts +22 -1
  218. package/src/daemon/profiler-run-store.ts +5 -5
  219. package/src/daemon/tool-setup-types.ts +2 -2
  220. package/src/documents/document-store.ts +119 -0
  221. package/src/filing/filing-service.ts +29 -5
  222. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +9 -16
  223. package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +36 -0
  224. package/src/heartbeat/heartbeat-run-store.ts +13 -0
  225. package/src/heartbeat/heartbeat-service.ts +205 -31
  226. package/src/home/feed-scheduler.ts +18 -0
  227. package/src/inbound/platform-callback-registration.ts +8 -15
  228. package/src/ipc/__tests__/clients-list-ipc.test.ts +169 -0
  229. package/src/ipc/assistant-server.ts +149 -38
  230. package/src/ipc/gateway-client.ts +37 -3
  231. package/src/ipc/skill-server.ts +99 -42
  232. package/src/live-voice/live-voice-archive.ts +4 -4
  233. package/src/live-voice/protocol.ts +5 -7
  234. package/src/media/image-service.ts +1 -7
  235. package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +21 -13
  236. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +34 -51
  237. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +0 -6
  238. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +272 -0
  239. package/src/memory/admin.ts +5 -9
  240. package/src/memory/context-search/agent-runner.ts +19 -2
  241. package/src/memory/context-search/sources/conversations.ts +2 -11
  242. package/src/memory/context-search/sources/memory-v2.ts +1 -16
  243. package/src/memory/context-search/sources/memory.ts +2 -3
  244. package/src/memory/context-search/sources/pkb.ts +2 -3
  245. package/src/memory/context-search/types.ts +0 -1
  246. package/src/memory/conversation-crud.ts +4 -12
  247. package/src/memory/db-init.ts +2 -0
  248. package/src/memory/embedding-runtime-manager.ts +119 -5
  249. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +136 -82
  250. package/src/memory/graph/__tests__/handle-remember-v2.test.ts +11 -26
  251. package/src/memory/graph/conversation-graph-memory.ts +72 -61
  252. package/src/memory/graph/extraction.ts +1 -3
  253. package/src/memory/graph/graph-search.test.ts +11 -67
  254. package/src/memory/graph/graph-search.ts +4 -24
  255. package/src/memory/graph/retriever.test.ts +12 -1
  256. package/src/memory/graph/retriever.ts +10 -15
  257. package/src/memory/graph/tool-handlers.ts +3 -4
  258. package/src/memory/graph/tools.ts +4 -4
  259. package/src/memory/indexer.ts +53 -45
  260. package/src/memory/job-handlers/backfill.ts +2 -11
  261. package/src/memory/job-handlers/cleanup.ts +43 -0
  262. package/src/memory/job-handlers/embedding.ts +6 -8
  263. package/src/memory/job-handlers/summarization.ts +2 -7
  264. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +116 -0
  265. package/src/memory/jobs/embed-concept-page.ts +223 -87
  266. package/src/memory/jobs-store.ts +48 -0
  267. package/src/memory/jobs-worker.ts +85 -43
  268. package/src/memory/memory-v2-activation-log-store.ts +32 -14
  269. package/src/memory/memory-v2-concept-frequency.ts +169 -0
  270. package/src/memory/migrations/239-trace-events-created-at-index.ts +18 -0
  271. package/src/memory/migrations/index.ts +1 -0
  272. package/src/memory/pkb/pkb-search.test.ts +7 -0
  273. package/src/memory/pkb/pkb-search.ts +4 -5
  274. package/src/memory/qdrant-client.ts +3 -13
  275. package/src/memory/rerank-local.ts +374 -0
  276. package/src/memory/search/semantic.ts +10 -72
  277. package/src/memory/trace-event-store.ts +1 -17
  278. package/src/memory/v2/__tests__/activation.test.ts +346 -255
  279. package/src/memory/v2/__tests__/consolidation-job.test.ts +61 -40
  280. package/src/memory/v2/__tests__/injection.test.ts +297 -190
  281. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +61 -2
  282. package/src/memory/v2/__tests__/qdrant.test.ts +326 -9
  283. package/src/memory/v2/__tests__/reranker.test.ts +338 -0
  284. package/src/memory/v2/__tests__/sim.test.ts +113 -196
  285. package/src/memory/v2/__tests__/skill-store.test.ts +71 -65
  286. package/src/memory/v2/__tests__/static-context.test.ts +77 -14
  287. package/src/memory/v2/__tests__/sweep-job.test.ts +19 -33
  288. package/src/memory/v2/activation.ts +149 -156
  289. package/src/memory/v2/consolidation-job.ts +69 -20
  290. package/src/memory/v2/injection.ts +75 -68
  291. package/src/memory/v2/page-store.ts +39 -0
  292. package/src/memory/v2/prompts/consolidation.ts +41 -1
  293. package/src/memory/v2/qdrant.ts +306 -46
  294. package/src/memory/v2/reranker.ts +177 -0
  295. package/src/memory/v2/sim.ts +77 -110
  296. package/src/memory/v2/skill-content.ts +4 -3
  297. package/src/memory/v2/skill-store.ts +82 -59
  298. package/src/memory/v2/static-context.ts +26 -8
  299. package/src/memory/v2/sweep-job.ts +5 -6
  300. package/src/memory/v2/types.ts +17 -10
  301. package/src/notifications/copy-composer.ts +47 -0
  302. package/src/notifications/decision-engine.ts +46 -0
  303. package/src/notifications/signal.ts +4 -0
  304. package/src/oauth/AGENTS.md +3 -1
  305. package/src/oauth/__tests__/oauth-connect-state.test.ts +137 -0
  306. package/src/oauth/connect-orchestrator.ts +2 -0
  307. package/src/oauth/connection-resolver.test.ts +66 -1
  308. package/src/oauth/connection-resolver.ts +55 -1
  309. package/src/oauth/oauth-connect-state.ts +77 -0
  310. package/src/oauth/seed-providers.ts +58 -1
  311. package/src/permissions/gateway-threshold-reader.ts +116 -8
  312. package/src/permissions/prompter.ts +86 -96
  313. package/src/permissions/secret-prompter.ts +31 -31
  314. package/src/plugins/defaults/injectors.ts +36 -4
  315. package/src/plugins/defaults/memory-retrieval.ts +5 -6
  316. package/src/plugins/types.ts +7 -0
  317. package/src/proactive-artifact/aux-message-injector.ts +74 -0
  318. package/src/proactive-artifact/decision.test.ts +226 -0
  319. package/src/proactive-artifact/decision.ts +165 -0
  320. package/src/proactive-artifact/index.ts +7 -0
  321. package/src/proactive-artifact/job.test.ts +914 -0
  322. package/src/proactive-artifact/job.ts +366 -0
  323. package/src/proactive-artifact/message-copy.ts +58 -0
  324. package/src/proactive-artifact/trigger-state.test.ts +277 -0
  325. package/src/proactive-artifact/trigger-state.ts +119 -0
  326. package/src/prompts/normalize-onboarding.ts +80 -0
  327. package/src/prompts/persona-resolver.ts +101 -9
  328. package/src/prompts/system-prompt.ts +21 -7
  329. package/src/prompts/templates/BOOTSTRAP.md +13 -5
  330. package/src/prompts/templates/SOUL.md +13 -28
  331. package/src/providers/__tests__/retry-callsite.test.ts +222 -1
  332. package/src/providers/model-intents.ts +7 -0
  333. package/src/providers/openrouter/client.ts +8 -0
  334. package/src/providers/retry.ts +50 -0
  335. package/src/providers/types.ts +1 -0
  336. package/src/runtime/__tests__/agent-wake.test.ts +456 -3
  337. package/src/runtime/agent-wake.ts +238 -100
  338. package/src/runtime/assistant-event-hub.ts +36 -6
  339. package/src/runtime/assistant-event.ts +0 -1
  340. package/src/runtime/auth/__tests__/route-policy.test.ts +64 -0
  341. package/src/runtime/auth/route-policy.ts +15 -1
  342. package/src/runtime/auth/same-actor.ts +216 -0
  343. package/src/runtime/channel-approvals.ts +3 -2
  344. package/src/runtime/channel-retry-sweep.ts +65 -1
  345. package/src/runtime/local-actor-identity.ts +52 -11
  346. package/src/runtime/pending-interactions.ts +27 -15
  347. package/src/runtime/routes/__tests__/client-routes.test.ts +155 -0
  348. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +0 -5
  349. package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +1 -1
  350. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +147 -0
  351. package/src/runtime/routes/approval-routes.ts +7 -3
  352. package/src/runtime/routes/client-routes.ts +20 -2
  353. package/src/runtime/routes/consolidation-routes.ts +8 -9
  354. package/src/runtime/routes/contact-routes.ts +0 -25
  355. package/src/runtime/routes/conversation-query-routes.ts +44 -1
  356. package/src/runtime/routes/conversation-routes.ts +35 -26
  357. package/src/runtime/routes/debug-bash-routes.ts +165 -0
  358. package/src/runtime/routes/disk-pressure-routes.ts +121 -0
  359. package/src/runtime/routes/document-pdf-renderer.ts +6 -2
  360. package/src/runtime/routes/documents-routes.ts +2 -75
  361. package/src/runtime/routes/events-routes.ts +41 -9
  362. package/src/runtime/routes/filing-routes.ts +2 -3
  363. package/src/runtime/routes/host-bash-routes.ts +23 -3
  364. package/src/runtime/routes/host-cu-routes.ts +33 -6
  365. package/src/runtime/routes/host-file-routes.ts +32 -6
  366. package/src/runtime/routes/host-transfer-routes.ts +79 -16
  367. package/src/runtime/routes/identity-routes.ts +7 -138
  368. package/src/runtime/routes/inbound-message-handler.ts +77 -12
  369. package/src/runtime/routes/index.ts +6 -0
  370. package/src/runtime/routes/memory-item-routes.test.ts +37 -17
  371. package/src/runtime/routes/memory-item-routes.ts +5 -6
  372. package/src/runtime/routes/memory-v2-routes.ts +136 -17
  373. package/src/runtime/routes/oauth-connect-routes.ts +153 -0
  374. package/src/runtime/verification-outbound-actions.ts +4 -4
  375. package/src/schedule/run-script.ts +37 -5
  376. package/src/schedule/scheduler.ts +20 -1
  377. package/src/security/encrypted-store.ts +2 -0
  378. package/src/security/secure-keys.ts +55 -0
  379. package/src/skills/include-graph.ts +35 -13
  380. package/src/skills/remote-skill-policy.ts +4 -10
  381. package/src/subagent/index.ts +1 -7
  382. package/src/subagent/manager.ts +1 -15
  383. package/src/tasks/task-runner.ts +0 -1
  384. package/src/tasks/task-store.ts +0 -3
  385. package/src/tools/background-tool-registry.ts +17 -3
  386. package/src/tools/document/document-tool.ts +20 -0
  387. package/src/tools/executor.ts +18 -2
  388. package/src/tools/host-filesystem/edit.test.ts +151 -0
  389. package/src/tools/host-filesystem/edit.ts +43 -1
  390. package/src/tools/host-filesystem/read.test.ts +129 -0
  391. package/src/tools/host-filesystem/read.ts +43 -1
  392. package/src/tools/host-filesystem/transfer.test.ts +127 -2
  393. package/src/tools/host-filesystem/transfer.ts +56 -11
  394. package/src/tools/host-filesystem/write.test.ts +134 -0
  395. package/src/tools/host-filesystem/write.ts +43 -1
  396. package/src/tools/host-terminal/host-shell.ts +13 -6
  397. package/src/tools/mcp/mcp-tool-factory.ts +2 -1
  398. package/src/tools/memory/register.test.ts +14 -9
  399. package/src/tools/memory/register.ts +1 -2
  400. package/src/tools/permission-checker.ts +15 -0
  401. package/src/tools/provider-tool-name.ts +28 -0
  402. package/src/tools/registry.ts +30 -9
  403. package/src/tools/skills/load.ts +24 -20
  404. package/src/tools/terminal/shell.ts +9 -1
  405. package/src/tools/tool-approval-handler.ts +31 -6
  406. package/src/tools/tool-name-aliases.ts +19 -0
  407. package/src/tools/types.ts +43 -3
  408. package/src/tts/provider-catalog.ts +3 -5
  409. package/src/util/disk-usage.ts +138 -0
  410. package/src/util/platform.ts +21 -11
  411. package/src/util/process-liveness.ts +26 -0
  412. package/src/workspace/heartbeat-service.ts +19 -0
  413. package/src/workspace/migrations/065-bump-stale-heartbeat-interval.ts +60 -0
  414. package/src/workspace/migrations/066-seed-heartbeat-callsite-cost-default.ts +146 -0
  415. package/src/workspace/migrations/067-release-notes-safe-storage-limits.ts +14 -0
  416. package/src/workspace/migrations/068-release-notes-local-timezone.ts +65 -0
  417. package/src/workspace/migrations/069-seed-onboarding-threads.ts +28 -0
  418. package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +31 -0
  419. package/src/workspace/migrations/071-remove-safe-storage-release-note.ts +111 -0
  420. package/src/workspace/migrations/registry.ts +14 -0
  421. package/src/__tests__/conversation-tool-setup-memory-scope.test.ts +0 -167
  422. package/src/memory/v2/__tests__/skill-qdrant.test.ts +0 -657
  423. package/src/memory/v2/skill-qdrant.ts +0 -404
  424. package/src/signals/bash.ts +0 -198
@@ -73,7 +73,7 @@ const DEFAULT_MIN_FREE_MB = 200;
73
73
 
74
74
  // ── Result type ─────────────────────────────────────────────────────────
75
75
 
76
- export interface ProfilerSweepResult {
76
+ interface ProfilerSweepResult {
77
77
  /** Number of completed runs pruned during this sweep. */
78
78
  prunedCount: number;
79
79
  /** Total bytes freed by pruning. */
@@ -159,7 +159,7 @@ function getFreeDiskBytes(path: string): number {
159
159
  // ── Core operations ─────────────────────────────────────────────────────
160
160
 
161
161
  /** Options for {@link rescanRuns}. */
162
- export interface RescanRunsOptions {
162
+ interface RescanRunsOptions {
163
163
  /**
164
164
  * When true, skip all `writeManifest()` calls — just read existing
165
165
  * manifests and recompute sizes without mutating the filesystem.
@@ -384,7 +384,7 @@ export function runProfilerSweep(): ProfilerSweepResult {
384
384
  // health-endpoint reporting and control-plane polling.
385
385
 
386
386
  /** Budget state for the active profiler run. */
387
- export interface ProfilerBudgetStatus {
387
+ interface ProfilerBudgetStatus {
388
388
  /** Configured maximum bytes across all runs. */
389
389
  maxBytes: number;
390
390
  /** Bytes remaining before the byte-count budget is exceeded. */
@@ -398,7 +398,7 @@ export interface ProfilerBudgetStatus {
398
398
  }
399
399
 
400
400
  /** Summary of the most recently completed profiler run. */
401
- export interface ProfilerLastCompletedRun {
401
+ interface ProfilerLastCompletedRun {
402
402
  runId: string;
403
403
  totalBytes: number;
404
404
  artifactCount: number;
@@ -407,7 +407,7 @@ export interface ProfilerLastCompletedRun {
407
407
  }
408
408
 
409
409
  /** Full runtime status snapshot for health-endpoint embedding. */
410
- export interface ProfilerRuntimeStatus {
410
+ interface ProfilerRuntimeStatus {
411
411
  /** Whether profiling is enabled (env vars present). */
412
412
  enabled: boolean;
413
413
  /** The profiling mode ("cpu", "heap", "cpu+heap"), or null when disabled. */
@@ -21,8 +21,8 @@ export interface ToolSetupContext extends SurfaceConversationContext {
21
21
  abortController: AbortController | null;
22
22
  /** When set, only tools in this set may execute during the current turn. */
23
23
  allowedToolNames?: Set<string>;
24
- /** Conversation memory policy used to propagate scopeId into ToolContext. */
25
- memoryPolicy: { scopeId: string };
24
+ /** Turn-scoped disk-pressure cleanup mode flag. */
25
+ diskPressureCleanupModeActive?: boolean;
26
26
  /** True when the conversation has no connected client (HTTP-only path). */
27
27
  hasNoClient?: boolean;
28
28
  /** When true, the conversation is executing a task run and must not become interactive. */
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Shared document persistence service.
3
+ *
4
+ * Extracted from documents-routes.ts so that both HTTP route handlers and
5
+ * background jobs (e.g. proactive artifact generation) can persist documents
6
+ * without going through the HTTP layer.
7
+ */
8
+ import { rawGet, rawRun } from "../memory/raw-query.js";
9
+ import { getLogger } from "../util/logger.js";
10
+
11
+ const log = getLogger("document-store");
12
+
13
+ // ---------------------------------------------------------------------------
14
+ // Junction table helper
15
+ // ---------------------------------------------------------------------------
16
+
17
+ /** Insert a document–conversation association (idempotent via INSERT OR IGNORE). */
18
+ export function addDocumentConversation(
19
+ surfaceId: string,
20
+ conversationId: string,
21
+ ): void {
22
+ rawRun(
23
+ /*sql*/ `INSERT OR IGNORE INTO document_conversations (surface_id, conversation_id, created_at) VALUES (?, ?, ?)`,
24
+ surfaceId,
25
+ conversationId,
26
+ Date.now(),
27
+ );
28
+ }
29
+
30
+ // ---------------------------------------------------------------------------
31
+ // Document persistence
32
+ // ---------------------------------------------------------------------------
33
+
34
+ export function saveDocument(params: {
35
+ surfaceId: string;
36
+ conversationId: string;
37
+ title: string;
38
+ content: string;
39
+ wordCount: number;
40
+ }): { success: true; surfaceId: string } | { success: false; error: string } {
41
+ try {
42
+ const now = Date.now();
43
+ rawRun(
44
+ `INSERT INTO documents (surface_id, conversation_id, title, content, word_count, created_at, updated_at)
45
+ VALUES (?, ?, ?, ?, ?, ?, ?)
46
+ ON CONFLICT(surface_id) DO UPDATE SET
47
+ title = excluded.title,
48
+ content = excluded.content,
49
+ word_count = excluded.word_count,
50
+ updated_at = excluded.updated_at`,
51
+ params.surfaceId,
52
+ params.conversationId,
53
+ params.title,
54
+ params.content,
55
+ params.wordCount,
56
+ now,
57
+ now,
58
+ );
59
+ log.info(
60
+ { surfaceId: params.surfaceId, title: params.title },
61
+ "Saved document",
62
+ );
63
+
64
+ // Best-effort: associate the document with the conversation.
65
+ // Failures (e.g. migration not yet applied, table missing) must not
66
+ // cause the save response to report failure — the document itself is
67
+ // already persisted at this point.
68
+ try {
69
+ addDocumentConversation(params.surfaceId, params.conversationId);
70
+ } catch (err) {
71
+ log.warn(
72
+ { err, surfaceId: params.surfaceId },
73
+ "Failed to record document–conversation association",
74
+ );
75
+ }
76
+
77
+ return { success: true, surfaceId: params.surfaceId };
78
+ } catch (error) {
79
+ log.error({ err: error, surfaceId: params.surfaceId }, "Save error");
80
+ return {
81
+ success: false,
82
+ error: error instanceof Error ? error.message : "Unknown error",
83
+ };
84
+ }
85
+ }
86
+
87
+ /** Update persisted document content (append or replace). */
88
+ export function updateDocumentContent(
89
+ surfaceId: string,
90
+ markdown: string,
91
+ mode: string,
92
+ ): void {
93
+ try {
94
+ const existing = rawGet<{ content: string }>(
95
+ /*sql*/ `SELECT content FROM documents WHERE surface_id = ?`,
96
+ surfaceId,
97
+ );
98
+ if (!existing) {
99
+ log.info({ surfaceId }, "No persisted document to update");
100
+ return;
101
+ }
102
+ const sep = mode === "append" && existing.content.length > 0 ? "\n\n" : "";
103
+ const newContent =
104
+ mode === "append" ? existing.content + sep + markdown : markdown;
105
+ const wordCount = newContent
106
+ .split(/\s+/)
107
+ .filter((w) => w.length > 0).length;
108
+ rawRun(
109
+ /*sql*/ `UPDATE documents SET content = ?, word_count = ?, updated_at = ? WHERE surface_id = ?`,
110
+ newContent,
111
+ wordCount,
112
+ Date.now(),
113
+ surfaceId,
114
+ );
115
+ log.info({ surfaceId, mode }, "Updated document content");
116
+ } catch (error) {
117
+ log.error({ err: error, surfaceId }, "Document content update error");
118
+ }
119
+ }
@@ -1,9 +1,13 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
 
4
- import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
5
4
  import { getConfig } from "../config/loader.js";
6
5
  import type { LLMCallSite } from "../config/schemas/llm.js";
6
+ import {
7
+ checkDiskPressureBackgroundGate,
8
+ diskPressureBackgroundSkipLogFields,
9
+ shouldLogDiskPressureBackgroundSkip,
10
+ } from "../daemon/disk-pressure-background-gate.js";
7
11
  import { processMessage } from "../daemon/process-message.js";
8
12
  import { bootstrapConversation } from "../memory/conversation-bootstrap.js";
9
13
  import { getLogger } from "../util/logger.js";
@@ -110,10 +114,7 @@ export class FilingService {
110
114
 
111
115
  start(): void {
112
116
  const fullConfig = getConfig();
113
- if (
114
- isAssistantFeatureFlagEnabled("memory-v2-enabled", fullConfig) &&
115
- fullConfig.memory.v2.enabled
116
- ) {
117
+ if (fullConfig.memory.v2.enabled) {
117
118
  log.info("Filing service disabled — memory v2 is active");
118
119
  this._nextRunAt = null;
119
120
  this._nextCompactionAt = null;
@@ -195,6 +196,10 @@ export class FilingService {
195
196
  const config = getConfig().filing;
196
197
  if (!force && !config.enabled) return false;
197
198
 
199
+ if (!force && this.shouldSkipForDiskPressure("filing")) {
200
+ return false;
201
+ }
202
+
198
203
  if (
199
204
  !force &&
200
205
  !this.isWithinActiveHoursNow(
@@ -245,6 +250,10 @@ export class FilingService {
245
250
  const config = getConfig().filing;
246
251
  if (!force && !config.compactionEnabled) return false;
247
252
 
253
+ if (!force && this.shouldSkipForDiskPressure("compaction")) {
254
+ return false;
255
+ }
256
+
248
257
  if (
249
258
  !force &&
250
259
  !this.isWithinActiveHoursNow(
@@ -299,6 +308,21 @@ export class FilingService {
299
308
  this._nextCompactionAt = Date.now() + intervalMs;
300
309
  }
301
310
 
311
+ private shouldSkipForDiskPressure(source: "filing" | "compaction"): boolean {
312
+ const diskPressureGate = checkDiskPressureBackgroundGate("background-work");
313
+ if (diskPressureGate.action === "allow") return false;
314
+ if (shouldLogDiskPressureBackgroundSkip(`filing-service:${source}`)) {
315
+ log.warn(
316
+ {
317
+ source,
318
+ ...diskPressureBackgroundSkipLogFields(diskPressureGate),
319
+ },
320
+ "Filing service skipped during disk pressure cleanup mode",
321
+ );
322
+ }
323
+ return true;
324
+ }
325
+
302
326
  private hasBufferContent(): boolean {
303
327
  const bufferPath = join(getWorkspaceDir(), "pkb", "buffer.md");
304
328
  if (!existsSync(bufferPath)) return false;
@@ -1,4 +1,4 @@
1
- import { mkdtempSync, readFileSync, rmSync } from "node:fs";
1
+ import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
2
2
  import { tmpdir } from "node:os";
3
3
  import { join } from "node:path";
4
4
  import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
@@ -15,6 +15,7 @@ mock.module("../heartbeat-run-store.js", () => ({
15
15
  markStaleRunsAsMissed: () => 0,
16
16
  markStaleRunningAsError: () => 0,
17
17
  listHeartbeatRuns: () => [],
18
+ countCompletedHeartbeatRuns: () => 10,
18
19
  }));
19
20
 
20
21
  // Stub the in-process SSE hub so the writer's publish path is a
@@ -146,6 +147,7 @@ interface OnDiskItem {
146
147
  }
147
148
 
148
149
  function readFeedItems(): OnDiskItem[] {
150
+ if (!existsSync(getHomeFeedPath())) return [];
149
151
  const raw = JSON.parse(readFileSync(getHomeFeedPath(), "utf-8"));
150
152
  return raw.items as OnDiskItem[];
151
153
  }
@@ -174,7 +176,7 @@ afterEach(() => {
174
176
  });
175
177
 
176
178
  describe("heartbeat feed events", () => {
177
- test("successful heartbeat emits feed event with priority 30 and no urgency", async () => {
179
+ test("successful heartbeat without an alert does not emit a feed event", async () => {
178
180
  _testProcessMessage = async () => ({ messageId: "msg-1" });
179
181
  const service = new HeartbeatService({
180
182
  alerter: () => {},
@@ -182,18 +184,12 @@ describe("heartbeat feed events", () => {
182
184
 
183
185
  await service.runOnce({ force: true });
184
186
 
185
- // Give the fire-and-forget emitFeedEvent time to flush.
187
+ // Give any fire-and-forget surfacing work time to flush.
186
188
  await new Promise((r) => setTimeout(r, 100));
187
189
 
188
190
  const items = readFeedItems();
189
191
  const heartbeatItem = items.find((i) => i.title === "Heartbeat");
190
- expect(heartbeatItem).toBeDefined();
191
- expect(heartbeatItem!.summary).toBe(
192
- "Periodic check completed. Tap to see details.",
193
- );
194
- expect(heartbeatItem!.priority).toBe(30);
195
- expect(heartbeatItem!.urgency).toBeUndefined();
196
- expect(heartbeatItem!.source).toBe("assistant");
192
+ expect(heartbeatItem).toBeUndefined();
197
193
  });
198
194
 
199
195
  test("failed heartbeat emits feed event with priority 55 and urgency medium", async () => {
@@ -218,13 +214,13 @@ describe("heartbeat feed events", () => {
218
214
  expect(heartbeatItem!.source).toBe("assistant");
219
215
  });
220
216
 
221
- test("dedupKey uses date for daily dedup", async () => {
217
+ test("repeated successful heartbeats without alerts stay silent", async () => {
222
218
  _testProcessMessage = async () => ({ messageId: "msg-1" });
223
219
  const service = new HeartbeatService({
224
220
  alerter: () => {},
225
221
  });
226
222
 
227
- // Run twice — same day should dedup to one item.
223
+ // Run twice — neither should create a generic success item.
228
224
  await service.runOnce({ force: true });
229
225
  await new Promise((r) => setTimeout(r, 100));
230
226
  await service.runOnce({ force: true });
@@ -232,9 +228,6 @@ describe("heartbeat feed events", () => {
232
228
 
233
229
  const items = readFeedItems();
234
230
  const heartbeatItems = items.filter((i) => i.title === "Heartbeat");
235
- expect(heartbeatItems).toHaveLength(1);
236
-
237
- const today = new Date().toISOString().split("T")[0];
238
- expect(heartbeatItems[0]!.id).toBe(`emit:assistant:heartbeat:ok:${today}`);
231
+ expect(heartbeatItems).toHaveLength(0);
239
232
  });
240
233
  });
@@ -15,6 +15,7 @@ import { getDb } from "../../memory/db-connection.js";
15
15
  import { initializeDb } from "../../memory/db-init.js";
16
16
  import {
17
17
  completeHeartbeatRun,
18
+ countCompletedHeartbeatRuns,
18
19
  insertPendingHeartbeatRun,
19
20
  listHeartbeatRuns,
20
21
  markStaleRunningAsError,
@@ -213,4 +214,39 @@ describe("heartbeat-run-store", () => {
213
214
  const rows = listHeartbeatRuns(3);
214
215
  expect(rows).toHaveLength(3);
215
216
  });
217
+
218
+ test("countCompletedHeartbeatRuns counts only ok rows", () => {
219
+ const now = Date.now();
220
+
221
+ // Insert runs with various statuses
222
+ const id1 = insertPendingHeartbeatRun(now);
223
+ startHeartbeatRun(id1);
224
+ completeHeartbeatRun(id1, { status: "ok", conversationId: "conv-1" });
225
+
226
+ const id2 = insertPendingHeartbeatRun(now + 1);
227
+ startHeartbeatRun(id2);
228
+ completeHeartbeatRun(id2, { status: "error", error: "something broke" });
229
+
230
+ const id3 = insertPendingHeartbeatRun(now + 2);
231
+ skipHeartbeatRun(id3, "disabled");
232
+
233
+ const id4 = insertPendingHeartbeatRun(now + 3);
234
+ startHeartbeatRun(id4);
235
+ completeHeartbeatRun(id4, { status: "ok", conversationId: "conv-2" });
236
+
237
+ expect(countCompletedHeartbeatRuns()).toBe(2);
238
+ });
239
+
240
+ test("countCompletedHeartbeatRuns returns 0 when no ok rows exist", () => {
241
+ const now = Date.now();
242
+
243
+ const id1 = insertPendingHeartbeatRun(now);
244
+ startHeartbeatRun(id1);
245
+ completeHeartbeatRun(id1, { status: "error", error: "fail" });
246
+
247
+ const id2 = insertPendingHeartbeatRun(now + 1);
248
+ skipHeartbeatRun(id2, "outside_active_hours");
249
+
250
+ expect(countCompletedHeartbeatRuns()).toBe(0);
251
+ });
216
252
  });
@@ -202,6 +202,19 @@ export function markStaleRunningAsError(
202
202
  return rawChanges();
203
203
  }
204
204
 
205
+ /**
206
+ * Count the number of heartbeat runs that completed with status `ok`.
207
+ */
208
+ export function countCompletedHeartbeatRuns(): number {
209
+ const db = getDb();
210
+ const row = db
211
+ .select({ count: sql<number>`count(*)` })
212
+ .from(heartbeatRuns)
213
+ .where(eq(heartbeatRuns.status, "ok"))
214
+ .get();
215
+ return row?.count ?? 0;
216
+ }
217
+
205
218
  /**
206
219
  * List heartbeat runs ordered by `scheduledFor` descending.
207
220
  */