@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
@@ -50,6 +50,10 @@ let lastCreateOptions: Record<string, unknown> | null = null;
50
50
  let lastConstructorOptions: Record<string, unknown> | null = null;
51
51
  let shouldThrow: Error | null = null;
52
52
 
53
+ function userMsg(text: string): Message {
54
+ return { role: "user", content: [{ type: "text", text }] };
55
+ }
56
+
53
57
  // Simulate OpenAI.APIError
54
58
  class FakeAPIError extends Error {
55
59
  status: number;
@@ -1294,10 +1298,6 @@ describe("effort config passthrough", () => {
1294
1298
  // ---------------------------------------------------------------------------
1295
1299
 
1296
1300
  describe("OpenRouterProvider reasoning", () => {
1297
- function userMsg(text: string): Message {
1298
- return { role: "user", content: [{ type: "text", text }] };
1299
- }
1300
-
1301
1301
  beforeEach(() => {
1302
1302
  fakeChunks = [textChunk("OK"), usageChunk(10, 2)];
1303
1303
  lastCreateParams = null;
@@ -1367,6 +1367,47 @@ describe("OpenRouterProvider reasoning", () => {
1367
1367
  });
1368
1368
  });
1369
1369
 
1370
+ describe("OpenRouterProvider Anthropic-compatible errors", () => {
1371
+ test("retags Anthropic ProviderError instances as OpenRouter errors", async () => {
1372
+ const provider = new OpenRouterProvider("or-key", "anthropic/claude-4.5");
1373
+ const abortReason = createAbortReason(
1374
+ "user_cancel",
1375
+ "openrouter-provider-test",
1376
+ );
1377
+ const cause = new Error("upstream cause");
1378
+ const innerError = new ProviderError(
1379
+ "Anthropic API error (402): Payment Required",
1380
+ "anthropic",
1381
+ 402,
1382
+ { cause, retryAfterMs: 1250, abortReason },
1383
+ );
1384
+
1385
+ (
1386
+ provider as unknown as {
1387
+ anthropicInner: {
1388
+ sendMessage: OpenRouterProvider["sendMessage"];
1389
+ };
1390
+ }
1391
+ ).anthropicInner = {
1392
+ sendMessage: async () => {
1393
+ throw innerError;
1394
+ },
1395
+ };
1396
+
1397
+ try {
1398
+ await provider.sendMessage([userMsg("hi")]);
1399
+ throw new Error("expected sendMessage to throw");
1400
+ } catch (error) {
1401
+ expect(error).toBeInstanceOf(ProviderError);
1402
+ expect((error as ProviderError).provider).toBe("openrouter");
1403
+ expect((error as ProviderError).statusCode).toBe(402);
1404
+ expect((error as ProviderError).retryAfterMs).toBe(1250);
1405
+ expect((error as ProviderError).abortReason).toBe(abortReason);
1406
+ expect((error as Error).cause).toBe(cause);
1407
+ }
1408
+ });
1409
+ });
1410
+
1370
1411
  // ---------------------------------------------------------------------------
1371
1412
  // Reasoning effort → OpenAI reasoning_effort mapping
1372
1413
  // ---------------------------------------------------------------------------
@@ -1374,10 +1415,6 @@ describe("OpenRouterProvider reasoning", () => {
1374
1415
  describe("OpenAIProvider reasoning_effort", () => {
1375
1416
  let provider: OpenAIProvider;
1376
1417
 
1377
- function userMsg(text: string): Message {
1378
- return { role: "user", content: [{ type: "text", text }] };
1379
- }
1380
-
1381
1418
  beforeEach(() => {
1382
1419
  fakeChunks = [textChunk("OK"), usageChunk(10, 2)];
1383
1420
  lastCreateParams = null;
@@ -27,6 +27,31 @@ mock.module("../util/logger.js", () => ({
27
27
 
28
28
  let writeRelationshipStateCalled = false;
29
29
  let sidecarPayload: unknown = null;
30
+ let writeOnboardingSectionPayload: unknown = null;
31
+
32
+ mock.module("../prompts/normalize-onboarding.js", () => ({
33
+ normalizeOnboardingContext: (ctx: unknown) => ctx,
34
+ }));
35
+
36
+ mock.module("../prompts/persona-resolver.js", () => ({
37
+ writeOnboardingSection: (payload: unknown) => {
38
+ writeOnboardingSectionPayload = payload;
39
+ },
40
+ resolveGuardianPersonaPath: () => join(TEST_DIR, "users", "guardian.md"),
41
+ resolveGuardianPersona: () => null,
42
+ resolveGuardianPersonaStrict: () => null,
43
+ resolveUserPersona: () => null,
44
+ resolveChannelPersona: () => null,
45
+ resolvePersonaContext: () => ({
46
+ userPersona: null,
47
+ userSlug: null,
48
+ channelPersona: null,
49
+ }),
50
+ resolveUserSlug: () => null,
51
+ ensureGuardianPersonaFile: () => {},
52
+ isGuardianPersonaCustomized: () => false,
53
+ GUARDIAN_PERSONA_TEMPLATE: "",
54
+ }));
30
55
 
31
56
  mock.module("../home/relationship-state-writer.js", () => ({
32
57
  RELATIONSHIP_STATE_FILENAME: "relationship-state.json",
@@ -59,13 +84,12 @@ describe("persistOnboardingArtifacts", () => {
59
84
  mkdirSync(TEST_DIR, { recursive: true });
60
85
  writeRelationshipStateCalled = false;
61
86
  sidecarPayload = null;
87
+ writeOnboardingSectionPayload = null;
62
88
  });
63
89
 
64
90
  afterEach(() => {
65
- for (const name of ["IDENTITY.md", "USER.md"]) {
66
- const p = workspacePath(name);
67
- if (existsSync(p)) rmSync(p, { force: true });
68
- }
91
+ const p = workspacePath("IDENTITY.md");
92
+ if (existsSync(p)) rmSync(p, { force: true });
69
93
  });
70
94
 
71
95
  test("seeds IDENTITY.md with assistant name when file does not exist", () => {
@@ -80,19 +104,7 @@ describe("persistOnboardingArtifacts", () => {
80
104
  expect(content).toBe("# Identity\n\n- **Name:** Nova\n");
81
105
  });
82
106
 
83
- test("seeds USER.md with user name when file does not exist", () => {
84
- persistOnboardingArtifacts({
85
- tools: ["slack"],
86
- tasks: ["email"],
87
- tone: "balanced",
88
- userName: "Alex",
89
- });
90
-
91
- const content = readFileSync(workspacePath("USER.md"), "utf-8");
92
- expect(content).toBe("# User\n\n- **Name:** Alex\n");
93
- });
94
-
95
- test("seeds both IDENTITY.md and USER.md when both names are provided", () => {
107
+ test("seeds IDENTITY.md when both names are provided", () => {
96
108
  persistOnboardingArtifacts({
97
109
  tools: [],
98
110
  tasks: [],
@@ -104,9 +116,6 @@ describe("persistOnboardingArtifacts", () => {
104
116
  expect(readFileSync(workspacePath("IDENTITY.md"), "utf-8")).toBe(
105
117
  "# Identity\n\n- **Name:** Pax\n",
106
118
  );
107
- expect(readFileSync(workspacePath("USER.md"), "utf-8")).toBe(
108
- "# User\n\n- **Name:** Alex\n",
109
- );
110
119
  });
111
120
 
112
121
  test("updates Name field in existing IDENTITY.md template", () => {
@@ -128,23 +137,6 @@ describe("persistOnboardingArtifacts", () => {
128
137
  );
129
138
  });
130
139
 
131
- test("updates Name field in existing USER.md template", () => {
132
- writeFileSync(
133
- workspacePath("USER.md"),
134
- "# User\n\n- **Name:** _(not yet chosen)_\n",
135
- );
136
-
137
- persistOnboardingArtifacts({
138
- tools: [],
139
- tasks: [],
140
- tone: "casual",
141
- userName: "NewUser",
142
- });
143
-
144
- const content = readFileSync(workspacePath("USER.md"), "utf-8");
145
- expect(content).toBe("# User\n\n- **Name:** NewUser\n");
146
- });
147
-
148
140
  test("updates old-format Name field in existing IDENTITY.md", () => {
149
141
  writeFileSync(
150
142
  workspacePath("IDENTITY.md"),
@@ -190,17 +182,6 @@ describe("persistOnboardingArtifacts", () => {
190
182
  expect(existsSync(workspacePath("IDENTITY.md"))).toBe(false);
191
183
  });
192
184
 
193
- test("skips USER.md when userName is missing", () => {
194
- persistOnboardingArtifacts({
195
- tools: ["notion"],
196
- tasks: ["project-management"],
197
- tone: "balanced",
198
- assistantName: "Nova",
199
- });
200
-
201
- expect(existsSync(workspacePath("USER.md"))).toBe(false);
202
- });
203
-
204
185
  test("skips IDENTITY.md when assistantName is whitespace-only", () => {
205
186
  persistOnboardingArtifacts({
206
187
  tools: [],
@@ -212,32 +193,17 @@ describe("persistOnboardingArtifacts", () => {
212
193
  expect(existsSync(workspacePath("IDENTITY.md"))).toBe(false);
213
194
  });
214
195
 
215
- test("skips USER.md when userName is whitespace-only", () => {
216
- persistOnboardingArtifacts({
217
- tools: [],
218
- tasks: [],
219
- tone: "balanced",
220
- userName: " ",
221
- });
222
-
223
- expect(existsSync(workspacePath("USER.md"))).toBe(false);
224
- });
225
-
226
- test("trims whitespace from names before writing", () => {
196
+ test("trims whitespace from assistantName before writing", () => {
227
197
  persistOnboardingArtifacts({
228
198
  tools: [],
229
199
  tasks: [],
230
200
  tone: "balanced",
231
- userName: " Alex ",
232
201
  assistantName: " Nova ",
233
202
  });
234
203
 
235
204
  expect(readFileSync(workspacePath("IDENTITY.md"), "utf-8")).toBe(
236
205
  "# Identity\n\n- **Name:** Nova\n",
237
206
  );
238
- expect(readFileSync(workspacePath("USER.md"), "utf-8")).toBe(
239
- "# User\n\n- **Name:** Alex\n",
240
- );
241
207
  });
242
208
 
243
209
  test("passes onboarding payload to writeOnboardingSidecar", () => {
@@ -263,4 +229,18 @@ describe("persistOnboardingArtifacts", () => {
263
229
 
264
230
  expect(writeRelationshipStateCalled).toBe(true);
265
231
  });
232
+
233
+ test("calls writeOnboardingSection with normalized data", () => {
234
+ const payload = {
235
+ tools: ["slack", "linear"],
236
+ tasks: ["code-building", "writing"],
237
+ tone: "professional",
238
+ userName: "Alex",
239
+ assistantName: "Nova",
240
+ };
241
+
242
+ persistOnboardingArtifacts(payload);
243
+
244
+ expect(writeOnboardingSectionPayload).toEqual(payload);
245
+ });
266
246
  });
@@ -0,0 +1,299 @@
1
+ /**
2
+ * Verifies that known-pattern secrets are redacted before being written to
3
+ * durable conversation storage while the live model history (pendingToolResults,
4
+ * raw message content) is left untouched.
5
+ *
6
+ * Touch points under test:
7
+ * - Tool result content blocks persisted by handleMessageComplete
8
+ * - Assistant message text blocks persisted by handleMessageComplete
9
+ */
10
+ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
11
+
12
+ // ── Shared mock plumbing (must precede module-under-test imports) ──────────
13
+
14
+ mock.module("../util/logger.js", () => ({
15
+ getLogger: () =>
16
+ new Proxy({} as Record<string, unknown>, {
17
+ get: () => () => {},
18
+ }),
19
+ }));
20
+
21
+ mock.module("../config/loader.js", () => ({
22
+ getConfig: () => ({
23
+ skills: {
24
+ entries: {},
25
+ load: { extraDirs: [], watch: true, watchDebounceMs: 250 },
26
+ install: { nodeManager: "npm" },
27
+ allowBundled: null,
28
+ remoteProviders: {
29
+ skillssh: { enabled: true },
30
+ clawhub: { enabled: true },
31
+ },
32
+ remotePolicy: {
33
+ blockSuspicious: true,
34
+ blockMalware: true,
35
+ maxSkillsShRisk: "medium",
36
+ },
37
+ },
38
+ }),
39
+ loadConfig: () => ({}),
40
+ }));
41
+
42
+ interface AddMessageCall {
43
+ conversationId: string;
44
+ role: string;
45
+ content: string;
46
+ metadata?: Record<string, unknown>;
47
+ }
48
+ const addMessageCalls: AddMessageCall[] = [];
49
+ mock.module("../memory/conversation-crud.js", () => ({
50
+ addMessage: (
51
+ conversationId: string,
52
+ role: string,
53
+ content: string,
54
+ metadata?: Record<string, unknown>,
55
+ ) => {
56
+ addMessageCalls.push({ conversationId, role, content, metadata });
57
+ return { id: `mock-msg-${addMessageCalls.length}` };
58
+ },
59
+ getConversation: () => null,
60
+ getMessageById: () => null,
61
+ updateMessageContent: () => {},
62
+ provenanceFromTrustContext: () => ({}),
63
+ }));
64
+
65
+ mock.module("../memory/llm-request-log-store.js", () => ({
66
+ recordRequestLog: () => {},
67
+ backfillMessageIdOnLogs: () => {},
68
+ }));
69
+
70
+ mock.module("../memory/memory-recall-log-store.js", () => ({
71
+ backfillMemoryRecallLogMessageId: () => {},
72
+ }));
73
+
74
+ mock.module("../memory/conversation-disk-view.js", () => ({
75
+ syncMessageToDisk: () => {},
76
+ }));
77
+
78
+ // ── Imports (after mocks) ──────────────────────────────────────────────────
79
+
80
+ import type { AgentEvent } from "../agent/loop.js";
81
+ import type {
82
+ EventHandlerDeps,
83
+ EventHandlerState,
84
+ } from "../daemon/conversation-agent-loop-handlers.js";
85
+ import {
86
+ createEventHandlerState,
87
+ handleMessageComplete,
88
+ } from "../daemon/conversation-agent-loop-handlers.js";
89
+
90
+ // ── Helpers ────────────────────────────────────────────────────────────────
91
+
92
+ const CONV = "conv-redact-test";
93
+
94
+ function makeDeps(): EventHandlerDeps {
95
+ return {
96
+ ctx: {
97
+ conversationId: CONV,
98
+ provider: { name: "anthropic" },
99
+ traceEmitter: { emit: () => {} },
100
+ currentTurnSurfaces: [],
101
+ trustContext: {
102
+ sourceChannel: "vellum",
103
+ trustClass: "guardian",
104
+ },
105
+ } as unknown as EventHandlerDeps["ctx"],
106
+ onEvent: () => {},
107
+ reqId: "test-req",
108
+ isFirstMessage: false,
109
+ shouldGenerateTitle: false,
110
+ rlog: new Proxy({} as Record<string, unknown>, {
111
+ get: () => () => {},
112
+ }) as unknown as EventHandlerDeps["rlog"],
113
+ turnChannelContext: {
114
+ userMessageChannel: "vellum",
115
+ assistantMessageChannel: "vellum",
116
+ } as EventHandlerDeps["turnChannelContext"],
117
+ turnInterfaceContext: {
118
+ userMessageInterface: "macos",
119
+ assistantMessageInterface: "macos",
120
+ } as EventHandlerDeps["turnInterfaceContext"],
121
+ } as EventHandlerDeps;
122
+ }
123
+
124
+ function makeMessageCompleteEvent(
125
+ text: string,
126
+ ): Extract<AgentEvent, { type: "message_complete" }> {
127
+ return {
128
+ type: "message_complete",
129
+ message: { role: "assistant", content: [{ type: "text", text }] },
130
+ };
131
+ }
132
+
133
+ function lastPersisted(role: "assistant" | "user"): AddMessageCall {
134
+ for (let i = addMessageCalls.length - 1; i >= 0; i--) {
135
+ if (addMessageCalls[i].role === role) return addMessageCalls[i];
136
+ }
137
+ throw new Error(`No ${role} message was persisted`);
138
+ }
139
+
140
+ // ── Tests ──────────────────────────────────────────────────────────────────
141
+
142
+ describe("persistence-layer secret redaction", () => {
143
+ let state: EventHandlerState;
144
+
145
+ beforeEach(() => {
146
+ addMessageCalls.length = 0;
147
+ state = createEventHandlerState();
148
+ state.turnStartedAt = 1_700_000_000_000;
149
+ });
150
+
151
+ afterEach(() => {
152
+ addMessageCalls.length = 0;
153
+ });
154
+
155
+ // ── Tool result content ──────────────────────────────────────────────────
156
+
157
+ test("redacts Anthropic API key in tool result content before persistence", async () => {
158
+ // Pattern requires 80+ chars after "sk-ant-"
159
+ const secret =
160
+ "sk-ant-api03-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" +
161
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
162
+ state.pendingToolResults.set("tool-use-1", {
163
+ content: `Here is the key: ${secret}`,
164
+ isError: false,
165
+ });
166
+
167
+ await handleMessageComplete(state, makeDeps(), makeMessageCompleteEvent("done"));
168
+
169
+ const persisted = lastPersisted("user");
170
+ const blocks = JSON.parse(persisted.content) as Array<{
171
+ type: string;
172
+ content: string;
173
+ }>;
174
+ expect(blocks[0].content).not.toContain("sk-ant-api03-");
175
+ expect(blocks[0].content).toContain("<redacted");
176
+ });
177
+
178
+ test("redacts GitHub PAT in tool result content before persistence", async () => {
179
+ // Pattern requires 36+ chars after "ghp_"
180
+ const secret = "ghp_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn";
181
+ state.pendingToolResults.set("tool-use-2", {
182
+ content: `token=${secret}`,
183
+ isError: false,
184
+ });
185
+
186
+ await handleMessageComplete(state, makeDeps(), makeMessageCompleteEvent("done"));
187
+
188
+ const persisted = lastPersisted("user");
189
+ const blocks = JSON.parse(persisted.content) as Array<{
190
+ type: string;
191
+ content: string;
192
+ }>;
193
+ expect(blocks[0].content).not.toContain("ghp_");
194
+ expect(blocks[0].content).toContain("<redacted");
195
+ });
196
+
197
+ test("does not redact non-secret content (UUID, hex hash) in tool result", async () => {
198
+ const safe = "id=550e8400-e29b-41d4-a716-446655440000 sha=a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2";
199
+ state.pendingToolResults.set("tool-use-3", {
200
+ content: safe,
201
+ isError: false,
202
+ });
203
+
204
+ await handleMessageComplete(state, makeDeps(), makeMessageCompleteEvent("done"));
205
+
206
+ const persisted = lastPersisted("user");
207
+ const blocks = JSON.parse(persisted.content) as Array<{
208
+ type: string;
209
+ content: string;
210
+ }>;
211
+ expect(blocks[0].content).toBe(safe);
212
+ });
213
+
214
+ test("live model state (pendingToolResults) is not modified by persistence redaction", async () => {
215
+ const secret =
216
+ "sk-ant-api03-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" +
217
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
218
+ const originalContent = `key=${secret}`;
219
+ state.pendingToolResults.set("tool-use-4", {
220
+ content: originalContent,
221
+ isError: false,
222
+ });
223
+
224
+ // Capture the content before handleMessageComplete clears pendingToolResults
225
+ const contentSnapshot = state.pendingToolResults.get("tool-use-4")!.content;
226
+
227
+ await handleMessageComplete(state, makeDeps(), makeMessageCompleteEvent("done"));
228
+
229
+ // The snapshot taken from live state before the call must be unmodified
230
+ expect(contentSnapshot).toBe(originalContent);
231
+ expect(contentSnapshot).toContain("sk-ant-api03-");
232
+ });
233
+
234
+ // ── Assistant message text ───────────────────────────────────────────────
235
+
236
+ test("redacts known-pattern secret quoted in assistant text before persistence", async () => {
237
+ const secret =
238
+ "sk-ant-api03-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" +
239
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
240
+ const text = `Your API key is \`${secret}\`. Keep it safe.`;
241
+
242
+ await handleMessageComplete(state, makeDeps(), makeMessageCompleteEvent(text));
243
+
244
+ const persisted = lastPersisted("assistant");
245
+ const blocks = JSON.parse(persisted.content) as Array<{
246
+ type: string;
247
+ text?: string;
248
+ }>;
249
+ const textBlock = blocks.find((b) => b.type === "text");
250
+ expect(textBlock?.text).not.toContain("sk-ant-api03-");
251
+ expect(textBlock?.text).toContain("<redacted");
252
+ });
253
+
254
+ test("redacts OpenAI Project Key quoted in assistant text before persistence", async () => {
255
+ // Pattern requires 40+ chars after "sk-proj-"
256
+ const secret = "sk-proj-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrst";
257
+ const text = `I found this key in the config: ${secret}`;
258
+
259
+ await handleMessageComplete(state, makeDeps(), makeMessageCompleteEvent(text));
260
+
261
+ const persisted = lastPersisted("assistant");
262
+ const blocks = JSON.parse(persisted.content) as Array<{
263
+ type: string;
264
+ text?: string;
265
+ }>;
266
+ const textBlock = blocks.find((b) => b.type === "text");
267
+ expect(textBlock?.text).not.toContain("sk-proj-");
268
+ expect(textBlock?.text).toContain("<redacted");
269
+ });
270
+
271
+ test("does not redact non-secret text in assistant message", async () => {
272
+ const safe = "Here is the file list: index.ts, util.ts, main.ts";
273
+
274
+ await handleMessageComplete(state, makeDeps(), makeMessageCompleteEvent(safe));
275
+
276
+ const persisted = lastPersisted("assistant");
277
+ const blocks = JSON.parse(persisted.content) as Array<{
278
+ type: string;
279
+ text?: string;
280
+ }>;
281
+ const textBlock = blocks.find((b) => b.type === "text");
282
+ expect(textBlock?.text).toBe(safe);
283
+ });
284
+
285
+ test("does not redact random-looking strings that lack known prefixes", async () => {
286
+ // High-entropy but no known credential prefix — should NOT be redacted
287
+ const text = "checksum: 8f14e45fceea167a5a36dedd4bea2543";
288
+
289
+ await handleMessageComplete(state, makeDeps(), makeMessageCompleteEvent(text));
290
+
291
+ const persisted = lastPersisted("assistant");
292
+ const blocks = JSON.parse(persisted.content) as Array<{
293
+ type: string;
294
+ text?: string;
295
+ }>;
296
+ const textBlock = blocks.find((b) => b.type === "text");
297
+ expect(textBlock?.text).toBe(text);
298
+ });
299
+ });
@@ -67,7 +67,6 @@ mock.module("../config/loader.js", () => ({
67
67
  getConfig: () => mockConfig,
68
68
  loadConfig: () => mockConfig,
69
69
  invalidateConfigCache: () => {},
70
- saveConfig: () => {},
71
70
  loadRawConfig: () => ({}),
72
71
  saveRawConfig: () => {},
73
72
  getNestedValue: () => undefined,
@@ -245,13 +244,11 @@ describe("platform-hosted bash auto-approval", () => {
245
244
  expect(promptCalled).toBe(true);
246
245
  });
247
246
 
248
- test("bash NOT auto-approved for non-guardian actors via platform path (sandbox bash is allowed)", async () => {
247
+ test("bash NOT auto-approved for non-guardian actors via platform path (trusted_contact requires grant)", async () => {
249
248
  checkResultOverride = { decision: "prompt", reason: "Needs approval" };
250
249
 
251
- const platformAutoApproveCalled = false;
252
250
  const trackingPrompter = {
253
251
  prompt: async () => {
254
- // If this is called, we know the platform auto-approve did NOT fire
255
252
  return { decision: "allow" as const };
256
253
  },
257
254
  resolveConfirmation: () => {},
@@ -270,11 +267,10 @@ describe("platform-hosted bash auto-approval", () => {
270
267
  }),
271
268
  );
272
269
 
273
- // With requireFreshApproval, trusted_contact+bash goes through check()
274
- // which returns "prompt" and then the interactive prompter is called.
275
- // The platform auto-approve path (guardian-only) is NOT taken.
276
- expect(result.isError).toBe(false);
277
- void platformAutoApproveCalled; // suppress unused warning
270
+ // trusted_contact now requires a guardian-scoped grant for side-effect
271
+ // tools. Without a grant, the pre-execution gate denies the invocation
272
+ // before the permission checker or prompter is reached.
273
+ expect(result.isError).toBe(true);
278
274
  });
279
275
 
280
276
  test("bash NOT auto-approved when requireFreshApproval is set", async () => {
@@ -5,7 +5,6 @@ import { credentialKey } from "../security/credential-key.js";
5
5
  let mockIsPlatform = true;
6
6
  let mockPlatformBaseUrl = "";
7
7
  let mockPlatformAssistantId = "";
8
- let mockPlatformInternalApiKey = "";
9
8
  let mockSecureKeys: Record<string, string> = {};
10
9
 
11
10
  mock.module("../config/env-registry.js", () => ({
@@ -15,7 +14,6 @@ mock.module("../config/env-registry.js", () => ({
15
14
  mock.module("../config/env.js", () => ({
16
15
  getPlatformBaseUrl: () => mockPlatformBaseUrl,
17
16
  getPlatformAssistantId: () => mockPlatformAssistantId,
18
- getPlatformInternalApiKey: () => mockPlatformInternalApiKey,
19
17
  }));
20
18
 
21
19
  mock.module("../security/secure-keys.js", () => ({
@@ -32,6 +30,7 @@ mock.module("../util/logger.js", () => ({
32
30
  }));
33
31
 
34
32
  const originalFetch = globalThis.fetch;
33
+ const originalEnvCredential = process.env.ASSISTANT_API_KEY;
35
34
 
36
35
  const { registerCallbackRoute, resolvePlatformCallbackRegistrationContext } =
37
36
  await import("../inbound/platform-callback-registration.js");
@@ -41,13 +40,18 @@ describe("platform callback registration", () => {
41
40
  mockIsPlatform = true;
42
41
  mockPlatformBaseUrl = "";
43
42
  mockPlatformAssistantId = "";
44
- mockPlatformInternalApiKey = "";
45
43
  mockSecureKeys = {};
44
+ delete process.env.ASSISTANT_API_KEY;
46
45
  globalThis.fetch = originalFetch;
47
46
  });
48
47
 
49
48
  afterEach(() => {
50
49
  globalThis.fetch = originalFetch;
50
+ if (originalEnvCredential === undefined) {
51
+ delete process.env.ASSISTANT_API_KEY;
52
+ } else {
53
+ process.env.ASSISTANT_API_KEY = originalEnvCredential;
54
+ }
51
55
  });
52
56
 
53
57
  test("resolves managed callback context from stored credentials", async () => {
@@ -64,7 +68,6 @@ describe("platform callback registration", () => {
64
68
  expect(context.isPlatform).toBe(true);
65
69
  expect(context.platformBaseUrl).toBe("https://platform.example.com");
66
70
  expect(context.assistantId).toBe("11111111-2222-4333-8444-555555555555");
67
- expect(context.hasInternalApiKey).toBe(false);
68
71
  expect(context.hasAssistantApiKey).toBe(true);
69
72
  expect(context.authHeader).toBe("Api-Key ast-managed-key");
70
73
  });
@@ -88,6 +91,20 @@ describe("platform callback registration", () => {
88
91
  expect(context.authHeader).toBe("Api-Key ast-self-hosted-key");
89
92
  });
90
93
 
94
+ test("uses ASSISTANT_API_KEY env fallback when stored credential is missing", async () => {
95
+ process.env.ASSISTANT_API_KEY = "env-key";
96
+ mockPlatformBaseUrl = "https://platform.example.com";
97
+ mockPlatformAssistantId = "33333333-4444-4555-8666-777777777777";
98
+
99
+ const context = await resolvePlatformCallbackRegistrationContext();
100
+
101
+ expect(context.enabled).toBe(true);
102
+ expect(context.platformBaseUrl).toBe("https://platform.example.com");
103
+ expect(context.assistantId).toBe("33333333-4444-4555-8666-777777777777");
104
+ expect(context.hasAssistantApiKey).toBe(true);
105
+ expect(context.authHeader).toBe("Api-Key env-key");
106
+ });
107
+
91
108
  test("registerCallbackRoute falls back to assistant API key auth", async () => {
92
109
  mockSecureKeys[credentialKey("vellum", "platform_base_url")] =
93
110
  "https://platform.example.com";
@@ -19,6 +19,7 @@ import {
19
19
  getWorkspacePromptPath,
20
20
  getWorkspaceSkillsDir,
21
21
  getXdgVellumConfigDirName,
22
+ vellumRoot,
22
23
  } from "../util/platform.js";
23
24
 
24
25
  const originalWorkspaceDir = process.env.VELLUM_WORKSPACE_DIR;
@@ -99,7 +100,7 @@ describe("path characterization", () => {
99
100
  ensureDataDir();
100
101
 
101
102
  // Root-level dirs (ensureDataDir always creates these)
102
- const root = join(homedir(), ".vellum");
103
+ const root = vellumRoot();
103
104
  expect(existsSync(root)).toBe(true);
104
105
 
105
106
  // Workspace dirs (in our temp location)