@vellumai/assistant 0.7.0 → 0.7.1

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 (666) hide show
  1. package/ARCHITECTURE.md +6 -7
  2. package/Dockerfile +1 -0
  3. package/README.md +2 -2
  4. package/__tests__/permissions/gateway-threshold-reader.test.ts +79 -139
  5. package/bun.lock +3 -0
  6. package/docs/architecture/security.md +18 -16
  7. package/knip.json +1 -0
  8. package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +1 -5
  9. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -5
  10. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -16
  11. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +1 -9
  12. package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +12 -12
  13. package/node_modules/@vellumai/slack-text/bun.lock +24 -0
  14. package/node_modules/@vellumai/slack-text/package.json +18 -0
  15. package/node_modules/@vellumai/slack-text/src/index.test.ts +153 -0
  16. package/node_modules/@vellumai/slack-text/src/index.ts +235 -0
  17. package/node_modules/@vellumai/slack-text/tsconfig.json +20 -0
  18. package/openapi.yaml +294 -107
  19. package/package.json +4 -2
  20. package/scripts/generate-openapi.ts +16 -111
  21. package/src/__tests__/agent-wake-override-profile.test.ts +23 -1
  22. package/src/__tests__/anthropic-provider.test.ts +56 -13
  23. package/src/__tests__/app-conversation-ids-backfill.test.ts +278 -0
  24. package/src/__tests__/app-conversation-ids.test.ts +151 -0
  25. package/src/__tests__/approval-cascade.test.ts +0 -15
  26. package/src/__tests__/approval-routes-http.test.ts +6 -17
  27. package/src/__tests__/assistant-event-hub.test.ts +126 -77
  28. package/src/__tests__/assistant-event.test.ts +0 -5
  29. package/src/__tests__/assistant-events-sse-hardening.test.ts +37 -15
  30. package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -29
  31. package/src/__tests__/background-shell-host-bash.test.ts +34 -43
  32. package/src/__tests__/call-controller.test.ts +1 -1
  33. package/src/__tests__/call-site-routing-provider.test.ts +193 -0
  34. package/src/__tests__/channel-approval-routes.test.ts +10 -296
  35. package/src/__tests__/channel-approvals.test.ts +25 -17
  36. package/src/__tests__/channel-guardian.test.ts +100 -146
  37. package/src/__tests__/checker.test.ts +20 -34
  38. package/src/__tests__/compact-event-conversation-id-guard.test.ts +50 -0
  39. package/src/__tests__/compaction-events.test.ts +2 -0
  40. package/src/__tests__/config-schema.test.ts +6 -48
  41. package/src/__tests__/config-watcher.test.ts +12 -0
  42. package/src/__tests__/connection-policy.test.ts +1 -52
  43. package/src/__tests__/contacts-write.test.ts +2 -64
  44. package/src/__tests__/context-image-dimensions.test.ts +1 -1
  45. package/src/__tests__/context-search-memory-source.test.ts +120 -1
  46. package/src/__tests__/context-search-memory-v2-source.test.ts +383 -0
  47. package/src/__tests__/context-search-pkb-source.test.ts +49 -0
  48. package/src/__tests__/context-search-workspace-source.test.ts +9 -22
  49. package/src/__tests__/context-window-manager.test.ts +46 -0
  50. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
  51. package/src/__tests__/conversation-agent-loop-overflow.test.ts +102 -29
  52. package/src/__tests__/conversation-agent-loop.test.ts +980 -13
  53. package/src/__tests__/conversation-analysis-routes.test.ts +12 -10
  54. package/src/__tests__/conversation-attention-telegram.test.ts +11 -3
  55. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -291
  56. package/src/__tests__/conversation-history-web-search.test.ts +4 -3
  57. package/src/__tests__/conversation-inference-profile-route.test.ts +12 -23
  58. package/src/__tests__/conversation-lifecycle.test.ts +4 -4
  59. package/src/__tests__/conversation-process-callsite.test.ts +79 -2
  60. package/src/__tests__/conversation-queue.test.ts +3 -8
  61. package/src/__tests__/conversation-routes-disk-view.test.ts +1 -161
  62. package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -32
  63. package/src/__tests__/conversation-routes-slash-commands.test.ts +75 -66
  64. package/src/__tests__/conversation-runtime-assembly.test.ts +257 -3
  65. package/src/__tests__/conversation-slash-commands.test.ts +24 -4
  66. package/src/__tests__/conversation-slash-queue.test.ts +2 -0
  67. package/src/__tests__/conversation-speed-override.test.ts +0 -3
  68. package/src/__tests__/conversation-starter-routes.test.ts +79 -2
  69. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -5
  70. package/src/__tests__/conversation-surfaces-standalone.test.ts +18 -14
  71. package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -2
  72. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +8 -46
  73. package/src/__tests__/conversation-usage.test.ts +253 -3
  74. package/src/__tests__/credential-execution-shell-lockdown.test.ts +0 -39
  75. package/src/__tests__/credential-health-service.test.ts +68 -0
  76. package/src/__tests__/credential-security-e2e.test.ts +4 -3
  77. package/src/__tests__/credential-security-invariants.test.ts +1 -5
  78. package/src/__tests__/credential-token-resolver.test.ts +180 -0
  79. package/src/__tests__/cu-unified-flow.test.ts +33 -16
  80. package/src/__tests__/daemon-assistant-events.test.ts +34 -21
  81. package/src/__tests__/daemon-credential-client.test.ts +4 -1
  82. package/src/__tests__/db-connection-isolation.test.ts +125 -0
  83. package/src/__tests__/db-migration-rollback.test.ts +101 -0
  84. package/src/__tests__/db-slack-compaction-watermark-migration.test.ts +169 -0
  85. package/src/__tests__/deterministic-verification-control-plane.test.ts +7 -80
  86. package/src/__tests__/document-conversations.test.ts +332 -0
  87. package/src/__tests__/embedding-managed-proxy-selection.test.ts +2 -2
  88. package/src/__tests__/emit-event-signal.test.ts +4 -6
  89. package/src/__tests__/events-client-registration.test.ts +193 -49
  90. package/src/__tests__/filing-service.test.ts +58 -7
  91. package/src/__tests__/first-greeting.test.ts +156 -150
  92. package/src/__tests__/fixtures/mock-chrome-extension.ts +108 -66
  93. package/src/__tests__/get-skill-detail-audit.test.ts +3 -8
  94. package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
  95. package/src/__tests__/guardian-dispatch.test.ts +1 -1
  96. package/src/__tests__/guardian-grant-minting.test.ts +7 -2
  97. package/src/__tests__/guardian-routing-invariants.test.ts +7 -2
  98. package/src/__tests__/guardian-routing-state.test.ts +1 -1
  99. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +32 -11
  100. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -83
  101. package/src/__tests__/headless-browser-mode.test.ts +4 -9
  102. package/src/__tests__/headless-browser-navigate.test.ts +21 -20
  103. package/src/__tests__/heartbeat-service.test.ts +289 -7
  104. package/src/__tests__/helpers/channel-test-adapter.ts +2 -2
  105. package/src/__tests__/helpers/create-guardian-binding.ts +91 -0
  106. package/src/__tests__/host-bash-proxy.test.ts +46 -122
  107. package/src/__tests__/host-browser-e2e-cloud.test.ts +36 -497
  108. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +26 -96
  109. package/src/__tests__/host-browser-proxy.test.ts +111 -185
  110. package/src/__tests__/host-browser-routes.test.ts +45 -75
  111. package/src/__tests__/host-browser-ws-events-e2e.test.ts +26 -30
  112. package/src/__tests__/host-cu-proxy.test.ts +56 -111
  113. package/src/__tests__/host-file-proxy.test.ts +44 -98
  114. package/src/__tests__/host-file-read-tool.test.ts +42 -21
  115. package/src/__tests__/host-shell-tool.test.ts +33 -68
  116. package/src/__tests__/host-transfer-pending-interactions.test.ts +2 -18
  117. package/src/__tests__/host-transfer-proxy.test.ts +43 -53
  118. package/src/__tests__/http-user-message-parity.test.ts +0 -6
  119. package/src/__tests__/inbound-slack-persistence.test.ts +31 -0
  120. package/src/__tests__/injector-chain.test.ts +10 -5
  121. package/src/__tests__/injector-pkb-v2-silenced.test.ts +124 -0
  122. package/src/__tests__/inline-command-runner.test.ts +0 -66
  123. package/src/__tests__/inline-skill-load-permissions.test.ts +0 -2
  124. package/src/__tests__/install-skill-routing.test.ts +1 -13
  125. package/src/__tests__/llm-callsite-catalog.test.ts +34 -0
  126. package/src/__tests__/llm-catalog-parity.test.ts +90 -0
  127. package/src/__tests__/llm-context-resolution.test.ts +180 -0
  128. package/src/__tests__/llm-resolver.test.ts +80 -12
  129. package/src/__tests__/llm-usage-store.test.ts +269 -4
  130. package/src/__tests__/log-export-routes.test.ts +89 -0
  131. package/src/__tests__/managed-profile-guard.test.ts +225 -0
  132. package/src/__tests__/managed-skill-lifecycle.test.ts +0 -10
  133. package/src/__tests__/manual-token-reconciliation.test.ts +334 -0
  134. package/src/__tests__/memory-v2-static-injector.test.ts +95 -0
  135. package/src/__tests__/migration-cross-version-compatibility.test.ts +197 -291
  136. package/src/__tests__/migration-export-http.test.ts +33 -26
  137. package/src/__tests__/migration-export-streaming.test.ts +18 -10
  138. package/src/__tests__/migration-export-to-gcs.test.ts +49 -9
  139. package/src/__tests__/migration-import-commit-http.test.ts +66 -21
  140. package/src/__tests__/migration-import-from-gcs.test.ts +50 -9
  141. package/src/__tests__/migration-import-from-url.test.ts +20 -6
  142. package/src/__tests__/migration-import-preflight-http.test.ts +95 -95
  143. package/src/__tests__/migration-parity-persistence.test.ts +62 -25
  144. package/src/__tests__/migration-transport.test.ts +115 -23
  145. package/src/__tests__/migration-validate-http.test.ts +105 -80
  146. package/src/__tests__/migration-wizard.test.ts +133 -27
  147. package/src/__tests__/non-member-access-request.test.ts +1 -1
  148. package/src/__tests__/notification-guardian-path.test.ts +1 -1
  149. package/src/__tests__/oauth-store.test.ts +19 -0
  150. package/src/__tests__/platform-bash-auto-approve.test.ts +21 -12
  151. package/src/__tests__/prechat-onboarding-contract.test.ts +31 -7
  152. package/src/__tests__/pricing.test.ts +68 -4
  153. package/src/__tests__/process-message-background-slack.test.ts +331 -0
  154. package/src/__tests__/provider-managed-proxy-integration.test.ts +153 -17
  155. package/src/__tests__/provider-send-message-override-profile.test.ts +50 -0
  156. package/src/__tests__/provider-usage-tracking.test.ts +208 -0
  157. package/src/__tests__/reaction-persistence.test.ts +9 -6
  158. package/src/__tests__/rebind-secrets-screen.test.ts +53 -16
  159. package/src/__tests__/recording-handler.test.ts +64 -81
  160. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +4 -3
  161. package/src/__tests__/relay-server.test.ts +18 -13
  162. package/src/__tests__/require-fresh-approval.test.ts +13 -22
  163. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
  164. package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
  165. package/src/__tests__/runtime-events-sse.test.ts +3 -12
  166. package/src/__tests__/search-skills-unified.test.ts +9 -15
  167. package/src/__tests__/secret-ingress-cli.test.ts +2 -5
  168. package/src/__tests__/secret-ingress-http.test.ts +0 -4
  169. package/src/__tests__/secret-onetime-send.test.ts +4 -2
  170. package/src/__tests__/secret-prompt-log-hygiene.test.ts +24 -7
  171. package/src/__tests__/secret-prompter-channel-fallback.test.ts +42 -47
  172. package/src/__tests__/secret-response-routing.test.ts +29 -15
  173. package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -1
  174. package/src/__tests__/secret-scanner.test.ts +2 -545
  175. package/src/__tests__/send-endpoint-busy.test.ts +9 -24
  176. package/src/__tests__/settings-routes.test.ts +1 -1
  177. package/src/__tests__/shell-credential-ref.test.ts +0 -8
  178. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -56
  179. package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -11
  180. package/src/__tests__/skill-tool-factory.test.ts +97 -0
  181. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -30
  182. package/src/__tests__/skills-files-catalog-fallback.test.ts +11 -17
  183. package/src/__tests__/slack-inbound-verification.test.ts +1 -62
  184. package/src/__tests__/subagent-fork-notifications.test.ts +57 -47
  185. package/src/__tests__/subagent-manager-notify.test.ts +70 -70
  186. package/src/__tests__/subagent-notify-parent.test.ts +80 -83
  187. package/src/__tests__/system-prompt.test.ts +115 -13
  188. package/src/__tests__/terminal-tools.test.ts +0 -89
  189. package/src/__tests__/thread-backfill.test.ts +945 -31
  190. package/src/__tests__/tool-domain-event-publisher.test.ts +0 -36
  191. package/src/__tests__/tool-execute-pipeline.test.ts +0 -6
  192. package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -16
  193. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +9 -19
  194. package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -7
  195. package/src/__tests__/tool-executor.test.ts +12 -19
  196. package/src/__tests__/tool-metrics-listener.test.ts +0 -35
  197. package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
  198. package/src/__tests__/tool-trace-listener.test.ts +0 -17
  199. package/src/__tests__/transfer-progress-screen.test.ts +63 -26
  200. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -149
  201. package/src/__tests__/trusted-contact-multichannel.test.ts +2 -4
  202. package/src/__tests__/trusted-contact-verification.test.ts +1 -1
  203. package/src/__tests__/tts-catalog-parity.test.ts +16 -5
  204. package/src/__tests__/usage-attribution.test.ts +247 -0
  205. package/src/__tests__/usage-cli.test.ts +143 -0
  206. package/src/__tests__/usage-grouped-buckets.test.ts +155 -0
  207. package/src/__tests__/usage-routes.test.ts +150 -0
  208. package/src/__tests__/validation-results-screen.test.ts +39 -16
  209. package/src/__tests__/vbundle-pax-and-symlink.test.ts +12 -3
  210. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +49 -137
  211. package/src/__tests__/verification-control-plane-policy.test.ts +4 -7
  212. package/src/__tests__/voice-session-bridge.test.ts +5 -5
  213. package/src/__tests__/workspace-migration-062-drop-memory-v2-edges-json.test.ts +103 -0
  214. package/src/__tests__/workspace-migration-063-release-notes-dynamic-model-context.test.ts +77 -0
  215. package/src/__tests__/workspace-migration-064-unwind-main-agent-opus-seed.test.ts +225 -0
  216. package/src/__tests__/workspace-migration-memory-v2-init.test.ts +8 -30
  217. package/src/acp/index.ts +0 -15
  218. package/src/acp/session-manager.ts +37 -34
  219. package/src/agent/loop.ts +16 -1
  220. package/src/approvals/AGENTS.md +4 -0
  221. package/src/approvals/__tests__/guardian-feed-event.test.ts +10 -3
  222. package/src/approvals/guardian-request-resolvers.ts +10 -2
  223. package/src/backup/__tests__/backup-worker.test.ts +36 -8
  224. package/src/backup/__tests__/paths.test.ts +2 -2
  225. package/src/backup/__tests__/restore.test.ts +45 -28
  226. package/src/backup/backup-worker.ts +36 -2
  227. package/src/backup/paths.ts +9 -6
  228. package/src/browser-session/events.ts +0 -9
  229. package/src/calls/call-store.ts +1 -34
  230. package/src/calls/guardian-question-copy.ts +0 -108
  231. package/src/calls/relay-server.ts +0 -24
  232. package/src/calls/twilio-rest.ts +0 -38
  233. package/src/calls/twilio-routes.ts +1 -1
  234. package/src/calls/voice-session-bridge.ts +7 -38
  235. package/src/channels/types.ts +1 -36
  236. package/src/cli/commands/__tests__/cache.test.ts +152 -5
  237. package/src/cli/commands/__tests__/memory-v2.test.ts +14 -28
  238. package/src/cli/commands/__tests__/trust.test.ts +21 -387
  239. package/src/cli/commands/backup.ts +4 -4
  240. package/src/cli/commands/cache-fs.ts +8 -0
  241. package/src/cli/commands/cache.ts +153 -82
  242. package/src/cli/commands/clients.ts +63 -5
  243. package/src/cli/commands/completions.ts +3 -3
  244. package/src/cli/commands/contacts.ts +231 -76
  245. package/src/cli/commands/keys.ts +4 -1
  246. package/src/cli/commands/memory-v2.ts +24 -52
  247. package/src/cli/commands/oauth/shared.ts +2 -29
  248. package/src/cli/commands/pending.ts +102 -0
  249. package/src/cli/commands/skills.ts +77 -35
  250. package/src/cli/commands/trust.ts +70 -430
  251. package/src/cli/commands/usage.ts +25 -16
  252. package/src/cli/lib/daemon-credential-client.ts +14 -0
  253. package/src/cli/program.ts +2 -0
  254. package/src/cli.ts +0 -21
  255. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  256. package/src/config/bundled-skills/messaging/TOOLS.json +14 -4
  257. package/src/config/env-registry.ts +12 -2
  258. package/src/config/env.ts +3 -14
  259. package/src/config/feature-flag-registry.json +30 -30
  260. package/src/config/llm-callsite-catalog.ts +12 -0
  261. package/src/config/llm-context-resolution.ts +80 -0
  262. package/src/config/llm-resolver.ts +58 -22
  263. package/src/config/loader.ts +3 -3
  264. package/src/config/schema.ts +2 -158
  265. package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
  266. package/src/config/schemas/call-site-catalog.ts +271 -0
  267. package/src/config/schemas/calls.ts +5 -5
  268. package/src/config/schemas/inference.ts +1 -1
  269. package/src/config/schemas/ingress.ts +1 -1
  270. package/src/config/schemas/llm.ts +31 -3
  271. package/src/config/schemas/memory-retrieval.ts +2 -2
  272. package/src/config/schemas/memory-v2.ts +9 -0
  273. package/src/config/schemas/security.ts +1 -42
  274. package/src/config/schemas/services.ts +6 -6
  275. package/src/config/schemas/skills.ts +5 -5
  276. package/src/config/schemas/tts.ts +1 -1
  277. package/src/config/seed-inference-profiles.ts +117 -0
  278. package/src/config/skills.ts +0 -90
  279. package/src/config/types.ts +3 -6
  280. package/src/contacts/contact-store.ts +0 -17
  281. package/src/contacts/contacts-write.ts +1 -105
  282. package/src/context/window-manager.ts +44 -5
  283. package/src/credential-execution/process-manager.ts +34 -10
  284. package/src/credential-health/credential-health-service.ts +21 -16
  285. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +75 -82
  286. package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -9
  287. package/src/daemon/connection-policy.ts +1 -26
  288. package/src/daemon/conversation-agent-loop-handlers.ts +53 -4
  289. package/src/daemon/conversation-agent-loop.ts +277 -36
  290. package/src/daemon/conversation-history.ts +8 -8
  291. package/src/daemon/conversation-launch.ts +20 -135
  292. package/src/daemon/conversation-lifecycle.ts +1 -1
  293. package/src/daemon/conversation-messaging.ts +1 -0
  294. package/src/daemon/conversation-process.ts +83 -163
  295. package/src/daemon/conversation-runtime-assembly.ts +219 -76
  296. package/src/daemon/conversation-slash.ts +47 -5
  297. package/src/daemon/conversation-store.ts +7 -31
  298. package/src/daemon/conversation-surfaces.ts +22 -28
  299. package/src/daemon/conversation-tool-setup.ts +3 -33
  300. package/src/daemon/conversation-usage.ts +36 -0
  301. package/src/daemon/conversation.ts +117 -233
  302. package/src/daemon/daemon-control.ts +3 -71
  303. package/src/daemon/daemon-skill-host.ts +8 -11
  304. package/src/daemon/dictation-profile-store.ts +2 -26
  305. package/src/daemon/first-greeting.ts +44 -156
  306. package/src/daemon/handlers/config-channels.ts +12 -12
  307. package/src/daemon/handlers/config-ingress.ts +4 -165
  308. package/src/daemon/handlers/config-model.ts +1 -1
  309. package/src/daemon/handlers/config-voice.ts +0 -42
  310. package/src/daemon/handlers/conversations.ts +11 -190
  311. package/src/daemon/handlers/recording.ts +26 -158
  312. package/src/daemon/handlers/shared.ts +23 -71
  313. package/src/daemon/handlers/skills.ts +42 -93
  314. package/src/daemon/host-bash-proxy.ts +67 -45
  315. package/src/daemon/host-browser-proxy.ts +65 -27
  316. package/src/daemon/host-cu-proxy.ts +40 -39
  317. package/src/daemon/host-file-proxy.ts +58 -37
  318. package/src/daemon/host-transfer-proxy.ts +84 -46
  319. package/src/daemon/lifecycle.ts +49 -15
  320. package/src/daemon/message-types/conversations.ts +7 -0
  321. package/src/daemon/message-types/host-bash.ts +1 -0
  322. package/src/daemon/message-types/host-cu.ts +1 -0
  323. package/src/daemon/message-types/host-file.ts +1 -0
  324. package/src/daemon/message-types/host-transfer.ts +1 -0
  325. package/src/daemon/message-types/messages.ts +10 -9
  326. package/src/daemon/message-types/workspace.ts +1 -1
  327. package/src/daemon/process-message.ts +102 -239
  328. package/src/daemon/server.ts +13 -462
  329. package/src/daemon/shutdown-handlers.ts +2 -2
  330. package/src/daemon/tool-side-effects.ts +125 -107
  331. package/src/daemon/trust-context.ts +13 -0
  332. package/src/daemon/wake-target-adapter.ts +4 -9
  333. package/src/events/domain-events.ts +0 -8
  334. package/src/events/tool-audit-listener.ts +3 -1
  335. package/src/events/tool-domain-event-publisher.ts +0 -10
  336. package/src/events/tool-metrics-listener.ts +0 -17
  337. package/src/events/tool-trace-listener.ts +0 -14
  338. package/src/filing/filing-service.ts +13 -1
  339. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +6 -2
  340. package/src/heartbeat/heartbeat-service.ts +23 -5
  341. package/src/home/__tests__/feed-writer.test.ts +0 -4
  342. package/src/home/__tests__/relationship-state-writer.test.ts +30 -0
  343. package/src/home/feed-writer.ts +1 -2
  344. package/src/home/relationship-state-writer.ts +16 -3
  345. package/src/ipc/__tests__/browser-ipc.test.ts +2 -12
  346. package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -1
  347. package/src/ipc/assistant-server.ts +3 -10
  348. package/src/ipc/routes/__tests__/memory-v2-backfill.test.ts +39 -20
  349. package/src/ipc/routes/route-adapter.ts +1 -1
  350. package/src/ipc/routes/trust-rules.test.ts +0 -95
  351. package/src/ipc/skill-ipc-types.ts +41 -0
  352. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +13 -27
  353. package/src/ipc/skill-routes/__tests__/identity.test.ts +4 -23
  354. package/src/ipc/skill-routes/events.ts +12 -23
  355. package/src/ipc/skill-routes/identity.ts +4 -17
  356. package/src/ipc/skill-routes/index.ts +1 -1
  357. package/src/ipc/skill-server.ts +6 -39
  358. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -8
  359. package/src/live-voice/protocol.ts +4 -13
  360. package/src/mcp/manager.ts +0 -5
  361. package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +55 -0
  362. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +127 -0
  363. package/src/memory/app-git-service.ts +0 -32
  364. package/src/memory/app-store.ts +154 -0
  365. package/src/memory/attachments-store.ts +6 -0
  366. package/src/memory/context-search/sources/memory-v2.ts +578 -0
  367. package/src/memory/context-search/sources/memory.ts +5 -0
  368. package/src/memory/context-search/sources/pkb.ts +10 -1
  369. package/src/memory/context-search/sources/workspace.ts +3 -2
  370. package/src/memory/conversation-crud.ts +29 -4
  371. package/src/memory/conversation-disk-view.ts +1 -5
  372. package/src/memory/conversation-starter-checkpoints.ts +63 -0
  373. package/src/memory/db-connection.ts +62 -0
  374. package/src/memory/db-init.ts +14 -0
  375. package/src/memory/embedding-backend.ts +3 -21
  376. package/src/memory/embedding-gemini.ts +0 -2
  377. package/src/memory/embedding-local.ts +6 -6
  378. package/src/memory/embedding-ollama.ts +6 -6
  379. package/src/memory/embedding-openai.ts +6 -6
  380. package/src/memory/embedding-types.ts +21 -0
  381. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +3 -7
  382. package/src/memory/graph/conversation-graph-memory.ts +35 -13
  383. package/src/memory/graph/injection.test.ts +2 -2
  384. package/src/memory/graph/injection.ts +1 -1
  385. package/src/memory/guardian-action-store.ts +0 -83
  386. package/src/memory/guardian-approvals.ts +0 -48
  387. package/src/memory/indexer.ts +1 -15
  388. package/src/memory/job-handlers/conversation-starters.ts +36 -53
  389. package/src/memory/job-utils.ts +0 -6
  390. package/src/memory/jobs-store.ts +0 -1
  391. package/src/memory/jobs-worker.ts +2 -16
  392. package/src/memory/llm-request-log-store.ts +0 -41
  393. package/src/memory/llm-usage-store.ts +129 -43
  394. package/src/memory/memory-v2-activation-log-store.ts +115 -0
  395. package/src/memory/migrations/233-document-conversations.ts +54 -0
  396. package/src/memory/migrations/234-memory-v2-activation-logs.ts +55 -0
  397. package/src/memory/migrations/235-llm-usage-attribution.ts +31 -0
  398. package/src/memory/migrations/235-slack-compaction-watermark.ts +44 -0
  399. package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +26 -0
  400. package/src/memory/migrations/__tests__/234-memory-v2-activation-logs.test.ts +182 -0
  401. package/src/memory/migrations/index.ts +14 -0
  402. package/src/memory/migrations/registry.ts +24 -0
  403. package/src/memory/raw-query.ts +2 -68
  404. package/src/memory/schema/conversations.ts +7 -0
  405. package/src/memory/schema/infrastructure.ts +25 -0
  406. package/src/memory/search/semantic.ts +5 -16
  407. package/src/memory/tool-usage-store.ts +2 -0
  408. package/src/memory/usage-buckets.ts +40 -1
  409. package/src/memory/usage-grouped-buckets.ts +127 -0
  410. package/src/memory/v2/__tests__/activation.test.ts +289 -90
  411. package/src/memory/v2/__tests__/backfill-jobs.test.ts +2 -129
  412. package/src/memory/v2/__tests__/consolidation-job.test.ts +28 -11
  413. package/src/memory/v2/__tests__/edge-index.test.ts +278 -0
  414. package/src/memory/v2/__tests__/injection.test.ts +384 -15
  415. package/src/memory/v2/__tests__/migration.test.ts +64 -36
  416. package/src/memory/v2/__tests__/page-store.test.ts +191 -8
  417. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +181 -0
  418. package/src/memory/v2/__tests__/skill-store.test.ts +115 -3
  419. package/src/memory/v2/__tests__/static-context.test.ts +153 -0
  420. package/src/memory/v2/activation.ts +168 -97
  421. package/src/memory/v2/backfill-jobs.ts +15 -100
  422. package/src/memory/v2/consolidation-job.ts +14 -12
  423. package/src/memory/v2/edge-index.ts +191 -0
  424. package/src/memory/v2/injection.ts +182 -58
  425. package/src/memory/v2/migration.ts +57 -64
  426. package/src/memory/v2/now-text.ts +2 -3
  427. package/src/memory/v2/page-store.ts +168 -31
  428. package/src/memory/v2/prompts/consolidation.ts +118 -42
  429. package/src/memory/v2/prompts/sweep.ts +3 -3
  430. package/src/memory/v2/skill-store.ts +55 -7
  431. package/src/memory/v2/static-context.ts +62 -0
  432. package/src/memory/v2/types.ts +10 -20
  433. package/src/memory/validation.ts +0 -11
  434. package/src/messaging/draft-store.ts +0 -6
  435. package/src/messaging/provider-types.ts +8 -0
  436. package/src/messaging/provider.ts +7 -0
  437. package/src/messaging/providers/gmail/client.ts +1 -121
  438. package/src/messaging/providers/outlook/client.ts +0 -73
  439. package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +226 -0
  440. package/src/messaging/providers/slack/adapter.ts +122 -21
  441. package/src/messaging/providers/slack/backfill.test.ts +95 -6
  442. package/src/messaging/providers/slack/backfill.ts +89 -11
  443. package/src/messaging/providers/slack/client.ts +10 -124
  444. package/src/messaging/providers/slack/message-metadata.ts +12 -2
  445. package/src/messaging/providers/slack/render-transcript.test.ts +56 -0
  446. package/src/messaging/providers/slack/render-transcript.ts +126 -25
  447. package/src/messaging/providers/slack/types.ts +1 -0
  448. package/src/oauth/connection-resolver.test.ts +8 -0
  449. package/src/oauth/connection-resolver.ts +8 -16
  450. package/src/oauth/credential-token-resolver.ts +97 -0
  451. package/src/oauth/manual-token-connection.ts +30 -34
  452. package/src/oauth/oauth-store.ts +6 -4
  453. package/src/outbound-proxy/certs.ts +0 -7
  454. package/src/outbound-proxy/config.ts +0 -74
  455. package/src/outbound-proxy/health.ts +0 -44
  456. package/src/outbound-proxy/index.ts +0 -22
  457. package/src/permissions/approval-provenance.test.ts +184 -0
  458. package/src/permissions/approval-provenance.ts +70 -0
  459. package/src/permissions/checker.ts +4 -1
  460. package/src/permissions/gateway-threshold-reader.ts +4 -1
  461. package/src/permissions/prompter.ts +9 -2
  462. package/src/permissions/secret-prompter.ts +21 -48
  463. package/src/permissions/types.ts +33 -0
  464. package/src/permissions/workspace-policy.ts +0 -5
  465. package/src/platform/sync-identity.ts +0 -8
  466. package/src/plugins/defaults/injectors.ts +69 -2
  467. package/src/plugins/defaults/overflow-reduce.ts +3 -2
  468. package/src/plugins/types.ts +8 -0
  469. package/src/prompts/system-prompt.ts +34 -70
  470. package/src/prompts/templates/BOOTSTRAP.md +52 -6
  471. package/src/prompts/update-bulletin-job.ts +2 -0
  472. package/src/providers/__tests__/retry-callsite.test.ts +138 -1
  473. package/src/providers/anthropic/client.ts +72 -33
  474. package/src/providers/call-site-routing.ts +42 -3
  475. package/src/providers/gemini/client.ts +18 -2
  476. package/src/providers/managed-proxy/context.ts +0 -5
  477. package/src/providers/model-catalog.ts +105 -19
  478. package/src/providers/openai/chat-completions-provider.ts +6 -0
  479. package/src/providers/openai/responses-provider.ts +7 -1
  480. package/src/providers/provider-send-message.ts +45 -2
  481. package/src/providers/ratelimit.ts +7 -2
  482. package/src/providers/registry.ts +14 -9
  483. package/src/providers/retry.ts +96 -8
  484. package/src/providers/types.ts +13 -0
  485. package/src/providers/usage-tracking.ts +96 -0
  486. package/src/runtime/AGENTS.md +10 -6
  487. package/src/runtime/__tests__/agent-wake.test.ts +89 -0
  488. package/src/runtime/agent-wake.ts +39 -2
  489. package/src/runtime/assistant-event-hub.ts +541 -45
  490. package/src/runtime/assistant-event.ts +1 -6
  491. package/src/runtime/auth/context.ts +0 -9
  492. package/src/runtime/auth/middleware.ts +1 -1
  493. package/src/runtime/auth/route-policy.ts +11 -9
  494. package/src/runtime/auth/token-service.ts +0 -11
  495. package/src/runtime/channel-approvals.ts +6 -2
  496. package/src/runtime/channel-verification-service.ts +3 -5
  497. package/src/runtime/http-errors.ts +0 -34
  498. package/src/runtime/http-router.ts +6 -3
  499. package/src/runtime/http-server.ts +22 -82
  500. package/src/runtime/http-types.ts +5 -0
  501. package/src/runtime/interactive-ui.ts +0 -1
  502. package/src/runtime/middleware/auth.ts +0 -20
  503. package/src/runtime/migrations/__tests__/v1-test-helpers.ts +112 -0
  504. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +11 -4
  505. package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +253 -0
  506. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +19 -6
  507. package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +71 -27
  508. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +41 -2
  509. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +143 -79
  510. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +143 -23
  511. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +2 -2
  512. package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +371 -0
  513. package/src/runtime/migrations/migration-transport.ts +46 -13
  514. package/src/runtime/migrations/migration-wizard.ts +2 -2
  515. package/src/runtime/migrations/origin-mode.ts +40 -0
  516. package/src/runtime/migrations/vbundle-builder.ts +133 -79
  517. package/src/runtime/migrations/vbundle-import-analyzer.ts +9 -7
  518. package/src/runtime/migrations/vbundle-importer.ts +7 -7
  519. package/src/runtime/migrations/vbundle-metadata-merge.ts +1 -1
  520. package/src/runtime/migrations/vbundle-streaming-importer.ts +3 -3
  521. package/src/runtime/migrations/vbundle-streaming-validator.ts +48 -26
  522. package/src/runtime/migrations/vbundle-validator.ts +214 -41
  523. package/src/runtime/pending-interactions.ts +13 -4
  524. package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -1
  525. package/src/runtime/routes/__tests__/backup-routes.test.ts +28 -19
  526. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +235 -0
  527. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +58 -0
  528. package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +54 -0
  529. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +19 -6
  530. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +7 -7
  531. package/src/runtime/routes/acp-routes.test.ts +0 -3
  532. package/src/runtime/routes/acp-routes.ts +3 -7
  533. package/src/runtime/routes/app-management-routes.ts +18 -9
  534. package/src/runtime/routes/approval-routes.ts +55 -14
  535. package/src/runtime/routes/avatar-routes.ts +3 -5
  536. package/src/runtime/routes/browser-routes.ts +1 -15
  537. package/src/runtime/routes/channel-guardian-routes.ts +1 -5
  538. package/src/runtime/routes/channel-readiness-routes.ts +3 -7
  539. package/src/runtime/routes/channel-route-shared.ts +2 -28
  540. package/src/runtime/routes/client-routes.ts +45 -12
  541. package/src/runtime/routes/consolidation-routes.ts +115 -0
  542. package/src/runtime/routes/conversation-list-routes.ts +12 -29
  543. package/src/runtime/routes/conversation-management-routes.ts +14 -51
  544. package/src/runtime/routes/conversation-query-routes.ts +120 -8
  545. package/src/runtime/routes/conversation-routes.ts +44 -528
  546. package/src/runtime/routes/conversation-starter-routes.ts +19 -40
  547. package/src/runtime/routes/documents-routes.ts +53 -18
  548. package/src/runtime/routes/events-routes.ts +59 -91
  549. package/src/runtime/routes/filing-routes.ts +18 -1
  550. package/src/runtime/routes/guardian-action-routes.ts +4 -9
  551. package/src/runtime/routes/host-bash-routes.ts +3 -2
  552. package/src/runtime/routes/host-browser-routes.ts +9 -33
  553. package/src/runtime/routes/host-cu-routes.ts +6 -1
  554. package/src/runtime/routes/host-file-routes.ts +3 -2
  555. package/src/runtime/routes/host-transfer-routes.ts +11 -15
  556. package/src/runtime/routes/identity-routes.ts +78 -6
  557. package/src/runtime/routes/inbound-message-handler.ts +580 -137
  558. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -88
  559. package/src/runtime/routes/inbound-stages/background-dispatch.ts +3 -0
  560. package/src/runtime/routes/index.ts +4 -0
  561. package/src/runtime/routes/integrations/slack/channel.ts +0 -24
  562. package/src/runtime/routes/llm-call-sites-routes.ts +22 -0
  563. package/src/runtime/routes/memory-v2-routes.ts +10 -15
  564. package/src/runtime/routes/migration-routes.ts +188 -31
  565. package/src/runtime/routes/playground/guard.ts +1 -1
  566. package/src/runtime/routes/playground/index.ts +0 -2
  567. package/src/runtime/routes/recording-routes.ts +4 -24
  568. package/src/runtime/routes/rename-conversation-routes.ts +2 -6
  569. package/src/runtime/routes/schedule-routes.ts +3 -6
  570. package/src/runtime/routes/secret-routes.ts +87 -18
  571. package/src/runtime/routes/settings-routes.ts +29 -28
  572. package/src/runtime/routes/skills-routes.ts +12 -31
  573. package/src/runtime/routes/suggest-trust-rule-routes.ts +32 -1
  574. package/src/runtime/routes/task-routes.ts +6 -6
  575. package/src/runtime/routes/trust-rules-routes.ts +3 -94
  576. package/src/runtime/routes/types.ts +4 -4
  577. package/src/runtime/routes/upgrade-broadcast-routes.ts +3 -10
  578. package/src/runtime/routes/usage-routes.ts +87 -10
  579. package/src/runtime/routes/user-routes.ts +17 -31
  580. package/src/runtime/routes/work-items-routes.ts +1 -4
  581. package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -2
  582. package/src/runtime/services/analyze-conversation.ts +7 -17
  583. package/src/runtime/services/conversation-serializer.ts +2 -4
  584. package/src/runtime/verification-outbound-actions.ts +1 -1
  585. package/src/runtime/verification-rate-limiter.ts +1 -1
  586. package/src/schedule/schedule-store.ts +0 -16
  587. package/src/security/secret-scanner.ts +14 -547
  588. package/src/security/secure-keys.ts +31 -11
  589. package/src/security/token-manager.ts +7 -3
  590. package/src/signals/cancel.ts +16 -25
  591. package/src/signals/conversation-undo.ts +2 -27
  592. package/src/signals/emit-event.ts +1 -2
  593. package/src/signals/user-message.ts +108 -22
  594. package/src/skills/catalog-install.ts +1 -0
  595. package/src/skills/clawhub.ts +2 -2
  596. package/src/skills/inline-command-runner.ts +1 -7
  597. package/src/subagent/manager.ts +67 -84
  598. package/src/tasks/task-store.ts +1 -28
  599. package/src/telemetry/types.ts +6 -0
  600. package/src/telemetry/usage-telemetry-reporter.test.ts +38 -15
  601. package/src/telemetry/usage-telemetry-reporter.ts +3 -5
  602. package/src/tools/acp/spawn.test.ts +1 -2
  603. package/src/tools/acp/steer.test.ts +1 -2
  604. package/src/tools/browser/__tests__/browser-status.test.ts +44 -127
  605. package/src/tools/browser/browser-execution.ts +31 -147
  606. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +92 -68
  607. package/src/tools/browser/cdp-client/factory.ts +48 -76
  608. package/src/tools/browser/cdp-client/index.ts +1 -14
  609. package/src/tools/executor.ts +44 -31
  610. package/src/tools/host-filesystem/edit.ts +3 -2
  611. package/src/tools/host-filesystem/read.ts +3 -2
  612. package/src/tools/host-filesystem/transfer.test.ts +45 -42
  613. package/src/tools/host-filesystem/transfer.ts +4 -3
  614. package/src/tools/host-filesystem/write.ts +3 -2
  615. package/src/tools/host-terminal/host-shell.ts +4 -3
  616. package/src/tools/network/script-proxy/index.ts +1 -10
  617. package/src/tools/permission-checker.ts +66 -1
  618. package/src/tools/skills/sandbox-runner.ts +1 -6
  619. package/src/tools/skills/skill-tool-factory.ts +32 -0
  620. package/src/tools/terminal/safe-env.ts +1 -0
  621. package/src/tools/terminal/shell.ts +2 -78
  622. package/src/tools/types.ts +12 -39
  623. package/src/tts/__tests__/provider-catalog.test.ts +2 -2
  624. package/src/tts/provider-catalog.ts +1 -1
  625. package/src/usage/actors.ts +2 -1
  626. package/src/usage/attribution.ts +185 -0
  627. package/src/usage/pricing.ts +166 -0
  628. package/src/usage/types.ts +14 -0
  629. package/src/util/json.ts +13 -0
  630. package/src/util/logger.ts +3 -3
  631. package/src/util/pricing.ts +50 -3
  632. package/src/work-items/work-item-runner.ts +15 -42
  633. package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +4 -3
  634. package/src/workspace/migrations/052-seed-default-inference-profiles.ts +3 -3
  635. package/src/workspace/migrations/060-memory-v2-init.ts +2 -18
  636. package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +59 -0
  637. package/src/workspace/migrations/062-drop-memory-v2-edges-json.ts +27 -0
  638. package/src/workspace/migrations/063-release-notes-dynamic-model-context.ts +70 -0
  639. package/src/workspace/migrations/064-unwind-main-agent-opus-seed.ts +64 -0
  640. package/src/workspace/migrations/registry.ts +8 -0
  641. package/src/workspace/provider-commit-message-generator.ts +3 -3
  642. package/src/__tests__/sandbox-diagnostics.test.ts +0 -138
  643. package/src/__tests__/sandbox-host-parity.test.ts +0 -1024
  644. package/src/__tests__/secret-detection-handler.test.ts +0 -67
  645. package/src/__tests__/secret-scanner-executor.test.ts +0 -450
  646. package/src/__tests__/tcc-sandbox-deny.test.ts +0 -198
  647. package/src/__tests__/terminal-sandbox.test.ts +0 -374
  648. package/src/__tests__/tool-notification-listener.test.ts +0 -65
  649. package/src/context/__tests__/microcompact.test.ts +0 -805
  650. package/src/context/microcompact.ts +0 -443
  651. package/src/daemon/handlers/slack-channel-oauth-install.ts +0 -197
  652. package/src/events/tool-notification-listener.ts +0 -17
  653. package/src/ipc/routes/__tests__/memory-v2-validate.test.ts +0 -219
  654. package/src/memory/v2/__tests__/edges.test.ts +0 -435
  655. package/src/memory/v2/edges.ts +0 -217
  656. package/src/prompts/__tests__/system-prompt-memory-v2.test.ts +0 -197
  657. package/src/runtime/__tests__/chrome-extension-registry.test.ts +0 -518
  658. package/src/runtime/__tests__/client-registry.test.ts +0 -271
  659. package/src/runtime/chrome-extension-registry.ts +0 -368
  660. package/src/runtime/client-registry.ts +0 -254
  661. package/src/runtime/routes/inbound-stages/verification-intercept.ts +0 -329
  662. package/src/tools/secret-detection-handler.ts +0 -269
  663. package/src/tools/terminal/backends/native.ts +0 -327
  664. package/src/tools/terminal/backends/types.ts +0 -37
  665. package/src/tools/terminal/sandbox-diagnostics.ts +0 -87
  666. package/src/tools/terminal/sandbox.ts +0 -40
@@ -8,6 +8,7 @@ import {
8
8
  createLocalBackend,
9
9
  } from "../../../browser-session/index.js";
10
10
  import { getConfig } from "../../../config/loader.js";
11
+ import { HostBrowserProxy } from "../../../daemon/host-browser-proxy.js";
11
12
  import { getLogger } from "../../../util/logger.js";
12
13
  import type { ToolContext } from "../../types.js";
13
14
  import { createCdpInspectClient } from "./cdp-inspect-client.js";
@@ -103,11 +104,10 @@ export interface GetCdpClientOptions {
103
104
  * invocation based on the ToolContext and config. Three backends are
104
105
  * considered in priority order:
105
106
  *
106
- * 1. **Extension** -- When `context.hostBrowserProxy` is set AND
107
- * `hostBrowserProxy.isAvailable()` returns `true` (i.e. the
108
- * proxy exists and the client is actually connected). This
109
- * prevents selecting the extension transport when the proxy
110
- * object exists but the underlying WebSocket is disconnected.
107
+ * 1. **Extension** -- When `HostBrowserProxy.instance` is available
108
+ * and `isAvailable()` returns `true` (i.e. a chrome extension
109
+ * connection exists in the registry). This prevents selecting
110
+ * the extension transport when no extension is connected.
111
111
  * 2. **cdp-inspect** -- When `hostBrowser.cdpInspect.enabled` is
112
112
  * `true` in config, construct a `CdpInspectClient` that attaches
113
113
  * to an already-running Chrome via the DevTools JSON protocol.
@@ -183,17 +183,15 @@ export function buildPinnedCandidateList(
183
183
  context: ToolContext,
184
184
  mode: Exclude<BrowserMode, "auto">,
185
185
  ): BackendCandidate[] {
186
- const { conversationId, hostBrowserProxy } = context;
186
+ const { conversationId } = context;
187
187
 
188
188
  switch (mode) {
189
189
  case "extension": {
190
- if (!hostBrowserProxy || !hostBrowserProxy.isAvailable()) {
191
- const reason = !hostBrowserProxy
192
- ? "no host browser proxy provisioned for this conversation"
193
- : "host browser proxy exists but is not connected";
190
+ const hostBrowserProxy = HostBrowserProxy.instance;
191
+ if (!hostBrowserProxy.isAvailable()) {
194
192
  throw new CdpError(
195
193
  "transport_error",
196
- `Pinned mode "extension" unavailable: ${reason}`,
194
+ `Pinned mode "extension" unavailable: no active extension connection`,
197
195
  {
198
196
  attemptDiagnostics: [
199
197
  {
@@ -201,7 +199,7 @@ export function buildPinnedCandidateList(
201
199
  inclusionReason: `pinned mode: extension`,
202
200
  stage: "candidate_selection",
203
201
  errorCode: "transport_error",
204
- errorMessage: reason,
202
+ errorMessage: "no active extension connection",
205
203
  },
206
204
  ],
207
205
  },
@@ -289,18 +287,16 @@ export function buildPinnedCandidateList(
289
287
  * Exported for testing.
290
288
  */
291
289
  export function buildCandidateList(context: ToolContext): BackendCandidate[] {
292
- const { conversationId, hostBrowserProxy } = context;
290
+ const { conversationId } = context;
293
291
  const candidates: BackendCandidate[] = [];
292
+ const hostBrowserProxy = HostBrowserProxy.instance;
294
293
 
295
- // 1. Extension -- preferred when a chrome-extension is bound AND
296
- // the proxy reports it is connected. Checking isAvailable()
297
- // prevents selecting the extension transport when the proxy
298
- // object exists (e.g. it was provisioned at conversation start)
299
- // but the client has since disconnected.
300
- if (hostBrowserProxy && hostBrowserProxy.isAvailable()) {
294
+ // 1. Extension -- preferred when the singleton proxy reports an active
295
+ // extension connection is available.
296
+ if (hostBrowserProxy.isAvailable()) {
301
297
  candidates.push({
302
298
  kind: "extension",
303
- reason: "hostBrowserProxy present and available",
299
+ reason: "extension connected via registry singleton",
304
300
  create() {
305
301
  const client = createExtensionCdpClient(
306
302
  hostBrowserProxy,
@@ -315,10 +311,10 @@ export function buildCandidateList(context: ToolContext): BackendCandidate[] {
315
311
  return { client, backend };
316
312
  },
317
313
  });
318
- } else if (hostBrowserProxy) {
314
+ } else {
319
315
  log.debug(
320
316
  { conversationId },
321
- "CDP factory: hostBrowserProxy present but not available, skipping extension candidate",
317
+ "CDP factory: no active extension connection, skipping extension candidate",
322
318
  );
323
319
  }
324
320
 
@@ -348,63 +344,39 @@ export function buildCandidateList(context: ToolContext): BackendCandidate[] {
348
344
  context.transportInterface === "macos" &&
349
345
  cdpInspectConfig.desktopAuto.enabled
350
346
  ) {
351
- // macOS desktop-auto: include cdp-inspect as a candidate unless:
352
- // (a) the hostBrowserProxy is registry-routed (extension-backed) and
353
- // temporarily unavailable the extension transport was explicitly
354
- // expected and the disconnection is transient, so inserting
355
- // cdp-inspect would cause a silent takeover. Only applies when
356
- // `hostBrowserRegistryRouted` is true (set when
357
- // `hostBrowserSenderOverride` was wired at turn-start).
358
- // SSE-backed proxies (macOS without an extension connection) that
359
- // report unavailable (e.g. non-interactive turns where
360
- // clientConnected=false) should NOT suppress cdp-inspect — the
361
- // SSE proxy was never expected to service browser requests.
362
- // (b) the cooldown from a recent failure is still active.
363
- //
364
- // When no hostBrowserProxy is present at all (extension not
365
- // provisioned for this conversation), cdp-inspect remains available
366
- // as a fallback per the desktop-auto contract.
367
- if (
368
- hostBrowserProxy &&
369
- !hostBrowserProxy.isAvailable() &&
370
- context.hostBrowserRegistryRouted
371
- ) {
347
+ // macOS desktop-auto: include cdp-inspect as a candidate unless
348
+ // the cooldown from a recent failure is still active. The extension
349
+ // candidate is already first in the list, so it wins when connected.
350
+ const { cooldownMs } = cdpInspectConfig.desktopAuto;
351
+ if (isDesktopAutoCooldownActive(cooldownMs)) {
372
352
  log.debug(
373
- { conversationId },
374
- "CDP factory: desktop-auto cdp-inspect skipped (extension transport expected but temporarily unavailable)",
353
+ {
354
+ conversationId,
355
+ cooldownMs,
356
+ cooldownSince: _desktopAutoCooldownSince,
357
+ },
358
+ "CDP factory: desktop-auto cdp-inspect skipped (cooldown active)",
375
359
  );
376
360
  } else {
377
- const { cooldownMs } = cdpInspectConfig.desktopAuto;
378
- if (isDesktopAutoCooldownActive(cooldownMs)) {
379
- log.debug(
380
- {
381
- conversationId,
382
- cooldownMs,
383
- cooldownSince: _desktopAutoCooldownSince,
384
- },
385
- "CDP factory: desktop-auto cdp-inspect skipped (cooldown active)",
386
- );
387
- } else {
388
- candidates.push({
389
- kind: "cdp-inspect",
390
- reason: "desktopAuto: macOS turn, cdp-inspect auto-attempted",
391
- create() {
392
- const client = createCdpInspectClient(conversationId, {
393
- host: cdpInspectConfig.host,
394
- port: cdpInspectConfig.port,
395
- discoveryTimeoutMs: cdpInspectConfig.probeTimeoutMs,
396
- wsConnectTimeoutMs: cdpInspectConfig.probeTimeoutMs,
397
- });
398
- const backend = createCdpInspectBackend({
399
- isAvailable: () => true,
400
- sendCdp: (command, signal) =>
401
- dispatchThroughClient(client, command, signal),
402
- dispose: () => client.dispose(),
403
- });
404
- return { client, backend };
405
- },
406
- });
407
- }
361
+ candidates.push({
362
+ kind: "cdp-inspect",
363
+ reason: "desktopAuto: macOS turn, cdp-inspect auto-attempted",
364
+ create() {
365
+ const client = createCdpInspectClient(conversationId, {
366
+ host: cdpInspectConfig.host,
367
+ port: cdpInspectConfig.port,
368
+ discoveryTimeoutMs: cdpInspectConfig.probeTimeoutMs,
369
+ wsConnectTimeoutMs: cdpInspectConfig.probeTimeoutMs,
370
+ });
371
+ const backend = createCdpInspectBackend({
372
+ isAvailable: () => true,
373
+ sendCdp: (command, signal) =>
374
+ dispatchThroughClient(client, command, signal),
375
+ dispose: () => client.dispose(),
376
+ });
377
+ return { client, backend };
378
+ },
379
+ });
408
380
  }
409
381
  }
410
382
 
@@ -1,22 +1,9 @@
1
1
  export {
2
- CdpInspectClient,
3
2
  type CdpInspectClientOptions,
4
3
  type CdpInspectHelpers,
5
- createCdpInspectClient,
6
4
  } from "./cdp-inspect-client.js";
7
5
  export { CdpError, type CdpErrorCode } from "./errors.js";
8
- export {
9
- createExtensionCdpClient,
10
- ExtensionCdpClient,
11
- } from "./extension-cdp-client.js";
12
- export {
13
- buildCandidateList,
14
- buildChainedClient,
15
- buildPinnedCandidateList,
16
- getCdpClient,
17
- type GetCdpClientOptions,
18
- } from "./factory.js";
19
- export { createLocalCdpClient, LocalCdpClient } from "./local-cdp-client.js";
6
+ export { type GetCdpClientOptions } from "./factory.js";
20
7
  export type {
21
8
  AttemptDiagnostic,
22
9
  AttemptStage,
@@ -22,7 +22,6 @@ import { getLogger } from "../util/logger.js";
22
22
  import { resolveExecutionTarget } from "./execution-target.js";
23
23
  import { executeWithTimeout, safeTimeoutMs } from "./execution-timeout.js";
24
24
  import { PermissionChecker } from "./permission-checker.js";
25
- import { SecretDetectionHandler } from "./secret-detection-handler.js";
26
25
  import { extractAndSanitize } from "./sensitive-output-placeholders.js";
27
26
  import { applyEdit } from "./shared/filesystem/edit-engine.js";
28
27
  import { sandboxPolicy } from "./shared/filesystem/path-policy.js";
@@ -39,13 +38,11 @@ const log = getLogger("tool-executor");
39
38
  export class ToolExecutor {
40
39
  private prompter: PermissionPrompter;
41
40
  private permissionChecker: PermissionChecker;
42
- private secretDetectionHandler: SecretDetectionHandler;
43
41
  private approvalHandler: ToolApprovalHandler;
44
42
 
45
43
  constructor(prompter: PermissionPrompter) {
46
44
  this.prompter = prompter;
47
45
  this.permissionChecker = new PermissionChecker(prompter);
48
- this.secretDetectionHandler = new SecretDetectionHandler(prompter);
49
46
  this.approvalHandler = new ToolApprovalHandler();
50
47
  }
51
48
 
@@ -105,6 +102,19 @@ export class ToolExecutor {
105
102
  const startTime = Date.now();
106
103
  let decision = "allow";
107
104
  let riskLevel: string = RiskLevel.Low;
105
+ let permRiskMeta:
106
+ | {
107
+ riskLevel: string;
108
+ riskReason: string;
109
+ riskScopeOptions: Array<{ pattern: string; label: string }>;
110
+ riskDirectoryScopeOptions?: Array<{ scope: string; label: string }>;
111
+ isContainerized?: boolean;
112
+ }
113
+ | undefined;
114
+ let permMatchedTrustRuleId: string | undefined;
115
+ let permApprovalMode: string | undefined;
116
+ let permApprovalReason: string | undefined;
117
+ let permRiskThreshold: string | undefined;
108
118
  const executionTarget = resolveExecutionTarget(name);
109
119
 
110
120
  emitLifecycleEvent(context, {
@@ -167,15 +177,6 @@ export class ToolExecutor {
167
177
  // Exception: requireFreshApproval tools always go through the
168
178
  // permission check even when a grant was consumed - the grant does
169
179
  // not substitute for an interactive human review.
170
- let permRiskMeta:
171
- | {
172
- riskLevel: string;
173
- riskReason: string;
174
- riskScopeOptions: Array<{ pattern: string; label: string }>;
175
- riskDirectoryScopeOptions?: Array<{ scope: string; label: string }>;
176
- isContainerized?: boolean;
177
- }
178
- | undefined;
179
180
  if (!gateResult.grantConsumed || context.requireFreshApproval) {
180
181
  // Check permissions via the extracted PermissionChecker
181
182
  const permResult = await this.permissionChecker.checkPermission(
@@ -192,6 +193,10 @@ export class ToolExecutor {
192
193
  riskLevel = permResult.riskLevel;
193
194
  decision = permResult.decision;
194
195
  permRiskMeta = permResult.riskMeta;
196
+ permMatchedTrustRuleId = permResult.matchedTrustRuleId;
197
+ permApprovalMode = permResult.approvalMode;
198
+ permApprovalReason = permResult.approvalReason;
199
+ permRiskThreshold = permResult.riskThreshold;
195
200
 
196
201
  if (!permResult.allowed) {
197
202
  return {
@@ -202,12 +207,21 @@ export class ToolExecutor {
202
207
  riskScopeOptions: permRiskMeta?.riskScopeOptions,
203
208
  riskDirectoryScopeOptions: permRiskMeta?.riskDirectoryScopeOptions,
204
209
  isContainerized: permRiskMeta?.isContainerized,
210
+ matchedTrustRuleId: permMatchedTrustRuleId,
211
+ approvalMode: permApprovalMode,
212
+ approvalReason: permApprovalReason,
213
+ riskThreshold: permRiskThreshold,
205
214
  };
206
215
  }
207
216
 
208
217
  if (permResult.wasPrompted) {
209
218
  context.approvedViaPrompt = true;
210
219
  }
220
+ } else {
221
+ // Grant consumed — permission check was skipped. Set provenance explicitly
222
+ // so the record shows how this execution was authorized.
223
+ permApprovalMode = "auto";
224
+ permApprovalReason = "grant_scoped_consumed";
211
225
  }
212
226
 
213
227
  // Execute the tool - proxy tools delegate to an external resolver.
@@ -231,6 +245,7 @@ export class ToolExecutor {
231
245
  conversationId: context.conversationId,
232
246
  requestId: context.requestId,
233
247
  riskLevel,
248
+ matchedTrustRuleId: permMatchedTrustRuleId,
234
249
  decision: "error",
235
250
  durationMs,
236
251
  errorMessage: msg,
@@ -268,6 +283,7 @@ export class ToolExecutor {
268
283
  conversationId: context.conversationId,
269
284
  requestId: context.requestId,
270
285
  riskLevel,
286
+ matchedTrustRuleId: permMatchedTrustRuleId,
271
287
  decision: "error",
272
288
  durationMs,
273
289
  errorMessage: msg,
@@ -334,6 +350,7 @@ export class ToolExecutor {
334
350
  conversationId: context.conversationId,
335
351
  requestId: context.requestId,
336
352
  riskLevel,
353
+ matchedTrustRuleId: permMatchedTrustRuleId,
337
354
  decision: "deny",
338
355
  reason: denialReason,
339
356
  durationMs,
@@ -352,6 +369,7 @@ export class ToolExecutor {
352
369
  conversationId: context.conversationId,
353
370
  requestId: context.requestId,
354
371
  riskLevel,
372
+ matchedTrustRuleId: permMatchedTrustRuleId,
355
373
  decision: "error",
356
374
  durationMs,
357
375
  errorMessage: errorMsg,
@@ -364,8 +382,6 @@ export class ToolExecutor {
364
382
 
365
383
  // Sensitive output extraction: strip directives, replace raw values
366
384
  // with placeholders, and attach bindings for agent-loop substitution.
367
- // Runs before secret detection so that raw sensitive values are already
368
- // replaced and won't trigger entropy-based redaction.
369
385
  const { sanitizedContent, bindings } = extractAndSanitize(
370
386
  execResult.content,
371
387
  );
@@ -377,23 +393,6 @@ export class ToolExecutor {
377
393
  };
378
394
  }
379
395
 
380
- // Secret detection on tool output
381
- const secretResult = await this.secretDetectionHandler.handle(
382
- execResult,
383
- name,
384
- input,
385
- context,
386
- executionTarget,
387
- riskLevel,
388
- decision,
389
- startTime,
390
- emitLifecycleEvent,
391
- );
392
- if (secretResult.earlyReturn) {
393
- return secretResult.result;
394
- }
395
- execResult = secretResult.result;
396
-
397
396
  const durationMs = Date.now() - startTime;
398
397
  // Strip sensitiveBindings from lifecycle event to prevent raw values leaking
399
398
  const { sensitiveBindings: _sb, ...safeResult } = execResult;
@@ -406,6 +405,7 @@ export class ToolExecutor {
406
405
  conversationId: context.conversationId,
407
406
  requestId: context.requestId,
408
407
  riskLevel,
408
+ matchedTrustRuleId: permMatchedTrustRuleId,
409
409
  decision,
410
410
  durationMs,
411
411
  result: safeResult,
@@ -424,6 +424,18 @@ export class ToolExecutor {
424
424
  isContainerized: permRiskMeta.isContainerized,
425
425
  };
426
426
  }
427
+ if (permMatchedTrustRuleId) {
428
+ execResult = { ...execResult, matchedTrustRuleId: permMatchedTrustRuleId };
429
+ }
430
+ if (permApprovalMode) {
431
+ execResult = { ...execResult, approvalMode: permApprovalMode };
432
+ }
433
+ if (permApprovalReason) {
434
+ execResult = { ...execResult, approvalReason: permApprovalReason };
435
+ }
436
+ if (permRiskThreshold) {
437
+ execResult = { ...execResult, riskThreshold: permRiskThreshold };
438
+ }
427
439
 
428
440
  return execResult;
429
441
  } catch (err) {
@@ -465,6 +477,7 @@ export class ToolExecutor {
465
477
  conversationId: context.conversationId,
466
478
  requestId: context.requestId,
467
479
  riskLevel,
480
+ matchedTrustRuleId: permMatchedTrustRuleId,
468
481
  decision: "error",
469
482
  durationMs,
470
483
  errorMessage: msg,
@@ -1,3 +1,4 @@
1
+ import { HostFileProxy } from "../../daemon/host-file-proxy.js";
1
2
  import { RiskLevel } from "../../permissions/types.js";
2
3
  import type { ToolDefinition } from "../../providers/types.js";
3
4
  import { FileSystemOps } from "../shared/filesystem/file-ops-service.js";
@@ -85,8 +86,8 @@ class HostFileEditTool implements Tool {
85
86
 
86
87
  // Proxy to connected client for execution on the user's machine
87
88
  // when a capable client is available (managed/cloud-hosted mode).
88
- if (context.hostFileProxy?.isAvailable()) {
89
- return context.hostFileProxy.request(
89
+ if (HostFileProxy.instance.isAvailable()) {
90
+ return HostFileProxy.instance.request(
90
91
  {
91
92
  operation: "edit",
92
93
  path: rawPath,
@@ -1,5 +1,6 @@
1
1
  import { extname } from "node:path";
2
2
 
3
+ import { HostFileProxy } from "../../daemon/host-file-proxy.js";
3
4
  import { RiskLevel } from "../../permissions/types.js";
4
5
  import type { ToolDefinition } from "../../providers/types.js";
5
6
  import { FileSystemOps } from "../shared/filesystem/file-ops-service.js";
@@ -57,8 +58,8 @@ class HostFileReadTool implements Tool {
57
58
  // Proxy to connected client for execution on the user's machine
58
59
  // when a capable client is available (managed/cloud-hosted mode),
59
60
  // including image reads that need the host filesystem view.
60
- if (context.hostFileProxy?.isAvailable()) {
61
- return context.hostFileProxy.request(
61
+ if (HostFileProxy.instance.isAvailable()) {
62
+ return HostFileProxy.instance.request(
62
63
  {
63
64
  operation: "read",
64
65
  path: rawPath,
@@ -1,14 +1,44 @@
1
1
  import { existsSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from "node:fs";
2
2
  import { tmpdir } from "node:os";
3
3
  import { join } from "node:path";
4
- import { afterEach, describe, expect, test } from "bun:test";
4
+ import { afterEach, describe, expect, mock, test } from "bun:test";
5
5
 
6
6
  import type { ToolContext } from "../types.js";
7
- import { hostFileTransferTool } from "./transfer.js";
7
+
8
+ // ---------------------------------------------------------------------------
9
+ // Singleton mock — must precede the tool import so bun's module mock applies.
10
+ // ---------------------------------------------------------------------------
11
+
12
+ let mockProxyAvailable = false;
13
+ const toSandboxCalls: Array<{ sourcePath: string; destPath: string }> = [];
14
+ const toHostCalls: Array<{ sourcePath: string; destPath: string }> = [];
15
+
16
+ mock.module("../../daemon/host-transfer-proxy.js", () => ({
17
+ HostTransferProxy: {
18
+ get instance() {
19
+ return {
20
+ isAvailable: () => mockProxyAvailable,
21
+ requestToSandbox: (args: { sourcePath: string; destPath: string; overwrite?: boolean; conversationId: string }) => {
22
+ toSandboxCalls.push({ sourcePath: args.sourcePath, destPath: args.destPath });
23
+ return Promise.resolve({ content: "ok", isError: false });
24
+ },
25
+ requestToHost: (args: { sourcePath: string; destPath: string; overwrite: boolean; conversationId: string }) => {
26
+ toHostCalls.push({ sourcePath: args.sourcePath, destPath: args.destPath });
27
+ return Promise.resolve({ content: "ok", isError: false });
28
+ },
29
+ };
30
+ },
31
+ },
32
+ }));
33
+
34
+ const { hostFileTransferTool } = await import("./transfer.js");
8
35
 
9
36
  const testDirs: string[] = [];
10
37
 
11
38
  afterEach(() => {
39
+ mockProxyAvailable = false;
40
+ toSandboxCalls.length = 0;
41
+ toHostCalls.length = 0;
12
42
  for (const dir of testDirs.splice(0)) {
13
43
  rmSync(dir, { recursive: true, force: true });
14
44
  }
@@ -25,7 +55,7 @@ function makeContext(workingDir: string): ToolContext {
25
55
  }
26
56
 
27
57
  // ---------------------------------------------------------------------------
28
- // Local-mode tests (no proxy; context.hostTransferProxy omitted)
58
+ // Local-mode tests (proxy unavailable — falls back to local copy)
29
59
  // ---------------------------------------------------------------------------
30
60
 
31
61
  describe("host_file_transfer local mode", () => {
@@ -176,93 +206,66 @@ describe("host_file_transfer local mode to_host", () => {
176
206
  });
177
207
 
178
208
  // ---------------------------------------------------------------------------
179
- // Managed-mode tests (mock proxy via context.hostTransferProxy)
209
+ // Managed-mode tests (singleton proxy available)
180
210
  // ---------------------------------------------------------------------------
181
211
 
182
212
  describe("host_file_transfer managed mode", () => {
183
213
  test("relative path is pre-resolved before proxy call", async () => {
214
+ mockProxyAvailable = true;
184
215
  const workingDir = makeTempDir();
185
216
  const srcDir = makeTempDir();
186
217
  const srcFile = join(srcDir, "source.txt");
187
218
  writeFileSync(srcFile, "content");
188
219
 
189
- const calls: Array<{ destPath: string }> = [];
190
- const mockProxy = {
191
- isAvailable: () => true,
192
- requestToSandbox: (args: { sourcePath: string; destPath: string; overwrite: boolean; conversationId: string }) => {
193
- calls.push({ destPath: args.destPath });
194
- return Promise.resolve({ content: "ok", isError: false });
195
- },
196
- };
197
- const ctx = { ...makeContext(workingDir), hostTransferProxy: mockProxy as any };
198
-
199
220
  await hostFileTransferTool.execute(
200
221
  {
201
222
  source_path: srcFile,
202
223
  dest_path: "relative/file.txt",
203
224
  direction: "to_sandbox",
204
225
  },
205
- ctx,
226
+ makeContext(workingDir),
206
227
  );
207
228
 
208
- expect(calls.length).toBe(1);
209
- expect(calls[0].destPath).toBe(join(workingDir, "relative", "file.txt"));
229
+ expect(toSandboxCalls.length).toBe(1);
230
+ expect(toSandboxCalls[0].destPath).toBe(join(workingDir, "relative", "file.txt"));
210
231
  });
211
232
 
212
233
  test("to_host relative source is pre-resolved before proxy call", async () => {
234
+ mockProxyAvailable = true;
213
235
  const workingDir = makeTempDir();
214
236
  writeFileSync(join(workingDir, "doc.md"), "content");
215
237
 
216
- const calls: Array<{ sourcePath: string }> = [];
217
- const mockProxy = {
218
- isAvailable: () => true,
219
- requestToHost: (args: { sourcePath: string; destPath: string; overwrite: boolean; conversationId: string }) => {
220
- calls.push({ sourcePath: args.sourcePath });
221
- return Promise.resolve({ content: "ok", isError: false });
222
- },
223
- };
224
- const ctx = { ...makeContext(workingDir), hostTransferProxy: mockProxy as any };
225
-
226
238
  await hostFileTransferTool.execute(
227
239
  {
228
240
  source_path: "doc.md",
229
241
  dest_path: "/Users/someone/Desktop/doc.md",
230
242
  direction: "to_host",
231
243
  },
232
- ctx,
244
+ makeContext(workingDir),
233
245
  );
234
246
 
235
- expect(calls.length).toBe(1);
236
- expect(calls[0].sourcePath).toBe(join(workingDir, "doc.md"));
247
+ expect(toHostCalls.length).toBe(1);
248
+ expect(toHostCalls[0].sourcePath).toBe(join(workingDir, "doc.md"));
237
249
  });
238
250
 
239
251
  test("out-of-bounds path rejected before proxy call", async () => {
252
+ mockProxyAvailable = true;
240
253
  const workingDir = makeTempDir();
241
254
  const srcDir = makeTempDir();
242
255
  const srcFile = join(srcDir, "source.txt");
243
256
  writeFileSync(srcFile, "content");
244
257
 
245
- const calls: Array<{ destPath: string }> = [];
246
- const mockProxy = {
247
- isAvailable: () => true,
248
- requestToSandbox: (args: { sourcePath: string; destPath: string; overwrite: boolean; conversationId: string }) => {
249
- calls.push({ destPath: args.destPath });
250
- return Promise.resolve({ content: "ok", isError: false });
251
- },
252
- };
253
- const ctx = { ...makeContext(workingDir), hostTransferProxy: mockProxy as any };
254
-
255
258
  const result = await hostFileTransferTool.execute(
256
259
  {
257
260
  source_path: srcFile,
258
261
  dest_path: "/etc/passwd",
259
262
  direction: "to_sandbox",
260
263
  },
261
- ctx,
264
+ makeContext(workingDir),
262
265
  );
263
266
 
264
267
  expect(result.isError).toBe(true);
265
268
  expect(result.content).toContain("Invalid destination path");
266
- expect(calls.length).toBe(0);
269
+ expect(toSandboxCalls.length).toBe(0);
267
270
  });
268
271
  });
@@ -2,6 +2,7 @@ import { constants } from "node:fs";
2
2
  import { copyFile, lstat, mkdir, realpath } from "node:fs/promises";
3
3
  import { dirname, isAbsolute } from "node:path";
4
4
 
5
+ import { HostTransferProxy } from "../../daemon/host-transfer-proxy.js";
5
6
  import { RiskLevel } from "../../permissions/types.js";
6
7
  import type { ToolDefinition } from "../../providers/types.js";
7
8
  import { sandboxPolicy } from "../shared/filesystem/path-policy.js";
@@ -125,9 +126,9 @@ class HostFileTransferTool implements Tool {
125
126
  }
126
127
 
127
128
  // Managed mode: delegate to the host transfer proxy when available.
128
- if (context.hostTransferProxy?.isAvailable()) {
129
+ if (HostTransferProxy.instance.isAvailable()) {
129
130
  if (direction === "to_host") {
130
- return context.hostTransferProxy.requestToHost(
131
+ return HostTransferProxy.instance.requestToHost(
131
132
  {
132
133
  sourcePath: resolvedSourcePath,
133
134
  destPath,
@@ -137,7 +138,7 @@ class HostFileTransferTool implements Tool {
137
138
  context.signal,
138
139
  );
139
140
  }
140
- return context.hostTransferProxy.requestToSandbox(
141
+ return HostTransferProxy.instance.requestToSandbox(
141
142
  {
142
143
  sourcePath,
143
144
  destPath: resolvedDestPath,
@@ -1,3 +1,4 @@
1
+ import { HostFileProxy } from "../../daemon/host-file-proxy.js";
1
2
  import { RiskLevel } from "../../permissions/types.js";
2
3
  import type { ToolDefinition } from "../../providers/types.js";
3
4
  import { FileSystemOps } from "../shared/filesystem/file-ops-service.js";
@@ -55,8 +56,8 @@ class HostFileWriteTool implements Tool {
55
56
 
56
57
  // Proxy to connected client for execution on the user's machine
57
58
  // when a capable client is available (managed/cloud-hosted mode).
58
- if (context.hostFileProxy?.isAvailable()) {
59
- return context.hostFileProxy.request(
59
+ if (HostFileProxy.instance.isAvailable()) {
60
+ return HostFileProxy.instance.request(
60
61
  {
61
62
  operation: "write",
62
63
  path: rawPath,