@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
@@ -68,22 +68,30 @@ import {
68
68
  type ForwardedCdpEvent,
69
69
  onCdpEvent,
70
70
  } from "../browser-session/index.js";
71
+ import { HostBrowserProxy } from "../daemon/host-browser-proxy.js";
71
72
  import { getDb } from "../memory/db-connection.js";
72
73
  import { initializeDb } from "../memory/db-init.js";
74
+ import { assistantEventHub } from "../runtime/assistant-event-hub.js";
75
+ import { mintToken } from "../runtime/auth/token-service.js";
73
76
  import {
74
77
  mintHostBrowserCapability,
75
78
  resetCapabilityTokenSecretForTests,
76
79
  setCapabilityTokenSecretForTests,
77
80
  } from "../runtime/capability-tokens.js";
78
- import {
79
- __resetChromeExtensionRegistryForTests,
80
- getChromeExtensionRegistry,
81
- } from "../runtime/chrome-extension-registry.js";
82
81
  import { RuntimeHttpServer } from "../runtime/http-server.js";
83
- import * as pendingInteractions from "../runtime/pending-interactions.js";
84
82
 
85
83
  initializeDb();
86
84
 
85
+ function mintSseToken(guardianId: string): string {
86
+ return mintToken({
87
+ aud: "vellum-daemon",
88
+ sub: `actor:self:${guardianId}`,
89
+ scope_profile: "actor_client_v1",
90
+ policy_epoch: 1,
91
+ ttlSeconds: 3600,
92
+ });
93
+ }
94
+
87
95
  // ── Helpers ─────────────────────────────────────────────────────────
88
96
 
89
97
  async function waitFor(
@@ -102,11 +110,12 @@ async function waitFor(
102
110
  }
103
111
 
104
112
  async function waitForRegistryEntry(
105
- guardianId: string,
113
+ _guardianId: string,
106
114
  timeoutMs = 2000,
107
115
  ): Promise<void> {
108
116
  await waitFor(
109
- () => getChromeExtensionRegistry().get(guardianId) !== undefined,
117
+ () =>
118
+ assistantEventHub.getMostRecentClientByCapability("host_browser") != null,
110
119
  timeoutMs,
111
120
  );
112
121
  }
@@ -124,8 +133,7 @@ describe("host_browser WS event + invalidation e2e", () => {
124
133
  const db = getDb();
125
134
  db.run("DELETE FROM contact_channels");
126
135
  db.run("DELETE FROM contacts");
127
- pendingInteractions.clear();
128
- __resetChromeExtensionRegistryForTests();
136
+ HostBrowserProxy.reset();
129
137
  __resetBrowserSessionEventsForTests();
130
138
 
131
139
  // Pick a non-colliding port in the same band as the other
@@ -139,8 +147,7 @@ describe("host_browser WS event + invalidation e2e", () => {
139
147
 
140
148
  afterEach(async () => {
141
149
  await server?.stop();
142
- pendingInteractions.clear();
143
- __resetChromeExtensionRegistryForTests();
150
+ HostBrowserProxy.reset();
144
151
  __resetBrowserSessionEventsForTests();
145
152
  resetCapabilityTokenSecretForTests();
146
153
  });
@@ -154,6 +161,7 @@ describe("host_browser WS event + invalidation e2e", () => {
154
161
  const mockExt = createMockChromeExtension({
155
162
  runtimeBaseUrl,
156
163
  token,
164
+ sseToken: mintSseToken(guardianId),
157
165
  resultTransport: "ws",
158
166
  });
159
167
  await mockExt.start();
@@ -195,6 +203,7 @@ describe("host_browser WS event + invalidation e2e", () => {
195
203
  const mockExt = createMockChromeExtension({
196
204
  runtimeBaseUrl,
197
205
  token,
206
+ sseToken: mintSseToken(guardianId),
198
207
  resultTransport: "ws",
199
208
  });
200
209
  await mockExt.start();
@@ -224,6 +233,7 @@ describe("host_browser WS event + invalidation e2e", () => {
224
233
  const mockExt = createMockChromeExtension({
225
234
  runtimeBaseUrl,
226
235
  token,
236
+ sseToken: mintSseToken(guardianId),
227
237
  resultTransport: "ws",
228
238
  });
229
239
  await mockExt.start();
@@ -301,37 +311,21 @@ describe("host_browser WS event + invalidation e2e", () => {
301
311
  const mockExt = createMockChromeExtension({
302
312
  runtimeBaseUrl,
303
313
  token,
314
+ sseToken: mintSseToken(guardianId),
304
315
  resultTransport: "ws",
305
316
  });
306
317
  await mockExt.start();
307
318
  await mockExt.waitForConnection();
308
319
  await waitForRegistryEntry(guardianId);
309
320
 
310
- // Grab the initial timestamps so we can verify that keepalive
311
- // bumps lastKeepaliveAt but NOT lastActiveAt (routing field).
312
- const connBefore = getChromeExtensionRegistry().get(guardianId)!;
313
- const lastActiveBefore = connBefore.lastActiveAt;
314
-
315
- // Small delay to ensure Date.now() advances at least 1ms.
316
- await new Promise((r) => setTimeout(r, 15));
317
-
318
321
  // Send a keepalive frame (the extension sends these periodically
319
322
  // to prevent the runtime from considering the connection stale).
320
323
  // The frame may contain extra keys (e.g. timestamp) that the
321
324
  // runtime should silently ignore (lenient validation).
322
325
  mockExt.sendRaw(JSON.stringify({ type: "keepalive", ts: Date.now() }));
323
326
 
324
- // Wait for the touch to propagate touch() updates
325
- // lastKeepaliveAt (not lastActiveAt) to avoid routing interference.
326
- await waitFor(() => {
327
- const conn = getChromeExtensionRegistry().get(guardianId);
328
- return conn !== undefined && (conn.lastKeepaliveAt ?? 0) > 0;
329
- });
330
-
331
- const connAfter = getChromeExtensionRegistry().get(guardianId)!;
332
- expect(connAfter.lastKeepaliveAt).toBeGreaterThan(0);
333
- // lastActiveAt must remain unchanged — keepalives must not affect routing.
334
- expect(connAfter.lastActiveAt).toBe(lastActiveBefore);
327
+ // Small delay to let the keepalive frame process.
328
+ await new Promise((r) => setTimeout(r, 15));
335
329
 
336
330
  // Verify the socket is still alive by sending a normal host_browser_event
337
331
  // frame after the keepalive — if the socket had been torn down, this
@@ -356,6 +350,7 @@ describe("host_browser WS event + invalidation e2e", () => {
356
350
  const mockExt = createMockChromeExtension({
357
351
  runtimeBaseUrl,
358
352
  token,
353
+ sseToken: mintSseToken(guardianId),
359
354
  resultTransport: "ws",
360
355
  });
361
356
  await mockExt.start();
@@ -404,6 +399,7 @@ describe("host_browser WS event + invalidation e2e", () => {
404
399
  const mockExt = createMockChromeExtension({
405
400
  runtimeBaseUrl,
406
401
  token,
402
+ sseToken: mintSseToken(guardianId),
407
403
  resultTransport: "ws",
408
404
  });
409
405
  await mockExt.start();
@@ -1,22 +1,38 @@
1
- import { afterEach, describe, expect, jest, test } from "bun:test";
2
-
3
- import { HostCuProxy } from "../daemon/host-cu-proxy.js";
1
+ import { afterEach, describe, expect, jest, mock, test } from "bun:test";
2
+
3
+ const sentMessages: unknown[] = [];
4
+ const resolvedInteractionIds: string[] = [];
5
+ let mockHasClient = false;
6
+
7
+ mock.module("../runtime/assistant-event-hub.js", () => ({
8
+ broadcastMessage: (msg: unknown) => sentMessages.push(msg),
9
+ assistantEventHub: {
10
+ getMostRecentClientByCapability: (cap: string) =>
11
+ cap === "host_cu" && mockHasClient ? { id: "mock-client" } : null,
12
+ },
13
+ }));
14
+
15
+ mock.module("../runtime/pending-interactions.js", () => ({
16
+ resolve: (requestId: string) => {
17
+ resolvedInteractionIds.push(requestId);
18
+ return undefined;
19
+ },
20
+ get: () => undefined,
21
+ getByKind: () => [],
22
+ getByConversation: () => [],
23
+ removeByConversation: () => {},
24
+ }));
25
+
26
+ const { HostCuProxy } = await import("../daemon/host-cu-proxy.js");
4
27
 
5
28
  describe("HostCuProxy", () => {
6
29
  let proxy: InstanceType<typeof HostCuProxy>;
7
- let sentMessages: unknown[];
8
- let sendToClient: (msg: unknown) => void;
9
- let resolvedRequestIds: string[];
10
30
 
11
31
  function setup(maxSteps?: number) {
12
- sentMessages = [];
13
- resolvedRequestIds = [];
14
- sendToClient = (msg: unknown) => sentMessages.push(msg);
15
- proxy = new HostCuProxy(
16
- sendToClient as never,
17
- (requestId: string) => resolvedRequestIds.push(requestId),
18
- maxSteps,
19
- );
32
+ sentMessages.length = 0;
33
+ resolvedInteractionIds.length = 0;
34
+ mockHasClient = false;
35
+ proxy = new HostCuProxy(maxSteps);
20
36
  }
21
37
 
22
38
  afterEach(() => {
@@ -888,87 +904,54 @@ describe("HostCuProxy", () => {
888
904
  });
889
905
 
890
906
  // -------------------------------------------------------------------------
891
- // sender throws synchronously
907
+ // pendingInteractions.resolve callback
892
908
  // -------------------------------------------------------------------------
893
909
 
894
- describe("sender throws synchronously", () => {
895
- test("rejects the promise, clears pending state and timer, invokes onInternalResolve", async () => {
896
- sentMessages = [];
897
- resolvedRequestIds = [];
898
- const throwingSend = () => {
899
- throw new Error("transport down");
900
- };
901
- proxy = new HostCuProxy(throwingSend as never, (requestId: string) =>
902
- resolvedRequestIds.push(requestId),
903
- );
910
+ describe("pendingInteractions.resolve callback", () => {
911
+ test("fires when abort signal fires", async () => {
912
+ setup();
904
913
 
905
- // request() synchronously calls sendToClient inside the Promise
906
- // executor. A throw there surfaces as a rejected promise.
914
+ const controller = new AbortController();
907
915
  const resultPromise = proxy.request(
908
916
  "computer_use_click",
909
917
  { element_id: 1 },
910
918
  "session-1",
911
919
  1,
920
+ undefined,
921
+ controller.signal,
912
922
  );
913
923
 
914
- await expect(resultPromise).rejects.toThrow("transport down");
924
+ const sent = sentMessages[0] as Record<string, unknown>;
925
+ const requestId = sent.requestId as string;
915
926
 
916
- // The internal resolve should fire exactly once as part of cleanup.
917
- expect(resolvedRequestIds).toHaveLength(1);
927
+ controller.abort();
918
928
 
919
- // Issue a new request on a fresh (non-throwing) sender and verify
920
- // the proxy is still functional — no stale timers or bookkeeping
921
- // from the failed request.
922
- sentMessages = [];
923
- proxy.updateSender(
924
- ((msg: unknown) => sentMessages.push(msg)) as never,
925
- true,
926
- );
927
- const okPromise = proxy.request(
928
- "computer_use_click",
929
- { element_id: 2 },
930
- "session-1",
931
- 2,
932
- );
933
- expect(sentMessages).toHaveLength(1);
934
- const okRequestId = (sentMessages[0] as Record<string, unknown>)
935
- .requestId as string;
936
- expect(proxy.hasPendingRequest(okRequestId)).toBe(true);
937
- proxy.resolve(okRequestId, { axTree: "Button [2]" });
938
- const okResult = await okPromise;
939
- expect(okResult.isError).toBe(false);
940
- expect(okResult.content).toContain("Button [2]");
929
+ await resultPromise;
930
+ expect(resolvedInteractionIds).toContain(requestId);
941
931
  });
942
- });
943
932
 
944
- // -------------------------------------------------------------------------
945
- // onInternalResolve callback
946
- // -------------------------------------------------------------------------
947
-
948
- describe("onInternalResolve", () => {
949
- test("calls onInternalResolve when abort signal fires", async () => {
933
+ test("fires on dispose", async () => {
950
934
  setup();
951
935
 
952
- const controller = new AbortController();
953
936
  const resultPromise = proxy.request(
954
937
  "computer_use_click",
955
938
  { element_id: 1 },
956
939
  "session-1",
957
940
  1,
958
- undefined,
959
- controller.signal,
960
941
  );
961
942
 
962
943
  const sent = sentMessages[0] as Record<string, unknown>;
963
944
  const requestId = sent.requestId as string;
964
945
 
965
- controller.abort();
946
+ proxy.dispose();
966
947
 
967
- await resultPromise;
968
- expect(resolvedRequestIds).toContain(requestId);
948
+ // dispose rejects pending requests — catch to avoid unhandled rejection
949
+ await resultPromise.catch(() => {});
950
+
951
+ expect(resolvedInteractionIds).toContain(requestId);
969
952
  });
970
953
 
971
- test("calls onInternalResolve on dispose", async () => {
954
+ test("does not fire on normal client-initiated resolve", async () => {
972
955
  setup();
973
956
 
974
957
  const resultPromise = proxy.request(
@@ -981,12 +964,10 @@ describe("HostCuProxy", () => {
981
964
  const sent = sentMessages[0] as Record<string, unknown>;
982
965
  const requestId = sent.requestId as string;
983
966
 
984
- proxy.dispose();
985
-
986
- // dispose rejects pending requests — catch to avoid unhandled rejection
987
- await resultPromise.catch(() => {});
967
+ proxy.resolve(requestId, { axTree: "Button [1]" });
988
968
 
989
- expect(resolvedRequestIds).toContain(requestId);
969
+ await resultPromise;
970
+ expect(resolvedInteractionIds).toEqual([]);
990
971
  });
991
972
  });
992
973
 
@@ -995,52 +976,16 @@ describe("HostCuProxy", () => {
995
976
  // -------------------------------------------------------------------------
996
977
 
997
978
  describe("isAvailable", () => {
998
- test("returns false by default", () => {
979
+ test("returns false when no client with host_cu capability is connected", () => {
999
980
  setup();
981
+ mockHasClient = false;
1000
982
  expect(proxy.isAvailable()).toBe(false);
1001
983
  });
1002
984
 
1003
- test("returns true after updateSender with clientConnected=true", () => {
985
+ test("returns true when a client with host_cu capability is connected", () => {
1004
986
  setup();
1005
- proxy.updateSender(sendToClient as never, true);
987
+ mockHasClient = true;
1006
988
  expect(proxy.isAvailable()).toBe(true);
1007
989
  });
1008
-
1009
- test("returns false after updateSender with clientConnected=false", () => {
1010
- setup();
1011
- proxy.updateSender(sendToClient as never, true);
1012
- proxy.updateSender(sendToClient as never, false);
1013
- expect(proxy.isAvailable()).toBe(false);
1014
- });
1015
- });
1016
-
1017
- // -------------------------------------------------------------------------
1018
- // updateSender
1019
- // -------------------------------------------------------------------------
1020
-
1021
- describe("updateSender", () => {
1022
- test("uses updated sender for new requests", async () => {
1023
- setup();
1024
-
1025
- const newMessages: unknown[] = [];
1026
- proxy.updateSender((msg) => newMessages.push(msg), true);
1027
-
1028
- const resultPromise = proxy.request(
1029
- "computer_use_click",
1030
- { element_id: 1 },
1031
- "session-1",
1032
- 1,
1033
- );
1034
-
1035
- expect(sentMessages).toHaveLength(0); // Old sender not used
1036
- expect(newMessages).toHaveLength(1); // New sender used
1037
-
1038
- const sent = newMessages[0] as Record<string, unknown>;
1039
- proxy.resolve(sent.requestId as string, {
1040
- axTree: "Button [1]",
1041
- });
1042
-
1043
- await resultPromise;
1044
- });
1045
990
  });
1046
991
  });
@@ -1,4 +1,27 @@
1
- import { afterEach, describe, expect, jest, test } from "bun:test";
1
+ import { afterEach, describe, expect, jest, mock, test } from "bun:test";
2
+
3
+ const sentMessages: unknown[] = [];
4
+ const resolvedInteractionIds: string[] = [];
5
+ let mockHasClient = false;
6
+
7
+ mock.module("../runtime/assistant-event-hub.js", () => ({
8
+ broadcastMessage: (msg: unknown) => sentMessages.push(msg),
9
+ assistantEventHub: {
10
+ getMostRecentClientByCapability: (cap: string) =>
11
+ cap === "host_file" && mockHasClient ? { id: "mock-client" } : null,
12
+ },
13
+ }));
14
+
15
+ mock.module("../runtime/pending-interactions.js", () => ({
16
+ resolve: (requestId: string) => {
17
+ resolvedInteractionIds.push(requestId);
18
+ return undefined;
19
+ },
20
+ get: () => undefined,
21
+ getByKind: () => [],
22
+ getByConversation: () => [],
23
+ removeByConversation: () => {},
24
+ }));
2
25
 
3
26
  const { HostFileProxy } = await import("../daemon/host-file-proxy.js");
4
27
 
@@ -10,17 +33,17 @@ const PNG_HEADER = Buffer.from([
10
33
 
11
34
  describe("HostFileProxy", () => {
12
35
  let proxy: InstanceType<typeof HostFileProxy>;
13
- let sentMessages: unknown[];
14
- let sendToClient: (msg: unknown) => void;
15
36
 
16
- function setup(onInternalResolve?: (requestId: string) => void) {
17
- sentMessages = [];
18
- sendToClient = (msg: unknown) => sentMessages.push(msg);
19
- proxy = new HostFileProxy(sendToClient, onInternalResolve);
37
+ function setup() {
38
+ sentMessages.length = 0;
39
+ resolvedInteractionIds.length = 0;
40
+ mockHasClient = false;
41
+ proxy = new (HostFileProxy as any)();
20
42
  }
21
43
 
22
44
  afterEach(() => {
23
45
  proxy?.dispose();
46
+ HostFileProxy.reset();
24
47
  });
25
48
 
26
49
  describe("request/resolve lifecycle (happy path)", () => {
@@ -271,24 +294,17 @@ describe("HostFileProxy", () => {
271
294
  });
272
295
 
273
296
  describe("isAvailable", () => {
274
- test("returns false by default (no client connected)", () => {
297
+ test("returns false when no client with host_file capability is connected", () => {
275
298
  setup();
299
+ mockHasClient = false;
276
300
  expect(proxy.isAvailable()).toBe(false);
277
301
  });
278
302
 
279
- test("returns true after updateSender with clientConnected=true", () => {
303
+ test("returns true when a client with host_file capability is connected", () => {
280
304
  setup();
281
- proxy.updateSender(sendToClient, true);
305
+ mockHasClient = true;
282
306
  expect(proxy.isAvailable()).toBe(true);
283
307
  });
284
-
285
- test("returns false after updateSender with clientConnected=false", () => {
286
- setup();
287
- proxy.updateSender(sendToClient, true);
288
- expect(proxy.isAvailable()).toBe(true);
289
- proxy.updateSender(sendToClient, false);
290
- expect(proxy.isAvailable()).toBe(false);
291
- });
292
308
  });
293
309
 
294
310
  describe("dispose", () => {
@@ -377,34 +393,6 @@ describe("HostFileProxy", () => {
377
393
  });
378
394
  });
379
395
 
380
- describe("updateSender", () => {
381
- test("uses updated sender for new requests", async () => {
382
- setup();
383
-
384
- const newMessages: unknown[] = [];
385
- proxy.updateSender((msg) => newMessages.push(msg), true);
386
-
387
- const resultPromise = proxy.request(
388
- {
389
- operation: "read",
390
- path: "/tmp/test.txt",
391
- },
392
- "session-1",
393
- );
394
-
395
- expect(sentMessages).toHaveLength(0); // Old sender not used
396
- expect(newMessages).toHaveLength(1); // New sender used
397
-
398
- const sent = newMessages[0] as Record<string, unknown>;
399
- proxy.resolve(sent.requestId as string, {
400
- content: "updated content",
401
- isError: false,
402
- });
403
-
404
- await resultPromise;
405
- });
406
- });
407
-
408
396
  describe("resolve with unknown requestId", () => {
409
397
  test("silently ignores unknown requestId", () => {
410
398
  setup();
@@ -522,49 +510,9 @@ describe("HostFileProxy", () => {
522
510
  });
523
511
  });
524
512
 
525
- describe("sender throws synchronously", () => {
526
- test("rejects the promise, clears pending state and timer, invokes onInternalResolve", async () => {
527
- const resolvedIds: string[] = [];
528
- sentMessages = [];
529
- sendToClient = () => {
530
- throw new Error("transport down");
531
- };
532
- proxy = new HostFileProxy(sendToClient, (id) => resolvedIds.push(id));
533
-
534
- const resultPromise = proxy.request(
535
- { operation: "read", path: "/tmp/test.txt" },
536
- "session-1",
537
- );
538
-
539
- await expect(resultPromise).rejects.toThrow("transport down");
540
-
541
- // The internal resolve should fire exactly once as part of cleanup.
542
- expect(resolvedIds).toHaveLength(1);
543
-
544
- // Issue a new request on a fresh (non-throwing) sender and verify
545
- // the proxy is still functional — no stale timers or bookkeeping
546
- // from the failed request.
547
- sentMessages = [];
548
- proxy.updateSender((msg) => sentMessages.push(msg), true);
549
- const okPromise = proxy.request(
550
- { operation: "read", path: "/tmp/ok.txt" },
551
- "session-1",
552
- );
553
- expect(sentMessages).toHaveLength(1);
554
- const okRequestId = (sentMessages[0] as Record<string, unknown>)
555
- .requestId as string;
556
- expect(proxy.hasPendingRequest(okRequestId)).toBe(true);
557
- proxy.resolve(okRequestId, { content: "ok", isError: false });
558
- const okResult = await okPromise;
559
- expect(okResult.content).toBe("ok");
560
- expect(okResult.isError).toBe(false);
561
- });
562
- });
563
-
564
- describe("onInternalResolve callback", () => {
513
+ describe("pendingInteractions.resolve callback", () => {
565
514
  test("fires on abort", async () => {
566
- const resolvedIds: string[] = [];
567
- setup((id) => resolvedIds.push(id));
515
+ setup();
568
516
 
569
517
  const controller = new AbortController();
570
518
  const resultPromise = proxy.request(
@@ -582,12 +530,11 @@ describe("HostFileProxy", () => {
582
530
  controller.abort();
583
531
  await resultPromise;
584
532
 
585
- expect(resolvedIds).toEqual([requestId]);
533
+ expect(resolvedInteractionIds).toContain(requestId);
586
534
  });
587
535
 
588
536
  test("fires for each pending request on dispose", () => {
589
- const resolvedIds: string[] = [];
590
- setup((id) => resolvedIds.push(id));
537
+ setup();
591
538
 
592
539
  // Create two pending requests and catch rejections from dispose
593
540
  const p1 = proxy.request(
@@ -614,14 +561,13 @@ describe("HostFileProxy", () => {
614
561
 
615
562
  proxy.dispose();
616
563
 
617
- expect(resolvedIds).toHaveLength(2);
618
- expect(resolvedIds).toContain(ids[0]);
619
- expect(resolvedIds).toContain(ids[1]);
564
+ expect(resolvedInteractionIds).toHaveLength(2);
565
+ expect(resolvedInteractionIds).toContain(ids[0]);
566
+ expect(resolvedInteractionIds).toContain(ids[1]);
620
567
  });
621
568
 
622
569
  test("does not fire on normal client-initiated resolve", async () => {
623
- const resolvedIds: string[] = [];
624
- setup((id) => resolvedIds.push(id));
570
+ setup();
625
571
 
626
572
  const resultPromise = proxy.request(
627
573
  {
@@ -634,14 +580,14 @@ describe("HostFileProxy", () => {
634
580
  const sent = sentMessages[0] as Record<string, unknown>;
635
581
  const requestId = sent.requestId as string;
636
582
 
637
- // Normal resolve from client — should NOT trigger onInternalResolve
583
+ // Normal resolve from client — should NOT trigger pendingInteractions.resolve
638
584
  proxy.resolve(requestId, {
639
585
  content: "file contents",
640
586
  isError: false,
641
587
  });
642
588
 
643
589
  await resultPromise;
644
- expect(resolvedIds).toEqual([]);
590
+ expect(resolvedInteractionIds).toEqual([]);
645
591
  });
646
592
  });
647
593
  });
@@ -1,9 +1,30 @@
1
1
  import { mkdirSync, mkdtempSync, 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 { HostFileInput } from "../daemon/host-file-proxy.js";
7
+ import type { ToolExecutionResult } from "../tools/types.js";
8
+
9
+ // Mock HostFileProxy singleton so proxy delegation tests can control it.
10
+ let mockFileProxyAvailable = false;
11
+ let mockFileProxyRequestFn: (
12
+ input: HostFileInput,
13
+ conversationId: string,
14
+ signal?: AbortSignal,
15
+ ) => Promise<ToolExecutionResult> = () => Promise.resolve({ content: "", isError: false });
16
+
17
+ mock.module("../daemon/host-file-proxy.js", () => ({
18
+ HostFileProxy: {
19
+ get instance() {
20
+ return {
21
+ isAvailable: () => mockFileProxyAvailable,
22
+ request: mockFileProxyRequestFn,
23
+ };
24
+ },
25
+ },
26
+ }));
27
+
7
28
  import { hostFileReadTool } from "../tools/host-filesystem/read.js";
8
29
  import type { ToolContext } from "../tools/types.js";
9
30
 
@@ -27,6 +48,8 @@ afterEach(() => {
27
48
  for (const dir of testDirs.splice(0)) {
28
49
  rmSync(dir, { recursive: true, force: true });
29
50
  }
51
+ mockFileProxyAvailable = false;
52
+ mockFileProxyRequestFn = () => Promise.resolve({ content: "", isError: false });
30
53
  });
31
54
 
32
55
  // Minimal valid JPEG: FF D8 FF E0 header
@@ -172,28 +195,26 @@ describe("host_file_read image support", () => {
172
195
  conversationId: string;
173
196
  signal?: AbortSignal;
174
197
  }> = [];
198
+ mockFileProxyAvailable = true;
199
+ mockFileProxyRequestFn = async (input, conversationId, signal) => {
200
+ requests.push({ input, conversationId, signal });
201
+ return {
202
+ content: "Image loaded: /host/screenshot.png",
203
+ isError: false,
204
+ contentBlocks: [
205
+ {
206
+ type: "image",
207
+ source: {
208
+ type: "base64",
209
+ media_type: "image/png",
210
+ data: PNG_HEADER.toString("base64"),
211
+ },
212
+ },
213
+ ],
214
+ };
215
+ };
175
216
  const proxyContext: ToolContext = {
176
217
  ...makeContext(),
177
- hostFileProxy: {
178
- isAvailable: () => true,
179
- request: async (input, conversationId, signal) => {
180
- requests.push({ input, conversationId, signal });
181
- return {
182
- content: "Image loaded: /host/screenshot.png",
183
- isError: false,
184
- contentBlocks: [
185
- {
186
- type: "image",
187
- source: {
188
- type: "base64",
189
- media_type: "image/png",
190
- data: PNG_HEADER.toString("base64"),
191
- },
192
- },
193
- ],
194
- };
195
- },
196
- } as ToolContext["hostFileProxy"],
197
218
  };
198
219
 
199
220
  const result = await hostFileReadTool.execute(