@vellumai/assistant 0.6.1 → 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (463) hide show
  1. package/bun.lock +40 -40
  2. package/bunfig.toml +3 -0
  3. package/docker-entrypoint.sh +12 -2
  4. package/docs/architecture/memory.md +1 -1
  5. package/node_modules/@vellumai/ces-contracts/src/handles.ts +7 -9
  6. package/node_modules/@vellumai/ces-contracts/src/rpc.ts +42 -0
  7. package/openapi.yaml +184 -69
  8. package/package.json +41 -41
  9. package/scripts/generate-openapi.ts +1 -2
  10. package/src/__tests__/acp-session.test.ts +43 -0
  11. package/src/__tests__/app-builder-tool-scripts.test.ts +1 -0
  12. package/src/__tests__/app-executors.test.ts +1 -0
  13. package/src/__tests__/app-source-watcher.test.ts +37 -11
  14. package/src/__tests__/approval-routes-http.test.ts +178 -1
  15. package/src/__tests__/assistant-event-hub.test.ts +30 -0
  16. package/src/__tests__/browser-fill-credential.test.ts +229 -94
  17. package/src/__tests__/browser-manager.test.ts +40 -27
  18. package/src/__tests__/catalog-files.test.ts +862 -0
  19. package/src/__tests__/channel-approvals.test.ts +53 -0
  20. package/src/__tests__/checker.test.ts +104 -170
  21. package/src/__tests__/cli-command-risk-guard.test.ts +1 -1
  22. package/src/__tests__/config-managed-gemini-defaults.test.ts +326 -0
  23. package/src/__tests__/config-schema-cmd.test.ts +2 -2
  24. package/src/__tests__/config-schema.test.ts +125 -48
  25. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +23 -0
  26. package/src/__tests__/context-overflow-approval.test.ts +21 -6
  27. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -1
  28. package/src/__tests__/conversation-agent-loop.test.ts +1 -1
  29. package/src/__tests__/conversation-analysis-routes.test.ts +169 -0
  30. package/src/__tests__/conversation-attachments.test.ts +80 -4
  31. package/src/__tests__/conversation-confirmation-signals.test.ts +155 -0
  32. package/src/__tests__/conversation-directories-parse.test.ts +105 -0
  33. package/src/__tests__/conversation-fork-crud.test.ts +17 -0
  34. package/src/__tests__/conversation-history-web-search.test.ts +1 -0
  35. package/src/__tests__/conversation-host-access-routes.test.ts +229 -0
  36. package/src/__tests__/conversation-inject-context.test.ts +103 -0
  37. package/src/__tests__/conversation-queue.test.ts +45 -2
  38. package/src/__tests__/conversation-routes-disk-view.test.ts +5 -0
  39. package/src/__tests__/conversation-routes-guardian-reply.test.ts +16 -0
  40. package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
  41. package/src/__tests__/conversation-runtime-assembly.test.ts +269 -46
  42. package/src/__tests__/conversation-starter-routes.test.ts +126 -0
  43. package/src/__tests__/conversation-starters-cadence.test.ts +161 -0
  44. package/src/__tests__/conversation-store.test.ts +195 -0
  45. package/src/__tests__/conversation-workspace-cache-state.test.ts +193 -0
  46. package/src/__tests__/credential-execution-approval-bridge.test.ts +32 -3
  47. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  48. package/src/__tests__/credential-vault-unit.test.ts +4 -4
  49. package/src/__tests__/credential-vault.test.ts +152 -13
  50. package/src/__tests__/credentials-cli.test.ts +2 -2
  51. package/src/__tests__/date-context.test.ts +4 -4
  52. package/src/__tests__/embedding-managed-proxy-selection.test.ts +256 -0
  53. package/src/__tests__/extension-id-sync-guard.test.ts +155 -0
  54. package/src/__tests__/fixtures/mock-chrome-extension.ts +375 -0
  55. package/src/__tests__/gateway-only-guard.test.ts +3 -0
  56. package/src/__tests__/gemini-provider.test.ts +2 -2
  57. package/src/__tests__/guardian-routing-invariants.test.ts +70 -2
  58. package/src/__tests__/headless-browser-interactions.test.ts +707 -371
  59. package/src/__tests__/headless-browser-navigate.test.ts +389 -47
  60. package/src/__tests__/headless-browser-read-tools.test.ts +266 -103
  61. package/src/__tests__/headless-browser-snapshot.test.ts +240 -77
  62. package/src/__tests__/host-bash-proxy.test.ts +150 -1
  63. package/src/__tests__/host-browser-e2e-cloud.test.ts +462 -0
  64. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +286 -0
  65. package/src/__tests__/host-browser-e2e-self-hosted.test.ts +374 -0
  66. package/src/__tests__/host-browser-event-routes.test.ts +350 -0
  67. package/src/__tests__/host-browser-proxy.test.ts +444 -0
  68. package/src/__tests__/host-browser-routes.test.ts +198 -0
  69. package/src/__tests__/host-browser-ws-events-e2e.test.ts +320 -0
  70. package/src/__tests__/host-cu-proxy.test.ts +171 -1
  71. package/src/__tests__/host-file-proxy.test.ts +185 -1
  72. package/src/__tests__/host-file-read-tool.test.ts +52 -0
  73. package/src/__tests__/host-proxy-interface.test.ts +165 -0
  74. package/src/__tests__/host-shell-tool.test.ts +1 -11
  75. package/src/__tests__/http-user-message-parity.test.ts +1 -0
  76. package/src/__tests__/init-feature-flag-overrides.test.ts +167 -0
  77. package/src/__tests__/inline-command-runner.test.ts +7 -5
  78. package/src/__tests__/integration-status.test.ts +6 -7
  79. package/src/__tests__/list-messages-tool-merge.test.ts +37 -12
  80. package/src/__tests__/log-export-workspace.test.ts +190 -0
  81. package/src/__tests__/managed-credential-catalog-cli.test.ts +12 -14
  82. package/src/__tests__/mcp-client-auth.test.ts +40 -4
  83. package/src/__tests__/mcp-health-check.test.ts +10 -3
  84. package/src/__tests__/migration-cross-version-compatibility.test.ts +3 -1
  85. package/src/__tests__/migration-export-http.test.ts +61 -2
  86. package/src/__tests__/migration-export-streaming.test.ts +66 -0
  87. package/src/__tests__/migration-import-commit-http.test.ts +101 -1
  88. package/src/__tests__/native-host-marker-sync-guard.test.ts +157 -0
  89. package/src/__tests__/navigate-settings-tab.test.ts +14 -1
  90. package/src/__tests__/notification-broadcaster.test.ts +65 -0
  91. package/src/__tests__/oauth-apps-routes.test.ts +17 -12
  92. package/src/__tests__/oauth-cli.test.ts +707 -60
  93. package/src/__tests__/oauth-connect-orchestrator.test.ts +116 -24
  94. package/src/__tests__/oauth-provider-seed-logos.test.ts +23 -0
  95. package/src/__tests__/oauth-provider-serializer.test.ts +146 -10
  96. package/src/__tests__/oauth-provider-visibility.test.ts +19 -21
  97. package/src/__tests__/oauth-providers-routes.test.ts +50 -14
  98. package/src/__tests__/oauth-store.test.ts +1386 -182
  99. package/src/__tests__/oauth2-gateway-transport.test.ts +211 -20
  100. package/src/__tests__/onboarding-template-contract.test.ts +74 -55
  101. package/src/__tests__/openai-provider.test.ts +2 -2
  102. package/src/__tests__/outlook-categories.test.ts +1 -1
  103. package/src/__tests__/outlook-client-automation.test.ts +1 -1
  104. package/src/__tests__/outlook-compose-tools.test.ts +1 -1
  105. package/src/__tests__/outlook-email-watcher.test.ts +1 -1
  106. package/src/__tests__/outlook-follow-up.test.ts +1 -1
  107. package/src/__tests__/outlook-messaging-provider.test.ts +2 -2
  108. package/src/__tests__/outlook-trash.test.ts +1 -1
  109. package/src/__tests__/outlook-unsubscribe.test.ts +1 -1
  110. package/src/__tests__/permission-checker-host-gate.test.ts +74 -14
  111. package/src/__tests__/permission-mode.test.ts +28 -56
  112. package/src/__tests__/pkb-autoinject.test.ts +96 -0
  113. package/src/__tests__/platform-callback-registration.test.ts +19 -0
  114. package/src/__tests__/post-turn-tool-result-truncation.test.ts +296 -0
  115. package/src/__tests__/proxy-approval-callback.test.ts +18 -0
  116. package/src/__tests__/require-fresh-approval.test.ts +40 -3
  117. package/src/__tests__/sandbox-diagnostics.test.ts +1 -32
  118. package/src/__tests__/sanitize-config-for-transfer.test.ts +132 -0
  119. package/src/__tests__/schedule-routes.test.ts +162 -0
  120. package/src/__tests__/secret-detection-handler.test.ts +84 -0
  121. package/src/__tests__/secret-ingress-http.test.ts +1 -0
  122. package/src/__tests__/send-endpoint-busy.test.ts +3 -0
  123. package/src/__tests__/set-permission-mode.test.ts +13 -250
  124. package/src/__tests__/skills-file-content-endpoint.test.ts +670 -0
  125. package/src/__tests__/skills-files-catalog-fallback.test.ts +450 -0
  126. package/src/__tests__/slack-channel-config.test.ts +12 -15
  127. package/src/__tests__/subagent-detail.test.ts +44 -2
  128. package/src/__tests__/subagent-disposal.test.ts +1 -0
  129. package/src/__tests__/subagent-fork-notifications.test.ts +291 -0
  130. package/src/__tests__/subagent-fork-spawn.test.ts +384 -0
  131. package/src/__tests__/subagent-manager-notify.test.ts +1 -0
  132. package/src/__tests__/subagent-notify-parent.test.ts +1 -0
  133. package/src/__tests__/subagent-spawn-tool-fork.test.ts +411 -0
  134. package/src/__tests__/subagent-tools.test.ts +1 -0
  135. package/src/__tests__/subagent-types.test.ts +1 -0
  136. package/src/__tests__/system-prompt-ask-mode.test.ts +27 -71
  137. package/src/__tests__/system-prompt.test.ts +72 -1
  138. package/src/__tests__/task-scheduler.test.ts +32 -6
  139. package/src/__tests__/telegram-config.test.ts +10 -13
  140. package/src/__tests__/terminal-sandbox.test.ts +1 -1
  141. package/src/__tests__/terminal-tools.test.ts +11 -5
  142. package/src/__tests__/test-preload.ts +14 -0
  143. package/src/__tests__/tool-approval-handler.test.ts +73 -0
  144. package/src/__tests__/tool-domain-event-publisher.test.ts +0 -1
  145. package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -8
  146. package/src/__tests__/tool-executor.test.ts +0 -1
  147. package/src/__tests__/tool-side-effects-slack-dm.test.ts +22 -0
  148. package/src/__tests__/top-level-renderer.test.ts +73 -1
  149. package/src/__tests__/transport-hints-queue.test.ts +62 -0
  150. package/src/__tests__/trust-store.test.ts +4 -4
  151. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +109 -0
  152. package/src/__tests__/v2-consent-policy.test.ts +103 -0
  153. package/src/__tests__/workspace-migration-030-seed-pkb-autoinject.test.ts +168 -0
  154. package/src/__tests__/workspace-policy.test.ts +2 -7
  155. package/src/acp/client-handler.ts +30 -4
  156. package/src/agent/loop.ts +12 -35
  157. package/src/approvals/guardian-request-resolvers.ts +21 -15
  158. package/src/browser-session/__tests__/manager.test.ts +297 -0
  159. package/src/browser-session/backends/cdp-inspect.ts +30 -0
  160. package/src/browser-session/backends/extension.ts +26 -0
  161. package/src/browser-session/backends/local.ts +24 -0
  162. package/src/browser-session/events.ts +164 -0
  163. package/src/browser-session/index.ts +27 -0
  164. package/src/browser-session/manager.ts +159 -0
  165. package/src/browser-session/types.ts +28 -0
  166. package/src/channels/__tests__/types.test.ts +134 -0
  167. package/src/channels/types.ts +55 -0
  168. package/src/cli/__tests__/run-assistant-command.ts +34 -7
  169. package/src/cli/__tests__/unknown-command.test.ts +33 -0
  170. package/src/cli/commands/browser-relay.ts +339 -409
  171. package/src/cli/commands/credentials.ts +3 -3
  172. package/src/cli/commands/default-action.ts +68 -1
  173. package/src/cli/commands/email.ts +18 -13
  174. package/src/cli/commands/mcp.ts +16 -4
  175. package/src/cli/commands/oauth/__tests__/connect.test.ts +68 -41
  176. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +21 -21
  177. package/src/cli/commands/oauth/__tests__/mode.test.ts +17 -17
  178. package/src/cli/commands/oauth/__tests__/ping.test.ts +16 -16
  179. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +31 -33
  180. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +329 -0
  181. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +116 -12
  182. package/src/cli/commands/oauth/__tests__/status.test.ts +10 -10
  183. package/src/cli/commands/oauth/__tests__/token.test.ts +7 -7
  184. package/src/cli/commands/oauth/apps.ts +7 -4
  185. package/src/cli/commands/oauth/connect.ts +16 -2
  186. package/src/cli/commands/oauth/disconnect.ts +1 -1
  187. package/src/cli/commands/oauth/providers.ts +200 -36
  188. package/src/cli/commands/oauth/shared.ts +5 -5
  189. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +259 -0
  190. package/src/cli/commands/platform/__tests__/connect.test.ts +1 -1
  191. package/src/cli/commands/platform/__tests__/disconnect.test.ts +1 -1
  192. package/src/cli/commands/platform/__tests__/status.test.ts +1 -1
  193. package/src/cli/commands/platform/index.ts +107 -10
  194. package/src/cli/commands/usage.ts +10 -9
  195. package/src/cli/lib/daemon-credential-client.ts +4 -0
  196. package/src/cli/program.ts +10 -3
  197. package/src/config/assistant-feature-flags.ts +59 -55
  198. package/src/config/bundled-skills/app-builder/SKILL.md +33 -173
  199. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +105 -0
  200. package/src/config/bundled-skills/app-builder/references/INTERACTION_HOOKS.md +56 -0
  201. package/src/config/bundled-skills/app-builder/references/WIDGETS.md +125 -0
  202. package/src/config/bundled-skills/contacts/SKILL.md +3 -0
  203. package/src/config/bundled-skills/document/SKILL.md +4 -0
  204. package/src/config/bundled-skills/gmail/SKILL.md +12 -7
  205. package/src/config/bundled-skills/gmail/TOOLS.json +1 -1
  206. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +2 -1
  207. package/src/config/bundled-skills/outlook/SKILL.md +7 -0
  208. package/src/config/bundled-skills/settings/TOOLS.json +1 -1
  209. package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +8 -3
  210. package/src/config/bundled-skills/subagent/SKILL.md +21 -0
  211. package/src/config/bundled-skills/subagent/TOOLS.json +8 -4
  212. package/src/config/bundled-skills/tasks/SKILL.md +5 -0
  213. package/src/config/env-registry.ts +14 -0
  214. package/src/config/env.ts +21 -0
  215. package/src/config/feature-flag-registry.json +46 -7
  216. package/src/config/loader.ts +56 -1
  217. package/src/config/sanitize-for-transfer.ts +47 -0
  218. package/src/config/schema.ts +46 -5
  219. package/src/config/schemas/host-browser.ts +66 -0
  220. package/src/config/schemas/memory-lifecycle.ts +1 -1
  221. package/src/config/schemas/memory-retrieval.ts +103 -0
  222. package/src/config/schemas/security.ts +0 -6
  223. package/src/config/schemas/services.ts +16 -0
  224. package/src/config/types.ts +0 -1
  225. package/src/context/post-turn-tool-result-truncation.ts +176 -0
  226. package/src/context/window-manager.ts +19 -1
  227. package/src/credential-execution/approval-bridge.ts +49 -16
  228. package/src/credential-execution/managed-catalog.ts +3 -7
  229. package/src/daemon/__tests__/conversation-tool-setup.test.ts +186 -0
  230. package/src/daemon/app-source-watcher.ts +35 -0
  231. package/src/daemon/config-watcher.ts +6 -2
  232. package/src/daemon/context-overflow-approval.ts +5 -1
  233. package/src/daemon/conversation-agent-loop-handlers.ts +17 -2
  234. package/src/daemon/conversation-agent-loop.ts +74 -19
  235. package/src/daemon/conversation-attachments.ts +40 -1
  236. package/src/daemon/conversation-messaging.ts +3 -0
  237. package/src/daemon/conversation-process.ts +66 -3
  238. package/src/daemon/conversation-queue-manager.ts +8 -0
  239. package/src/daemon/conversation-runtime-assembly.ts +159 -20
  240. package/src/daemon/conversation-surfaces.ts +78 -12
  241. package/src/daemon/conversation-tool-setup.ts +74 -11
  242. package/src/daemon/conversation-workspace.ts +12 -0
  243. package/src/daemon/conversation.ts +227 -11
  244. package/src/daemon/date-context.ts +10 -10
  245. package/src/daemon/first-greeting.ts +3 -2
  246. package/src/daemon/handlers/conversations.ts +9 -139
  247. package/src/daemon/handlers/shared.ts +65 -0
  248. package/src/daemon/handlers/skills.ts +232 -37
  249. package/src/daemon/host-bash-proxy.ts +48 -13
  250. package/src/daemon/host-browser-proxy.ts +191 -0
  251. package/src/daemon/host-cu-proxy.ts +36 -11
  252. package/src/daemon/host-file-proxy.ts +57 -9
  253. package/src/daemon/lifecycle.ts +86 -12
  254. package/src/daemon/message-protocol.ts +7 -0
  255. package/src/daemon/message-types/conversations.ts +59 -13
  256. package/src/daemon/message-types/host-browser.ts +100 -0
  257. package/src/daemon/message-types/messages.ts +5 -6
  258. package/src/daemon/message-types/notifications.ts +12 -0
  259. package/src/daemon/message-types/settings.ts +12 -0
  260. package/src/daemon/message-types/skills.ts +10 -0
  261. package/src/daemon/message-types/subagents.ts +2 -0
  262. package/src/daemon/server.ts +112 -35
  263. package/src/daemon/tool-side-effects.ts +6 -0
  264. package/src/daemon/transport-hints.ts +14 -0
  265. package/src/inbound/platform-callback-registration.ts +18 -17
  266. package/src/index.ts +1 -1
  267. package/src/mcp/client.ts +59 -24
  268. package/src/memory/app-store.ts +31 -1
  269. package/src/memory/conversation-crud.ts +38 -10
  270. package/src/memory/conversation-directories.ts +39 -0
  271. package/src/memory/conversation-group-migration.ts +65 -5
  272. package/src/memory/conversation-starters-cadence.ts +76 -0
  273. package/src/memory/conversation-title-service.ts +5 -2
  274. package/src/memory/db-init.ts +12 -0
  275. package/src/memory/embedding-backend.test.ts +75 -0
  276. package/src/memory/embedding-backend.ts +131 -5
  277. package/src/memory/embedding-gemini.test.ts +54 -0
  278. package/src/memory/embedding-gemini.ts +20 -9
  279. package/src/memory/embedding-local.ts +177 -18
  280. package/src/memory/graph/capability-seed.ts +3 -5
  281. package/src/memory/graph/consolidation.ts +10 -23
  282. package/src/memory/graph/extraction-job.ts +15 -0
  283. package/src/memory/graph/retriever.ts +40 -22
  284. package/src/memory/graph/store.test.ts +7 -3
  285. package/src/memory/graph/store.ts +47 -12
  286. package/src/memory/group-crud.ts +25 -9
  287. package/src/memory/llm-usage-store.ts +45 -4
  288. package/src/memory/migrations/213-oauth-providers-scope-separator.ts +13 -0
  289. package/src/memory/migrations/214-oauth-providers-refresh-url.ts +11 -0
  290. package/src/memory/migrations/215-oauth-providers-revoke.ts +14 -0
  291. package/src/memory/migrations/216-oauth-providers-token-auth-method.ts +30 -0
  292. package/src/memory/migrations/217-conversation-host-access.ts +40 -0
  293. package/src/memory/migrations/218-oauth-providers-logo-url.ts +11 -0
  294. package/src/memory/migrations/index.ts +6 -0
  295. package/src/memory/migrations/registry.ts +8 -0
  296. package/src/memory/schema/conversations.ts +1 -0
  297. package/src/memory/schema/oauth.ts +18 -13
  298. package/src/messaging/provider.ts +1 -1
  299. package/src/notifications/broadcaster.ts +6 -0
  300. package/src/notifications/conversation-pairing.ts +12 -4
  301. package/src/notifications/emit-signal.ts +14 -0
  302. package/src/notifications/signal.ts +11 -0
  303. package/src/oauth/AGENTS.md +76 -0
  304. package/src/oauth/__tests__/identity-verifier.test.ts +24 -19
  305. package/src/oauth/__tests__/seed-providers-managed.test.ts +32 -0
  306. package/src/oauth/byo-connection.test.ts +8 -8
  307. package/src/oauth/byo-connection.ts +7 -7
  308. package/src/oauth/connect-orchestrator.ts +23 -21
  309. package/src/oauth/connect-types.ts +3 -3
  310. package/src/oauth/connection-resolver.test.ts +17 -4
  311. package/src/oauth/connection-resolver.ts +16 -16
  312. package/src/oauth/connection.ts +1 -1
  313. package/src/oauth/manual-token-connection.ts +13 -13
  314. package/src/oauth/oauth-store.ts +214 -100
  315. package/src/oauth/platform-connection.test.ts +5 -5
  316. package/src/oauth/platform-connection.ts +4 -4
  317. package/src/oauth/provider-serializer.ts +31 -5
  318. package/src/oauth/revoke.ts +76 -0
  319. package/src/oauth/seed-providers.ts +127 -87
  320. package/src/oauth/token-persistence.ts +1 -1
  321. package/src/permissions/checker.ts +3 -3
  322. package/src/permissions/defaults.ts +7 -8
  323. package/src/permissions/permission-mode.ts +4 -11
  324. package/src/permissions/prompter.ts +13 -3
  325. package/src/permissions/v2-consent-policy.ts +87 -0
  326. package/src/platform/client.ts +1 -1
  327. package/src/prompts/system-prompt.ts +18 -21
  328. package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +3 -65
  329. package/src/prompts/templates/BOOTSTRAP.md +59 -96
  330. package/src/prompts/templates/SOUL.md +11 -11
  331. package/src/providers/anthropic/client.ts +1 -0
  332. package/src/providers/types.ts +1 -1
  333. package/src/runtime/AGENTS.md +23 -0
  334. package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +715 -0
  335. package/src/runtime/__tests__/capability-tokens.test.ts +258 -0
  336. package/src/runtime/__tests__/chrome-extension-registry.test.ts +518 -0
  337. package/src/runtime/assistant-event-hub.ts +24 -2
  338. package/src/runtime/auth/__tests__/guard-tests.test.ts +1 -0
  339. package/src/runtime/auth/__tests__/middleware.test.ts +116 -1
  340. package/src/runtime/auth/__tests__/route-policy.test.ts +8 -0
  341. package/src/runtime/auth/middleware.ts +98 -0
  342. package/src/runtime/auth/route-policy.ts +6 -7
  343. package/src/runtime/auth/token-service.ts +8 -0
  344. package/src/runtime/capability-tokens.ts +414 -0
  345. package/src/runtime/channel-approvals.ts +18 -5
  346. package/src/runtime/chrome-extension-registry.ts +332 -0
  347. package/src/runtime/confirmation-request-guardian-bridge.ts +6 -0
  348. package/src/runtime/guardian-decision-types.ts +7 -0
  349. package/src/runtime/http-server.ts +425 -70
  350. package/src/runtime/migrations/__tests__/rebind-secrets-credentials.test.ts +172 -0
  351. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +276 -0
  352. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +162 -0
  353. package/src/runtime/migrations/migration-transport.ts +6 -0
  354. package/src/runtime/migrations/migration-wizard.ts +22 -2
  355. package/src/runtime/migrations/rebind-secrets-screen.ts +76 -15
  356. package/src/runtime/migrations/vbundle-builder.ts +145 -38
  357. package/src/runtime/migrations/vbundle-import-analyzer.ts +19 -0
  358. package/src/runtime/migrations/vbundle-importer.ts +55 -5
  359. package/src/runtime/pending-interactions.ts +29 -13
  360. package/src/runtime/routes/approval-routes.ts +90 -16
  361. package/src/runtime/routes/browser-cdp-routes.ts +229 -0
  362. package/src/runtime/routes/browser-extension-pair-routes.ts +497 -0
  363. package/src/runtime/routes/conversation-analysis-routes.ts +18 -5
  364. package/src/runtime/routes/conversation-management-routes.ts +108 -0
  365. package/src/runtime/routes/conversation-routes.ts +308 -28
  366. package/src/runtime/routes/conversation-starter-routes.ts +78 -16
  367. package/src/runtime/routes/group-routes.ts +22 -8
  368. package/src/runtime/routes/guardian-action-routes.ts +24 -13
  369. package/src/runtime/routes/host-browser-routes.ts +279 -0
  370. package/src/runtime/routes/host-file-routes.ts +9 -1
  371. package/src/runtime/routes/identity-routes.ts +259 -16
  372. package/src/runtime/routes/log-export/AGENTS.md +104 -0
  373. package/src/runtime/routes/log-export/__tests__/workspace-allowlist-error-contract.test.ts +103 -0
  374. package/src/runtime/routes/log-export/__tests__/workspace-allowlist.test.ts +716 -0
  375. package/src/runtime/routes/log-export/workspace-allowlist.ts +458 -0
  376. package/src/runtime/routes/log-export-routes.ts +60 -25
  377. package/src/runtime/routes/memory-item-routes.ts +1 -7
  378. package/src/runtime/routes/migration-routes.ts +87 -2
  379. package/src/runtime/routes/oauth-apps.ts +15 -17
  380. package/src/runtime/routes/oauth-providers.ts +4 -0
  381. package/src/runtime/routes/schedule-routes.ts +24 -11
  382. package/src/runtime/routes/settings-routes.ts +9 -97
  383. package/src/runtime/routes/skills-routes.ts +52 -2
  384. package/src/runtime/routes/subagents-routes.ts +14 -10
  385. package/src/runtime/routes/usage-routes.ts +8 -7
  386. package/src/runtime/routes/workspace-routes.test.ts +22 -0
  387. package/src/runtime/routes/workspace-routes.ts +8 -1
  388. package/src/runtime/routes/workspace-utils.ts +2 -0
  389. package/src/schedule/scheduler.ts +7 -5
  390. package/src/security/ces-credential-client.ts +20 -0
  391. package/src/security/ces-rpc-credential-backend.ts +17 -0
  392. package/src/security/credential-backend.ts +5 -0
  393. package/src/security/oauth2.ts +42 -25
  394. package/src/security/secure-keys.ts +118 -25
  395. package/src/security/token-manager.ts +23 -10
  396. package/src/skills/catalog-files.ts +492 -0
  397. package/src/skills/inline-command-runner.ts +12 -14
  398. package/src/subagent/manager.ts +131 -26
  399. package/src/subagent/types.ts +19 -0
  400. package/src/tools/apps/executors.ts +11 -2
  401. package/src/tools/browser/__tests__/auth-detector.test.ts +202 -108
  402. package/src/tools/browser/auth-detector.ts +43 -12
  403. package/src/tools/browser/browser-execution.ts +645 -340
  404. package/src/tools/browser/browser-manager.ts +36 -12
  405. package/src/tools/browser/cdp-client/__tests__/accessibility-snapshot.test.ts +318 -0
  406. package/src/tools/browser/cdp-client/__tests__/cdp-dom-helpers.test.ts +1175 -0
  407. package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +870 -0
  408. package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +330 -0
  409. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +377 -0
  410. package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-nested-frames.json +64 -0
  411. package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-simple.json +69 -0
  412. package/src/tools/browser/cdp-client/__tests__/local-cdp-client.test.ts +310 -0
  413. package/src/tools/browser/cdp-client/__tests__/types.test.ts +96 -0
  414. package/src/tools/browser/cdp-client/accessibility-snapshot.ts +387 -0
  415. package/src/tools/browser/cdp-client/cdp-dom-helpers.ts +695 -0
  416. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/discovery.test.ts +743 -0
  417. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +580 -0
  418. package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +578 -0
  419. package/src/tools/browser/cdp-client/cdp-inspect/ws-transport.ts +579 -0
  420. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +635 -0
  421. package/src/tools/browser/cdp-client/errors.ts +34 -0
  422. package/src/tools/browser/cdp-client/extension-cdp-client.ts +125 -0
  423. package/src/tools/browser/cdp-client/factory.ts +204 -0
  424. package/src/tools/browser/cdp-client/index.ts +14 -0
  425. package/src/tools/browser/cdp-client/local-cdp-client.ts +187 -0
  426. package/src/tools/browser/cdp-client/types.ts +52 -0
  427. package/src/tools/filesystem/edit.ts +1 -1
  428. package/src/tools/filesystem/list.ts +1 -1
  429. package/src/tools/filesystem/read.ts +1 -1
  430. package/src/tools/filesystem/write.ts +2 -1
  431. package/src/tools/host-filesystem/edit.ts +1 -1
  432. package/src/tools/host-filesystem/read.ts +12 -15
  433. package/src/tools/host-filesystem/write.ts +1 -1
  434. package/src/tools/host-terminal/host-shell.ts +21 -16
  435. package/src/tools/permission-checker.ts +77 -100
  436. package/src/tools/registry.ts +0 -2
  437. package/src/tools/secret-detection-handler.ts +34 -1
  438. package/src/tools/shared/filesystem/image-read.ts +61 -40
  439. package/src/tools/skills/sandbox-runner.ts +3 -6
  440. package/src/tools/subagent/spawn.ts +47 -3
  441. package/src/tools/subagent/status.ts +2 -0
  442. package/src/tools/system/register.ts +2 -16
  443. package/src/tools/terminal/safe-env.ts +7 -0
  444. package/src/tools/terminal/sandbox-diagnostics.ts +4 -4
  445. package/src/tools/terminal/sandbox.ts +4 -1
  446. package/src/tools/terminal/shell.ts +24 -21
  447. package/src/tools/tool-approval-handler.ts +48 -2
  448. package/src/tools/types.ts +2 -3
  449. package/src/util/platform.ts +14 -19
  450. package/src/watcher/provider-types.ts +1 -1
  451. package/src/workspace/migrations/029-seed-pkb.ts +1 -0
  452. package/src/workspace/migrations/030-seed-pkb-autoinject.ts +73 -0
  453. package/src/workspace/migrations/registry.ts +2 -0
  454. package/src/workspace/top-level-renderer.ts +19 -1
  455. package/src/__tests__/chrome-cdp.test.ts +0 -419
  456. package/src/__tests__/permission-mode-sse.test.ts +0 -418
  457. package/src/__tests__/permission-mode-store.test.ts +0 -277
  458. package/src/browser-extension-relay/protocol.ts +0 -63
  459. package/src/browser-extension-relay/server.ts +0 -203
  460. package/src/config/schemas/sandbox.ts +0 -14
  461. package/src/permissions/permission-mode-store.ts +0 -180
  462. package/src/tools/browser/chrome-cdp.ts +0 -239
  463. package/src/tools/system/set-permission-mode.ts +0 -103
@@ -0,0 +1,229 @@
1
+ import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
2
+
3
+ let authDisabled = true;
4
+ let boundGuardianPrincipalId: string | null = null;
5
+
6
+ mock.module("../util/logger.js", () => ({
7
+ getLogger: () =>
8
+ new Proxy({} as Record<string, unknown>, {
9
+ get: () => () => {},
10
+ }),
11
+ }));
12
+
13
+ mock.module("../config/env.js", () => ({
14
+ isHttpAuthDisabled: () => authDisabled,
15
+ hasUngatedHttpAuthDisabled: () => false,
16
+ getGatewayInternalBaseUrl: () => "http://127.0.0.1:7830",
17
+ getGatewayPort: () => 7830,
18
+ getRuntimeHttpPort: () => 7821,
19
+ getRuntimeHttpHost: () => "127.0.0.1",
20
+ getRuntimeGatewayOriginSecret: () => undefined,
21
+ getIngressPublicBaseUrl: () => undefined,
22
+ setIngressPublicBaseUrl: () => {},
23
+ }));
24
+
25
+ mock.module("../contacts/contact-store.js", () => ({
26
+ findGuardianForChannel: () =>
27
+ boundGuardianPrincipalId
28
+ ? {
29
+ channel: { externalUserId: undefined },
30
+ contact: { principalId: boundGuardianPrincipalId },
31
+ }
32
+ : null,
33
+ }));
34
+
35
+ mock.module("../config/loader.js", () => ({
36
+ getConfig: () => ({
37
+ ui: {},
38
+ model: "test",
39
+ provider: "test",
40
+ memory: { enabled: false },
41
+ rateLimit: { maxRequestsPerMinute: 0 },
42
+ secretDetection: { enabled: false },
43
+ }),
44
+ }));
45
+
46
+ import {
47
+ createConversation,
48
+ updateConversationHostAccess,
49
+ } from "../memory/conversation-crud.js";
50
+ import { getDb, initializeDb, resetDb } from "../memory/db.js";
51
+ import { assistantEventHub } from "../runtime/assistant-event-hub.js";
52
+ import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
53
+ import { RuntimeHttpServer } from "../runtime/http-server.js";
54
+ import { conversationManagementRouteDefinitions } from "../runtime/routes/conversation-management-routes.js";
55
+
56
+ initializeDb();
57
+
58
+ const routes = conversationManagementRouteDefinitions({
59
+ switchConversation: async (conversationId) => {
60
+ const conversation = {
61
+ conversationId,
62
+ title: "Switched conversation",
63
+ conversationType: "standard",
64
+ hostAccess: false,
65
+ };
66
+ return conversation;
67
+ },
68
+ renameConversation: () => true,
69
+ clearAllConversations: () => 0,
70
+ cancelGeneration: () => true,
71
+ destroyConversation: () => {},
72
+ undoLastMessage: async () => null,
73
+ regenerateResponse: async () => null,
74
+ });
75
+
76
+ function findRoute(method: string, endpoint: string) {
77
+ const route = routes.find(
78
+ (routeDef) => routeDef.method === method && routeDef.endpoint === endpoint,
79
+ );
80
+ if (!route) {
81
+ throw new Error(`Route not found: ${method} ${endpoint}`);
82
+ }
83
+ return route;
84
+ }
85
+
86
+ function clearTables(): void {
87
+ const db = getDb();
88
+ db.run("DELETE FROM conversation_assistant_attention_state");
89
+ db.run("DELETE FROM external_conversation_bindings");
90
+ db.run("DELETE FROM conversation_keys");
91
+ db.run("DELETE FROM messages");
92
+ db.run("DELETE FROM conversations");
93
+ }
94
+
95
+ describe("conversation host-access transport", () => {
96
+ let server: RuntimeHttpServer | null = null;
97
+
98
+ beforeEach(async () => {
99
+ await server?.stop();
100
+ server = null;
101
+ authDisabled = true;
102
+ boundGuardianPrincipalId = null;
103
+ clearTables();
104
+ });
105
+
106
+ afterAll(async () => {
107
+ await server?.stop();
108
+ resetDb();
109
+ mock.restore();
110
+ });
111
+
112
+ test("GET and PATCH /v1/conversations/:id/host-access use the conversation store", async () => {
113
+ const conversation = createConversation("Host access test");
114
+
115
+ const getRoute = findRoute("GET", "conversations/:id/host-access");
116
+ const getResponse = await getRoute.handler({
117
+ req: new Request("http://localhost/v1/conversations/test/host-access"),
118
+ url: new URL("http://localhost/v1/conversations/test/host-access"),
119
+ server: null as never,
120
+ authContext: {} as never,
121
+ params: { id: conversation.id },
122
+ });
123
+
124
+ expect(getResponse.status).toBe(200);
125
+ expect(await getResponse.json()).toEqual({
126
+ conversationId: conversation.id,
127
+ hostAccess: false,
128
+ });
129
+
130
+ const received: Array<{
131
+ assistantId: string;
132
+ type: string;
133
+ conversationId?: string;
134
+ hostAccess?: boolean;
135
+ }> = [];
136
+ const subscription = assistantEventHub.subscribe(
137
+ { assistantId: DAEMON_INTERNAL_ASSISTANT_ID },
138
+ (event) => {
139
+ received.push({
140
+ assistantId: event.assistantId,
141
+ type: event.message.type,
142
+ conversationId: event.conversationId,
143
+ hostAccess:
144
+ event.message.type === "conversation_host_access_updated"
145
+ ? event.message.hostAccess
146
+ : undefined,
147
+ });
148
+ },
149
+ );
150
+
151
+ const patchRoute = findRoute("PATCH", "conversations/:id/host-access");
152
+ const patchResponse = await patchRoute.handler({
153
+ req: new Request("http://localhost/v1/conversations/test/host-access", {
154
+ method: "PATCH",
155
+ headers: { "Content-Type": "application/json" },
156
+ body: JSON.stringify({ hostAccess: true }),
157
+ }),
158
+ url: new URL("http://localhost/v1/conversations/test/host-access"),
159
+ server: null as never,
160
+ authContext: {} as never,
161
+ params: { id: conversation.id },
162
+ });
163
+
164
+ await Promise.resolve();
165
+
166
+ expect(patchResponse.status).toBe(200);
167
+ expect(await patchResponse.json()).toEqual({
168
+ conversationId: conversation.id,
169
+ hostAccess: true,
170
+ });
171
+ expect(received).toHaveLength(1);
172
+ expect(received[0]).toEqual({
173
+ assistantId: DAEMON_INTERNAL_ASSISTANT_ID,
174
+ type: "conversation_host_access_updated",
175
+ conversationId: conversation.id,
176
+ hostAccess: true,
177
+ });
178
+ subscription.dispose();
179
+ });
180
+
181
+ test("conversation summaries include hostAccess", async () => {
182
+ const conversation = createConversation("Summary host access");
183
+ updateConversationHostAccess(conversation.id, true);
184
+
185
+ server = new RuntimeHttpServer({
186
+ port: 0,
187
+ bearerToken: "test-bearer-token",
188
+ });
189
+ await server.start();
190
+
191
+ const response = await fetch(
192
+ `http://127.0.0.1:${server.actualPort}/v1/conversations/${conversation.id}`,
193
+ );
194
+ expect(response.status).toBe(200);
195
+
196
+ const body = (await response.json()) as {
197
+ conversation: {
198
+ id: string;
199
+ hostAccess: boolean;
200
+ };
201
+ };
202
+
203
+ expect(body.conversation.id).toBe(conversation.id);
204
+ expect(body.conversation.hostAccess).toBe(true);
205
+ });
206
+
207
+ test("PATCH /v1/conversations/:id/host-access rejects non-guardian actors when auth is enforced", async () => {
208
+ authDisabled = false;
209
+ boundGuardianPrincipalId = "guardian-principal";
210
+ const conversation = createConversation("Guarded host access");
211
+
212
+ const patchRoute = findRoute("PATCH", "conversations/:id/host-access");
213
+ const patchResponse = await patchRoute.handler({
214
+ req: new Request("http://localhost/v1/conversations/test/host-access", {
215
+ method: "PATCH",
216
+ headers: { "Content-Type": "application/json" },
217
+ body: JSON.stringify({ hostAccess: true }),
218
+ }),
219
+ url: new URL("http://localhost/v1/conversations/test/host-access"),
220
+ server: null as never,
221
+ authContext: {
222
+ actorPrincipalId: "trusted-contact-principal",
223
+ } as never,
224
+ params: { id: conversation.id },
225
+ });
226
+
227
+ expect(patchResponse.status).toBe(403);
228
+ });
229
+ });
@@ -0,0 +1,103 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import type { Message } from "../providers/types.js";
4
+
5
+ /**
6
+ * Unit tests for Conversation.injectInheritedContext() and
7
+ * Conversation.getCurrentSystemPrompt().
8
+ *
9
+ * These methods are thin enough to test via a minimal stub that mirrors the
10
+ * Conversation fields they touch, avoiding the heavyweight constructor
11
+ * dependencies.
12
+ */
13
+
14
+ /**
15
+ * Minimal stub that replicates the subset of Conversation used by
16
+ * injectInheritedContext() and getCurrentSystemPrompt().
17
+ */
18
+ function createStub(systemPrompt: string) {
19
+ return {
20
+ messages: [] as Message[],
21
+ systemPrompt,
22
+
23
+ injectInheritedContext(messages: Message[]): void {
24
+ if (this.messages.length !== 0) {
25
+ throw new Error(
26
+ "injectInheritedContext must be called before any messages have been added",
27
+ );
28
+ }
29
+ this.messages = [...messages];
30
+ },
31
+
32
+ getCurrentSystemPrompt(): string {
33
+ return this.systemPrompt;
34
+ },
35
+ };
36
+ }
37
+
38
+ const sampleMessages: Message[] = [
39
+ { role: "user", content: [{ type: "text", text: "Hello from parent" }] },
40
+ {
41
+ role: "assistant",
42
+ content: [{ type: "text", text: "Hi there, I am the assistant" }],
43
+ },
44
+ {
45
+ role: "user",
46
+ content: [{ type: "text", text: "Follow-up question" }],
47
+ },
48
+ ];
49
+
50
+ describe("Conversation.injectInheritedContext", () => {
51
+ test("injected messages appear in this.messages after injection", () => {
52
+ const stub = createStub("You are a helpful assistant.");
53
+ stub.injectInheritedContext(sampleMessages);
54
+
55
+ expect(stub.messages).toHaveLength(3);
56
+ expect(stub.messages[0]).toEqual(sampleMessages[0]);
57
+ expect(stub.messages[1]).toEqual(sampleMessages[1]);
58
+ expect(stub.messages[2]).toEqual(sampleMessages[2]);
59
+ });
60
+
61
+ test("injected messages are a shallow copy, not the same array reference", () => {
62
+ const stub = createStub("prompt");
63
+ stub.injectInheritedContext(sampleMessages);
64
+
65
+ expect(stub.messages).not.toBe(sampleMessages);
66
+ // Individual message objects are shared (shallow copy)
67
+ expect(stub.messages[0]).toBe(sampleMessages[0]);
68
+ });
69
+
70
+ test("assertion fires if called after messages have been added", () => {
71
+ const stub = createStub("prompt");
72
+ // Simulate a message already being present (as if persistUserMessage was called)
73
+ stub.messages.push({
74
+ role: "user",
75
+ content: [{ type: "text", text: "existing message" }],
76
+ });
77
+
78
+ expect(() => stub.injectInheritedContext(sampleMessages)).toThrow(
79
+ "injectInheritedContext must be called before any messages have been added",
80
+ );
81
+ });
82
+
83
+ test("injecting an empty array leaves messages empty", () => {
84
+ const stub = createStub("prompt");
85
+ stub.injectInheritedContext([]);
86
+
87
+ expect(stub.messages).toHaveLength(0);
88
+ });
89
+ });
90
+
91
+ describe("Conversation.getCurrentSystemPrompt", () => {
92
+ test("returns the construction-time system prompt", () => {
93
+ const prompt = "You are a research assistant with deep knowledge.";
94
+ const stub = createStub(prompt);
95
+
96
+ expect(stub.getCurrentSystemPrompt()).toBe(prompt);
97
+ });
98
+
99
+ test("returns empty string when constructed with empty prompt", () => {
100
+ const stub = createStub("");
101
+ expect(stub.getCurrentSystemPrompt()).toBe("");
102
+ });
103
+ });
@@ -1,5 +1,13 @@
1
1
  import { rmSync, writeFileSync } from "node:fs";
2
- import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
2
+ import {
3
+ afterAll,
4
+ afterEach,
5
+ beforeEach,
6
+ describe,
7
+ expect,
8
+ mock,
9
+ test,
10
+ } from "bun:test";
3
11
 
4
12
  import type {
5
13
  AgentEvent,
@@ -95,6 +103,8 @@ mock.module("../config/loader.js", () => ({
95
103
  invalidateConfigCache: () => {},
96
104
  }));
97
105
 
106
+ const mockedConversationHostAccess = new Map<string, boolean>();
107
+
98
108
  mock.module("../prompts/system-prompt.js", () => ({
99
109
  buildSystemPrompt: () => "system prompt",
100
110
  }));
@@ -113,6 +123,7 @@ mock.module("../permissions/trust-store.js", () => ({
113
123
  addRule: () => {},
114
124
  findHighestPriorityRule: () => null,
115
125
  clearCache: () => {},
126
+ patternMatchesCandidate: () => false,
116
127
  }));
117
128
 
118
129
  mock.module("../security/secret-allowlist.js", () => ({
@@ -123,6 +134,14 @@ mock.module("../memory/conversation-crud.js", () => ({
123
134
  getConversationType: () => "default",
124
135
  setConversationOriginChannelIfUnset: () => {},
125
136
  updateConversationContextWindow: () => {},
137
+ getConversationHostAccess: (conversationId: string) =>
138
+ mockedConversationHostAccess.get(conversationId) ?? false,
139
+ updateConversationHostAccess: (
140
+ conversationId: string,
141
+ hostAccess: boolean,
142
+ ) => {
143
+ mockedConversationHostAccess.set(conversationId, hostAccess);
144
+ },
126
145
  deleteMessageById: () => {},
127
146
  provenanceFromTrustContext: () => ({
128
147
  source: "user",
@@ -1315,8 +1334,18 @@ describe("Terminal trace events on rejection/failure", () => {
1315
1334
  // ---------------------------------------------------------------------------
1316
1335
 
1317
1336
  describe("Conversation host attachment directives", () => {
1318
- beforeEach(() => {
1337
+ beforeEach(async () => {
1319
1338
  pendingRuns = [];
1339
+ mockedConversationHostAccess.clear();
1340
+ const { _setOverridesForTesting } =
1341
+ await import("../config/assistant-feature-flags.js");
1342
+ _setOverridesForTesting({ "permission-controls-v2": true });
1343
+ });
1344
+
1345
+ afterEach(async () => {
1346
+ const { _setOverridesForTesting } =
1347
+ await import("../config/assistant-feature-flags.js");
1348
+ _setOverridesForTesting({});
1320
1349
  });
1321
1350
 
1322
1351
  test("host attachment prompts and resolves when user allows", async () => {
@@ -1364,6 +1393,19 @@ describe("Conversation host attachment directives", () => {
1364
1393
  (e) => e.type === "confirmation_request",
1365
1394
  );
1366
1395
  expect(confirmation).toBeDefined();
1396
+ expect(
1397
+ (confirmation as { persistentDecisionsAllowed?: boolean })
1398
+ .persistentDecisionsAllowed,
1399
+ ).toBe(false);
1400
+ expect(
1401
+ (
1402
+ confirmation as {
1403
+ temporaryOptionsAvailable?: Array<
1404
+ "allow_10m" | "allow_conversation"
1405
+ >;
1406
+ }
1407
+ ).temporaryOptionsAvailable ?? [],
1408
+ ).toEqual([]);
1367
1409
  conversation.handleConfirmationResponse(
1368
1410
  (confirmation as { requestId: string }).requestId,
1369
1411
  "allow",
@@ -1371,6 +1413,7 @@ describe("Conversation host attachment directives", () => {
1371
1413
 
1372
1414
  await p1;
1373
1415
 
1416
+ expect(mockedConversationHostAccess.get("conv-1")).toBe(true);
1374
1417
  expect(conversation.lastAssistantAttachments).toHaveLength(1);
1375
1418
  expect(conversation.lastAssistantAttachments[0].sourceType).toBe(
1376
1419
  "host_file",
@@ -114,6 +114,7 @@ function createFakeConversation(conversationId: string): Conversation {
114
114
  } | null,
115
115
  messages: [] as Array<unknown>,
116
116
  hostBashProxy: undefined as unknown,
117
+ hostBrowserProxy: undefined as unknown,
117
118
  hostFileProxy: undefined as unknown,
118
119
  hostCuProxy: undefined as unknown,
119
120
  usageStats: { inputTokens: 0, outputTokens: 0, estimatedCost: 0 },
@@ -178,12 +179,16 @@ function createFakeConversation(conversationId: string): Conversation {
178
179
  setHostBashProxy(this: { hostBashProxy: unknown }, proxy: unknown) {
179
180
  this.hostBashProxy = proxy;
180
181
  },
182
+ setHostBrowserProxy(this: { hostBrowserProxy: unknown }, proxy: unknown) {
183
+ this.hostBrowserProxy = proxy;
184
+ },
181
185
  setHostFileProxy(this: { hostFileProxy: unknown }, proxy: unknown) {
182
186
  this.hostFileProxy = proxy;
183
187
  },
184
188
  setHostCuProxy(this: { hostCuProxy: unknown }, proxy: unknown) {
185
189
  this.hostCuProxy = proxy;
186
190
  },
191
+ restoreBrowserProxyAvailability: () => {},
187
192
  addPreactivatedSkillId: () => {},
188
193
  hasAnyPendingConfirmation: () => false,
189
194
  hasPendingConfirmation: () => false,
@@ -170,8 +170,10 @@ describe("handleSendMessage canonical guardian reply interception", () => {
170
170
  trustContext: undefined,
171
171
  hasPendingConfirmation: () => false,
172
172
  setHostBashProxy: () => {},
173
+ setHostBrowserProxy: () => {},
173
174
  setHostFileProxy: () => {},
174
175
  setHostCuProxy: () => {},
176
+ restoreBrowserProxyAvailability: () => {},
175
177
  addPreactivatedSkillId: () => {},
176
178
  } as unknown as import("../daemon/conversation.js").Conversation;
177
179
 
@@ -247,8 +249,10 @@ describe("handleSendMessage canonical guardian reply interception", () => {
247
249
  trustContext: undefined,
248
250
  hasPendingConfirmation: () => false,
249
251
  setHostBashProxy: () => {},
252
+ setHostBrowserProxy: () => {},
250
253
  setHostFileProxy: () => {},
251
254
  setHostCuProxy: () => {},
255
+ restoreBrowserProxyAvailability: () => {},
252
256
  addPreactivatedSkillId: () => {},
253
257
  } as unknown as import("../daemon/conversation.js").Conversation;
254
258
 
@@ -320,8 +324,10 @@ describe("handleSendMessage canonical guardian reply interception", () => {
320
324
  hasPendingConfirmation: (requestId: string) =>
321
325
  requestId === "tool-approval-live",
322
326
  setHostBashProxy: () => {},
327
+ setHostBrowserProxy: () => {},
323
328
  setHostFileProxy: () => {},
324
329
  setHostCuProxy: () => {},
330
+ restoreBrowserProxyAvailability: () => {},
325
331
  addPreactivatedSkillId: () => {},
326
332
  } as unknown as import("../daemon/conversation.js").Conversation;
327
333
 
@@ -397,8 +403,10 @@ describe("handleSendMessage canonical guardian reply interception", () => {
397
403
  trustContext: undefined,
398
404
  hasPendingConfirmation: (id: string) => id === "tool-req-code-1",
399
405
  setHostBashProxy: () => {},
406
+ setHostBrowserProxy: () => {},
400
407
  setHostFileProxy: () => {},
401
408
  setHostCuProxy: () => {},
409
+ restoreBrowserProxyAvailability: () => {},
402
410
  addPreactivatedSkillId: () => {},
403
411
  } as unknown as import("../daemon/conversation.js").Conversation;
404
412
 
@@ -470,8 +478,10 @@ describe("handleSendMessage canonical guardian reply interception", () => {
470
478
  trustContext: undefined,
471
479
  hasPendingConfirmation: (id: string) => id === "pending-reject-1",
472
480
  setHostBashProxy: () => {},
481
+ setHostBrowserProxy: () => {},
473
482
  setHostFileProxy: () => {},
474
483
  setHostCuProxy: () => {},
484
+ restoreBrowserProxyAvailability: () => {},
475
485
  addPreactivatedSkillId: () => {},
476
486
  } as unknown as import("../daemon/conversation.js").Conversation;
477
487
 
@@ -537,8 +547,10 @@ describe("handleSendMessage canonical guardian reply interception", () => {
537
547
  trustContext: undefined,
538
548
  hasPendingConfirmation: (id: string) => id === "pending-1",
539
549
  setHostBashProxy: () => {},
550
+ setHostBrowserProxy: () => {},
540
551
  setHostFileProxy: () => {},
541
552
  setHostCuProxy: () => {},
553
+ restoreBrowserProxyAvailability: () => {},
542
554
  addPreactivatedSkillId: () => {},
543
555
  } as unknown as import("../daemon/conversation.js").Conversation;
544
556
 
@@ -606,8 +618,10 @@ describe("handleSendMessage canonical guardian reply interception", () => {
606
618
  trustContext: undefined,
607
619
  hasPendingConfirmation: () => false,
608
620
  setHostBashProxy: () => {},
621
+ setHostBrowserProxy: () => {},
609
622
  setHostFileProxy: () => {},
610
623
  setHostCuProxy: () => {},
624
+ restoreBrowserProxyAvailability: () => {},
611
625
  addPreactivatedSkillId: () => {},
612
626
  } as unknown as import("../daemon/conversation.js").Conversation;
613
627
 
@@ -676,8 +690,10 @@ describe("handleSendMessage canonical guardian reply interception", () => {
676
690
  trustContext: undefined,
677
691
  hasPendingConfirmation: () => false,
678
692
  setHostBashProxy: () => {},
693
+ setHostBrowserProxy: () => {},
679
694
  setHostFileProxy: () => {},
680
695
  setHostCuProxy: () => {},
696
+ restoreBrowserProxyAvailability: () => {},
681
697
  addPreactivatedSkillId: () => {},
682
698
  } as unknown as import("../daemon/conversation.js").Conversation;
683
699
 
@@ -207,6 +207,7 @@ function makeConversation() {
207
207
  trustContext: undefined,
208
208
  hasPendingConfirmation: () => false,
209
209
  setHostBashProxy: () => {},
210
+ setHostBrowserProxy: () => {},
210
211
  setHostFileProxy: () => {},
211
212
  setHostCuProxy: () => {},
212
213
  addPreactivatedSkillId: () => {},