@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
@@ -58,6 +58,7 @@ afterAll(() => {
58
58
  });
59
59
 
60
60
  import { invalidateConfigCache, loadConfig } from "../config/loader.js";
61
+ import { applyContextDefaultsToRawConfig } from "../runtime/routes/conversation-query-routes.js";
61
62
  import { _setStorePath } from "../security/encrypted-store.js";
62
63
 
63
64
  // ---------------------------------------------------------------------------
@@ -184,7 +185,7 @@ describe("platform-managed config defaults", () => {
184
185
  ) + "\n",
185
186
  );
186
187
 
187
- loadConfig();
188
+ const config = loadConfig();
188
189
 
189
190
  const written = readConfig() as { services?: Record<string, unknown> };
190
191
  expect(written.services).toBeDefined();
@@ -192,5 +193,287 @@ describe("platform-managed config defaults", () => {
192
193
  expect(
193
194
  (written.services!["inference"] as { mode?: string })?.mode,
194
195
  ).toBe("your-own");
196
+ // ...and the in-memory config must mirror the explicit user choice (the
197
+ // fill-defaults pass must not override an explicit "your-own").
198
+ expect(
199
+ (config.services.inference as { mode: string }).mode,
200
+ ).toBe("your-own");
201
+ });
202
+
203
+ test("IS_PLATFORM=true, config file exists without a services key → in-memory config has all managed modes", () => {
204
+ // Regression guard for the platform-managed boot order: by the time
205
+ // `loadConfig()` runs, lifecycle steps such as `seedInferenceProfiles`
206
+ // have already written `config.json` (with `llm.profiles` etc.), so
207
+ // `configFileExisted` is true even on a brand-new platform-managed
208
+ // assistant. Deployment-context defaults must still be applied to the
209
+ // in-memory config for any leaf keys that are absent from disk.
210
+ process.env.IS_PLATFORM = "true";
211
+
212
+ writeFileSync(
213
+ CONFIG_PATH,
214
+ JSON.stringify(
215
+ {
216
+ llm: {
217
+ profiles: {
218
+ balanced: { provider: "anthropic", model: "claude-sonnet-4.5" },
219
+ },
220
+ activeProfile: "balanced",
221
+ },
222
+ },
223
+ null,
224
+ 2,
225
+ ) + "\n",
226
+ );
227
+
228
+ const config = loadConfig();
229
+
230
+ // In-memory config has the deployment-context defaults applied for the
231
+ // missing service-mode fields.
232
+ for (const svc of MANAGED_SERVICES) {
233
+ expect(
234
+ (
235
+ config.services as unknown as Record<
236
+ string,
237
+ { mode: string }
238
+ >
239
+ )[svc]!.mode,
240
+ ).toBe("managed");
241
+ }
242
+
243
+ // The on-disk file is NOT modified by the fill pass — disk reflects only
244
+ // what was already there. Existing-file branch never re-writes config.json.
245
+ const onDisk = readConfig() as Record<string, unknown>;
246
+ expect(onDisk["services"]).toBeUndefined();
247
+ });
248
+
249
+ test("IS_PLATFORM=true, config file exists with a partial service subtree → preserves user fields, fills missing mode", () => {
250
+ process.env.IS_PLATFORM = "true";
251
+
252
+ // User has an image-generation provider configured but never explicitly
253
+ // chose a mode for that service. The fill pass must apply
254
+ // `mode: "managed"` without clobbering the user-supplied provider.
255
+ // (The inference schema dropped per-service model/provider in
256
+ // migration 039 — image-generation still carries them, so it's the
257
+ // right schema to exercise the partial-subtree case.)
258
+ writeFileSync(
259
+ CONFIG_PATH,
260
+ JSON.stringify(
261
+ {
262
+ services: {
263
+ "image-generation": { provider: "openai" },
264
+ },
265
+ },
266
+ null,
267
+ 2,
268
+ ) + "\n",
269
+ );
270
+
271
+ const config = loadConfig();
272
+
273
+ const imageGen = (
274
+ config.services as unknown as Record<
275
+ string,
276
+ { mode: string; provider?: string }
277
+ >
278
+ )["image-generation"]!;
279
+ expect(imageGen.mode).toBe("managed");
280
+ expect(imageGen.provider).toBe("openai");
281
+ });
282
+
283
+ test("IS_PLATFORM=false, config file exists without services key → in-memory config keeps schema your-own defaults", () => {
284
+ // Sanity guard: deployment-context defaults are a no-op when IS_PLATFORM
285
+ // is not enabled, regardless of whether config.json existed.
286
+ process.env.IS_PLATFORM = "false";
287
+
288
+ writeFileSync(
289
+ CONFIG_PATH,
290
+ JSON.stringify(
291
+ {
292
+ llm: {
293
+ profiles: {
294
+ balanced: { provider: "anthropic", model: "claude-sonnet-4.5" },
295
+ },
296
+ activeProfile: "balanced",
297
+ },
298
+ },
299
+ null,
300
+ 2,
301
+ ) + "\n",
302
+ );
303
+
304
+ const config = loadConfig();
305
+
306
+ for (const svc of MANAGED_SERVICES) {
307
+ expect(
308
+ (
309
+ config.services as unknown as Record<
310
+ string,
311
+ { mode: string }
312
+ >
313
+ )[svc]!.mode,
314
+ ).toBe("your-own");
315
+ }
316
+ });
317
+ });
318
+
319
+ /**
320
+ * Regression guard for the `handleGetConfig` route handler in
321
+ * `assistant/src/runtime/routes/conversation-query-routes.ts`. That handler
322
+ * returns the raw on-disk JSON to clients (macOS, web, CLI) via
323
+ * `GET /v1/config`, but first layers deployment-context defaults on top
324
+ * via the `applyContextDefaultsToRawConfig` helper.
325
+ *
326
+ * macOS's `loadServiceModes(config:)` only updates `inferenceMode` when
327
+ * `services.inference.mode` is present in the response — without the fill
328
+ * pass, freshly-hatched platform-managed assistants would have no `services`
329
+ * key on disk (only `llm.profiles` from `seedInferenceProfiles`) and macOS
330
+ * would fall back to its `@Published` default of "your-own". The helper is
331
+ * also responsible for guarding against `loadRawConfig()` returning a
332
+ * non-object payload from a malformed-but-parseable `config.json`.
333
+ */
334
+ describe("GET /v1/config handler — context-default fill on raw response", () => {
335
+ const originalIsPlatform = process.env.IS_PLATFORM;
336
+
337
+ afterEach(() => {
338
+ if (originalIsPlatform === undefined) {
339
+ delete process.env.IS_PLATFORM;
340
+ } else {
341
+ process.env.IS_PLATFORM = originalIsPlatform;
342
+ }
343
+ });
344
+
345
+ test("IS_PLATFORM=true, raw config has no services key → response includes managed defaults", () => {
346
+ process.env.IS_PLATFORM = "true";
347
+
348
+ // Mirrors the real-world fresh-hatch state: lifecycle wrote
349
+ // `llm.profiles` to disk, but never persisted any service modes.
350
+ const raw: Record<string, unknown> = {
351
+ llm: {
352
+ profiles: {
353
+ balanced: { provider: "anthropic", model: "claude-sonnet-4.5" },
354
+ },
355
+ activeProfile: "balanced",
356
+ },
357
+ };
358
+
359
+ const result = applyContextDefaultsToRawConfig(raw) as Record<
360
+ string,
361
+ unknown
362
+ >;
363
+ const services = result["services"] as Record<string, { mode: string }>;
364
+ expect(services).toBeDefined();
365
+ for (const svc of MANAGED_SERVICES) {
366
+ expect(services[svc]!.mode).toBe("managed");
367
+ }
368
+ });
369
+
370
+ test("IS_PLATFORM=true, raw config has explicit services.inference.mode='your-own' → preserved", () => {
371
+ process.env.IS_PLATFORM = "true";
372
+
373
+ // User has explicitly chosen "your-own" via the macOS Save flow.
374
+ // The patch handler persisted that to disk; the fill pass must not
375
+ // override an explicit user choice.
376
+ const raw: Record<string, unknown> = {
377
+ services: {
378
+ inference: { mode: "your-own" },
379
+ },
380
+ };
381
+
382
+ const result = applyContextDefaultsToRawConfig(raw) as Record<
383
+ string,
384
+ unknown
385
+ >;
386
+ const services = result["services"] as Record<string, { mode: string }>;
387
+ expect(services["inference"]!.mode).toBe("your-own");
388
+ // Other services were missing entirely → context defaults fill them in.
389
+ expect(services["image-generation"]!.mode).toBe("managed");
390
+ expect(services["web-search"]!.mode).toBe("managed");
391
+ });
392
+
393
+ test("IS_PLATFORM=false, raw config has no services key → response is unchanged", () => {
394
+ process.env.IS_PLATFORM = "false";
395
+
396
+ const raw: Record<string, unknown> = {
397
+ llm: {
398
+ profiles: {
399
+ balanced: { provider: "anthropic", model: "claude-sonnet-4.5" },
400
+ },
401
+ },
402
+ };
403
+
404
+ const result = applyContextDefaultsToRawConfig(raw) as Record<
405
+ string,
406
+ unknown
407
+ >;
408
+ expect(result["services"]).toBeUndefined();
409
+ });
410
+
411
+ test("IS_PLATFORM=true, raw config has partial services.inference subtree → preserves user fields, fills missing mode", () => {
412
+ process.env.IS_PLATFORM = "true";
413
+
414
+ // User set image-generation.provider but never chose a mode for any
415
+ // service. The fill pass adds the missing modes without clobbering
416
+ // the user-supplied provider.
417
+ const raw: Record<string, unknown> = {
418
+ services: {
419
+ "image-generation": { provider: "openai" },
420
+ },
421
+ };
422
+
423
+ const result = applyContextDefaultsToRawConfig(raw) as Record<
424
+ string,
425
+ unknown
426
+ >;
427
+ const services = result["services"] as Record<
428
+ string,
429
+ { mode: string; provider?: string }
430
+ >;
431
+ expect(services["image-generation"]!.mode).toBe("managed");
432
+ expect(services["image-generation"]!.provider).toBe("openai");
433
+ // Inference, which was missing entirely, picks up the context default.
434
+ expect(services["inference"]!.mode).toBe("managed");
435
+ });
436
+
437
+ // -------------------------------------------------------------------------
438
+ // Malformed-but-parseable config.json — must not 500 the GET endpoint.
439
+ //
440
+ // `loadRawConfig()` is typed `Record<string, unknown>` but `JSON.parse`
441
+ // will happily return `null`, primitives, or arrays for a syntactically
442
+ // valid file like `null` / `42` / `[]`. The helper must return those
443
+ // payloads unchanged rather than throwing inside
444
+ // `fillContextDefaultsForMissingKeys`.
445
+ // -------------------------------------------------------------------------
446
+
447
+ test("IS_PLATFORM=true, raw config is null → returned unchanged (no throw)", () => {
448
+ process.env.IS_PLATFORM = "true";
449
+ expect(applyContextDefaultsToRawConfig(null)).toBe(null);
450
+ });
451
+
452
+ test("IS_PLATFORM=true, raw config is a primitive number → returned unchanged (no throw)", () => {
453
+ process.env.IS_PLATFORM = "true";
454
+ expect(applyContextDefaultsToRawConfig(42)).toBe(42);
455
+ });
456
+
457
+ test("IS_PLATFORM=true, raw config is an array → returned unchanged (no throw)", () => {
458
+ process.env.IS_PLATFORM = "true";
459
+ const raw: unknown[] = [{ foo: "bar" }];
460
+ const result = applyContextDefaultsToRawConfig(raw);
461
+ expect(result).toBe(raw);
462
+ // No `services` key was synthesized onto the array.
463
+ expect((result as { services?: unknown }).services).toBeUndefined();
464
+ });
465
+
466
+ test("IS_PLATFORM=true, raw config is a string → returned unchanged (no throw)", () => {
467
+ process.env.IS_PLATFORM = "true";
468
+ expect(applyContextDefaultsToRawConfig("not-an-object")).toBe(
469
+ "not-an-object",
470
+ );
471
+ });
472
+
473
+ test("IS_PLATFORM=false, raw config is null → returned unchanged (no throw)", () => {
474
+ // Sanity check: when there are no context defaults to apply, the helper
475
+ // also short-circuits cleanly on non-object payloads.
476
+ process.env.IS_PLATFORM = "false";
477
+ expect(applyContextDefaultsToRawConfig(null)).toBe(null);
195
478
  });
196
479
  });
@@ -358,6 +358,7 @@ describe("AssistantConfigSchema", () => {
358
358
  supersededItemRetentionMs: 30 * 24 * 60 * 60 * 1000,
359
359
  conversationRetentionDays: 0,
360
360
  llmRequestLogRetentionMs: 1 * 60 * 60 * 1000,
361
+ traceEventRetentionDays: 3,
361
362
  });
362
363
  });
363
364
 
@@ -37,6 +37,7 @@ describe("cleanupSettingsChanged", () => {
37
37
  supersededItemRetentionMs: 30 * 24 * 60 * 60 * 1000,
38
38
  conversationRetentionDays: 0,
39
39
  llmRequestLogRetentionMs: 1 * 24 * 60 * 60 * 1000,
40
+ traceEventRetentionDays: 3,
40
41
  };
41
42
 
42
43
  test("returns false when either side is undefined", () => {
@@ -128,11 +129,9 @@ mock.module("../util/logger.js", () => ({
128
129
  truncateForLog: (v: string) => v,
129
130
  }));
130
131
 
131
- // Simulate a config-cache layer: `diskConfig` is the on-disk value,
132
- // `cachedConfig` is what getConfig() returns until invalidateConfigCache()
133
- // is called. This matches the production behavior where getConfig() returns
134
- // a memoized value that only refreshes after explicit invalidation. Tests
135
- // mutate `diskConfig` to simulate a user writing a new config.json.
132
+ // Simulate a config-cache layer: `diskConfig` is the on-disk value and
133
+ // `cachedConfig` is the in-memory value returned by getConfig() when present.
134
+ // Tests mutate `diskConfig` to simulate a user writing a new config.json.
136
135
  interface TestConfig {
137
136
  memory: {
138
137
  enabled: boolean;
@@ -199,10 +198,6 @@ mock.module("../providers/registry.js", () => ({
199
198
  initializeProviders: async () => {},
200
199
  }));
201
200
 
202
- mock.module("../signals/bash.js", () => ({
203
- handleBashSignal: () => {},
204
- }));
205
-
206
201
  mock.module("../signals/cancel.js", () => ({
207
202
  handleCancelSignal: () => {},
208
203
  }));
@@ -252,6 +247,20 @@ describe("ConfigWatcher.refreshConfigFromSources cleanup throttle reset", () =>
252
247
  expect(resetCleanupScheduleThrottleCalls).toBe(1);
253
248
  });
254
249
 
250
+ test("resets throttle when the loader cache has already observed the disk change", async () => {
251
+ const watcher = new ConfigWatcher();
252
+ watcher.initFingerprint(diskConfig as never);
253
+
254
+ diskConfig = makeConfig({
255
+ llmRequestLogRetentionMs: 7 * 24 * 60 * 60 * 1000,
256
+ });
257
+ cachedConfig = null;
258
+
259
+ const changed = await watcher.refreshConfigFromSources();
260
+ expect(changed).toBe(true);
261
+ expect(resetCleanupScheduleThrottleCalls).toBe(1);
262
+ });
263
+
255
264
  test("does NOT reset throttle when config is identical (no fingerprint change)", async () => {
256
265
  const watcher = new ConfigWatcher();
257
266
  watcher.initFingerprint(diskConfig as never);