@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
@@ -23,6 +23,7 @@ import {
23
23
  assistantEventHub,
24
24
  broadcastMessage,
25
25
  } from "../runtime/assistant-event-hub.js";
26
+ import { enforceSameActorOrErrorResult } from "../runtime/auth/same-actor.js";
26
27
  import * as pendingInteractions from "../runtime/pending-interactions.js";
27
28
  import type { ToolExecutionResult } from "../tools/types.js";
28
29
  import { AssistantError, ErrorCode } from "../util/errors.js";
@@ -121,6 +122,16 @@ export class HostCuProxy {
121
122
  // Request / resolve lifecycle
122
123
  // ---------------------------------------------------------------------------
123
124
 
125
+ /**
126
+ * Send a CU request to the connected desktop client.
127
+ *
128
+ * When `targetClientId` is supplied, the proxy validates that the target
129
+ * exists and advertises the `host_cu` capability, mirroring HostFileProxy's
130
+ * resolver-side checks so that the proxy is safe to call as a standalone
131
+ * API. It additionally enforces that the caller (`sourceActorPrincipalId`)
132
+ * and the target client share the same actor principal — cross-user
133
+ * targeted dispatch is rejected.
134
+ */
124
135
  request(
125
136
  toolName: string,
126
137
  input: Record<string, unknown>,
@@ -129,6 +140,7 @@ export class HostCuProxy {
129
140
  reasoning?: string,
130
141
  signal?: AbortSignal,
131
142
  targetClientId?: string,
143
+ sourceActorPrincipalId?: string,
132
144
  ): Promise<ToolExecutionResult> {
133
145
  if (signal?.aborted) {
134
146
  return Promise.resolve({
@@ -144,6 +156,38 @@ export class HostCuProxy {
144
156
  });
145
157
  }
146
158
 
159
+ // Existence + capability validation for explicit targets. Mirrors
160
+ // HostFileProxy's resolver-side guard so that the proxy is safe even
161
+ // when called outside the conversation-surfaces dispatch (which has
162
+ // its own validation layer).
163
+ if (targetClientId != null) {
164
+ const client = assistantEventHub.getClientById(targetClientId);
165
+ if (!client) {
166
+ return Promise.resolve({
167
+ content: `No connected client with id '${targetClientId}' supports host_cu. Run \`assistant clients list --capability host_cu\` to see available clients.`,
168
+ isError: true,
169
+ });
170
+ }
171
+ if (!client.capabilities.includes("host_cu")) {
172
+ return Promise.resolve({
173
+ content: `Client '${targetClientId}' does not support host_cu. Run \`assistant clients list --capability host_cu\` to see available clients.`,
174
+ isError: true,
175
+ });
176
+ }
177
+
178
+ // Same-user enforcement: targeted CU dispatch must be owned by the
179
+ // same actor on both sides. This is the authoritative gate — the
180
+ // dispatch layer (conversation-surfaces.ts) skips its own check
181
+ // and relies on the proxy.
182
+ const rejection = enforceSameActorOrErrorResult({
183
+ hub: assistantEventHub,
184
+ sourceActorPrincipalId,
185
+ targetClientId,
186
+ op: "host_cu",
187
+ });
188
+ if (rejection) return Promise.resolve(rejection);
189
+ }
190
+
147
191
  const requestId = uuid();
148
192
 
149
193
  return new Promise<ToolExecutionResult>((resolve, reject) => {
@@ -170,9 +214,7 @@ export class HostCuProxy {
170
214
  type: "host_cu_cancel",
171
215
  requestId,
172
216
  conversationId,
173
- ...(targetClientId != null
174
- ? { targetClientId }
175
- : {}),
217
+ ...(targetClientId != null ? { targetClientId } : {}),
176
218
  },
177
219
  conversationId,
178
220
  { targetClientId },
@@ -193,7 +235,11 @@ export class HostCuProxy {
193
235
  conversationId,
194
236
  kind: "host_cu",
195
237
  targetClientId,
196
- rpcResolve: resolve,
238
+ targetActorPrincipalId:
239
+ targetClientId != null
240
+ ? assistantEventHub.getActorPrincipalIdForClient(targetClientId)
241
+ : undefined,
242
+ rpcResolve: resolve as (v: unknown) => void,
197
243
  rpcReject: reject,
198
244
  timer,
199
245
  detachAbort,
@@ -4,6 +4,11 @@ import {
4
4
  assistantEventHub,
5
5
  broadcastMessage,
6
6
  } from "../runtime/assistant-event-hub.js";
7
+ import {
8
+ ambiguousSameUserError,
9
+ enforceSameActorOrErrorResult,
10
+ pickSameUserAutoResolve,
11
+ } from "../runtime/auth/same-actor.js";
7
12
  import * as pendingInteractions from "../runtime/pending-interactions.js";
8
13
  import { readImageBase64 } from "../tools/shared/filesystem/image-read.js";
9
14
  import type { ToolExecutionResult } from "../tools/types.js";
@@ -68,15 +73,18 @@ export class HostFileProxy {
68
73
  conversationId: string,
69
74
  signal?: AbortSignal,
70
75
  targetClientId?: string,
76
+ sourceActorPrincipalId?: string,
71
77
  ): Promise<ToolExecutionResult> {
72
78
  if (signal?.aborted) {
73
79
  return Promise.resolve({ content: "Aborted", isError: true });
74
80
  }
75
81
 
76
- // Resolve targetClientId: explicit → validate; single capable client → auto-resolve.
77
- // Callers may embed targetClientId in the input object (tool handlers) or pass it as
78
- // the 4th parameter (legacy). Prefer the explicit param; fall back to input field.
79
- let resolvedTargetClientId: string | undefined = targetClientId ?? input.targetClientId;
82
+ // Resolve targetClientId: explicit → validate; single same-user
83
+ // capable client → auto-resolve. Callers may embed targetClientId in
84
+ // the input object (tool handlers) or pass it as the 4th parameter
85
+ // (legacy). Prefer the explicit param; fall back to input field.
86
+ let resolvedTargetClientId: string | undefined =
87
+ targetClientId ?? input.targetClientId;
80
88
  if (resolvedTargetClientId != null) {
81
89
  const client = assistantEventHub.getClientById(resolvedTargetClientId);
82
90
  if (!client) {
@@ -92,10 +100,32 @@ export class HostFileProxy {
92
100
  });
93
101
  }
94
102
  } else {
95
- const capable = assistantEventHub.listClientsByCapability("host_file");
96
- if (capable.length === 1) {
97
- resolvedTargetClientId = capable[0].clientId;
103
+ // Auto-resolve to the unique same-user client. Reject ambiguous
104
+ // (multi-machine) cases so a single targeted-style request cannot
105
+ // fan out across the user's machines.
106
+ const resolved = pickSameUserAutoResolve({
107
+ hub: assistantEventHub,
108
+ capability: "host_file",
109
+ sourceActorPrincipalId,
110
+ });
111
+ if (resolved.kind === "ambiguous") {
112
+ return Promise.resolve(ambiguousSameUserError("host_file"));
98
113
  }
114
+ resolvedTargetClientId =
115
+ resolved.kind === "match" ? resolved.clientId : undefined;
116
+ }
117
+
118
+ // Same-user check: targeted host_file requests must be bound to the same
119
+ // authenticated user identity that opened the target client's SSE stream.
120
+ // Prevents cross-user routing through actor token mis-targeting.
121
+ if (resolvedTargetClientId != null) {
122
+ const rejection = enforceSameActorOrErrorResult({
123
+ hub: assistantEventHub,
124
+ sourceActorPrincipalId,
125
+ targetClientId: resolvedTargetClientId,
126
+ op: "host_file",
127
+ });
128
+ if (rejection) return Promise.resolve(rejection);
99
129
  }
100
130
 
101
131
  const requestId = uuid();
@@ -150,7 +180,13 @@ export class HostFileProxy {
150
180
  conversationId,
151
181
  kind: "host_file",
152
182
  targetClientId: resolvedTargetClientId,
153
- rpcResolve: resolve,
183
+ targetActorPrincipalId:
184
+ resolvedTargetClientId != null
185
+ ? assistantEventHub.getActorPrincipalIdForClient(
186
+ resolvedTargetClientId,
187
+ )
188
+ : undefined,
189
+ rpcResolve: resolve as (v: unknown) => void,
154
190
  rpcReject: reject,
155
191
  timer,
156
192
  detachAbort,
@@ -9,6 +9,11 @@ import {
9
9
  assistantEventHub,
10
10
  broadcastMessage,
11
11
  } from "../runtime/assistant-event-hub.js";
12
+ import {
13
+ ambiguousSameUserError,
14
+ enforceSameActorOrErrorResult,
15
+ pickSameUserAutoResolve,
16
+ } from "../runtime/auth/same-actor.js";
12
17
  import * as pendingInteractions from "../runtime/pending-interactions.js";
13
18
  import type { ToolExecutionResult } from "../tools/types.js";
14
19
  import { AssistantError, ErrorCode } from "../util/errors.js";
@@ -31,6 +36,13 @@ interface TransferEntry {
31
36
  sha256?: string;
32
37
  fileBuffer?: Buffer;
33
38
  targetClientId?: string;
39
+ /**
40
+ * Snapshot of `targetClientId`'s `actorPrincipalId` taken at registration
41
+ * time. Persisted so the GET/PUT content routes compare against a stable
42
+ * value rather than the live hub — the target client's SSE subscription
43
+ * may briefly disconnect between dispatch and content fetch/upload.
44
+ */
45
+ targetActorPrincipalId?: string;
34
46
  }
35
47
 
36
48
  /**
@@ -124,6 +136,8 @@ export class HostTransferProxy {
124
136
  targetClientId?: string;
125
137
  },
126
138
  signal?: AbortSignal,
139
+ // Principal ID of the actor on whose behalf this request is initiated.
140
+ sourceActorPrincipalId?: string,
127
141
  ): Promise<ToolExecutionResult> {
128
142
  if (signal?.aborted) {
129
143
  return Promise.resolve({ content: "Aborted", isError: true });
@@ -145,8 +159,29 @@ export class HostTransferProxy {
145
159
  });
146
160
  }
147
161
  } else {
148
- const capable = assistantEventHub.listClientsByCapability("host_file");
149
- if (capable.length === 1) resolvedTargetClientId = capable[0].clientId;
162
+ // Auto-resolve to the unique same-user client; reject ambiguous
163
+ // (multi-machine) cases so a single targeted-style transfer cannot
164
+ // fan out across the user's machines.
165
+ const resolved = pickSameUserAutoResolve({
166
+ hub: assistantEventHub,
167
+ capability: "host_file",
168
+ sourceActorPrincipalId,
169
+ });
170
+ if (resolved.kind === "ambiguous") {
171
+ return Promise.resolve(ambiguousSameUserError("host_file"));
172
+ }
173
+ resolvedTargetClientId =
174
+ resolved.kind === "match" ? resolved.clientId : undefined;
175
+ }
176
+
177
+ if (resolvedTargetClientId != null) {
178
+ const rejection = enforceSameActorOrErrorResult({
179
+ hub: assistantEventHub,
180
+ sourceActorPrincipalId,
181
+ targetClientId: resolvedTargetClientId,
182
+ op: "host_transfer",
183
+ });
184
+ if (rejection != null) return Promise.resolve(rejection);
150
185
  }
151
186
 
152
187
  const requestId = uuid();
@@ -220,13 +255,25 @@ export class HostTransferProxy {
220
255
  sha256,
221
256
  fileBuffer,
222
257
  targetClientId: resolvedTargetClientId,
258
+ targetActorPrincipalId:
259
+ resolvedTargetClientId != null
260
+ ? assistantEventHub.getActorPrincipalIdForClient(
261
+ resolvedTargetClientId,
262
+ )
263
+ : undefined,
223
264
  });
224
265
 
225
266
  pendingInteractions.register(requestId, {
226
267
  conversationId: input.conversationId,
227
268
  kind: "host_transfer",
228
269
  targetClientId: resolvedTargetClientId,
229
- rpcResolve: resolve,
270
+ targetActorPrincipalId:
271
+ resolvedTargetClientId != null
272
+ ? assistantEventHub.getActorPrincipalIdForClient(
273
+ resolvedTargetClientId,
274
+ )
275
+ : undefined,
276
+ rpcResolve: resolve as (v: unknown) => void,
230
277
  rpcReject: reject,
231
278
  timer,
232
279
  detachAbort,
@@ -291,6 +338,8 @@ export class HostTransferProxy {
291
338
  targetClientId?: string;
292
339
  },
293
340
  signal?: AbortSignal,
341
+ // Principal ID of the actor on whose behalf this request is initiated.
342
+ sourceActorPrincipalId?: string,
294
343
  ): Promise<ToolExecutionResult> {
295
344
  if (signal?.aborted) {
296
345
  return Promise.resolve({ content: "Aborted", isError: true });
@@ -312,8 +361,29 @@ export class HostTransferProxy {
312
361
  });
313
362
  }
314
363
  } else {
315
- const capable = assistantEventHub.listClientsByCapability("host_file");
316
- if (capable.length === 1) resolvedTargetClientId = capable[0].clientId;
364
+ // Auto-resolve to the unique same-user client; reject ambiguous
365
+ // (multi-machine) cases so a single targeted-style transfer cannot
366
+ // fan out across the user's machines.
367
+ const resolved = pickSameUserAutoResolve({
368
+ hub: assistantEventHub,
369
+ capability: "host_file",
370
+ sourceActorPrincipalId,
371
+ });
372
+ if (resolved.kind === "ambiguous") {
373
+ return Promise.resolve(ambiguousSameUserError("host_file"));
374
+ }
375
+ resolvedTargetClientId =
376
+ resolved.kind === "match" ? resolved.clientId : undefined;
377
+ }
378
+
379
+ if (resolvedTargetClientId != null) {
380
+ const rejection = enforceSameActorOrErrorResult({
381
+ hub: assistantEventHub,
382
+ sourceActorPrincipalId,
383
+ targetClientId: resolvedTargetClientId,
384
+ op: "host_transfer",
385
+ });
386
+ if (rejection != null) return Promise.resolve(rejection);
317
387
  }
318
388
 
319
389
  const requestId = uuid();
@@ -374,13 +444,25 @@ export class HostTransferProxy {
374
444
  filePath: input.destPath,
375
445
  overwrite: input.overwrite,
376
446
  targetClientId: resolvedTargetClientId,
447
+ targetActorPrincipalId:
448
+ resolvedTargetClientId != null
449
+ ? assistantEventHub.getActorPrincipalIdForClient(
450
+ resolvedTargetClientId,
451
+ )
452
+ : undefined,
377
453
  });
378
454
 
379
455
  pendingInteractions.register(requestId, {
380
456
  conversationId: input.conversationId,
381
457
  kind: "host_transfer",
382
458
  targetClientId: resolvedTargetClientId,
383
- rpcResolve: resolve,
459
+ targetActorPrincipalId:
460
+ resolvedTargetClientId != null
461
+ ? assistantEventHub.getActorPrincipalIdForClient(
462
+ resolvedTargetClientId,
463
+ )
464
+ : undefined,
465
+ rpcResolve: resolve as (v: unknown) => void,
384
466
  rpcReject: reject,
385
467
  timer,
386
468
  detachAbort,
@@ -623,6 +705,15 @@ export class HostTransferProxy {
623
705
  return this.transfers.get(transferId)?.targetClientId ?? null;
624
706
  }
625
707
 
708
+ /**
709
+ * Look up the persisted `targetActorPrincipalId` for a given transferId
710
+ * without consuming the entry. Routes call this for the same-actor
711
+ * binding check so it's stable across brief SSE reconnects.
712
+ */
713
+ getTargetActorPrincipalIdForTransfer(transferId: string): string | undefined {
714
+ return this.transfers.get(transferId)?.targetActorPrincipalId;
715
+ }
716
+
626
717
  dispose(): void {
627
718
  for (const entry of pendingInteractions.getByKind("host_transfer")) {
628
719
  const transferId = entry.metadata?.transferId as string | undefined;