@vellumai/assistant 0.7.1 → 0.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (739) hide show
  1. package/ARCHITECTURE.md +48 -50
  2. package/Dockerfile +1 -0
  3. package/README.md +1 -2
  4. package/__tests__/permissions/gateway-threshold-reader.test.ts +9 -3
  5. package/bun.lock +26 -26
  6. package/docs/architecture/memory.md +5 -2
  7. package/docs/architecture/security.md +20 -0
  8. package/docs/plugins.md +7 -9
  9. package/knip.json +1 -0
  10. package/node_modules/@vellumai/gateway-client/src/index.ts +1 -0
  11. package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +52 -5
  12. package/node_modules/@vellumai/gateway-client/src/types.ts +11 -0
  13. package/node_modules/@vellumai/service-contracts/package.json +2 -0
  14. package/node_modules/@vellumai/service-contracts/src/__tests__/contracts.test.ts +4 -0
  15. package/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +107 -0
  16. package/node_modules/@vellumai/service-contracts/src/index.ts +5 -1
  17. package/node_modules/@vellumai/service-contracts/src/ingress.ts +24 -0
  18. package/node_modules/@vellumai/service-contracts/src/twilio-ingress.ts +84 -0
  19. package/node_modules/@vellumai/slack-text/src/index.test.ts +18 -35
  20. package/node_modules/@vellumai/slack-text/src/index.ts +2 -48
  21. package/node_modules/@vellumai/twilio-client/bun.lock +24 -0
  22. package/node_modules/@vellumai/twilio-client/package.json +18 -0
  23. package/node_modules/@vellumai/twilio-client/src/__tests__/twilio-client.test.ts +128 -0
  24. package/node_modules/@vellumai/twilio-client/src/index.ts +179 -0
  25. package/node_modules/@vellumai/twilio-client/tsconfig.json +20 -0
  26. package/openapi.yaml +1020 -40
  27. package/package.json +6 -3
  28. package/src/__tests__/app-builder-tool-scripts.test.ts +3 -3
  29. package/src/__tests__/app-bundler.test.ts +170 -1
  30. package/src/__tests__/app-control-flow.test.ts +384 -0
  31. package/src/__tests__/app-control-no-global-cgevent.test.ts +98 -0
  32. package/src/__tests__/app-control-tool-schemas.test.ts +621 -0
  33. package/src/__tests__/app-executors.test.ts +30 -43
  34. package/src/__tests__/approval-routes-http.test.ts +23 -6
  35. package/src/__tests__/assistant-event-hub-machine-name.test.ts +146 -0
  36. package/src/__tests__/assistant-event-hub-targeted.test.ts +257 -0
  37. package/src/__tests__/assistant-event-hub.test.ts +157 -2
  38. package/src/__tests__/assistant-feature-flags-integration.test.ts +29 -7
  39. package/src/__tests__/auto-analysis-end-to-end.test.ts +62 -1
  40. package/src/__tests__/background-shell-host-bash.test.ts +14 -15
  41. package/src/__tests__/background-workers-disk-pressure.test.ts +268 -0
  42. package/src/__tests__/bootstrap-turn-cleanup.test.ts +44 -0
  43. package/src/__tests__/btw-routes.test.ts +13 -4
  44. package/src/__tests__/call-controller.test.ts +49 -1
  45. package/src/__tests__/call-conversation-messages.test.ts +8 -2
  46. package/src/__tests__/call-domain.test.ts +0 -2
  47. package/src/__tests__/call-routes-http.test.ts +0 -2
  48. package/src/__tests__/channel-inbound-disk-pressure.test.ts +537 -0
  49. package/src/__tests__/channel-readiness-service.test.ts +62 -2
  50. package/src/__tests__/checker.test.ts +3 -4
  51. package/src/__tests__/config-loader-backfill.test.ts +461 -147
  52. package/src/__tests__/config-loader-platform-defaults.test.ts +196 -0
  53. package/src/__tests__/config-schema-cmd.test.ts +0 -1
  54. package/src/__tests__/config-schema.test.ts +1 -0
  55. package/src/__tests__/config-set-platform-guard.test.ts +48 -4
  56. package/src/__tests__/config-watcher-cleanup-throttle.test.ts +20 -11
  57. package/src/__tests__/config-watcher.test.ts +142 -71
  58. package/src/__tests__/context-search-agent-runner.test.ts +61 -3
  59. package/src/__tests__/context-search-conversations-source.test.ts +0 -24
  60. package/src/__tests__/context-search-fanout.test.ts +0 -1
  61. package/src/__tests__/context-search-memory-source.test.ts +3 -7
  62. package/src/__tests__/context-search-memory-v2-source.test.ts +0 -2
  63. package/src/__tests__/context-search-pkb-source.test.ts +0 -1
  64. package/src/__tests__/context-search-workspace-source.test.ts +0 -1
  65. package/src/__tests__/conversation-abort-tool-results.test.ts +6 -0
  66. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +223 -0
  67. package/src/__tests__/conversation-agent-loop.test.ts +454 -5
  68. package/src/__tests__/conversation-app-control-instantiation.test.ts +392 -0
  69. package/src/__tests__/conversation-app-control-lifecycle.test.ts +237 -0
  70. package/src/__tests__/conversation-error.test.ts +150 -3
  71. package/src/__tests__/conversation-init.benchmark.test.ts +0 -2
  72. package/src/__tests__/conversation-lifecycle.test.ts +36 -0
  73. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +283 -0
  74. package/src/__tests__/conversation-process-callsite.test.ts +43 -0
  75. package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
  76. package/src/__tests__/conversation-routes-disk-view.test.ts +6 -0
  77. package/src/__tests__/conversation-routes-guardian-reply.test.ts +120 -72
  78. package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
  79. package/src/__tests__/conversation-runtime-assembly.test.ts +65 -0
  80. package/src/__tests__/conversation-slash-commands.test.ts +0 -4
  81. package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
  82. package/src/__tests__/conversation-speed-override.test.ts +0 -3
  83. package/src/__tests__/conversation-store.test.ts +0 -18
  84. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +202 -0
  85. package/src/__tests__/conversation-surfaces-app-control.test.ts +328 -0
  86. package/src/__tests__/conversation-surfaces-data-persist.test.ts +404 -0
  87. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +2 -5
  88. package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
  89. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -0
  90. package/src/__tests__/credential-execution-feature-gates.test.ts +5 -12
  91. package/src/__tests__/credential-execution-managed-contract.test.ts +3 -131
  92. package/src/__tests__/credentials-cli.test.ts +12 -12
  93. package/src/__tests__/cu-unified-flow.test.ts +351 -23
  94. package/src/__tests__/daemon-credential-client.test.ts +101 -19
  95. package/src/__tests__/date-context.test.ts +164 -2
  96. package/src/__tests__/db-schedule-syntax-migration.test.ts +2 -0
  97. package/src/__tests__/disk-pressure-guard.test.ts +262 -0
  98. package/src/__tests__/disk-pressure-lifecycle.test.ts +168 -0
  99. package/src/__tests__/disk-pressure-policy.test.ts +241 -0
  100. package/src/__tests__/disk-pressure-routes.test.ts +379 -0
  101. package/src/__tests__/disk-pressure-tools.test.ts +277 -0
  102. package/src/__tests__/disk-usage.test.ts +150 -0
  103. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
  104. package/src/__tests__/events-client-registration.test.ts +52 -0
  105. package/src/__tests__/events-dev-bypass-actor.test.ts +162 -0
  106. package/src/__tests__/file-write-tool.test.ts +4 -10
  107. package/src/__tests__/filing-service.test.ts +3 -4
  108. package/src/__tests__/gateway-only-enforcement.test.ts +0 -1
  109. package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -2
  110. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +0 -2
  111. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +0 -1
  112. package/src/__tests__/heartbeat-disk-pressure.test.ts +183 -0
  113. package/src/__tests__/heartbeat-service.test.ts +968 -2
  114. package/src/__tests__/helpers/call-route-handler.ts +7 -1
  115. package/src/__tests__/host-app-control-proxy.test.ts +772 -0
  116. package/src/__tests__/host-app-control-routes.test.ts +263 -0
  117. package/src/__tests__/host-bash-proxy.test.ts +439 -47
  118. package/src/__tests__/host-bash-routes.test.ts +459 -0
  119. package/src/__tests__/host-browser-proxy.test.ts +24 -22
  120. package/src/__tests__/host-browser-routes.test.ts +39 -13
  121. package/src/__tests__/host-cu-proxy.test.ts +248 -52
  122. package/src/__tests__/host-cu-routes-targeted.test.ts +429 -0
  123. package/src/__tests__/host-file-edit-tool.test.ts +47 -1
  124. package/src/__tests__/host-file-proxy-targeted.test.ts +378 -0
  125. package/src/__tests__/host-file-proxy.test.ts +301 -45
  126. package/src/__tests__/host-file-read-tool.test.ts +17 -0
  127. package/src/__tests__/host-file-routes-targeted.test.ts +420 -0
  128. package/src/__tests__/host-file-write-tool.test.ts +42 -1
  129. package/src/__tests__/host-proxy-base.test.ts +312 -0
  130. package/src/__tests__/host-shell-tool.test.ts +22 -4
  131. package/src/__tests__/host-transfer-proxy-targeted.test.ts +932 -0
  132. package/src/__tests__/host-transfer-proxy.test.ts +121 -22
  133. package/src/__tests__/host-transfer-routes-targeted.test.ts +662 -0
  134. package/src/__tests__/http-user-message-parity.test.ts +108 -1
  135. package/src/__tests__/identity-intro-cache.test.ts +29 -0
  136. package/src/__tests__/identity-routes.test.ts +103 -1
  137. package/src/__tests__/init-feature-flag-overrides.test.ts +26 -3
  138. package/src/__tests__/injector-chain.test.ts +18 -6
  139. package/src/__tests__/injector-disk-pressure.test.ts +224 -0
  140. package/src/__tests__/inline-command-runner.test.ts +0 -1
  141. package/src/__tests__/inline-skill-load-permissions.test.ts +5 -11
  142. package/src/__tests__/integration-status.test.ts +85 -5
  143. package/src/__tests__/intent-routing.test.ts +0 -1
  144. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +95 -5
  145. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +17 -0
  146. package/src/__tests__/managed-profile-guard.test.ts +18 -0
  147. package/src/__tests__/managed-skill-lifecycle.test.ts +0 -1
  148. package/src/__tests__/mcp-abort-signal.test.ts +130 -0
  149. package/src/__tests__/mcp-auth-routes.test.ts +197 -0
  150. package/src/__tests__/mcp-cli.test.ts +338 -2
  151. package/src/__tests__/memory-admin-recall.test.ts +3 -11
  152. package/src/__tests__/memory-jobs-worker-lanes.test.ts +188 -0
  153. package/src/__tests__/memory-retrieval-pipeline.test.ts +22 -1
  154. package/src/__tests__/migration-import-commit-http.test.ts +108 -2
  155. package/src/__tests__/mock-gateway-ipc.ts +1 -0
  156. package/src/__tests__/normalize-onboarding.test.ts +180 -0
  157. package/src/__tests__/oauth-cli.test.ts +0 -2
  158. package/src/__tests__/oauth-connect-routes.test.ts +316 -0
  159. package/src/__tests__/oauth-provider-seed-logos.test.ts +24 -2
  160. package/src/__tests__/oauth2-gateway-transport.test.ts +0 -1
  161. package/src/__tests__/onboarding-persona-write.test.ts +308 -0
  162. package/src/__tests__/openai-provider.test.ts +45 -8
  163. package/src/__tests__/persist-onboarding-artifacts.test.ts +44 -64
  164. package/src/__tests__/persistence-secret-redaction.test.ts +299 -0
  165. package/src/__tests__/platform-bash-auto-approve.test.ts +5 -9
  166. package/src/__tests__/platform-callback-registration.test.ts +21 -4
  167. package/src/__tests__/platform.test.ts +2 -1
  168. package/src/__tests__/playbook-execution.test.ts +0 -43
  169. package/src/__tests__/plugin-tool-contribution.test.ts +47 -0
  170. package/src/__tests__/prechat-onboarding-contract.test.ts +214 -25
  171. package/src/__tests__/process-message-background-slack.test.ts +2 -0
  172. package/src/__tests__/provider-commit-message-generator.test.ts +0 -1
  173. package/src/__tests__/provider-tool-name.test.ts +23 -0
  174. package/src/__tests__/public-ingress-urls.test.ts +97 -0
  175. package/src/__tests__/relay-server.test.ts +15 -4
  176. package/src/__tests__/require-fresh-approval.test.ts +0 -1
  177. package/src/__tests__/retry-backoff.test.ts +87 -0
  178. package/src/__tests__/runtime-events-sse.test.ts +2 -2
  179. package/src/__tests__/sanitize-config-for-transfer.test.ts +24 -2
  180. package/src/__tests__/schedule-retry.test.ts +715 -0
  181. package/src/__tests__/scheduler-disk-pressure.test.ts +148 -0
  182. package/src/__tests__/script-proxy-mitm-handler.test.ts +1 -1
  183. package/src/__tests__/secret-ingress-http.test.ts +1 -1
  184. package/src/__tests__/send-endpoint-busy.test.ts +3 -0
  185. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -1
  186. package/src/__tests__/skill-feature-flags.test.ts +43 -41
  187. package/src/__tests__/skill-load-feature-flag.test.ts +13 -14
  188. package/src/__tests__/skill-load-inline-command.test.ts +0 -51
  189. package/src/__tests__/skill-load-inline-includes.test.ts +0 -43
  190. package/src/__tests__/skill-projection.benchmark.test.ts +0 -1
  191. package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -1
  192. package/src/__tests__/slack-channel-config.test.ts +9 -14
  193. package/src/__tests__/suggestion-routes.test.ts +46 -0
  194. package/src/__tests__/system-prompt-ask-mode.test.ts +0 -1
  195. package/src/__tests__/system-prompt.test.ts +0 -1
  196. package/src/__tests__/telegram-config.test.ts +0 -1
  197. package/src/__tests__/test-preload.ts +8 -0
  198. package/src/__tests__/tool-approval-handler.test.ts +3 -4
  199. package/src/__tests__/tool-audit-listener.test.ts +48 -0
  200. package/src/__tests__/tool-execute-pipeline.test.ts +0 -1
  201. package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -1
  202. package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -1
  203. package/src/__tests__/tool-executor.test.ts +0 -1
  204. package/src/__tests__/twilio-config.test.ts +3 -16
  205. package/src/__tests__/twilio-routes.test.ts +3 -5
  206. package/src/__tests__/twilio-validation.test.ts +93 -0
  207. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +1 -4
  208. package/src/__tests__/verification-control-plane-policy.test.ts +2 -4
  209. package/src/__tests__/voice-ingress-preflight.test.ts +19 -0
  210. package/src/__tests__/workspace-migration-006-services-config.test.ts +3 -2
  211. package/src/__tests__/workspace-migration-065-bump-stale-heartbeat-interval.test.ts +122 -0
  212. package/src/__tests__/workspace-migration-066-seed-heartbeat-callsite-cost-default.test.ts +285 -0
  213. package/src/__tests__/workspace-migration-068-release-notes-local-timezone.test.ts +90 -0
  214. package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +1 -5
  215. package/src/__tests__/workspace-migration-down-functions.test.ts +8 -8
  216. package/src/__tests__/workspace-migration-safe-storage-limits-release.test.ts +90 -0
  217. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +10 -6
  218. package/src/approvals/guardian-decision-primitive.ts +13 -0
  219. package/src/approvals/guardian-request-resolvers.ts +16 -17
  220. package/src/backup/__tests__/paths.test.ts +0 -22
  221. package/src/backup/__tests__/restore.test.ts +51 -151
  222. package/src/backup/paths.ts +2 -18
  223. package/src/backup/restore.ts +107 -231
  224. package/src/backup/snapshot-lock.ts +2 -27
  225. package/src/bundler/app-bundler.ts +51 -3
  226. package/src/bundler/compiler-tools.ts +3 -2
  227. package/src/calls/call-conversation-messages.ts +46 -10
  228. package/src/calls/relay-server.ts +4 -44
  229. package/src/calls/twilio-config.ts +2 -17
  230. package/src/calls/twilio-rest.ts +33 -105
  231. package/src/calls/twilio-routes.ts +11 -12
  232. package/src/channels/types.ts +8 -7
  233. package/src/cli/commands/__tests__/backup.test.ts +6 -277
  234. package/src/cli/commands/__tests__/gateway.test.ts +288 -0
  235. package/src/cli/commands/__tests__/memory-v2.test.ts +4 -0
  236. package/src/cli/commands/__tests__/webhooks.test.ts +0 -5
  237. package/src/cli/commands/backup.ts +6 -331
  238. package/src/cli/commands/bash.ts +35 -108
  239. package/src/cli/commands/clients.ts +36 -37
  240. package/src/cli/commands/contacts.ts +137 -25
  241. package/src/cli/commands/conversations.ts +2 -5
  242. package/src/cli/commands/credentials.ts +71 -7
  243. package/src/cli/commands/domain.ts +66 -15
  244. package/src/cli/commands/gateway.ts +183 -0
  245. package/src/cli/commands/keys.ts +9 -6
  246. package/src/cli/commands/mcp.ts +116 -156
  247. package/src/cli/commands/memory-v2.ts +303 -7
  248. package/src/cli/commands/oauth/__tests__/connect.test.ts +437 -1
  249. package/src/cli/commands/oauth/connect.ts +127 -1
  250. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -4
  251. package/src/cli/commands/platform/__tests__/connect.test.ts +7 -3
  252. package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -3
  253. package/src/cli/commands/platform/__tests__/status.test.ts +116 -21
  254. package/src/cli/commands/platform/disconnect.ts +5 -4
  255. package/src/cli/commands/platform/index.ts +16 -25
  256. package/src/cli/commands/status.ts +57 -0
  257. package/src/cli/lib/daemon-credential-client.ts +110 -28
  258. package/src/cli/program.ts +6 -2
  259. package/src/config/assistant-feature-flags.ts +79 -12
  260. package/src/config/bundled-skills/acp/SKILL.md +6 -0
  261. package/src/config/bundled-skills/acp/TOOLS.json +1 -22
  262. package/src/config/bundled-skills/app-builder/SKILL.md +14 -109
  263. package/src/config/bundled-skills/app-builder/TOOLS.json +1 -28
  264. package/src/config/bundled-skills/app-builder/tools/app-create.ts +1 -10
  265. package/src/config/bundled-skills/app-control/SKILL.md +75 -0
  266. package/src/config/bundled-skills/app-control/TOOLS.json +299 -0
  267. package/src/config/bundled-skills/app-control/tools/app-control-click.ts +12 -0
  268. package/src/config/bundled-skills/app-control/tools/app-control-combo.ts +12 -0
  269. package/src/config/bundled-skills/app-control/tools/app-control-drag.ts +12 -0
  270. package/src/config/bundled-skills/app-control/tools/app-control-observe.ts +12 -0
  271. package/src/config/bundled-skills/app-control/tools/app-control-press.ts +12 -0
  272. package/src/config/bundled-skills/app-control/tools/app-control-sequence.ts +12 -0
  273. package/src/config/bundled-skills/app-control/tools/app-control-start.ts +12 -0
  274. package/src/config/bundled-skills/app-control/tools/app-control-stop.ts +12 -0
  275. package/src/config/bundled-skills/app-control/tools/app-control-type.ts +12 -0
  276. package/src/config/bundled-skills/computer-use/SKILL.md +6 -0
  277. package/src/config/bundled-skills/computer-use/TOOLS.json +67 -43
  278. package/src/config/bundled-skills/contacts/TOOLS.json +0 -16
  279. package/src/config/bundled-skills/document/TOOLS.json +0 -8
  280. package/src/config/bundled-skills/followups/TOOLS.json +0 -12
  281. package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
  282. package/src/config/bundled-skills/image-studio/TOOLS.json +0 -4
  283. package/src/config/bundled-skills/media-processing/TOOLS.json +0 -24
  284. package/src/config/bundled-skills/messaging/TOOLS.json +0 -40
  285. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +4 -3
  286. package/src/config/bundled-skills/phone-calls/TOOLS.json +0 -12
  287. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +25 -4
  288. package/src/config/bundled-skills/playbooks/TOOLS.json +0 -16
  289. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +2 -2
  290. package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +2 -2
  291. package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +2 -2
  292. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +2 -2
  293. package/src/config/bundled-skills/schedule/TOOLS.json +14 -14
  294. package/src/config/bundled-skills/sequences/TOOLS.json +0 -36
  295. package/src/config/bundled-skills/settings/SKILL.md +4 -0
  296. package/src/config/bundled-skills/settings/TOOLS.json +0 -12
  297. package/src/config/bundled-skills/skill-management/SKILL.md +6 -0
  298. package/src/config/bundled-skills/skill-management/TOOLS.json +0 -8
  299. package/src/config/bundled-skills/subagent/SKILL.md +6 -2
  300. package/src/config/bundled-skills/subagent/TOOLS.json +0 -20
  301. package/src/config/bundled-skills/transcribe/SKILL.md +4 -0
  302. package/src/config/bundled-skills/transcribe/TOOLS.json +0 -4
  303. package/src/config/bundled-tool-registry.ts +21 -0
  304. package/src/config/env-registry.ts +0 -2
  305. package/src/config/env.ts +19 -20
  306. package/src/config/feature-flag-registry.json +47 -135
  307. package/src/config/loader.ts +197 -104
  308. package/src/config/sanitize-for-transfer.ts +2 -0
  309. package/src/config/schemas/__tests__/memory-lifecycle.test.ts +80 -0
  310. package/src/config/schemas/__tests__/memory-v2.test.ts +17 -9
  311. package/src/config/schemas/call-site-catalog.ts +14 -0
  312. package/src/config/schemas/calls.ts +0 -9
  313. package/src/config/schemas/channels.ts +0 -5
  314. package/src/config/schemas/heartbeat.ts +64 -1
  315. package/src/config/schemas/ingress.ts +10 -6
  316. package/src/config/schemas/llm.ts +7 -10
  317. package/src/config/schemas/memory-lifecycle.ts +90 -24
  318. package/src/config/schemas/memory-v2.ts +121 -13
  319. package/src/config/schemas/platform.ts +49 -3
  320. package/src/config/schemas/services.ts +29 -15
  321. package/src/config/schemas/skills.ts +0 -6
  322. package/src/config/seed-inference-profiles.ts +230 -33
  323. package/src/contacts/contact-store.ts +0 -55
  324. package/src/contacts/contacts-write.ts +0 -27
  325. package/src/context/window-manager.ts +1 -2
  326. package/src/credential-execution/feature-gates.ts +10 -10
  327. package/src/credential-execution/process-manager.ts +12 -41
  328. package/src/daemon/__tests__/conversation-tool-setup.test.ts +187 -5
  329. package/src/daemon/assistant-attachments.ts +4 -4
  330. package/src/daemon/bootstrap-turn-cleanup.ts +45 -0
  331. package/src/daemon/config-watcher.ts +89 -60
  332. package/src/daemon/conversation-agent-loop-handlers.ts +27 -3
  333. package/src/daemon/conversation-agent-loop.ts +202 -61
  334. package/src/daemon/conversation-error.ts +87 -15
  335. package/src/daemon/conversation-lifecycle.ts +9 -4
  336. package/src/daemon/conversation-process.ts +24 -11
  337. package/src/daemon/conversation-runtime-assembly.ts +28 -2
  338. package/src/daemon/conversation-store.ts +2 -2
  339. package/src/daemon/conversation-surfaces.ts +305 -4
  340. package/src/daemon/conversation-tool-setup.ts +66 -62
  341. package/src/daemon/conversation.ts +38 -24
  342. package/src/daemon/date-context.ts +71 -22
  343. package/src/daemon/disk-pressure-background-gate.ts +73 -0
  344. package/src/daemon/disk-pressure-guard.ts +343 -0
  345. package/src/daemon/disk-pressure-policy.ts +163 -0
  346. package/src/daemon/doordash-steps.ts +1 -1
  347. package/src/daemon/handlers/shared.ts +4 -2
  348. package/src/daemon/handlers/skills.ts +3 -4
  349. package/src/daemon/host-app-control-proxy.ts +389 -0
  350. package/src/daemon/host-bash-proxy.ts +117 -82
  351. package/src/daemon/host-browser-proxy.ts +67 -82
  352. package/src/daemon/host-cu-proxy.ts +127 -86
  353. package/src/daemon/host-file-proxy.ts +129 -69
  354. package/src/daemon/host-proxy-base.ts +294 -0
  355. package/src/daemon/host-proxy-preactivation.ts +82 -0
  356. package/src/daemon/host-transfer-proxy.ts +338 -129
  357. package/src/daemon/lifecycle.ts +194 -145
  358. package/src/daemon/meet-host-supervisor.ts +4 -4
  359. package/src/daemon/meet-manifest-loader.ts +0 -1
  360. package/src/daemon/memory-v2-startup.ts +14 -4
  361. package/src/daemon/message-protocol.ts +6 -8
  362. package/src/daemon/message-types/contacts.ts +23 -1
  363. package/src/daemon/message-types/conversations.ts +15 -8
  364. package/src/daemon/message-types/disk-pressure.ts +9 -0
  365. package/src/daemon/message-types/host-app-control.ts +150 -0
  366. package/src/daemon/message-types/host-bash.ts +4 -0
  367. package/src/daemon/message-types/host-cu.ts +2 -0
  368. package/src/daemon/message-types/host-file.ts +4 -0
  369. package/src/daemon/message-types/host-transfer.ts +3 -0
  370. package/src/daemon/message-types/messages.ts +3 -0
  371. package/src/daemon/message-types/schedules.ts +8 -3
  372. package/src/daemon/message-types/skills.ts +2 -2
  373. package/src/daemon/process-message.ts +18 -1
  374. package/src/daemon/profiler-run-store.ts +5 -5
  375. package/src/daemon/shutdown-handlers.ts +0 -3
  376. package/src/daemon/tool-setup-types.ts +51 -0
  377. package/src/daemon/tool-side-effects.ts +1 -1
  378. package/src/documents/document-store.ts +85 -0
  379. package/src/events/tool-audit-listener.ts +2 -1
  380. package/src/filing/filing-service.ts +30 -5
  381. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +24 -23
  382. package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +252 -0
  383. package/src/heartbeat/heartbeat-run-store.ts +249 -0
  384. package/src/heartbeat/heartbeat-service.ts +459 -54
  385. package/src/home/__tests__/post-connect-feed.test.ts +99 -0
  386. package/src/home/__tests__/relationship-state-writer.test.ts +11 -9
  387. package/src/home/__tests__/suggested-prompts.test.ts +89 -0
  388. package/src/home/feed-scheduler.ts +18 -0
  389. package/src/home/post-connect-feed.ts +68 -0
  390. package/src/home/relationship-state-writer.ts +17 -92
  391. package/src/home/suggested-prompts.ts +46 -10
  392. package/src/inbound/platform-callback-registration.ts +8 -15
  393. package/src/inbound/public-ingress-urls.ts +32 -34
  394. package/src/ipc/__tests__/clients-list-ipc.test.ts +169 -0
  395. package/src/ipc/__tests__/route-error-envelope.test.ts +80 -0
  396. package/src/ipc/assistant-server.ts +70 -3
  397. package/src/ipc/cli-client.ts +32 -1
  398. package/src/ipc/gateway-client.ts +37 -3
  399. package/src/live-voice/live-voice-archive.ts +4 -4
  400. package/src/live-voice/live-voice-metrics.ts +10 -10
  401. package/src/live-voice/protocol.ts +5 -7
  402. package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +304 -0
  403. package/src/mcp/mcp-auth-orchestrator.ts +213 -0
  404. package/src/mcp/mcp-auth-state.ts +133 -0
  405. package/src/mcp/mcp-oauth-provider.ts +19 -0
  406. package/src/media/image-service.ts +1 -7
  407. package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +21 -13
  408. package/src/memory/__tests__/jobs-store-job-classes.test.ts +24 -0
  409. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +52 -22
  410. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +0 -6
  411. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +272 -0
  412. package/src/memory/__tests__/qdrant-client-sentinel.test.ts +49 -0
  413. package/src/memory/__tests__/sparse-tokenize.test.ts +66 -0
  414. package/src/memory/admin.ts +5 -9
  415. package/src/memory/anisotropy.test.ts +247 -0
  416. package/src/memory/anisotropy.ts +443 -0
  417. package/src/memory/auto-analysis-constants.ts +17 -0
  418. package/src/memory/auto-analysis-guard.ts +5 -15
  419. package/src/memory/canonical-guardian-store.ts +7 -7
  420. package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +122 -0
  421. package/src/memory/context-search/agent-protocol.ts +6 -6
  422. package/src/memory/context-search/agent-runner.ts +51 -9
  423. package/src/memory/context-search/sources/conversations.ts +2 -11
  424. package/src/memory/context-search/sources/memory-v2.ts +22 -9
  425. package/src/memory/context-search/sources/memory.ts +0 -1
  426. package/src/memory/context-search/types.ts +0 -1
  427. package/src/memory/conversation-crud.ts +5 -13
  428. package/src/memory/conversation-key-store.ts +2 -15
  429. package/src/memory/db-init.ts +6 -0
  430. package/src/memory/embedding-backend.ts +9 -21
  431. package/src/memory/embedding-runtime-manager.ts +119 -5
  432. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +81 -25
  433. package/src/memory/graph/conversation-graph-memory.ts +43 -78
  434. package/src/memory/graph/extraction.ts +1 -3
  435. package/src/memory/graph/graph-search.test.ts +10 -67
  436. package/src/memory/graph/graph-search.ts +9 -20
  437. package/src/memory/graph/retriever.test.ts +6 -0
  438. package/src/memory/graph/retriever.ts +34 -10
  439. package/src/memory/graph/tools.ts +1 -1
  440. package/src/memory/indexer.ts +54 -45
  441. package/src/memory/job-handlers/backfill.ts +2 -11
  442. package/src/memory/job-handlers/cleanup.ts +43 -0
  443. package/src/memory/job-handlers/embedding.ts +6 -8
  444. package/src/memory/job-handlers/summarization.ts +2 -7
  445. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +8 -2
  446. package/src/memory/jobs/embed-concept-page.ts +28 -2
  447. package/src/memory/jobs/embed-pkb-file.test.ts +2 -2
  448. package/src/memory/jobs-store.ts +114 -22
  449. package/src/memory/jobs-worker.ts +193 -106
  450. package/src/memory/memory-v2-activation-log-store.ts +33 -15
  451. package/src/memory/memory-v2-concept-frequency.ts +169 -0
  452. package/src/memory/migrations/237-heartbeat-runs.ts +45 -0
  453. package/src/memory/migrations/238-schedule-retry-policy.ts +20 -0
  454. package/src/memory/migrations/239-trace-events-created-at-index.ts +18 -0
  455. package/src/memory/migrations/index.ts +6 -0
  456. package/src/memory/migrations/registry.ts +8 -0
  457. package/src/memory/pkb/pkb-search.test.ts +6 -0
  458. package/src/memory/pkb/pkb-search.ts +7 -0
  459. package/src/memory/qdrant-client.ts +49 -32
  460. package/src/memory/rerank-local.ts +374 -0
  461. package/src/memory/schema/infrastructure.ts +15 -0
  462. package/src/memory/search/semantic.ts +13 -67
  463. package/src/memory/sparse-tokenize.ts +49 -0
  464. package/src/memory/trace-event-store.ts +1 -17
  465. package/src/memory/v2/__tests__/activation.test.ts +387 -344
  466. package/src/memory/v2/__tests__/consolidation-job.test.ts +40 -8
  467. package/src/memory/v2/__tests__/injection.test.ts +181 -169
  468. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +61 -2
  469. package/src/memory/v2/__tests__/qdrant.test.ts +16 -0
  470. package/src/memory/v2/__tests__/reranker.test.ts +338 -0
  471. package/src/memory/v2/__tests__/sim.test.ts +154 -188
  472. package/src/memory/v2/__tests__/skill-store.test.ts +71 -65
  473. package/src/memory/v2/__tests__/sparse-bm25.test.ts +292 -0
  474. package/src/memory/v2/__tests__/static-context.test.ts +76 -2
  475. package/src/memory/v2/activation.ts +213 -239
  476. package/src/memory/v2/consolidation-job.ts +65 -17
  477. package/src/memory/v2/constants.ts +7 -0
  478. package/src/memory/v2/injection.ts +123 -103
  479. package/src/memory/v2/prompts/consolidation.ts +348 -92
  480. package/src/memory/v2/qdrant.ts +198 -1
  481. package/src/memory/v2/reranker.ts +177 -0
  482. package/src/memory/v2/sim.ts +113 -77
  483. package/src/memory/v2/skill-content.ts +4 -3
  484. package/src/memory/v2/skill-store.ts +91 -53
  485. package/src/memory/v2/sparse-bm25.ts +245 -0
  486. package/src/memory/v2/static-context.ts +28 -5
  487. package/src/memory/v2/types.ts +10 -10
  488. package/src/messaging/providers/gmail/types.ts +0 -49
  489. package/src/messaging/providers/slack/adapter.ts +1 -31
  490. package/src/messaging/providers/slack/types.ts +0 -32
  491. package/src/notifications/README.md +10 -10
  492. package/src/notifications/broadcaster.ts +1 -1
  493. package/src/notifications/copy-composer.ts +13 -0
  494. package/src/notifications/guardian-question-mode.ts +5 -5
  495. package/src/notifications/signal.ts +4 -0
  496. package/src/oauth/AGENTS.md +3 -1
  497. package/src/oauth/__tests__/oauth-connect-state.test.ts +137 -0
  498. package/src/oauth/connect-orchestrator.ts +6 -0
  499. package/src/oauth/connection-resolver.test.ts +66 -1
  500. package/src/oauth/connection-resolver.ts +55 -1
  501. package/src/oauth/credential-token-resolver.ts +1 -3
  502. package/src/oauth/manual-token-connection.ts +0 -4
  503. package/src/oauth/oauth-connect-state.ts +77 -0
  504. package/src/oauth/seed-providers.ts +58 -1
  505. package/src/outbound-proxy/index.ts +1 -37
  506. package/src/outbound-proxy/logging.ts +1 -1
  507. package/src/outbound-proxy/policy.ts +6 -5
  508. package/src/outbound-proxy/router.ts +2 -1
  509. package/src/permissions/approval-policy.test.ts +6 -275
  510. package/src/permissions/approval-policy.ts +0 -51
  511. package/src/permissions/checker.test.ts +0 -1
  512. package/src/permissions/checker.ts +3 -17
  513. package/src/permissions/gateway-threshold-reader.ts +2 -0
  514. package/src/permissions/prompter.ts +34 -1
  515. package/src/permissions/secret-prompter.ts +6 -2
  516. package/src/plugins/defaults/injectors.ts +35 -2
  517. package/src/plugins/defaults/memory-retrieval.ts +5 -6
  518. package/src/plugins/types.ts +7 -0
  519. package/src/proactive-artifact/aux-message-injector.ts +74 -0
  520. package/src/proactive-artifact/decision.test.ts +226 -0
  521. package/src/proactive-artifact/decision.ts +165 -0
  522. package/src/proactive-artifact/index.ts +7 -0
  523. package/src/proactive-artifact/job.test.ts +867 -0
  524. package/src/proactive-artifact/job.ts +352 -0
  525. package/src/proactive-artifact/message-copy.ts +41 -0
  526. package/src/proactive-artifact/trigger-state.test.ts +277 -0
  527. package/src/proactive-artifact/trigger-state.ts +119 -0
  528. package/src/prompts/bootstrap-cleanup.ts +27 -0
  529. package/src/prompts/normalize-onboarding.ts +80 -0
  530. package/src/prompts/persona-resolver.ts +101 -9
  531. package/src/prompts/system-prompt.ts +23 -24
  532. package/src/prompts/templates/BOOTSTRAP.md +13 -5
  533. package/src/prompts/templates/SOUL.md +13 -1
  534. package/src/providers/__tests__/retry-callsite.test.ts +222 -1
  535. package/src/providers/model-intents.ts +7 -0
  536. package/src/providers/openrouter/client.ts +8 -0
  537. package/src/providers/retry.ts +50 -0
  538. package/src/providers/speech-to-text/provider-catalog.ts +7 -8
  539. package/src/providers/types.ts +1 -0
  540. package/src/runtime/__tests__/agent-wake.test.ts +456 -3
  541. package/src/runtime/agent-wake.ts +238 -100
  542. package/src/runtime/assistant-event-hub.ts +151 -99
  543. package/src/runtime/auth/__tests__/middleware.test.ts +11 -56
  544. package/src/runtime/auth/__tests__/route-policy.test.ts +64 -0
  545. package/src/runtime/auth/middleware.ts +0 -96
  546. package/src/runtime/auth/route-policy.ts +32 -0
  547. package/src/runtime/auth/same-actor.ts +216 -0
  548. package/src/runtime/btw-sidechain.ts +2 -3
  549. package/src/runtime/channel-invite-transport.ts +2 -48
  550. package/src/runtime/channel-invite-transports/email.ts +1 -1
  551. package/src/runtime/channel-invite-transports/slack.ts +1 -1
  552. package/src/runtime/channel-invite-transports/telegram.ts +1 -1
  553. package/src/runtime/channel-invite-transports/voice.ts +1 -1
  554. package/src/runtime/channel-invite-transports/whatsapp.ts +1 -1
  555. package/src/runtime/channel-invite-types.ts +54 -0
  556. package/src/runtime/channel-readiness-service.ts +32 -13
  557. package/src/runtime/channel-retry-sweep.ts +65 -1
  558. package/src/runtime/guardian-reply-router.ts +10 -0
  559. package/src/runtime/http-server.ts +3 -329
  560. package/src/runtime/http-types.ts +0 -5
  561. package/src/runtime/local-actor-identity.ts +52 -11
  562. package/src/runtime/migrations/__tests__/vbundle-import-parity.test.ts +413 -0
  563. package/src/runtime/migrations/__tests__/vbundle-import-policy.test.ts +260 -0
  564. package/src/runtime/migrations/__tests__/vbundle-import-version-compat.test.ts +189 -0
  565. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +153 -1
  566. package/src/runtime/migrations/__tests__/vbundle-symlink-importer.test.ts +451 -0
  567. package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -0
  568. package/src/runtime/migrations/__tests__/vbundle-symlink-streaming.test.ts +515 -0
  569. package/src/runtime/migrations/__tests__/vbundle-symlink-tar.test.ts +437 -0
  570. package/src/runtime/migrations/__tests__/vbundle-symlink-walker.test.ts +319 -0
  571. package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +51 -1
  572. package/src/runtime/migrations/migration-transport.ts +7 -7
  573. package/src/runtime/migrations/vbundle-builder.ts +327 -60
  574. package/src/runtime/migrations/vbundle-import-analyzer.ts +4 -4
  575. package/src/runtime/migrations/vbundle-import-policy.ts +172 -0
  576. package/src/runtime/migrations/vbundle-importer.ts +245 -68
  577. package/src/runtime/migrations/vbundle-streaming-importer.ts +326 -35
  578. package/src/runtime/migrations/vbundle-streaming-validator.ts +157 -4
  579. package/src/runtime/migrations/vbundle-tar-stream.ts +15 -6
  580. package/src/runtime/migrations/vbundle-validator.ts +114 -0
  581. package/src/runtime/pending-interactions.ts +43 -9
  582. package/src/runtime/routes/__tests__/backup-routes.test.ts +22 -150
  583. package/src/runtime/routes/__tests__/client-routes.test.ts +155 -0
  584. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +98 -5
  585. package/src/runtime/routes/__tests__/gateway-log-routes.test.ts +242 -0
  586. package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +112 -0
  587. package/src/runtime/routes/approval-interception-types.ts +13 -0
  588. package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +1 -1
  589. package/src/runtime/routes/backup-routes.ts +15 -38
  590. package/src/runtime/routes/btw-routes.ts +14 -37
  591. package/src/runtime/routes/client-routes.ts +21 -2
  592. package/src/runtime/routes/contact-prompt-routes.ts +183 -0
  593. package/src/runtime/routes/contact-routes.ts +0 -25
  594. package/src/runtime/routes/conversation-query-routes.ts +36 -1
  595. package/src/runtime/routes/conversation-routes.ts +65 -39
  596. package/src/runtime/routes/debug-bash-routes.ts +163 -0
  597. package/src/runtime/routes/disk-pressure-routes.ts +121 -0
  598. package/src/runtime/routes/document-pdf-renderer.ts +169 -0
  599. package/src/runtime/routes/documents-routes.ts +32 -75
  600. package/src/runtime/routes/errors.ts +19 -4
  601. package/src/runtime/routes/events-routes.ts +38 -0
  602. package/src/runtime/routes/gateway-log-routes.ts +79 -0
  603. package/src/runtime/routes/guardian-approval-interception.ts +2 -8
  604. package/src/runtime/routes/heartbeat-routes.ts +103 -38
  605. package/src/runtime/routes/host-app-control-routes.ts +134 -0
  606. package/src/runtime/routes/host-bash-routes.ts +56 -6
  607. package/src/runtime/routes/host-browser-routes.ts +108 -13
  608. package/src/runtime/routes/host-cu-routes.ts +66 -9
  609. package/src/runtime/routes/host-file-routes.ts +54 -5
  610. package/src/runtime/routes/host-transfer-routes.ts +122 -19
  611. package/src/runtime/routes/http-adapter.ts +1 -0
  612. package/src/runtime/routes/identity-intro-cache.ts +30 -0
  613. package/src/runtime/routes/identity-routes.ts +21 -180
  614. package/src/runtime/routes/inbound-message-handler.ts +78 -21
  615. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +0 -7
  616. package/src/runtime/routes/inbound-stages/edit-intercept.ts +0 -8
  617. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +3 -0
  618. package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +0 -20
  619. package/src/runtime/routes/inbound-stages/transcribe-audio.ts +5 -13
  620. package/src/runtime/routes/index.ts +14 -0
  621. package/src/runtime/routes/mcp-auth-routes.ts +132 -0
  622. package/src/runtime/routes/memory-item-routes.test.ts +41 -15
  623. package/src/runtime/routes/memory-item-routes.ts +10 -12
  624. package/src/runtime/routes/memory-v2-routes.ts +474 -1
  625. package/src/runtime/routes/migration-routes.ts +96 -0
  626. package/src/runtime/routes/oauth-connect-routes.ts +153 -0
  627. package/src/runtime/routes/schedule-routes.ts +7 -0
  628. package/src/runtime/verification-outbound-actions.ts +4 -4
  629. package/src/runtime/verification-templates.ts +4 -7
  630. package/src/schedule/integration-status.ts +66 -2
  631. package/src/schedule/recurrence-engine.ts +4 -1
  632. package/src/schedule/retry-backoff.ts +18 -0
  633. package/src/schedule/retry-policy.ts +82 -0
  634. package/src/schedule/run-script.ts +37 -5
  635. package/src/schedule/schedule-recovery.ts +64 -0
  636. package/src/schedule/schedule-store.ts +106 -2
  637. package/src/schedule/scheduler-types.ts +25 -0
  638. package/src/schedule/scheduler.ts +83 -39
  639. package/src/security/encrypted-store.ts +2 -0
  640. package/src/security/oauth-callback-registry.ts +8 -0
  641. package/src/security/secure-keys.ts +55 -0
  642. package/src/sequence/analytics.ts +5 -5
  643. package/src/sequence/engine.ts +1 -1
  644. package/src/skills/catalog-files.ts +2 -8
  645. package/src/skills/include-graph.ts +5 -5
  646. package/src/skills/remote-skill-policy.ts +10 -16
  647. package/src/skills/skill-file-provider.ts +1 -1
  648. package/src/skills/skill-file-types.ts +13 -0
  649. package/src/skills/skillssh-audit-types.ts +28 -0
  650. package/src/skills/skillssh-registry.ts +8 -21
  651. package/src/subagent/index.ts +1 -7
  652. package/src/subagent/manager.ts +1 -15
  653. package/src/tasks/task-runner.ts +0 -1
  654. package/src/tasks/task-store.ts +0 -3
  655. package/src/telemetry/types.ts +2 -0
  656. package/src/telemetry/usage-telemetry-reporter.test.ts +21 -0
  657. package/src/telemetry/usage-telemetry-reporter.ts +1 -0
  658. package/src/tools/app-control/skill-proxy-bridge.ts +28 -0
  659. package/src/tools/apps/executors.ts +56 -69
  660. package/src/tools/background-tool-registry.ts +17 -3
  661. package/src/tools/browser/__tests__/browser-status.test.ts +21 -18
  662. package/src/tools/browser/browser-execution.ts +2 -2
  663. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +55 -4
  664. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +12 -6
  665. package/src/tools/browser/cdp-client/factory.ts +23 -24
  666. package/src/tools/browser/cdp-client/index.ts +1 -14
  667. package/src/tools/computer-use/definitions.ts +42 -20
  668. package/src/tools/executor.ts +2 -0
  669. package/src/tools/host-filesystem/edit.test.ts +151 -0
  670. package/src/tools/host-filesystem/edit.ts +68 -0
  671. package/src/tools/host-filesystem/read.test.ts +129 -0
  672. package/src/tools/host-filesystem/read.ts +68 -0
  673. package/src/tools/host-filesystem/transfer.test.ts +127 -2
  674. package/src/tools/host-filesystem/transfer.ts +78 -3
  675. package/src/tools/host-filesystem/write.test.ts +134 -0
  676. package/src/tools/host-filesystem/write.ts +68 -0
  677. package/src/tools/host-terminal/host-shell.ts +66 -1
  678. package/src/tools/mcp/mcp-tool-factory.ts +2 -1
  679. package/src/tools/memory/register.test.ts +12 -9
  680. package/src/tools/memory/register.ts +1 -2
  681. package/src/tools/provider-tool-name.ts +28 -0
  682. package/src/tools/registry.ts +30 -9
  683. package/src/tools/schedule/create.ts +6 -0
  684. package/src/tools/schedule/list.ts +2 -0
  685. package/src/tools/schedule/update.ts +10 -0
  686. package/src/tools/shared/filesystem/file-ops-service.ts +2 -0
  687. package/src/tools/shared/filesystem/path-policy.ts +25 -1
  688. package/src/tools/skills/load.ts +0 -32
  689. package/src/tools/terminal/shell.ts +9 -1
  690. package/src/tools/tool-approval-handler.ts +32 -11
  691. package/src/tools/types.ts +28 -2
  692. package/src/tts/provider-catalog.ts +3 -5
  693. package/src/usage/pricing.ts +1 -1
  694. package/src/util/disk-usage.ts +138 -0
  695. package/src/util/platform.ts +21 -11
  696. package/src/util/process-liveness.ts +26 -0
  697. package/src/workspace/hatched-date.ts +86 -0
  698. package/src/workspace/heartbeat-service.ts +19 -0
  699. package/src/workspace/migrations/003-seed-device-id.ts +1 -1
  700. package/src/workspace/migrations/006-services-config.ts +8 -5
  701. package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +3 -9
  702. package/src/workspace/migrations/021-move-signals-to-workspace.ts +4 -10
  703. package/src/workspace/migrations/022-move-hooks-to-workspace.ts +4 -10
  704. package/src/workspace/migrations/023-move-config-files-to-workspace.ts +4 -11
  705. package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +3 -10
  706. package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +3 -2
  707. package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +2 -1
  708. package/src/workspace/migrations/059-move-pid-to-workspace.ts +3 -8
  709. package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +3 -8
  710. package/src/workspace/migrations/065-bump-stale-heartbeat-interval.ts +60 -0
  711. package/src/workspace/migrations/066-seed-heartbeat-callsite-cost-default.ts +146 -0
  712. package/src/workspace/migrations/067-release-notes-safe-storage-limits.ts +72 -0
  713. package/src/workspace/migrations/068-release-notes-local-timezone.ts +65 -0
  714. package/src/workspace/migrations/AGENTS.md +1 -1
  715. package/src/workspace/migrations/migrate-to-workspace-volume.ts +4 -10
  716. package/src/workspace/migrations/registry.ts +8 -0
  717. package/src/workspace/migrations/utils.ts +21 -0
  718. package/src/__tests__/conversation-tool-setup-memory-scope.test.ts +0 -167
  719. package/src/__tests__/host-browser-e2e-cloud.test.ts +0 -443
  720. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +0 -226
  721. package/src/__tests__/host-browser-ws-events-e2e.test.ts +0 -427
  722. package/src/__tests__/twilio-rest.test.ts +0 -34
  723. package/src/backup/__tests__/backup-key.test.ts +0 -152
  724. package/src/backup/__tests__/backup-worker.test.ts +0 -782
  725. package/src/backup/__tests__/offsite-writer.test.ts +0 -641
  726. package/src/backup/__tests__/stream-crypt.test.ts +0 -228
  727. package/src/backup/backup-key.ts +0 -137
  728. package/src/backup/backup-worker.ts +0 -472
  729. package/src/backup/offsite-writer.ts +0 -222
  730. package/src/backup/stream-crypt.ts +0 -263
  731. package/src/daemon/message-types/pairing.ts +0 -58
  732. package/src/memory/v2/__tests__/skill-qdrant.test.ts +0 -657
  733. package/src/memory/v2/skill-qdrant.ts +0 -395
  734. package/src/outbound-proxy/config.ts +0 -20
  735. package/src/outbound-proxy/health.ts +0 -18
  736. package/src/outbound-proxy/types.ts +0 -150
  737. package/src/runtime/capability-tokens.ts +0 -190
  738. package/src/signals/bash.ts +0 -198
  739. package/src/signals/mcp-reload.ts +0 -18
@@ -206,6 +206,7 @@ function makeConversation(overrides: Record<string, unknown> = {}) {
206
206
  updateClient: () => {},
207
207
  setHostBrowserProxy: () => {},
208
208
  setHostCuProxy: () => {},
209
+ setHostAppControlProxy: () => {},
209
210
  addPreactivatedSkillId: () => {},
210
211
  emitConfirmationStateChanged: () => {},
211
212
  emitActivityState: () => {},
@@ -251,12 +252,24 @@ async function sendMessage(
251
252
  content: string,
252
253
  conversationObj: import("../daemon/conversation.js").Conversation,
253
254
  extra: Record<string, unknown> = {},
255
+ options: {
256
+ onGetOrCreateConversation?: (
257
+ conversationId: string,
258
+ opts?: Record<string, unknown>,
259
+ ) => void;
260
+ } = {},
254
261
  ) {
255
262
  return callHandler(
256
263
  (args) =>
257
264
  handleSendMessage(args, {
258
265
  sendMessageDeps: {
259
- getOrCreateConversation: async () => conversationObj,
266
+ getOrCreateConversation: async (conversationId, opts) => {
267
+ options.onGetOrCreateConversation?.(
268
+ conversationId,
269
+ opts as Record<string, unknown> | undefined,
270
+ );
271
+ return conversationObj;
272
+ },
260
273
  assistantEventHub: { publish: async () => {} } as any,
261
274
  resolveAttachments: () => [],
262
275
  },
@@ -325,3 +338,97 @@ describe("HTTP POST /v1/messages does not intercept recording intents (by design
325
338
  expect(runAgentLoop).toHaveBeenCalledTimes(1);
326
339
  });
327
340
  });
341
+
342
+ // ============================================================================
343
+ // CLIENT TIMEZONE — optional HTTP metadata
344
+ // ============================================================================
345
+ describe("HTTP POST /v1/messages clientTimezone transport metadata", () => {
346
+ beforeEach(() => {
347
+ routeGuardianReplyMock.mockClear();
348
+ listPendingByDestinationMock.mockClear();
349
+ listCanonicalMock.mockClear();
350
+ addMessageMock.mockClear();
351
+ });
352
+
353
+ test("passes canonical clientTimezone through host-proxy transport", async () => {
354
+ const persistUserMessage = mock(async () => "persisted-msg-id");
355
+ const runAgentLoop = mock(async () => undefined);
356
+ const conversation = makeConversation({ persistUserMessage, runAgentLoop });
357
+ let capturedOptions: Record<string, unknown> | undefined;
358
+
359
+ const res = await sendMessage(
360
+ "hello",
361
+ conversation,
362
+ { clientTimezone: "america/new_york" },
363
+ {
364
+ onGetOrCreateConversation: (_conversationId, opts) => {
365
+ capturedOptions = opts;
366
+ },
367
+ },
368
+ );
369
+
370
+ expect(res.status).toBe(202);
371
+ expect(capturedOptions).toEqual({
372
+ transport: {
373
+ channelId: "vellum",
374
+ interfaceId: "macos",
375
+ clientTimezone: "America/New_York",
376
+ },
377
+ });
378
+ });
379
+
380
+ test("passes canonical clientTimezone through non-host-proxy transport", async () => {
381
+ const persistUserMessage = mock(async () => "persisted-msg-id");
382
+ const runAgentLoop = mock(async () => undefined);
383
+ const conversation = makeConversation({ persistUserMessage, runAgentLoop });
384
+ let capturedOptions: Record<string, unknown> | undefined;
385
+
386
+ const res = await sendMessage(
387
+ "hello",
388
+ conversation,
389
+ { interface: "ios", clientTimezone: "europe/london" },
390
+ {
391
+ onGetOrCreateConversation: (_conversationId, opts) => {
392
+ capturedOptions = opts;
393
+ },
394
+ },
395
+ );
396
+
397
+ expect(res.status).toBe(202);
398
+ expect(capturedOptions).toEqual({
399
+ transport: {
400
+ channelId: "vellum",
401
+ interfaceId: "ios",
402
+ clientTimezone: "Europe/London",
403
+ },
404
+ });
405
+ });
406
+
407
+ test("drops invalid clientTimezone without rejecting the message", async () => {
408
+ const persistUserMessage = mock(async () => "persisted-msg-id");
409
+ const runAgentLoop = mock(async () => undefined);
410
+ const conversation = makeConversation({ persistUserMessage, runAgentLoop });
411
+ let capturedOptions: Record<string, unknown> | undefined;
412
+
413
+ const res = await sendMessage(
414
+ "hello",
415
+ conversation,
416
+ { clientTimezone: "not-a-timezone" },
417
+ {
418
+ onGetOrCreateConversation: (_conversationId, opts) => {
419
+ capturedOptions = opts;
420
+ },
421
+ },
422
+ );
423
+
424
+ expect(res.status).toBe(202);
425
+ expect(capturedOptions).toEqual({
426
+ transport: {
427
+ channelId: "vellum",
428
+ interfaceId: "macos",
429
+ },
430
+ });
431
+ expect(persistUserMessage).toHaveBeenCalledTimes(1);
432
+ expect(runAgentLoop).toHaveBeenCalledTimes(1);
433
+ });
434
+ });
@@ -60,6 +60,7 @@ mock.module("../prompts/persona-resolver.js", () => ({
60
60
  import {
61
61
  computeIdentityContentHash,
62
62
  getCachedIntro,
63
+ readWorkspaceIdentityIntro,
63
64
  setCachedIntro,
64
65
  } from "../runtime/routes/identity-intro-cache.js";
65
66
 
@@ -80,6 +81,34 @@ afterEach(() => {
80
81
  // ---------------------------------------------------------------------------
81
82
 
82
83
  describe("identity intro cache", () => {
84
+ test("reads explicit intro from IDENTITY.md before SOUL.md", () => {
85
+ workspaceFiles["IDENTITY.md"] = [
86
+ "# Identity",
87
+ "",
88
+ "## Identity Intro",
89
+ "Nova here.",
90
+ ].join("\n");
91
+ workspaceFiles["SOUL.md"] = [
92
+ "# Soul",
93
+ "",
94
+ "## Identity Intro",
95
+ "Soul fallback.",
96
+ ].join("\n");
97
+
98
+ expect(readWorkspaceIdentityIntro()).toBe("Nova here.");
99
+ });
100
+
101
+ test("falls back to SOUL.md identity intro for legacy workspaces", () => {
102
+ workspaceFiles["SOUL.md"] = [
103
+ "# Soul",
104
+ "",
105
+ "## Identity Intro",
106
+ "Soul fallback.",
107
+ ].join("\n");
108
+
109
+ expect(readWorkspaceIdentityIntro()).toBe("Soul fallback.");
110
+ });
111
+
83
112
  test("returns null when cache is empty", () => {
84
113
  expect(getCachedIntro()).toBeNull();
85
114
  });
@@ -22,8 +22,16 @@ mock.module("../util/logger.js", () => ({
22
22
  }),
23
23
  }));
24
24
 
25
- import { handleDetailedHealth } from "../runtime/routes/identity-routes.js";
25
+ import {
26
+ handleDetailedHealth,
27
+ ROUTES,
28
+ } from "../runtime/routes/identity-routes.js";
26
29
  import { getWorkspaceDir } from "../util/platform.js";
30
+ import {
31
+ getHatchedSidecarPath,
32
+ resolveHatchedAtReadOnly,
33
+ selectHatchedAtFromStats,
34
+ } from "../workspace/hatched-date.js";
27
35
 
28
36
  // ── Env helpers ─────────────────────────────────────────────────────────
29
37
 
@@ -118,6 +126,9 @@ beforeEach(() => {
118
126
  if (existsSync(profilerRunsDir)) {
119
127
  rmSync(profilerRunsDir, { recursive: true, force: true });
120
128
  }
129
+
130
+ rmSync(getHatchedSidecarPath(), { force: true });
131
+ rmSync(join(getWorkspaceDir(), "IDENTITY.md"), { force: true });
121
132
  });
122
133
 
123
134
  afterEach(() => {
@@ -326,3 +337,94 @@ describe("identity routes — health endpoint", () => {
326
337
  });
327
338
  });
328
339
  });
340
+
341
+ describe("identity routes — createdAt selection", () => {
342
+ test("falls back to mtime when birthtime is the Unix epoch", () => {
343
+ const mtime = new Date("2026-05-01T14:49:47.519Z");
344
+
345
+ expect(
346
+ selectHatchedAtFromStats({
347
+ birthtime: new Date(0),
348
+ mtime,
349
+ })?.toISOString(),
350
+ ).toBe(mtime.toISOString());
351
+ });
352
+
353
+ test("prefers birthtime when it is valid", () => {
354
+ const birthtime = new Date("2026-04-30T12:00:00.000Z");
355
+ const mtime = new Date("2026-05-01T14:49:47.519Z");
356
+
357
+ expect(
358
+ selectHatchedAtFromStats({
359
+ birthtime,
360
+ mtime,
361
+ })?.toISOString(),
362
+ ).toBe(birthtime.toISOString());
363
+ });
364
+
365
+ test("returns undefined when both birthtime and mtime are the Unix epoch", () => {
366
+ expect(
367
+ selectHatchedAtFromStats({
368
+ birthtime: new Date(0),
369
+ mtime: new Date(0),
370
+ }),
371
+ ).toBeUndefined();
372
+ });
373
+
374
+ test("read-only resolver falls back to current time without writing sidecar", () => {
375
+ const now = new Date("2026-05-04T12:00:00.000Z");
376
+
377
+ expect(
378
+ resolveHatchedAtReadOnly(
379
+ join(getWorkspaceDir(), "missing-identity.md"),
380
+ now,
381
+ ),
382
+ ).toBe(now.toISOString());
383
+ expect(existsSync(getHatchedSidecarPath())).toBe(false);
384
+ });
385
+
386
+ test("/identity uses persisted hatched sidecar instead of live file metadata", () => {
387
+ const workspaceDir = getWorkspaceDir();
388
+ const dataDir = join(workspaceDir, "data");
389
+ const identityPath = join(workspaceDir, "IDENTITY.md");
390
+ const persistedHatchedAt = "2026-05-01T14:49:47.519Z";
391
+
392
+ mkdirSync(dataDir, { recursive: true });
393
+ writeFileSync(
394
+ identityPath,
395
+ "# Identity\n\n- **Name:** Example Assistant\n",
396
+ "utf-8",
397
+ );
398
+ writeFileSync(
399
+ getHatchedSidecarPath(),
400
+ JSON.stringify({ hatchedAt: persistedHatchedAt }),
401
+ "utf-8",
402
+ );
403
+
404
+ const route = ROUTES.find(
405
+ (candidate) => candidate.operationId === "identity",
406
+ );
407
+ expect(route).toBeDefined();
408
+
409
+ const body = route!.handler({}) as { createdAt?: string };
410
+ expect(body.createdAt).toBe(persistedHatchedAt);
411
+ });
412
+
413
+ test("/identity does not write hatched sidecar on read", () => {
414
+ const identityPath = join(getWorkspaceDir(), "IDENTITY.md");
415
+ writeFileSync(
416
+ identityPath,
417
+ "# Identity\n\n- **Name:** Example Assistant\n",
418
+ "utf-8",
419
+ );
420
+
421
+ const route = ROUTES.find(
422
+ (candidate) => candidate.operationId === "identity",
423
+ );
424
+ expect(route).toBeDefined();
425
+
426
+ const body = route!.handler({}) as { createdAt?: string };
427
+ expect(Date.parse(body.createdAt ?? "")).toBeGreaterThan(0);
428
+ expect(existsSync(getHatchedSidecarPath())).toBe(false);
429
+ });
430
+ });
@@ -41,8 +41,11 @@ describe("initFeatureFlagOverrides", () => {
41
41
  it("falls back gracefully when gateway socket is unavailable", async () => {
42
42
  mockGatewayIpc(null, { error: true });
43
43
 
44
- // Should not throw
45
- await initFeatureFlagOverrides();
44
+ // Disable retries — production retries the IPC fetch on failure to
45
+ // dodge the daemon-vs-gateway startup race, but here we're explicitly
46
+ // testing the no-gateway fallback and don't want the test to wait
47
+ // through the backoff schedule.
48
+ await initFeatureFlagOverrides({ retryBackoffsMs: [] });
46
49
 
47
50
  // Without gateway data or file, undeclared flags default to true
48
51
  const config = {} as any;
@@ -64,7 +67,10 @@ describe("initFeatureFlagOverrides", () => {
64
67
  it("does not cache empty gateway response", async () => {
65
68
  mockGatewayIpc({});
66
69
 
67
- await initFeatureFlagOverrides();
70
+ // Disable retries — this test explicitly simulates a sustained empty
71
+ // response (gateway up but reporting zero flags) and should not wait
72
+ // through the production backoff schedule.
73
+ await initFeatureFlagOverrides({ retryBackoffsMs: [] });
68
74
 
69
75
  // Undeclared flags without overrides default to true (not false from
70
76
  // a cached empty map)
@@ -72,6 +78,23 @@ describe("initFeatureFlagOverrides", () => {
72
78
  expect(isAssistantFeatureFlagEnabled("foo-enabled", config)).toBe(true);
73
79
  });
74
80
 
81
+ it("retries empty gateway responses and picks up flags once they become available", async () => {
82
+ // Simulate the daemon-vs-gateway startup race: the first IPC call
83
+ // returns empty (gateway not yet ready), but a later attempt sees
84
+ // the populated flag map. The retry loop in init should bridge this
85
+ // gap without losing the flag.
86
+ mockGatewayIpc({});
87
+ setTimeout(() => {
88
+ resetMockGatewayIpc();
89
+ mockGatewayIpc({ "retry-test-flag": true });
90
+ }, 50);
91
+
92
+ await initFeatureFlagOverrides({ retryBackoffsMs: [200] });
93
+
94
+ const config = {} as any;
95
+ expect(isAssistantFeatureFlagEnabled("retry-test-flag", config)).toBe(true);
96
+ });
97
+
75
98
  it("does not re-fetch when cache is already populated", async () => {
76
99
  mockGatewayIpc({ "first-call": true });
77
100
 
@@ -4,10 +4,11 @@
4
4
  *
5
5
  * Covers:
6
6
  *
7
- * 1. The nine default injectors registered by `defaultInjectorsPlugin` come
8
- * back from `getInjectors()` in the documented order (workspace-context →
9
- * unified-turn-contextpkb-context → pkb-reminder → memory-v2-static
10
- * now-mdsubagent-statusslack-messagesthread-focus).
7
+ * 1. The ten default injectors registered by `defaultInjectorsPlugin` come
8
+ * back from `getInjectors()` in the documented order
9
+ * (disk-pressure-warningworkspace-context → unified-turn-context
10
+ * pkb-contextpkb-remindermemory-v2-staticnow-md →
11
+ * subagent-status → slack-messages → thread-focus).
11
12
  * 2. A third-party-registered injector at `order: 25` slots between
12
13
  * `unified-turn-context` (order 20) and `pkb` (order 30), proving the
13
14
  * extensibility contract.
@@ -25,6 +26,7 @@
25
26
 
26
27
  import { beforeEach, describe, expect, test } from "bun:test";
27
28
 
29
+ import { _setOverridesForTesting } from "../config/assistant-feature-flags.js";
28
30
  import {
29
31
  applyRuntimeInjections,
30
32
  composeInjectorChain,
@@ -33,6 +35,11 @@ import {
33
35
  DEFAULT_INJECTOR_ORDER,
34
36
  defaultInjectorsPlugin,
35
37
  } from "../plugins/defaults/injectors.js";
38
+
39
+ // This test exercises v1 PKB injection. The `memory-v2-enabled` flag
40
+ // (registry default `true`) makes the PKB injector go silent — disable it
41
+ // here so the v1 injection chain assertions stay meaningful.
42
+ _setOverridesForTesting({ "memory-v2-enabled": false });
36
43
  import {
37
44
  getInjectors,
38
45
  registerPlugin,
@@ -76,11 +83,12 @@ describe("injector chain", () => {
76
83
  resetPluginRegistryForTests();
77
84
  });
78
85
 
79
- test("defaultInjectorsPlugin registers the nine defaults in the documented order", () => {
86
+ test("defaultInjectorsPlugin registers the ten defaults in the documented order", () => {
80
87
  registerPlugin(defaultInjectorsPlugin);
81
88
 
82
89
  const names = getInjectors().map((i) => i.name);
83
90
  expect(names).toEqual([
91
+ "disk-pressure-warning",
84
92
  "workspace-context",
85
93
  "unified-turn-context",
86
94
  "pkb-context",
@@ -97,6 +105,9 @@ describe("injector chain", () => {
97
105
  registerPlugin(defaultInjectorsPlugin);
98
106
 
99
107
  const byName = new Map(getInjectors().map((i) => [i.name, i.order]));
108
+ expect(byName.get("disk-pressure-warning")).toBe(
109
+ DEFAULT_INJECTOR_ORDER.diskPressureWarning,
110
+ );
100
111
  expect(byName.get("workspace-context")).toBe(
101
112
  DEFAULT_INJECTOR_ORDER.workspaceContext,
102
113
  );
@@ -132,6 +143,7 @@ describe("injector chain", () => {
132
143
 
133
144
  const names = getInjectors().map((i) => i.name);
134
145
  expect(names).toEqual([
146
+ "disk-pressure-warning", // 5
135
147
  "workspace-context", // 10
136
148
  "unified-turn-context", // 20
137
149
  "plugin-25", // 25 — slots in
@@ -146,7 +158,7 @@ describe("injector chain", () => {
146
158
  });
147
159
 
148
160
  test("composeInjectorChain returns empty string when every injector opts out", async () => {
149
- // The default chain is the golden-path: all nine defaults return `null`
161
+ // The default chain is the golden-path: all ten defaults return `null`
150
162
  // on an empty turn context, so the composed block is an empty string.
151
163
  registerPlugin(defaultInjectorsPlugin);
152
164
 
@@ -0,0 +1,224 @@
1
+ import { beforeEach, describe, expect, test } from "bun:test";
2
+
3
+ import { _setOverridesForTesting } from "../config/assistant-feature-flags.js";
4
+ import {
5
+ applyRuntimeInjections,
6
+ stripInjectionsForCompaction,
7
+ } from "../daemon/conversation-runtime-assembly.js";
8
+ import {
9
+ DEFAULT_INJECTOR_ORDER,
10
+ defaultInjectorsPlugin,
11
+ DISK_PRESSURE_WARNING_PROMPT,
12
+ } from "../plugins/defaults/injectors.js";
13
+ import {
14
+ registerPlugin,
15
+ resetPluginRegistryForTests,
16
+ } from "../plugins/registry.js";
17
+ import type { Injector, TurnContext } from "../plugins/types.js";
18
+ import type { Message } from "../providers/types.js";
19
+
20
+ function findInjector(name: string): Injector {
21
+ const injector = defaultInjectorsPlugin.injectors?.find(
22
+ (candidate) => candidate.name === name,
23
+ );
24
+ if (!injector) {
25
+ throw new Error(`injector '${name}' not registered`);
26
+ }
27
+ return injector;
28
+ }
29
+
30
+ function makeContext(overrides: Partial<TurnContext> = {}): TurnContext {
31
+ return {
32
+ requestId: "req-test",
33
+ conversationId: "conv-test",
34
+ turnIndex: 0,
35
+ trust: { sourceChannel: "vellum", trustClass: "guardian" },
36
+ ...overrides,
37
+ };
38
+ }
39
+
40
+ function tailTexts(messages: Message[]): string[] {
41
+ const tail = messages[messages.length - 1];
42
+ if (!tail || tail.role !== "user") return [];
43
+ return tail.content
44
+ .filter((block): block is { type: "text"; text: string } => {
45
+ return block.type === "text";
46
+ })
47
+ .map((block) => block.text);
48
+ }
49
+
50
+ const diskPressureInjector = findInjector("disk-pressure-warning");
51
+ const cleanupContext = { cleanupModeActive: true };
52
+
53
+ describe("disk-pressure-warning injector", () => {
54
+ beforeEach(() => {
55
+ resetPluginRegistryForTests();
56
+ registerPlugin(defaultInjectorsPlugin);
57
+ _setOverridesForTesting({ "safe-storage-limits": true });
58
+ });
59
+
60
+ test("emits the exact cleanup prompt while safe storage limits are enabled", async () => {
61
+ const block = await diskPressureInjector.produce(
62
+ makeContext({
63
+ injectionInputs: { diskPressureContext: cleanupContext },
64
+ }),
65
+ );
66
+
67
+ expect(block).toEqual({
68
+ id: "disk-pressure-warning",
69
+ text: DISK_PRESSURE_WARNING_PROMPT,
70
+ placement: "prepend-user-tail",
71
+ });
72
+ expect(diskPressureInjector.order).toBe(
73
+ DEFAULT_INJECTOR_ORDER.diskPressureWarning,
74
+ );
75
+ expect(DISK_PRESSURE_WARNING_PROMPT).toBe(`<disk_pressure_warning>
76
+ Disk usage is critically low: this assistant is in storage cleanup mode because the workspace volume is at least 95% full.
77
+
78
+ In your first paragraph, warn the user that storage is critically low and that normal work is suspended until space is freed.
79
+
80
+ Then help the user clean up storage. Prefer safe inspection steps first, such as checking available space and finding large directories. Ask before deleting files or caches unless the user has already clearly approved the specific cleanup action.
81
+
82
+ Do not work on unrelated tasks until disk usage drops below the critical threshold or the user explicitly overrides the lock. Background processes and messages from trusted contacts are blocked while this cleanup mode is active.
83
+ </disk_pressure_warning>`);
84
+ });
85
+
86
+ test("omits the prompt when cleanup context is null or inactive", async () => {
87
+ await expect(
88
+ diskPressureInjector.produce(
89
+ makeContext({ injectionInputs: { diskPressureContext: null } }),
90
+ ),
91
+ ).resolves.toBeNull();
92
+
93
+ await expect(
94
+ diskPressureInjector.produce(
95
+ makeContext({
96
+ injectionInputs: {
97
+ diskPressureContext: { cleanupModeActive: false },
98
+ },
99
+ }),
100
+ ),
101
+ ).resolves.toBeNull();
102
+ });
103
+
104
+ test("omits the prompt when safe storage limits are disabled", async () => {
105
+ _setOverridesForTesting({ "safe-storage-limits": false });
106
+
107
+ await expect(
108
+ diskPressureInjector.produce(
109
+ makeContext({
110
+ injectionInputs: { diskPressureContext: cleanupContext },
111
+ }),
112
+ ),
113
+ ).resolves.toBeNull();
114
+ });
115
+
116
+ test("prepends ahead of workspace and unified turn context in full mode", async () => {
117
+ const runMessages: Message[] = [
118
+ { role: "user", content: [{ type: "text", text: "clean up space" }] },
119
+ ];
120
+ const workspace = "<workspace>\nRoot: /workspace\n</workspace>";
121
+ const turnContext = "<turn_context>\ninterface: macos\n</turn_context>";
122
+
123
+ const result = await applyRuntimeInjections(runMessages, {
124
+ turnContext: makeContext(),
125
+ diskPressureContext: cleanupContext,
126
+ workspaceTopLevelContext: workspace,
127
+ unifiedTurnContext: turnContext,
128
+ });
129
+
130
+ expect(tailTexts(result.messages).slice(0, 4)).toEqual([
131
+ DISK_PRESSURE_WARNING_PROMPT,
132
+ workspace,
133
+ turnContext,
134
+ "clean up space",
135
+ ]);
136
+ expect(
137
+ result.blocks.injectorChainBlock?.startsWith(
138
+ DISK_PRESSURE_WARNING_PROMPT,
139
+ ),
140
+ ).toBe(true);
141
+ });
142
+
143
+ test("survives minimal mode as safety-critical context", async () => {
144
+ const result = await applyRuntimeInjections(
145
+ [{ role: "user", content: [{ type: "text", text: "status" }] }],
146
+ {
147
+ turnContext: makeContext(),
148
+ mode: "minimal",
149
+ diskPressureContext: cleanupContext,
150
+ workspaceTopLevelContext: "<workspace>...</workspace>",
151
+ unifiedTurnContext: "<turn_context>...</turn_context>",
152
+ },
153
+ );
154
+
155
+ expect(tailTexts(result.messages)).toEqual([
156
+ DISK_PRESSURE_WARNING_PROMPT,
157
+ "<turn_context>...</turn_context>",
158
+ "status",
159
+ ]);
160
+ });
161
+
162
+ test("applies after Slack chronological transcript replacement", async () => {
163
+ const originalRun: Message[] = [
164
+ {
165
+ role: "user",
166
+ content: [{ type: "text", text: "latest raw user text" }],
167
+ },
168
+ ];
169
+ const slackTranscript: Message[] = [
170
+ {
171
+ role: "user",
172
+ content: [{ type: "text", text: "[12:00 user]: earlier" }],
173
+ },
174
+ {
175
+ role: "user",
176
+ content: [{ type: "text", text: "[12:01 @assistant]: cleanup?" }],
177
+ },
178
+ ];
179
+
180
+ const result = await applyRuntimeInjections(originalRun, {
181
+ turnContext: makeContext(),
182
+ diskPressureContext: cleanupContext,
183
+ channelCapabilities: {
184
+ channel: "slack",
185
+ dashboardCapable: false,
186
+ supportsDynamicUi: false,
187
+ supportsVoiceInput: false,
188
+ chatType: "channel",
189
+ },
190
+ slackChronologicalMessages: slackTranscript,
191
+ });
192
+
193
+ expect(result.messages).toHaveLength(2);
194
+ const texts = tailTexts(result.messages);
195
+ expect(texts[0]).toBe(DISK_PRESSURE_WARNING_PROMPT);
196
+ expect(
197
+ texts.some((text) => text.startsWith("<channel_capabilities>")),
198
+ ).toBe(true);
199
+ expect(texts[texts.length - 1]).toBe("[12:01 @assistant]: cleanup?");
200
+ });
201
+
202
+ test("compaction strip plus re-apply does not duplicate the warning", async () => {
203
+ const runMessages: Message[] = [
204
+ { role: "user", content: [{ type: "text", text: "find large files" }] },
205
+ ];
206
+
207
+ const first = await applyRuntimeInjections(runMessages, {
208
+ turnContext: makeContext(),
209
+ diskPressureContext: cleanupContext,
210
+ });
211
+ const stripped = stripInjectionsForCompaction(first.messages);
212
+ expect(tailTexts(stripped)).toEqual(["find large files"]);
213
+
214
+ const second = await applyRuntimeInjections(stripped, {
215
+ turnContext: makeContext(),
216
+ diskPressureContext: cleanupContext,
217
+ });
218
+ expect(
219
+ tailTexts(second.messages).filter(
220
+ (text) => text === DISK_PRESSURE_WARNING_PROMPT,
221
+ ),
222
+ ).toHaveLength(1);
223
+ });
224
+ });
@@ -27,7 +27,6 @@ mock.module("../config/loader.js", () => ({
27
27
  getConfig: () => mockConfig,
28
28
  loadConfig: () => mockConfig,
29
29
  invalidateConfigCache: () => {},
30
- saveConfig: () => {},
31
30
  loadRawConfig: () => ({}),
32
31
  saveRawConfig: () => {},
33
32
  getNestedValue: () => undefined,