@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
@@ -119,6 +119,7 @@ let mockSingletonProxy: HostBrowserProxy | null = null;
119
119
  /** Default proxy that reports unavailable — used when no test override is set. */
120
120
  const unavailableFallback: HostBrowserProxy = {
121
121
  isAvailable: () => false,
122
+ hasExtensionClient: () => false,
122
123
  request: () => Promise.reject(new Error("no extension")),
123
124
  resolve: () => {},
124
125
  hasPendingRequest: () => false,
@@ -161,23 +162,38 @@ function makeContext(
161
162
  }
162
163
 
163
164
  /**
164
- * Create a fake HostBrowserProxy that reports as available.
165
+ * Create a fake HostBrowserProxy with a Chrome Extension client connected.
166
+ * Both isAvailable() and hasExtensionClient() return true.
165
167
  */
166
168
  function makeAvailableProxy(): HostBrowserProxy {
167
169
  return {
168
170
  request: mock(async () => ({})),
169
171
  isAvailable: () => true,
172
+ hasExtensionClient: () => true,
173
+ } as unknown as HostBrowserProxy;
174
+ }
175
+
176
+ /**
177
+ * Create a fake HostBrowserProxy where only the macOS SSE bridge is connected
178
+ * (no Chrome Extension). isAvailable() is true but hasExtensionClient() is false.
179
+ */
180
+ function makeMacosBridgeOnlyProxy(): HostBrowserProxy {
181
+ return {
182
+ request: mock(async () => ({})),
183
+ isAvailable: () => true,
184
+ hasExtensionClient: () => false,
170
185
  } as unknown as HostBrowserProxy;
171
186
  }
172
187
 
173
188
  /**
174
189
  * Create a fake HostBrowserProxy that reports as unavailable
175
- * (proxy exists but client is disconnected).
190
+ * (proxy exists but no client of any kind is connected).
176
191
  */
177
192
  function makeUnavailableProxy(): HostBrowserProxy {
178
193
  return {
179
194
  request: mock(async () => ({})),
180
195
  isAvailable: () => false,
196
+ hasExtensionClient: () => false,
181
197
  } as unknown as HostBrowserProxy;
182
198
  }
183
199
 
@@ -682,6 +698,22 @@ describe("buildCandidateList", () => {
682
698
  expect(candidates[0].kind).toBe("local");
683
699
  });
684
700
 
701
+ test("excludes extension candidate when only macOS SSE bridge is connected", () => {
702
+ // isAvailable() = true but hasExtensionClient() = false: only macOS bridge.
703
+ // The macOS bridge routes through localhost:9222 on the host, so it must
704
+ // NOT be included under the "extension" candidate kind.
705
+ const fakeProxy = makeMacosBridgeOnlyProxy();
706
+ mockSingletonProxy = fakeProxy;
707
+ const ctx = makeContext({
708
+ conversationId: "candidates-macos-bridge-only",
709
+ });
710
+
711
+ const candidates = buildCandidateList(ctx);
712
+
713
+ expect(candidates.every((c) => c.kind !== "extension")).toBe(true);
714
+ expect(candidates[candidates.length - 1].kind).toBe("local");
715
+ });
716
+
685
717
  test("includes cdp-inspect candidate when enabled in config", () => {
686
718
  cdpInspectEnabled = true;
687
719
  const ctx = makeContext({ conversationId: "candidates-inspect" });
@@ -1435,7 +1467,7 @@ describe("pinned-mode selection", () => {
1435
1467
  const cdpErr = err as CdpError;
1436
1468
  expect(cdpErr.code).toBe("transport_error");
1437
1469
  expect(cdpErr.message).toContain('Pinned mode "extension" unavailable');
1438
- expect(cdpErr.message).toContain("no active extension connection");
1470
+ expect(cdpErr.message).toContain("no Chrome Extension connected");
1439
1471
  expect(cdpErr.attemptDiagnostics).toBeDefined();
1440
1472
  expect(cdpErr.attemptDiagnostics).toHaveLength(1);
1441
1473
  expect(cdpErr.attemptDiagnostics![0].candidateKind).toBe("extension");
@@ -1457,7 +1489,7 @@ describe("pinned-mode selection", () => {
1457
1489
  } catch (err) {
1458
1490
  const cdpErr = err as CdpError;
1459
1491
  expect(cdpErr.code).toBe("transport_error");
1460
- expect(cdpErr.message).toContain("no active extension connection");
1492
+ expect(cdpErr.message).toContain("no Chrome Extension connected");
1461
1493
  expect(cdpErr.attemptDiagnostics![0].stage).toBe("candidate_selection");
1462
1494
  }
1463
1495
  });
@@ -1667,6 +1699,25 @@ describe("buildPinnedCandidateList", () => {
1667
1699
  });
1668
1700
  }
1669
1701
  });
1702
+
1703
+ test("extension mode throws when only macOS SSE bridge is connected", () => {
1704
+ // This is the bug case: isAvailable() = true but hasExtensionClient() = false.
1705
+ // Before the fix, this would build an extension candidate that silently
1706
+ // dispatched to the macOS bridge and failed with a misleading localhost:9222 error.
1707
+ const fakeProxy = makeMacosBridgeOnlyProxy();
1708
+ mockSingletonProxy = fakeProxy;
1709
+ const ctx = makeContext({ conversationId: "bpl-ext-macos-bridge-only" });
1710
+
1711
+ try {
1712
+ buildPinnedCandidateList(ctx, "extension");
1713
+ expect(true).toBe(false); // should not reach
1714
+ } catch (err) {
1715
+ expect(err).toBeInstanceOf(CdpError);
1716
+ const cdpErr = err as CdpError;
1717
+ expect(cdpErr.code).toBe("transport_error");
1718
+ expect(cdpErr.message).toContain("no Chrome Extension connected");
1719
+ }
1720
+ });
1670
1721
  });
1671
1722
 
1672
1723
  // ── Attempt diagnostics & fallback log tests ─────────────────────────────
@@ -511,14 +511,19 @@ describe("connectCdpWsTransport", () => {
511
511
  });
512
512
 
513
513
  test("addEventListener returns an unsubscribe function", async () => {
514
+ // Use a sentinel request to gate event emission on the server: the
515
+ // listener is registered before send() runs, so by the time the server
516
+ // receives the sentinel and starts emitting events the client listener
517
+ // is guaranteed to be attached. A bare setTimeout-after-open race is
518
+ // tight enough to flake on busy CI runners.
514
519
  const server = startFakeWsServer({
515
- onOpen(ws) {
520
+ onMessage(ws, frame) {
521
+ if (frame.method !== "Test.startEvents") return;
522
+ ws.send(JSON.stringify({ id: frame.id, result: {} }));
523
+ ws.send(JSON.stringify({ method: "Ev.first", params: {} }));
516
524
  setTimeout(() => {
517
- ws.send(JSON.stringify({ method: "Ev.first", params: {} }));
518
- setTimeout(() => {
519
- ws.send(JSON.stringify({ method: "Ev.second", params: {} }));
520
- }, 10);
521
- }, 5);
525
+ ws.send(JSON.stringify({ method: "Ev.second", params: {} }));
526
+ }, 10);
522
527
  },
523
528
  });
524
529
  try {
@@ -528,6 +533,7 @@ describe("connectCdpWsTransport", () => {
528
533
  received.push(ev.method);
529
534
  if (ev.method === "Ev.first") unsub();
530
535
  });
536
+ await transport.send("Test.startEvents");
531
537
  await new Promise((r) => setTimeout(r, 60));
532
538
  expect(received).toEqual(["Ev.first"]);
533
539
  });
@@ -187,25 +187,25 @@ export function buildPinnedCandidateList(
187
187
 
188
188
  switch (mode) {
189
189
  case "extension": {
190
- const hostBrowserProxy = HostBrowserProxy.instance;
191
- if (!hostBrowserProxy.isAvailable()) {
192
- throw new CdpError(
193
- "transport_error",
194
- `Pinned mode "extension" unavailable: no active extension connection`,
195
- {
196
- attemptDiagnostics: [
197
- {
198
- candidateKind: "extension",
199
- inclusionReason: `pinned mode: extension`,
200
- stage: "candidate_selection",
201
- errorCode: "transport_error",
202
- errorMessage: "no active extension connection",
203
- },
204
- ],
205
- },
206
- );
207
- }
208
- return [
190
+ const hostBrowserProxy = HostBrowserProxy.instance;
191
+ if (!hostBrowserProxy.hasExtensionClient()) {
192
+ throw new CdpError(
193
+ "transport_error",
194
+ `Pinned mode "extension" unavailable: no Chrome Extension connected`,
195
+ {
196
+ attemptDiagnostics: [
197
+ {
198
+ candidateKind: "extension",
199
+ inclusionReason: `pinned mode: extension`,
200
+ stage: "candidate_selection",
201
+ errorCode: "transport_error",
202
+ errorMessage: "no Chrome Extension connected",
203
+ },
204
+ ],
205
+ },
206
+ );
207
+ }
208
+ return [
209
209
  {
210
210
  kind: "extension",
211
211
  reason: "pinned mode: extension",
@@ -291,12 +291,11 @@ export function buildCandidateList(context: ToolContext): BackendCandidate[] {
291
291
  const candidates: BackendCandidate[] = [];
292
292
  const hostBrowserProxy = HostBrowserProxy.instance;
293
293
 
294
- // 1. Extension -- preferred when the singleton proxy reports an active
295
- // extension connection is available.
296
- if (hostBrowserProxy.isAvailable()) {
294
+ // 1. Extension -- preferred when a Chrome Extension client is connected.
295
+ if (hostBrowserProxy.hasExtensionClient()) {
297
296
  candidates.push({
298
297
  kind: "extension",
299
- reason: "extension connected via registry singleton",
298
+ reason: "Chrome Extension connected via registry singleton",
300
299
  create() {
301
300
  const client = createExtensionCdpClient(
302
301
  hostBrowserProxy,
@@ -314,7 +313,7 @@ export function buildCandidateList(context: ToolContext): BackendCandidate[] {
314
313
  } else {
315
314
  log.debug(
316
315
  { conversationId },
317
- "CDP factory: no active extension connection, skipping extension candidate",
316
+ "CDP factory: no Chrome Extension connected, skipping extension candidate",
318
317
  );
319
318
  }
320
319
 
@@ -1,15 +1,2 @@
1
- export {
2
- type CdpInspectClientOptions,
3
- type CdpInspectHelpers,
4
- } from "./cdp-inspect-client.js";
5
1
  export { CdpError, type CdpErrorCode } from "./errors.js";
6
- export { type GetCdpClientOptions } from "./factory.js";
7
- export type {
8
- AttemptDiagnostic,
9
- AttemptStage,
10
- BackendCandidate,
11
- BrowserMode,
12
- CdpClient,
13
- CdpClientKind,
14
- ScopedCdpClient,
15
- } from "./types.js";
2
+ export type { CdpClient, CdpClientKind, ScopedCdpClient } from "./types.js";
@@ -21,12 +21,6 @@ function proxyExecute(): Promise<ToolExecutionResult> {
21
21
  );
22
22
  }
23
23
 
24
- const activityProperty = {
25
- type: "string" as const,
26
- description:
27
- "Brief non-technical explanation of why this tool is being called",
28
- };
29
-
30
24
  // ---------------------------------------------------------------------------
31
25
  // click (unified - click_type selects single / double / right)
32
26
  // ---------------------------------------------------------------------------
@@ -69,7 +63,11 @@ export const computerUseClickTool: Tool = {
69
63
  description:
70
64
  "Explanation of what you see and why you are clicking here",
71
65
  },
72
- activity: activityProperty,
66
+ target_client_id: {
67
+ type: "string",
68
+ description:
69
+ "ID of the specific client to target. Required when multiple clients support host_cu; omit when only one is connected. Obtain IDs from `assistant clients list --capability host_cu`.",
70
+ },
73
71
  },
74
72
  required: ["reasoning"],
75
73
  },
@@ -106,7 +104,11 @@ export const computerUseTypeTextTool: Tool = {
106
104
  type: "string",
107
105
  description: "Explanation of what you are typing and why",
108
106
  },
109
- activity: activityProperty,
107
+ target_client_id: {
108
+ type: "string",
109
+ description:
110
+ "ID of the specific client to target. Required when multiple clients support host_cu; omit when only one is connected. Obtain IDs from `assistant clients list --capability host_cu`.",
111
+ },
110
112
  },
111
113
  required: ["text", "reasoning"],
112
114
  },
@@ -144,7 +146,11 @@ export const computerUseKeyTool: Tool = {
144
146
  type: "string",
145
147
  description: "Explanation of why you are pressing this key",
146
148
  },
147
- activity: activityProperty,
149
+ target_client_id: {
150
+ type: "string",
151
+ description:
152
+ "ID of the specific client to target. Required when multiple clients support host_cu; omit when only one is connected. Obtain IDs from `assistant clients list --capability host_cu`.",
153
+ },
148
154
  },
149
155
  required: ["key", "reasoning"],
150
156
  },
@@ -199,7 +205,11 @@ export const computerUseScrollTool: Tool = {
199
205
  type: "string",
200
206
  description: "Explanation of why you are scrolling",
201
207
  },
202
- activity: activityProperty,
208
+ target_client_id: {
209
+ type: "string",
210
+ description:
211
+ "ID of the specific client to target. Required when multiple clients support host_cu; omit when only one is connected. Obtain IDs from `assistant clients list --capability host_cu`.",
212
+ },
203
213
  },
204
214
  required: ["direction", "amount", "reasoning"],
205
215
  },
@@ -260,7 +270,11 @@ export const computerUseDragTool: Tool = {
260
270
  type: "string",
261
271
  description: "Explanation of what you are dragging and why",
262
272
  },
263
- activity: activityProperty,
273
+ target_client_id: {
274
+ type: "string",
275
+ description:
276
+ "ID of the specific client to target. Required when multiple clients support host_cu; omit when only one is connected. Obtain IDs from `assistant clients list --capability host_cu`.",
277
+ },
264
278
  },
265
279
  required: ["reasoning"],
266
280
  },
@@ -296,7 +310,11 @@ export const computerUseWaitTool: Tool = {
296
310
  type: "string",
297
311
  description: "Explanation of what you are waiting for",
298
312
  },
299
- activity: activityProperty,
313
+ target_client_id: {
314
+ type: "string",
315
+ description:
316
+ "ID of the specific client to target. Required when multiple clients support host_cu; omit when only one is connected. Obtain IDs from `assistant clients list --capability host_cu`.",
317
+ },
300
318
  },
301
319
  required: ["duration_ms", "reasoning"],
302
320
  },
@@ -335,7 +353,11 @@ export const computerUseOpenAppTool: Tool = {
335
353
  description:
336
354
  "Explanation of why you need to open or switch to this app",
337
355
  },
338
- activity: activityProperty,
356
+ target_client_id: {
357
+ type: "string",
358
+ description:
359
+ "ID of the specific client to target. Required when multiple clients support host_cu; omit when only one is connected. Obtain IDs from `assistant clients list --capability host_cu`.",
360
+ },
339
361
  },
340
362
  required: ["app_name", "reasoning"],
341
363
  },
@@ -373,7 +395,11 @@ export const computerUseRunAppleScriptTool: Tool = {
373
395
  description:
374
396
  "Explanation of what this script does and why AppleScript is better than UI interaction for this step",
375
397
  },
376
- activity: activityProperty,
398
+ target_client_id: {
399
+ type: "string",
400
+ description:
401
+ "ID of the specific client to target. Required when multiple clients support host_cu; omit when only one is connected. Obtain IDs from `assistant clients list --capability host_cu`.",
402
+ },
377
403
  },
378
404
  required: ["script", "reasoning"],
379
405
  },
@@ -406,7 +432,6 @@ export const computerUseDoneTool: Tool = {
406
432
  type: "string",
407
433
  description: "Human-readable summary of what was accomplished",
408
434
  },
409
- activity: activityProperty,
410
435
  },
411
436
  required: ["summary"],
412
437
  },
@@ -443,7 +468,6 @@ export const computerUseRespondTool: Tool = {
443
468
  type: "string",
444
469
  description: "Explanation of how you determined the answer",
445
470
  },
446
- activity: activityProperty,
447
471
  },
448
472
  required: ["answer", "reasoning"],
449
473
  },
@@ -471,10 +495,8 @@ const computerUseObserveTool: Tool = {
471
495
  description: this.description,
472
496
  input_schema: {
473
497
  type: "object",
474
- properties: {
475
- activity: activityProperty,
476
- },
477
- required: ["activity"],
498
+ properties: {},
499
+ required: [],
478
500
  },
479
501
  };
480
502
  },
@@ -406,6 +406,8 @@ export class ToolExecutor {
406
406
  requestId: context.requestId,
407
407
  riskLevel,
408
408
  matchedTrustRuleId: permMatchedTrustRuleId,
409
+ approvalMode: permApprovalMode,
410
+ approvalReason: permApprovalReason,
409
411
  decision,
410
412
  durationMs,
411
413
  result: safeResult,
@@ -0,0 +1,151 @@
1
+ import { mkdtempSync, realpathSync, rmSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { afterEach, describe, expect, mock, test } from "bun:test";
5
+
6
+ import type { ToolContext } from "../types.js";
7
+
8
+ // ---------------------------------------------------------------------------
9
+ // Singleton mocks — must precede the tool import so bun's module mock applies.
10
+ // ---------------------------------------------------------------------------
11
+
12
+ let mockProxyAvailable = false;
13
+
14
+ mock.module("../../daemon/host-file-proxy.js", () => ({
15
+ HostFileProxy: {
16
+ get instance() {
17
+ return {
18
+ isAvailable: () => mockProxyAvailable,
19
+ request: () => Promise.resolve({ content: "ok", isError: false }),
20
+ };
21
+ },
22
+ },
23
+ }));
24
+
25
+ mock.module("../../runtime/assistant-event-hub.js", () => ({
26
+ assistantEventHub: {
27
+ listClientsByCapability: () => [],
28
+ },
29
+ }));
30
+
31
+ const { hostFileEditTool } = await import("./edit.js");
32
+
33
+ const testDirs: string[] = [];
34
+
35
+ afterEach(() => {
36
+ mockProxyAvailable = false;
37
+ for (const dir of testDirs.splice(0)) {
38
+ rmSync(dir, { recursive: true, force: true });
39
+ }
40
+ });
41
+
42
+ function makeTempDir(): string {
43
+ const dir = realpathSync(mkdtempSync(join(tmpdir(), "host-edit-test-")));
44
+ testDirs.push(dir);
45
+ return dir;
46
+ }
47
+
48
+ function makeContext(
49
+ workingDir: string,
50
+ transportInterface: ToolContext["transportInterface"],
51
+ ): ToolContext {
52
+ return {
53
+ workingDir,
54
+ conversationId: "test-conv",
55
+ trustClass: "guardian",
56
+ transportInterface,
57
+ };
58
+ }
59
+
60
+ describe("host_file_edit cross-client guards", () => {
61
+ test("returns 'no client' error on web transport when proxy unavailable and no targetClientId", async () => {
62
+ const workingDir = makeTempDir();
63
+ const result = await hostFileEditTool.execute(
64
+ {
65
+ path: "/some/host/path.txt",
66
+ old_string: "foo",
67
+ new_string: "bar",
68
+ },
69
+ makeContext(workingDir, "web"),
70
+ );
71
+ expect(result.isError).toBe(true);
72
+ expect(result.content).toContain(
73
+ "no client with host_file capability is connected",
74
+ );
75
+ });
76
+
77
+ test("returns 'specified client disconnected' error when targetClientId set but proxy unavailable on web", async () => {
78
+ const workingDir = makeTempDir();
79
+ const result = await hostFileEditTool.execute(
80
+ {
81
+ path: "/some/host/path.txt",
82
+ old_string: "foo",
83
+ new_string: "bar",
84
+ target_client_id: "abc-123",
85
+ },
86
+ makeContext(workingDir, "web"),
87
+ );
88
+ expect(result.isError).toBe(true);
89
+ expect(result.content).toContain(
90
+ 'target client "abc-123" is no longer connected',
91
+ );
92
+ });
93
+
94
+ test("falls through to local fs on macos transport when proxy unavailable", async () => {
95
+ const workingDir = makeTempDir();
96
+ const result = await hostFileEditTool.execute(
97
+ {
98
+ path: "/nonexistent/x.txt",
99
+ old_string: "foo",
100
+ new_string: "bar",
101
+ },
102
+ makeContext(workingDir, "macos"),
103
+ );
104
+ // Proves the guard did NOT fire on macOS — instead we got the
105
+ // local FileSystemOps error path (file not found / IO error).
106
+ expect(result.isError).toBe(true);
107
+ expect(result.content.toLowerCase()).toMatch(/not found|enoent|editing/);
108
+ });
109
+
110
+ test("does NOT reject on macos transport with a stale target_client_id when proxy unavailable (regression: P2 fix)", async () => {
111
+ const workingDir = makeTempDir();
112
+ const result = await hostFileEditTool.execute(
113
+ {
114
+ path: "/nonexistent/x.txt",
115
+ old_string: "foo",
116
+ new_string: "bar",
117
+ target_client_id: "stale-mac",
118
+ },
119
+ makeContext(workingDir, "macos"),
120
+ );
121
+ // The disconnected-target guard is scoped to non-host-proxy transports
122
+ // (!supportsHostProxy). On macos, a stale target_client_id auto-filled
123
+ // from a prior cross-client turn must be silently ignored and the call
124
+ // must fall through to local FileSystemOps, NOT reject with "target
125
+ // client ... is no longer connected".
126
+ expect(result.isError).toBe(true);
127
+ expect(result.content).not.toContain("is no longer connected");
128
+ expect(result.content.toLowerCase()).toMatch(/not found|enoent|editing/);
129
+ });
130
+
131
+ test("rejects when target_client_id is set but transport metadata is missing (legacy/backwards-compat path)", async () => {
132
+ const workingDir = makeTempDir();
133
+ const result = await hostFileEditTool.execute(
134
+ {
135
+ path: "/some/host/path.txt",
136
+ old_string: "foo",
137
+ new_string: "bar",
138
+ target_client_id: "abc-123",
139
+ },
140
+ // transportInterface intentionally undefined (legacy callers).
141
+ makeContext(workingDir, undefined),
142
+ );
143
+ // Without transport metadata, falling through to local fs would
144
+ // silently target the daemon container. The guard fires for undefined
145
+ // transport AND non-host-proxy transports — only macos turns skip it.
146
+ expect(result.isError).toBe(true);
147
+ expect(result.content).toContain(
148
+ 'target client "abc-123" is no longer connected',
149
+ );
150
+ });
151
+ });
@@ -1,6 +1,8 @@
1
+ import { supportsHostProxy } from "../../channels/types.js";
1
2
  import { HostFileProxy } from "../../daemon/host-file-proxy.js";
2
3
  import { RiskLevel } from "../../permissions/types.js";
3
4
  import type { ToolDefinition } from "../../providers/types.js";
5
+ import { assistantEventHub } from "../../runtime/assistant-event-hub.js";
4
6
  import { FileSystemOps } from "../shared/filesystem/file-ops-service.js";
5
7
  import { formatEditDiff } from "../shared/filesystem/format-diff.js";
6
8
  import { hostPolicy } from "../shared/filesystem/path-policy.js";
@@ -37,6 +39,11 @@ class HostFileEditTool implements Tool {
37
39
  description:
38
40
  "Replace all occurrences instead of requiring a unique match (default: false)",
39
41
  },
42
+ target_client_id: {
43
+ type: "string",
44
+ description:
45
+ "ID of the specific client to execute this on. Required when multiple clients support host_file; omit when only one is connected. Obtain IDs from `assistant clients list --capability host_file`.",
46
+ },
40
47
  },
41
48
  required: ["path", "old_string", "new_string"],
42
49
  },
@@ -84,6 +91,64 @@ class HostFileEditTool implements Tool {
84
91
 
85
92
  const replaceAll = input.replace_all === true;
86
93
 
94
+ const targetClientId =
95
+ typeof input.target_client_id === "string" &&
96
+ input.target_client_id !== ""
97
+ ? input.target_client_id
98
+ : undefined;
99
+
100
+ const transportInterface = context.transportInterface;
101
+ if (
102
+ targetClientId == null &&
103
+ transportInterface != null &&
104
+ !supportsHostProxy(transportInterface) &&
105
+ assistantEventHub.listClientsByCapability("host_file").length > 1
106
+ ) {
107
+ return {
108
+ content: `Error: multiple clients support host_file. Specify which client to use with \`target_client_id\`. Run \`assistant clients list --capability host_file\` to see client IDs and labels.`,
109
+ isError: true,
110
+ };
111
+ }
112
+
113
+ // Guard: non-host-proxy interfaces with no capable clients connected.
114
+ // Without this guard, the request would fall through to local
115
+ // FileSystemOps below and read the daemon container's filesystem
116
+ // instead of the user's host machine.
117
+ if (
118
+ targetClientId == null &&
119
+ transportInterface != null &&
120
+ !supportsHostProxy(transportInterface) &&
121
+ !HostFileProxy.instance.isAvailable()
122
+ ) {
123
+ return {
124
+ content:
125
+ "Error: no client with host_file capability is connected. Connect a macOS client to use host_file from a non-desktop interface.",
126
+ isError: true,
127
+ };
128
+ }
129
+
130
+ // Guard: explicit targetClientId provided but proxy is unavailable.
131
+ // Fires on non-host-proxy transports (web, ios) AND on legacy callers
132
+ // without transport metadata, where falling through to local fs would
133
+ // silently target the daemon container's filesystem instead of the
134
+ // intended host client. Skips only when transport is explicitly
135
+ // host-proxy-capable (macos), where local-fs fallback IS the intended
136
+ // offline behavior — a stale target_client_id auto-filled from a prior
137
+ // cross-client turn is silently ignored on those turns.
138
+ // Note: this scoping deliberately differs from host_bash
139
+ // (host-shell.ts:239-247), which rejects unconditionally for any
140
+ // stale target_client_id regardless of transport.
141
+ if (
142
+ targetClientId != null &&
143
+ !HostFileProxy.instance.isAvailable() &&
144
+ (transportInterface == null || !supportsHostProxy(transportInterface))
145
+ ) {
146
+ return {
147
+ content: `Error: target client "${targetClientId}" is no longer connected. The specified client may have disconnected since the tool was called. Run \`assistant clients list --capability host_file\` to see currently connected clients.`,
148
+ isError: true,
149
+ };
150
+ }
151
+
87
152
  // Proxy to connected client for execution on the user's machine
88
153
  // when a capable client is available (managed/cloud-hosted mode).
89
154
  if (HostFileProxy.instance.isAvailable()) {
@@ -94,9 +159,12 @@ class HostFileEditTool implements Tool {
94
159
  old_string: oldString as string,
95
160
  new_string: newString as string,
96
161
  replace_all: replaceAll,
162
+ targetClientId,
97
163
  },
98
164
  context.conversationId,
99
165
  context.signal,
166
+ targetClientId,
167
+ context.sourceActorPrincipalId,
100
168
  );
101
169
  }
102
170