@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
@@ -2,7 +2,8 @@
2
2
  * Unit tests for the /v1/host-browser-result route handler.
3
3
  *
4
4
  * Resolution goes through HostBrowserProxy.instance (singleton). The
5
- * mock below controls the proxy's pending request map and resolve spy.
5
+ * mock below spies on resolveResult; the real pendingInteractions
6
+ * module provides the guard check for unknown request IDs.
6
7
  */
7
8
  import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
8
9
 
@@ -19,20 +20,15 @@ interface ResolveCall {
19
20
  }
20
21
 
21
22
  const resolveSpy: ResolveCall[] = [];
22
- const pendingRequests = new Set<string>();
23
23
 
24
24
  mock.module("../daemon/host-browser-proxy.js", () => ({
25
25
  HostBrowserProxy: {
26
26
  get instance() {
27
27
  return {
28
- hasPendingRequest(requestId: string) {
29
- return pendingRequests.has(requestId);
30
- },
31
- resolve(
28
+ resolveResult(
32
29
  requestId: string,
33
30
  response: { content: string; isError: boolean },
34
31
  ) {
35
- pendingRequests.delete(requestId);
36
32
  resolveSpy.push({ requestId, response });
37
33
  },
38
34
  };
@@ -40,9 +36,16 @@ mock.module("../daemon/host-browser-proxy.js", () => ({
40
36
  },
41
37
  }));
42
38
 
39
+ // Use the real pending-interactions module for the guard check.
40
+ const pendingInteractions = await import("../runtime/pending-interactions.js");
41
+
43
42
  // ── Real imports (after mocks) ───────────────────────────────────────
44
43
 
45
- import { BadRequestError, NotFoundError } from "../runtime/routes/errors.js";
44
+ import {
45
+ BadRequestError,
46
+ ConflictError,
47
+ NotFoundError,
48
+ } from "../runtime/routes/errors.js";
46
49
  import { ROUTES } from "../runtime/routes/host-browser-routes.js";
47
50
 
48
51
  afterAll(() => {
@@ -57,13 +60,16 @@ const handleHostBrowserResult = ROUTES.find(
57
60
 
58
61
  describe("handleHostBrowserResult", () => {
59
62
  beforeEach(() => {
60
- pendingRequests.clear();
63
+ pendingInteractions.clear();
61
64
  resolveSpy.length = 0;
62
65
  });
63
66
 
64
67
  test("happy path: resolves a pending host_browser request via singleton", async () => {
65
68
  const requestId = "browser-req-happy";
66
- pendingRequests.add(requestId);
69
+ pendingInteractions.register(requestId, {
70
+ conversationId: "conv-1",
71
+ kind: "host_browser",
72
+ });
67
73
 
68
74
  const result = await handleHostBrowserResult({
69
75
  body: { requestId, content: "ok", isError: false },
@@ -73,8 +79,6 @@ describe("handleHostBrowserResult", () => {
73
79
  expect(resolveSpy).toHaveLength(1);
74
80
  expect(resolveSpy[0].requestId).toBe(requestId);
75
81
  expect(resolveSpy[0].response).toEqual({ content: "ok", isError: false });
76
-
77
- expect(pendingRequests.has(requestId)).toBe(false);
78
82
  });
79
83
 
80
84
  test("missing body: throws BadRequestError", () => {
@@ -99,9 +103,31 @@ describe("handleHostBrowserResult", () => {
99
103
  ).toThrow(NotFoundError);
100
104
  });
101
105
 
106
+ test("kind mismatch: throws ConflictError when pending interaction is not host_browser", () => {
107
+ const requestId = "bash-req-kind-mismatch";
108
+ pendingInteractions.register(requestId, {
109
+ conversationId: "conv-1",
110
+ kind: "host_bash", // wrong kind
111
+ });
112
+
113
+ expect(() =>
114
+ handleHostBrowserResult({
115
+ body: { requestId, content: "x", isError: false },
116
+ }),
117
+ ).toThrow(ConflictError);
118
+
119
+ // Interaction must NOT have been consumed — the bash proxy can still resolve it
120
+ expect(pendingInteractions.get(requestId)).toBeDefined();
121
+ // resolveResult should never have been called
122
+ expect(resolveSpy).toHaveLength(0);
123
+ });
124
+
102
125
  test("defaults: missing content/isError default to '' and false", async () => {
103
126
  const requestId = "browser-req-defaults";
104
- pendingRequests.add(requestId);
127
+ pendingInteractions.register(requestId, {
128
+ conversationId: "conv-1",
129
+ kind: "host_browser",
130
+ });
105
131
 
106
132
  const result = await handleHostBrowserResult({ body: { requestId } });
107
133
 
@@ -1,28 +1,28 @@
1
1
  import { afterEach, describe, expect, jest, mock, test } from "bun:test";
2
2
 
3
3
  const sentMessages: unknown[] = [];
4
- const resolvedInteractionIds: string[] = [];
5
4
  let mockHasClient = false;
5
+ type MockClient = {
6
+ clientId: string;
7
+ capabilities: string[];
8
+ actorPrincipalId?: string;
9
+ };
10
+ let mockClients: MockClient[] = [];
6
11
 
7
12
  mock.module("../runtime/assistant-event-hub.js", () => ({
8
13
  broadcastMessage: (msg: unknown) => sentMessages.push(msg),
9
14
  assistantEventHub: {
10
15
  getMostRecentClientByCapability: (cap: string) =>
11
16
  cap === "host_cu" && mockHasClient ? { id: "mock-client" } : null,
17
+ getClientById: (id: string) =>
18
+ mockClients.find((c) => c.clientId === id) ?? undefined,
19
+ getActorPrincipalIdForClient: (id: string) =>
20
+ mockClients.find((c) => c.clientId === id)?.actorPrincipalId,
12
21
  },
13
22
  }));
14
23
 
15
- mock.module("../runtime/pending-interactions.js", () => ({
16
- resolve: (requestId: string) => {
17
- resolvedInteractionIds.push(requestId);
18
- return undefined;
19
- },
20
- get: () => undefined,
21
- getByKind: () => [],
22
- getByConversation: () => [],
23
- removeByConversation: () => {},
24
- }));
25
-
24
+ // Use the REAL pending-interactions module the proxy self-registers here.
25
+ const pendingInteractions = await import("../runtime/pending-interactions.js");
26
26
  const { HostCuProxy } = await import("../daemon/host-cu-proxy.js");
27
27
 
28
28
  describe("HostCuProxy", () => {
@@ -30,13 +30,15 @@ describe("HostCuProxy", () => {
30
30
 
31
31
  function setup(maxSteps?: number) {
32
32
  sentMessages.length = 0;
33
- resolvedInteractionIds.length = 0;
34
33
  mockHasClient = false;
34
+ mockClients = [];
35
+ pendingInteractions.clear();
35
36
  proxy = new HostCuProxy(maxSteps);
36
37
  }
37
38
 
38
39
  afterEach(() => {
39
40
  proxy?.dispose();
41
+ pendingInteractions.clear();
40
42
  });
41
43
 
42
44
  // -------------------------------------------------------------------------
@@ -66,9 +68,9 @@ describe("HostCuProxy", () => {
66
68
  expect(typeof sent.requestId).toBe("string");
67
69
 
68
70
  const requestId = sent.requestId as string;
69
- expect(proxy.hasPendingRequest(requestId)).toBe(true);
71
+ expect(pendingInteractions.get(requestId)).toBeDefined();
70
72
 
71
- proxy.resolve(requestId, {
73
+ proxy.processObservation(requestId, {
72
74
  axTree: "Button [1]\nLabel [2]",
73
75
  executionResult: "Clicked element 42",
74
76
  });
@@ -78,7 +80,7 @@ describe("HostCuProxy", () => {
78
80
  expect(result.content).toContain("<ax-tree>");
79
81
  expect(result.content).toContain("CURRENT SCREEN STATE:");
80
82
  expect(result.isError).toBe(false);
81
- expect(proxy.hasPendingRequest(requestId)).toBe(false);
83
+ expect(pendingInteractions.get(requestId)).toBeUndefined();
82
84
  });
83
85
 
84
86
  test("formats error observation correctly", async () => {
@@ -94,7 +96,7 @@ describe("HostCuProxy", () => {
94
96
  const sent = sentMessages[0] as Record<string, unknown>;
95
97
  const requestId = sent.requestId as string;
96
98
 
97
- proxy.resolve(requestId, {
99
+ proxy.processObservation(requestId, {
98
100
  executionError: "Element not found",
99
101
  axTree: "Window [1]",
100
102
  });
@@ -118,7 +120,7 @@ describe("HostCuProxy", () => {
118
120
  const sent = sentMessages[0] as Record<string, unknown>;
119
121
  const requestId = sent.requestId as string;
120
122
 
121
- proxy.resolve(requestId, {
123
+ proxy.processObservation(requestId, {
122
124
  axTree: "Button [1]",
123
125
  screenshot: "base64data",
124
126
  screenshotWidthPx: 1920,
@@ -142,7 +144,7 @@ describe("HostCuProxy", () => {
142
144
  test("resolves with unknown requestId is silently ignored", () => {
143
145
  setup();
144
146
  // Should not throw
145
- proxy.resolve("unknown-id", { axTree: "something" });
147
+ proxy.processObservation("unknown-id", { axTree: "something" });
146
148
  });
147
149
  });
148
150
 
@@ -165,10 +167,10 @@ describe("HostCuProxy", () => {
165
167
 
166
168
  const sent = sentMessages[0] as Record<string, unknown>;
167
169
  const requestId = sent.requestId as string;
168
- expect(proxy.hasPendingRequest(requestId)).toBe(true);
170
+ expect(pendingInteractions.get(requestId)).toBeDefined();
169
171
 
170
172
  // Resolve to avoid test hanging
171
- proxy.resolve(requestId, { axTree: "resolved" });
173
+ proxy.processObservation(requestId, { axTree: "resolved" });
172
174
  await resultPromise;
173
175
  });
174
176
  });
@@ -193,14 +195,14 @@ describe("HostCuProxy", () => {
193
195
 
194
196
  const sent = sentMessages[0] as Record<string, unknown>;
195
197
  const requestId = sent.requestId as string;
196
- expect(proxy.hasPendingRequest(requestId)).toBe(true);
198
+ expect(pendingInteractions.get(requestId)).toBeDefined();
197
199
 
198
200
  controller.abort();
199
201
 
200
202
  const result = await resultPromise;
201
203
  expect(result.content).toContain("Aborted");
202
204
  expect(result.isError).toBe(true);
203
- expect(proxy.hasPendingRequest(requestId)).toBe(false);
205
+ expect(pendingInteractions.get(requestId)).toBeUndefined();
204
206
  });
205
207
 
206
208
  test("sends host_cu_cancel to client on abort", async () => {
@@ -296,7 +298,7 @@ describe("HostCuProxy", () => {
296
298
  expect(sentMessages).toHaveLength(1); // Message was sent
297
299
 
298
300
  const sent = sentMessages[0] as Record<string, unknown>;
299
- proxy.resolve(sent.requestId as string, { axTree: "screen" });
301
+ proxy.processObservation(sent.requestId as string, { axTree: "screen" });
300
302
 
301
303
  const result = await resultPromise;
302
304
  expect(result.isError).toBe(false);
@@ -370,7 +372,7 @@ describe("HostCuProxy", () => {
370
372
  );
371
373
  proxy.recordAction("computer_use_click", { element_id: 1 });
372
374
  const sent1 = sentMessages[0] as Record<string, unknown>;
373
- proxy.resolve(sent1.requestId as string, {
375
+ proxy.processObservation(sent1.requestId as string, {
374
376
  axTree: "Button [1]",
375
377
  });
376
378
  await p1;
@@ -384,7 +386,7 @@ describe("HostCuProxy", () => {
384
386
  );
385
387
  proxy.recordAction("computer_use_click", { element_id: 1 });
386
388
  const sent2 = sentMessages[1] as Record<string, unknown>;
387
- proxy.resolve(sent2.requestId as string, {
389
+ proxy.processObservation(sent2.requestId as string, {
388
390
  axTree: "Button [1]",
389
391
  // No axDiff — screen unchanged
390
392
  });
@@ -402,7 +404,7 @@ describe("HostCuProxy", () => {
402
404
  );
403
405
  proxy.recordAction("computer_use_click", { element_id: 1 });
404
406
  const sent3 = sentMessages[2] as Record<string, unknown>;
405
- proxy.resolve(sent3.requestId as string, {
407
+ proxy.processObservation(sent3.requestId as string, {
406
408
  axTree: "Button [1]",
407
409
  });
408
410
  const result3 = await p3;
@@ -424,7 +426,7 @@ describe("HostCuProxy", () => {
424
426
  1,
425
427
  );
426
428
  const sent1 = sentMessages[0] as Record<string, unknown>;
427
- proxy.resolve(sent1.requestId as string, {
429
+ proxy.processObservation(sent1.requestId as string, {
428
430
  axTree: "Button [1]",
429
431
  // No axDiff on first observation — this is normal, not unchanged
430
432
  });
@@ -444,7 +446,7 @@ describe("HostCuProxy", () => {
444
446
  );
445
447
  proxy.recordAction("computer_use_click", { element_id: 1 });
446
448
  const sent1 = sentMessages[0] as Record<string, unknown>;
447
- proxy.resolve(sent1.requestId as string, {
449
+ proxy.processObservation(sent1.requestId as string, {
448
450
  axTree: "Button [1]",
449
451
  });
450
452
  await p1;
@@ -458,7 +460,7 @@ describe("HostCuProxy", () => {
458
460
  );
459
461
  proxy.recordAction("computer_use_wait", { duration_ms: 2000 });
460
462
  const sent2 = sentMessages[1] as Record<string, unknown>;
461
- proxy.resolve(sent2.requestId as string, {
463
+ proxy.processObservation(sent2.requestId as string, {
462
464
  axTree: "Button [1]",
463
465
  // No axDiff — screen unchanged, but that's expected after wait
464
466
  });
@@ -478,7 +480,7 @@ describe("HostCuProxy", () => {
478
480
  );
479
481
  proxy.recordAction("computer_use_click", { element_id: 1 });
480
482
  const sent1 = sentMessages[0] as Record<string, unknown>;
481
- proxy.resolve(sent1.requestId as string, {
483
+ proxy.processObservation(sent1.requestId as string, {
482
484
  axTree: "Button [1]",
483
485
  });
484
486
  await p1;
@@ -492,7 +494,7 @@ describe("HostCuProxy", () => {
492
494
  );
493
495
  proxy.recordAction("computer_use_click", { element_id: 1 });
494
496
  const sent2 = sentMessages[1] as Record<string, unknown>;
495
- proxy.resolve(sent2.requestId as string, {
497
+ proxy.processObservation(sent2.requestId as string, {
496
498
  axTree: "Button [1]",
497
499
  });
498
500
  await p2;
@@ -507,7 +509,7 @@ describe("HostCuProxy", () => {
507
509
  );
508
510
  proxy.recordAction("computer_use_click", { element_id: 2 });
509
511
  const sent3 = sentMessages[2] as Record<string, unknown>;
510
- proxy.resolve(sent3.requestId as string, {
512
+ proxy.processObservation(sent3.requestId as string, {
511
513
  axTree: "TextField [1]",
512
514
  axDiff: "+ TextField [1]\n- Button [1]",
513
515
  });
@@ -719,11 +721,11 @@ describe("HostCuProxy", () => {
719
721
 
720
722
  const sent = sentMessages[0] as Record<string, unknown>;
721
723
  const requestId = sent.requestId as string;
722
- expect(proxy.hasPendingRequest(requestId)).toBe(true);
724
+ expect(pendingInteractions.get(requestId)).toBeDefined();
723
725
 
724
726
  proxy.dispose();
725
727
 
726
- expect(proxy.hasPendingRequest(requestId)).toBe(false);
728
+ expect(pendingInteractions.get(requestId)).toBeUndefined();
727
729
  await expect(resultPromise).rejects.toThrow("Host CU proxy disposed");
728
730
  });
729
731
 
@@ -786,9 +788,9 @@ describe("HostCuProxy", () => {
786
788
  expect(result.content).toContain("Aborted");
787
789
 
788
790
  // Late resolve should be silently ignored (no throw, no double-resolve)
789
- proxy.resolve(requestId, { axTree: "late response" });
791
+ proxy.processObservation(requestId, { axTree: "late response" });
790
792
 
791
- expect(proxy.hasPendingRequest(requestId)).toBe(false);
793
+ expect(pendingInteractions.get(requestId)).toBeUndefined();
792
794
  });
793
795
  });
794
796
 
@@ -811,17 +813,11 @@ describe("HostCuProxy", () => {
811
813
  const s = source as any;
812
814
  const origAdd = source.addEventListener.bind(source);
813
815
  const origRemove = source.removeEventListener.bind(source);
814
- s.addEventListener = (
815
- type: string,
816
- ...rest: any[]
817
- ) => {
816
+ s.addEventListener = (type: string, ...rest: any[]) => {
818
817
  addCalls.push(type);
819
818
  return (origAdd as any)(type, ...rest);
820
819
  };
821
- s.removeEventListener = (
822
- type: string,
823
- ...rest: any[]
824
- ) => {
820
+ s.removeEventListener = (type: string, ...rest: any[]) => {
825
821
  removeCalls.push(type);
826
822
  return (origRemove as any)(type, ...rest);
827
823
  };
@@ -847,7 +843,7 @@ describe("HostCuProxy", () => {
847
843
 
848
844
  const requestId = (sentMessages[0] as Record<string, unknown>)
849
845
  .requestId as string;
850
- proxy.resolve(requestId, { axTree: "Button [1]" });
846
+ proxy.processObservation(requestId, { axTree: "Button [1]" });
851
847
  await resultPromise;
852
848
 
853
849
  // Listener is detached after normal completion.
@@ -881,7 +877,7 @@ describe("HostCuProxy", () => {
881
877
 
882
878
  const requestId = (sentMessages[0] as Record<string, unknown>)
883
879
  .requestId as string;
884
- expect(proxy.hasPendingRequest(requestId)).toBe(true);
880
+ expect(pendingInteractions.get(requestId)).toBeDefined();
885
881
 
886
882
  // Advance past the 60s internal timeout.
887
883
  jest.advanceTimersByTime(61 * 1000);
@@ -889,7 +885,7 @@ describe("HostCuProxy", () => {
889
885
  const result = await resultPromise;
890
886
  expect(result.isError).toBe(true);
891
887
  expect(result.content).toContain("Host CU proxy timed out");
892
- expect(proxy.hasPendingRequest(requestId)).toBe(false);
888
+ expect(pendingInteractions.get(requestId)).toBeUndefined();
893
889
 
894
890
  // Listener is detached after the timer fires.
895
891
  expect(spy.removeCalls).toEqual(["abort"]);
@@ -927,7 +923,7 @@ describe("HostCuProxy", () => {
927
923
  controller.abort();
928
924
 
929
925
  await resultPromise;
930
- expect(resolvedInteractionIds).toContain(requestId);
926
+ expect(pendingInteractions.get(requestId)).toBeUndefined();
931
927
  });
932
928
 
933
929
  test("fires on dispose", async () => {
@@ -948,7 +944,7 @@ describe("HostCuProxy", () => {
948
944
  // dispose rejects pending requests — catch to avoid unhandled rejection
949
945
  await resultPromise.catch(() => {});
950
946
 
951
- expect(resolvedInteractionIds).toContain(requestId);
947
+ expect(pendingInteractions.get(requestId)).toBeUndefined();
952
948
  });
953
949
 
954
950
  test("does not fire on normal client-initiated resolve", async () => {
@@ -964,10 +960,10 @@ describe("HostCuProxy", () => {
964
960
  const sent = sentMessages[0] as Record<string, unknown>;
965
961
  const requestId = sent.requestId as string;
966
962
 
967
- proxy.resolve(requestId, { axTree: "Button [1]" });
963
+ proxy.processObservation(requestId, { axTree: "Button [1]" });
968
964
 
969
965
  await resultPromise;
970
- expect(resolvedInteractionIds).toEqual([]);
966
+ expect(pendingInteractions.get(requestId)).toBeUndefined();
971
967
  });
972
968
  });
973
969
 
@@ -988,4 +984,204 @@ describe("HostCuProxy", () => {
988
984
  expect(proxy.isAvailable()).toBe(true);
989
985
  });
990
986
  });
987
+
988
+ // -------------------------------------------------------------------------
989
+ // targetClientId validation
990
+ //
991
+ // The surfaceProxyResolver layer validates first (so an invalid ID does
992
+ // not burn a step or pollute action history — see cu-unified-flow.test.ts
993
+ // for those tests). The proxy ALSO validates internally because it is
994
+ // exposed as a separately-callable API; these tests exercise that
995
+ // backstop along with the same-user enforcement.
996
+ // -------------------------------------------------------------------------
997
+
998
+ describe("targetClientId validation", () => {
999
+ test("rejects when targetClientId does not match any connected client", async () => {
1000
+ setup();
1001
+ mockClients = [
1002
+ {
1003
+ clientId: "real-client",
1004
+ capabilities: ["host_cu"],
1005
+ actorPrincipalId: "user-1",
1006
+ },
1007
+ ];
1008
+
1009
+ const result = await proxy.request(
1010
+ "computer_use_click",
1011
+ { element_id: 1 },
1012
+ "session-1",
1013
+ 1,
1014
+ undefined,
1015
+ undefined,
1016
+ "ghost-client",
1017
+ "user-1",
1018
+ );
1019
+
1020
+ expect(result.isError).toBe(true);
1021
+ expect(result.content).toContain("ghost-client");
1022
+ expect(result.content).toContain("host_cu");
1023
+ expect(sentMessages).toHaveLength(0);
1024
+ });
1025
+
1026
+ test("rejects when target client lacks host_cu capability", async () => {
1027
+ setup();
1028
+ mockClients = [
1029
+ {
1030
+ clientId: "no-cu-client",
1031
+ capabilities: ["host_bash"],
1032
+ actorPrincipalId: "user-1",
1033
+ },
1034
+ ];
1035
+
1036
+ const result = await proxy.request(
1037
+ "computer_use_click",
1038
+ { element_id: 1 },
1039
+ "session-1",
1040
+ 1,
1041
+ undefined,
1042
+ undefined,
1043
+ "no-cu-client",
1044
+ "user-1",
1045
+ );
1046
+
1047
+ expect(result.isError).toBe(true);
1048
+ expect(result.content).toContain("does not support host_cu");
1049
+ expect(sentMessages).toHaveLength(0);
1050
+ });
1051
+
1052
+ test("succeeds when caller and target share the same actor principal", async () => {
1053
+ setup();
1054
+ mockClients = [
1055
+ {
1056
+ clientId: "cu-client",
1057
+ capabilities: ["host_cu"],
1058
+ actorPrincipalId: "user-1",
1059
+ },
1060
+ ];
1061
+
1062
+ const resultPromise = proxy.request(
1063
+ "computer_use_click",
1064
+ { element_id: 1 },
1065
+ "session-1",
1066
+ 1,
1067
+ undefined,
1068
+ undefined,
1069
+ "cu-client",
1070
+ "user-1",
1071
+ );
1072
+
1073
+ expect(sentMessages).toHaveLength(1);
1074
+ const sent = sentMessages[0] as Record<string, unknown>;
1075
+ expect(sent.type).toBe("host_cu_request");
1076
+ expect(sent.targetClientId).toBe("cu-client");
1077
+
1078
+ proxy.processObservation(sent.requestId as string, { axTree: "ok" });
1079
+ const result = await resultPromise;
1080
+ expect(result.isError).toBe(false);
1081
+ });
1082
+
1083
+ test("rejects cross-user targeted request", async () => {
1084
+ setup();
1085
+ mockClients = [
1086
+ {
1087
+ clientId: "cu-client",
1088
+ capabilities: ["host_cu"],
1089
+ actorPrincipalId: "user-2",
1090
+ },
1091
+ ];
1092
+
1093
+ const result = await proxy.request(
1094
+ "computer_use_click",
1095
+ { element_id: 1 },
1096
+ "session-1",
1097
+ 1,
1098
+ undefined,
1099
+ undefined,
1100
+ "cu-client",
1101
+ "user-1",
1102
+ );
1103
+
1104
+ expect(result.isError).toBe(true);
1105
+ expect(result.content).toContain(
1106
+ "Submitting actor does not match the target client's actor",
1107
+ );
1108
+ expect(sentMessages).toHaveLength(0);
1109
+ });
1110
+
1111
+ test("rejects when source actor principal is missing", async () => {
1112
+ setup();
1113
+ mockClients = [
1114
+ {
1115
+ clientId: "cu-client",
1116
+ capabilities: ["host_cu"],
1117
+ actorPrincipalId: "user-1",
1118
+ },
1119
+ ];
1120
+
1121
+ const result = await proxy.request(
1122
+ "computer_use_click",
1123
+ { element_id: 1 },
1124
+ "session-1",
1125
+ 1,
1126
+ undefined,
1127
+ undefined,
1128
+ "cu-client",
1129
+ // sourceActorPrincipalId omitted
1130
+ );
1131
+
1132
+ expect(result.isError).toBe(true);
1133
+ expect(result.content).toContain(
1134
+ "Submitting actor does not match the target client's actor",
1135
+ );
1136
+ expect(sentMessages).toHaveLength(0);
1137
+ });
1138
+
1139
+ test("rejects when target actor principal is missing", async () => {
1140
+ setup();
1141
+ mockClients = [
1142
+ {
1143
+ clientId: "cu-client",
1144
+ capabilities: ["host_cu"],
1145
+ // actorPrincipalId omitted
1146
+ },
1147
+ ];
1148
+
1149
+ const result = await proxy.request(
1150
+ "computer_use_click",
1151
+ { element_id: 1 },
1152
+ "session-1",
1153
+ 1,
1154
+ undefined,
1155
+ undefined,
1156
+ "cu-client",
1157
+ "user-1",
1158
+ );
1159
+
1160
+ expect(result.isError).toBe(true);
1161
+ expect(result.content).toContain(
1162
+ "Submitting actor does not match the target client's actor",
1163
+ );
1164
+ expect(sentMessages).toHaveLength(0);
1165
+ });
1166
+
1167
+ test("untargeted request bypasses same-user check", async () => {
1168
+ setup();
1169
+ // No targetClientId, no sourceActorPrincipalId — flow proceeds.
1170
+ const resultPromise = proxy.request(
1171
+ "computer_use_click",
1172
+ { element_id: 1 },
1173
+ "session-1",
1174
+ 1,
1175
+ );
1176
+
1177
+ expect(sentMessages).toHaveLength(1);
1178
+ const sent = sentMessages[0] as Record<string, unknown>;
1179
+ expect(sent.type).toBe("host_cu_request");
1180
+ expect(sent.targetClientId).toBeUndefined();
1181
+
1182
+ proxy.processObservation(sent.requestId as string, { axTree: "ok" });
1183
+ const result = await resultPromise;
1184
+ expect(result.isError).toBe(false);
1185
+ });
1186
+ });
991
1187
  });