@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
@@ -53,28 +53,28 @@ mock.module("../security/secure-keys.js", () => ({
53
53
  onCesClientChanged: () => ({ unsubscribe: () => {} }),
54
54
  setCesReconnect: () => {},
55
55
  getActiveBackendName: () => "file",
56
+ getActiveBackendInfoAsync: async () => ({
57
+ backend: "encrypted-store",
58
+ storePath: "/tmp/keys.enc",
59
+ storeKeyPath: "/tmp/store.key",
60
+ storeExists: false,
61
+ storeKeyExists: false,
62
+ }),
56
63
  _resetBackend: () => {},
57
64
  }));
58
65
 
59
66
  mock.module("../cli/lib/daemon-credential-client.js", () => ({
60
- setSecureKeyViaDaemon: async (
61
- type: string,
62
- name: string,
63
- value: string,
64
- ): Promise<boolean> => {
67
+ setSecureKeyViaDaemon: async (type: string, name: string, value: string) => {
65
68
  secureKeyStore.set(normalizeCredentialAccount(type, name), value);
66
- return true;
69
+ return { ok: true };
67
70
  },
68
- deleteSecureKeyViaDaemon: async (
69
- type: string,
70
- name: string,
71
- ): Promise<"deleted" | "not-found" | "error"> => {
71
+ deleteSecureKeyViaDaemon: async (type: string, name: string) => {
72
72
  const key = normalizeCredentialAccount(type, name);
73
73
  if (secureKeyStore.has(key)) {
74
74
  secureKeyStore.delete(key);
75
- return "deleted";
75
+ return { result: "deleted" as const };
76
76
  }
77
- return "not-found";
77
+ return { result: "not-found" as const };
78
78
  },
79
79
  }));
80
80
 
@@ -9,28 +9,41 @@ import { afterEach, describe, expect, mock, test } from "bun:test";
9
9
 
10
10
  const sentMessages: unknown[] = [];
11
11
  let mockHasClient = true; // Default to true for CU unified flow tests
12
+ // Default principal id used for both ctx.trustContext and clients in the
13
+ // existing single-user tests. Tests that exercise cross-user behaviour
14
+ // override this on individual clients and on the SurfaceConversationContext.
15
+ const DEFAULT_PRINCIPAL = "user-1";
16
+ let mockCuClients: Array<{
17
+ clientId: string;
18
+ capabilities: string[];
19
+ actorPrincipalId?: string;
20
+ }> = [
21
+ {
22
+ clientId: "mock-client-1",
23
+ capabilities: ["host_cu"],
24
+ actorPrincipalId: DEFAULT_PRINCIPAL,
25
+ },
26
+ ];
12
27
 
13
28
  mock.module("../runtime/assistant-event-hub.js", () => ({
14
29
  broadcastMessage: (msg: unknown) => sentMessages.push(msg),
15
30
  assistantEventHub: {
16
31
  getMostRecentClientByCapability: (cap: string) =>
17
32
  cap === "host_cu" && mockHasClient ? { id: "mock-client" } : null,
33
+ listClientsByCapability: (cap: string) =>
34
+ cap === "host_cu" ? mockCuClients : [],
35
+ getClientById: (id: string) =>
36
+ mockCuClients.find((c) => c.clientId === id) ?? null,
37
+ getActorPrincipalIdForClient: (id: string) =>
38
+ mockCuClients.find((c) => c.clientId === id)?.actorPrincipalId,
18
39
  },
19
40
  }));
20
41
 
21
- mock.module("../runtime/pending-interactions.js", () => ({
22
- resolve: () => undefined,
23
- get: () => undefined,
24
- getByKind: () => [],
25
- getByConversation: () => [],
26
- removeByConversation: () => {},
27
- }));
28
-
29
- const { surfaceProxyResolver } = await import(
30
- "../daemon/conversation-surfaces.js"
31
- );
42
+ const { surfaceProxyResolver } =
43
+ await import("../daemon/conversation-surfaces.js");
32
44
  const { HostCuProxy } = await import("../daemon/host-cu-proxy.js");
33
- type SurfaceConversationContext = import("../daemon/conversation-surfaces.js").SurfaceConversationContext;
45
+ type SurfaceConversationContext =
46
+ import("../daemon/conversation-surfaces.js").SurfaceConversationContext;
34
47
 
35
48
  // ---------------------------------------------------------------------------
36
49
  // Test helpers
@@ -39,12 +52,25 @@ type SurfaceConversationContext = import("../daemon/conversation-surfaces.js").S
39
52
  /**
40
53
  * Build a minimal SurfaceConversationContext with optional hostCuProxy.
41
54
  * Only the fields required by the CU routing path are populated.
55
+ *
56
+ * `trustContext` defaults to a guardian context owned by `DEFAULT_PRINCIPAL`.
57
+ * Pass `null` to omit the field entirely (used to verify same-user
58
+ * enforcement when the conversation has no source actor principal).
42
59
  */
43
60
  function buildMockContext(
44
61
  hostCuProxy?: InstanceType<typeof HostCuProxy>,
62
+ trustGuardianPrincipalId: string | null = DEFAULT_PRINCIPAL,
45
63
  ): SurfaceConversationContext {
46
64
  return {
47
65
  conversationId: "test-session",
66
+ trustContext:
67
+ trustGuardianPrincipalId != null
68
+ ? {
69
+ sourceChannel: "vellum",
70
+ trustClass: "guardian",
71
+ guardianPrincipalId: trustGuardianPrincipalId,
72
+ }
73
+ : undefined,
48
74
  traceEmitter: { emit: () => {} },
49
75
  sendToClient: () => {},
50
76
  pendingSurfaceActions: new Map(),
@@ -73,6 +99,13 @@ describe("surfaceProxyResolver — CU tool routing", () => {
73
99
  function setupProxy(maxSteps?: number): SurfaceConversationContext {
74
100
  sentMessages.length = 0;
75
101
  mockHasClient = true;
102
+ mockCuClients = [
103
+ {
104
+ clientId: "mock-client-1",
105
+ capabilities: ["host_cu"],
106
+ actorPrincipalId: DEFAULT_PRINCIPAL,
107
+ },
108
+ ];
76
109
  proxy = new HostCuProxy(maxSteps);
77
110
  return buildMockContext(proxy);
78
111
  }
@@ -239,7 +272,7 @@ describe("surfaceProxyResolver — CU tool routing", () => {
239
272
 
240
273
  // Simulate client resolving with observation
241
274
  const requestId = sent.requestId as string;
242
- proxy.resolve(requestId, {
275
+ proxy.processObservation(requestId, {
243
276
  axTree: "SubmitButton [1]\nTextField [2]",
244
277
  executionResult: "Clicked element 42",
245
278
  });
@@ -265,7 +298,7 @@ describe("surfaceProxyResolver — CU tool routing", () => {
265
298
  expect(sent.type).toBe("host_cu_request");
266
299
  expect(sent.toolName).toBe("computer_use_screenshot");
267
300
 
268
- proxy.resolve(sent.requestId as string, {
301
+ proxy.processObservation(sent.requestId as string, {
269
302
  axTree: "Window [1]",
270
303
  screenshot: "base64screenshot",
271
304
  screenshotWidthPx: 1920,
@@ -302,7 +335,7 @@ describe("surfaceProxyResolver — CU tool routing", () => {
302
335
  reasoning: "Type into search box",
303
336
  });
304
337
 
305
- proxy.resolve(sent.requestId as string, {
338
+ proxy.processObservation(sent.requestId as string, {
306
339
  axTree: "SearchBox [1] value='Hello world'",
307
340
  executionResult: "Typed text",
308
341
  });
@@ -326,7 +359,7 @@ describe("surfaceProxyResolver — CU tool routing", () => {
326
359
  reasoning: "Check what's on screen",
327
360
  });
328
361
  const sent1 = sentMessages[0] as Record<string, unknown>;
329
- proxy.resolve(sent1.requestId as string, {
362
+ proxy.processObservation(sent1.requestId as string, {
330
363
  axTree: "LoginButton [1]\nUsernameField [2]",
331
364
  });
332
365
  const r1 = await p1;
@@ -340,7 +373,7 @@ describe("surfaceProxyResolver — CU tool routing", () => {
340
373
  reasoning: "Click login button",
341
374
  });
342
375
  const sent2 = sentMessages[1] as Record<string, unknown>;
343
- proxy.resolve(sent2.requestId as string, {
376
+ proxy.processObservation(sent2.requestId as string, {
344
377
  axTree: "PasswordField [1]\nSubmitButton [2]",
345
378
  axDiff: "+ PasswordField [1]\n+ SubmitButton [2]\n- LoginButton [1]",
346
379
  executionResult: "Clicked element 1",
@@ -370,6 +403,301 @@ describe("surfaceProxyResolver — CU tool routing", () => {
370
403
  // Step limit enforced through resolver
371
404
  // -------------------------------------------------------------------------
372
405
 
406
+ // -------------------------------------------------------------------------
407
+ // Multi-client ambiguity guard
408
+ // -------------------------------------------------------------------------
409
+
410
+ describe("multi-client ambiguity guard", () => {
411
+ test("returns error when multiple same-user CU clients connected and no target_client_id given", async () => {
412
+ const ctx = setupProxy();
413
+ mockCuClients = [
414
+ {
415
+ clientId: "client-a",
416
+ capabilities: ["host_cu"],
417
+ actorPrincipalId: DEFAULT_PRINCIPAL,
418
+ },
419
+ {
420
+ clientId: "client-b",
421
+ capabilities: ["host_cu"],
422
+ actorPrincipalId: DEFAULT_PRINCIPAL,
423
+ },
424
+ ];
425
+
426
+ const result = await surfaceProxyResolver(ctx, "computer_use_click", {
427
+ element_id: 1,
428
+ reasoning: "click",
429
+ });
430
+
431
+ expect(result.isError).toBe(true);
432
+ expect(result.content).toContain("multiple clients support host_cu");
433
+ expect(result.content).toContain("target_client_id");
434
+ // No message should have been dispatched
435
+ expect(sentMessages).toHaveLength(0);
436
+ });
437
+
438
+ test("proceeds when multiple clients connected and target_client_id is given", async () => {
439
+ const ctx = setupProxy();
440
+ mockCuClients = [
441
+ {
442
+ clientId: "client-a",
443
+ capabilities: ["host_cu"],
444
+ actorPrincipalId: DEFAULT_PRINCIPAL,
445
+ },
446
+ {
447
+ clientId: "client-b",
448
+ capabilities: ["host_cu"],
449
+ actorPrincipalId: DEFAULT_PRINCIPAL,
450
+ },
451
+ ];
452
+
453
+ const resultPromise = surfaceProxyResolver(ctx, "computer_use_click", {
454
+ element_id: 1,
455
+ reasoning: "click",
456
+ target_client_id: "client-a",
457
+ });
458
+
459
+ // Should have dispatched the request
460
+ expect(sentMessages).toHaveLength(1);
461
+ const sent = sentMessages[0] as Record<string, unknown>;
462
+ expect(sent.type).toBe("host_cu_request");
463
+ expect(sent.targetClientId).toBe("client-a");
464
+
465
+ proxy.processObservation(sent.requestId as string, { axTree: "ok" });
466
+ const result = await resultPromise;
467
+ expect(result.isError).toBe(false);
468
+ });
469
+
470
+ test("proceeds normally when exactly one CU client is connected", async () => {
471
+ const ctx = setupProxy();
472
+ // mockCuClients already has 1 entry from setupProxy
473
+
474
+ const resultPromise = surfaceProxyResolver(ctx, "computer_use_click", {
475
+ element_id: 2,
476
+ reasoning: "safe click",
477
+ });
478
+
479
+ expect(sentMessages).toHaveLength(1);
480
+ const sent = sentMessages[0] as Record<string, unknown>;
481
+ expect(sent.type).toBe("host_cu_request");
482
+
483
+ proxy.processObservation(sent.requestId as string, { axTree: "ok" });
484
+ const result = await resultPromise;
485
+ expect(result.isError).toBe(false);
486
+ });
487
+
488
+ test("multi-client guard does not apply to terminal tools (computer_use_done)", async () => {
489
+ const ctx = setupProxy();
490
+ mockCuClients = [
491
+ { clientId: "client-a", capabilities: ["host_cu"] },
492
+ { clientId: "client-b", capabilities: ["host_cu"] },
493
+ ];
494
+
495
+ // Terminal tools short-circuit before the ambiguity check
496
+ const result = await surfaceProxyResolver(ctx, "computer_use_done", {
497
+ summary: "all done",
498
+ });
499
+
500
+ expect(result.isError).toBe(false);
501
+ expect(result.content).toBe("all done");
502
+ expect(sentMessages).toHaveLength(0);
503
+ });
504
+ });
505
+
506
+ // -------------------------------------------------------------------------
507
+ // targetClientId validation (lives at resolver layer so step count and
508
+ // action history are not mutated when validation rejects the request).
509
+ // -------------------------------------------------------------------------
510
+
511
+ describe("targetClientId validation", () => {
512
+ test("returns fast error when targetClientId does not match any connected client", async () => {
513
+ const ctx = setupProxy();
514
+ mockCuClients = [{ clientId: "real-client", capabilities: ["host_cu"] }];
515
+ const stepCountBefore = proxy.stepCount;
516
+
517
+ const result = await surfaceProxyResolver(ctx, "computer_use_click", {
518
+ element_id: 1,
519
+ reasoning: "click",
520
+ target_client_id: "nonexistent-client",
521
+ });
522
+
523
+ expect(result.isError).toBe(true);
524
+ expect(result.content).toContain("nonexistent-client");
525
+ expect(result.content).toContain("host_cu");
526
+ // Critical: validation must run BEFORE recordAction. stepCount and
527
+ // actionHistory must be unchanged when rejection fires — otherwise
528
+ // every invalid target_client_id burns a step and leaves a ghost
529
+ // entry the LLM can reason about.
530
+ expect(proxy.stepCount).toBe(stepCountBefore);
531
+ expect(proxy.actionHistory).toHaveLength(0);
532
+ expect(sentMessages).toHaveLength(0);
533
+ });
534
+
535
+ test("returns fast error when targetClientId points to a client without host_cu capability", async () => {
536
+ const ctx = setupProxy();
537
+ mockCuClients = [
538
+ { clientId: "no-cu-client", capabilities: ["host_bash"] }, // bash, not cu
539
+ ];
540
+ const stepCountBefore = proxy.stepCount;
541
+
542
+ const result = await surfaceProxyResolver(ctx, "computer_use_click", {
543
+ element_id: 1,
544
+ reasoning: "click",
545
+ target_client_id: "no-cu-client",
546
+ });
547
+
548
+ expect(result.isError).toBe(true);
549
+ expect(result.content).toContain("no-cu-client");
550
+ expect(result.content).toContain("host_cu");
551
+ // No step burned, no ghost in history.
552
+ expect(proxy.stepCount).toBe(stepCountBefore);
553
+ expect(proxy.actionHistory).toHaveLength(0);
554
+ expect(sentMessages).toHaveLength(0);
555
+ });
556
+
557
+ test("dispatches and records action when targetClientId is valid", async () => {
558
+ const ctx = setupProxy();
559
+ mockCuClients = [
560
+ {
561
+ clientId: "cu-client",
562
+ capabilities: ["host_cu"],
563
+ actorPrincipalId: DEFAULT_PRINCIPAL,
564
+ },
565
+ // Second client present to ensure target_client_id resolves
566
+ // unambiguously and would otherwise trip the ambiguity guard.
567
+ {
568
+ clientId: "client-b",
569
+ capabilities: ["host_cu"],
570
+ actorPrincipalId: DEFAULT_PRINCIPAL,
571
+ },
572
+ ];
573
+
574
+ const resultPromise = surfaceProxyResolver(ctx, "computer_use_click", {
575
+ element_id: 5,
576
+ reasoning: "click",
577
+ target_client_id: "cu-client",
578
+ });
579
+
580
+ expect(sentMessages).toHaveLength(1);
581
+ const sent = sentMessages[0] as Record<string, unknown>;
582
+ expect(sent.type).toBe("host_cu_request");
583
+ expect(sent.targetClientId).toBe("cu-client");
584
+ // recordAction did fire on the success path.
585
+ expect(proxy.stepCount).toBe(1);
586
+ expect(proxy.actionHistory).toHaveLength(1);
587
+
588
+ proxy.processObservation(sent.requestId as string, { axTree: "ok" });
589
+ const result = await resultPromise;
590
+ expect(result.isError).toBe(false);
591
+ });
592
+ });
593
+
594
+ // -------------------------------------------------------------------------
595
+ // Same-user enforcement (dispatch layer)
596
+ //
597
+ // The proxy enforces this internally as well — these tests verify the
598
+ // dispatch performs the same-user rejection before the proxy is invoked
599
+ // (so no step is burned and no action history mutated), and uses the
600
+ // canonical rejection message.
601
+ // -------------------------------------------------------------------------
602
+
603
+ describe("same-user enforcement", () => {
604
+ test("rejects targeted CU dispatch from a different actor principal", async () => {
605
+ sentMessages.length = 0;
606
+ mockHasClient = true;
607
+ mockCuClients = [
608
+ {
609
+ clientId: "cu-client",
610
+ capabilities: ["host_cu"],
611
+ actorPrincipalId: "user-other",
612
+ },
613
+ ];
614
+ proxy = new HostCuProxy();
615
+ const ctx = buildMockContext(proxy, DEFAULT_PRINCIPAL);
616
+
617
+ const result = await surfaceProxyResolver(ctx, "computer_use_click", {
618
+ element_id: 1,
619
+ reasoning: "click",
620
+ target_client_id: "cu-client",
621
+ });
622
+
623
+ expect(result.isError).toBe(true);
624
+ expect(result.content).toContain(
625
+ "Submitting actor does not match the target client's actor",
626
+ );
627
+ // No state mutation, no dispatch.
628
+ expect(proxy.stepCount).toBe(0);
629
+ expect(proxy.actionHistory).toHaveLength(0);
630
+ expect(sentMessages).toHaveLength(0);
631
+ });
632
+
633
+ test("rejects when the conversation has no source actor principal", async () => {
634
+ sentMessages.length = 0;
635
+ mockHasClient = true;
636
+ mockCuClients = [
637
+ {
638
+ clientId: "cu-client",
639
+ capabilities: ["host_cu"],
640
+ actorPrincipalId: DEFAULT_PRINCIPAL,
641
+ },
642
+ ];
643
+ proxy = new HostCuProxy();
644
+ const ctx = buildMockContext(proxy, null);
645
+
646
+ const result = await surfaceProxyResolver(ctx, "computer_use_click", {
647
+ element_id: 1,
648
+ reasoning: "click",
649
+ target_client_id: "cu-client",
650
+ });
651
+
652
+ expect(result.isError).toBe(true);
653
+ expect(result.content).toContain(
654
+ "Submitting actor does not match the target client's actor",
655
+ );
656
+ expect(sentMessages).toHaveLength(0);
657
+ });
658
+
659
+ test("auto-resolves to the unique same-user CU client when cross-user clients are present", async () => {
660
+ // Regression: previously the dispatch counted only same-user clients
661
+ // for the multi-client guard, so 1 same-user + 1 cross-user passed the
662
+ // guard with no targetClientId — and the proxy then broadcast to ALL
663
+ // host_cu subscribers, including the cross-user one.
664
+ sentMessages.length = 0;
665
+ mockHasClient = true;
666
+ mockCuClients = [
667
+ {
668
+ clientId: "cu-mine",
669
+ capabilities: ["host_cu"],
670
+ actorPrincipalId: DEFAULT_PRINCIPAL,
671
+ },
672
+ {
673
+ clientId: "cu-other",
674
+ capabilities: ["host_cu"],
675
+ actorPrincipalId: "user-other",
676
+ },
677
+ ];
678
+ proxy = new HostCuProxy();
679
+ const ctx = buildMockContext(proxy, DEFAULT_PRINCIPAL);
680
+
681
+ const resultPromise = surfaceProxyResolver(ctx, "computer_use_click", {
682
+ element_id: 1,
683
+ reasoning: "click",
684
+ // Intentionally no target_client_id — exercises auto-resolve.
685
+ });
686
+
687
+ // Broadcast happens, but with the same-user clientId set so only
688
+ // that client receives it.
689
+ expect(sentMessages).toHaveLength(1);
690
+ const sent = sentMessages[0] as Record<string, unknown>;
691
+ expect(sent.targetClientId).toBe("cu-mine");
692
+
693
+ // Manually resolve to clean up the pending promise.
694
+ proxy.processObservation(sent.requestId as string, {
695
+ executionResult: "ok",
696
+ });
697
+ await resultPromise;
698
+ });
699
+ });
700
+
373
701
  describe("step limit enforcement through resolver", () => {
374
702
  test("rejects action tools when step limit exceeded", async () => {
375
703
  const ctx = setupProxy(2); // maxSteps = 2
@@ -423,7 +751,7 @@ describe("surfaceProxyResolver — CU tool routing", () => {
423
751
  });
424
752
 
425
753
  const sent = sentMessages[0] as Record<string, unknown>;
426
- proxy.resolve(sent.requestId as string, {
754
+ proxy.processObservation(sent.requestId as string, {
427
755
  executionError: "Element 999 not found in AX tree",
428
756
  axTree: "Window [1]",
429
757
  });
@@ -452,7 +780,7 @@ describe("surfaceProxyResolver — CU tool routing", () => {
452
780
  expect(sent.reasoning).toBe("Submit the form");
453
781
 
454
782
  // Resolve to avoid unhandled rejection on dispose
455
- proxy.resolve(sent.requestId as string, { axTree: "..." });
783
+ proxy.processObservation(sent.requestId as string, { axTree: "..." });
456
784
  await resultPromise;
457
785
  });
458
786
 
@@ -469,7 +797,7 @@ describe("surfaceProxyResolver — CU tool routing", () => {
469
797
 
470
798
  // Resolve to avoid hanging
471
799
  const sent = sentMessages[0] as Record<string, unknown>;
472
- proxy.resolve(sent.requestId as string, { axTree: "..." });
800
+ proxy.processObservation(sent.requestId as string, { axTree: "..." });
473
801
  });
474
802
  });
475
803
 
@@ -515,7 +843,7 @@ describe("surfaceProxyResolver — CU tool routing", () => {
515
843
  reasoning: "first",
516
844
  });
517
845
  const s1 = sentMessages[0] as Record<string, unknown>;
518
- proxy.resolve(s1.requestId as string, { axTree: "A" });
846
+ proxy.processObservation(s1.requestId as string, { axTree: "A" });
519
847
  await p1;
520
848
  expect(proxy.stepCount).toBe(1);
521
849
 
@@ -525,7 +853,7 @@ describe("surfaceProxyResolver — CU tool routing", () => {
525
853
  reasoning: "second",
526
854
  });
527
855
  const s2 = sentMessages[1] as Record<string, unknown>;
528
- proxy.resolve(s2.requestId as string, { axTree: "B" });
856
+ proxy.processObservation(s2.requestId as string, { axTree: "B" });
529
857
  await p2;
530
858
  expect(proxy.stepCount).toBe(2);
531
859
 
@@ -536,7 +864,7 @@ describe("surfaceProxyResolver — CU tool routing", () => {
536
864
  reasoning: "third",
537
865
  });
538
866
  const s3 = sentMessages[2] as Record<string, unknown>;
539
- proxy.resolve(s3.requestId as string, { axTree: "C" });
867
+ proxy.processObservation(s3.requestId as string, { axTree: "C" });
540
868
  await p3;
541
869
  expect(proxy.stepCount).toBe(3);
542
870
 
@@ -1,16 +1,20 @@
1
1
  import { describe, expect, mock, test } from "bun:test";
2
2
 
3
3
  /**
4
- * Mock only the IPC client (to simulate daemon-unreachable) and the logger.
4
+ * Mock the IPC client and logger. The IPC mock returns configurable
5
+ * responses so we can test success, failure, and unreachable paths.
6
+ *
5
7
  * Do NOT mock secure-keys.js — daemon-credential-client falls back to it
6
8
  * for writes/deletes when the daemon is unreachable.
7
9
  */
8
10
 
11
+ let _ipcResponse: { ok: boolean; result?: unknown; error?: string } = {
12
+ ok: false,
13
+ error: "Could not connect to assistant daemon. Is it running?",
14
+ };
15
+
9
16
  mock.module("../ipc/cli-client.js", () => ({
10
- cliIpcCall: async () => ({
11
- ok: false,
12
- error: "Could not connect to assistant daemon. Is it running?",
13
- }),
17
+ cliIpcCall: async () => _ipcResponse,
14
18
  }));
15
19
 
16
20
  mock.module("../util/logger.js", () => ({
@@ -20,22 +24,100 @@ mock.module("../util/logger.js", () => ({
20
24
  }),
21
25
  }));
22
26
 
23
- import { setSecureKeyViaDaemon } from "../cli/lib/daemon-credential-client.js";
27
+ import {
28
+ deleteSecureKeyViaDaemon,
29
+ setSecureKeyViaDaemon,
30
+ } from "../cli/lib/daemon-credential-client.js";
24
31
  import { credentialKey } from "../security/credential-key.js";
25
32
  import { getSecureKeyAsync } from "../security/secure-keys.js";
26
33
 
27
- describe("daemon credential writes (daemon unreachable)", () => {
28
- test("falls back to direct write when daemon is not running", async () => {
29
- const result = await setSecureKeyViaDaemon(
30
- "api_key",
31
- "test-provider",
32
- "test-value",
33
- );
34
- expect(result).toBe(true);
35
-
36
- const readBack = await getSecureKeyAsync(
37
- credentialKey("test-provider", "api_key"),
38
- );
39
- expect(readBack).toBe("test-value");
34
+ describe("daemon credential client", () => {
35
+ describe("set daemon unreachable", () => {
36
+ test("falls back to direct write when daemon is not running", async () => {
37
+ _ipcResponse = {
38
+ ok: false,
39
+ error: "Could not connect to assistant daemon. Is it running?",
40
+ };
41
+
42
+ const result = await setSecureKeyViaDaemon(
43
+ "api_key",
44
+ "test-provider",
45
+ "test-value",
46
+ );
47
+ expect(result.ok).toBe(true);
48
+
49
+ const readBack = await getSecureKeyAsync(
50
+ credentialKey("test-provider", "api_key"),
51
+ );
52
+ expect(readBack).toBe("test-value");
53
+ });
54
+ });
55
+
56
+ describe("set — daemon error", () => {
57
+ test("surfaces daemon error message on IPC failure", async () => {
58
+ _ipcResponse = {
59
+ ok: false,
60
+ error:
61
+ "Failed to store credential in secure storage (backend: ces-rpc)",
62
+ };
63
+
64
+ const result = await setSecureKeyViaDaemon(
65
+ "credential",
66
+ "vellum:webhook_secret",
67
+ "some-value",
68
+ );
69
+ expect(result.ok).toBe(false);
70
+ expect(result.error).toBe(
71
+ "Failed to store credential in secure storage (backend: ces-rpc)",
72
+ );
73
+ });
74
+
75
+ test("surfaces validation error from daemon result", async () => {
76
+ _ipcResponse = {
77
+ ok: true,
78
+ result: {
79
+ success: false,
80
+ error: "API key validation failed: invalid format",
81
+ },
82
+ };
83
+
84
+ const result = await setSecureKeyViaDaemon(
85
+ "api_key",
86
+ "anthropic",
87
+ "bad-key",
88
+ );
89
+ expect(result.ok).toBe(false);
90
+ expect(result.error).toBe("API key validation failed: invalid format");
91
+ });
92
+ });
93
+
94
+ describe("delete — daemon error", () => {
95
+ test("surfaces daemon error message", async () => {
96
+ _ipcResponse = {
97
+ ok: false,
98
+ error: "Credential store is unreachable",
99
+ };
100
+
101
+ const result = await deleteSecureKeyViaDaemon(
102
+ "credential",
103
+ "vellum:temp_cred",
104
+ );
105
+ expect(result.result).toBe("error");
106
+ expect(result.error).toBe("Credential store is unreachable");
107
+ });
108
+
109
+ test("returns not-found for 404 errors", async () => {
110
+ _ipcResponse = {
111
+ ok: false,
112
+ error: "Credential not found (404)",
113
+ };
114
+
115
+ const result = await deleteSecureKeyViaDaemon(
116
+ "credential",
117
+ "vellum:missing",
118
+ );
119
+ expect(result.result).toBe("not-found");
120
+ expect(result.error).toBeUndefined();
121
+ });
40
122
  });
41
123
  });