@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,332 @@
1
+ /**
2
+ * Registry mapping guardianId → active Chrome extension WebSocket connections.
3
+ *
4
+ * Populated by the `/v1/browser-relay` WebSocket upgrade handler when a
5
+ * chrome-extension client connects; drained on close. Used by
6
+ * conversation-routes.ts to route `host_browser_request` frames to the
7
+ * connected extension for the appropriate guardian.
8
+ *
9
+ * This is the chrome-extension counterpart to the SSE hub used by the macOS
10
+ * client for the same purpose.
11
+ *
12
+ * A single guardian may have multiple simultaneous extension connections —
13
+ * e.g. the same guardian signed in on two Chrome profiles, two desktops
14
+ * sharing a sync identity, or a power user with parallel installs for
15
+ * testing. Each install generates a stable `clientInstanceId` on first
16
+ * run and sends it on every handshake; the registry keys inner entries by
17
+ * that id so sibling instances don't evict each other on register/unregister.
18
+ *
19
+ * Routing semantics:
20
+ * - When a caller does not pin a specific instance, the registry picks
21
+ * the "most recently active" instance for the guardian (highest
22
+ * `lastActiveAt` timestamp). `lastActiveAt` is bumped on register and
23
+ * on every successful `send()`, which is a good enough stand-in for
24
+ * WebSocket heartbeats under the current load profile.
25
+ * - When no `clientInstanceId` is present on the handshake (older
26
+ * extension builds, dev bypass paths), we synthesize a placeholder
27
+ * `legacy:<connectionId>` key. The send/lookup path treats it the
28
+ * same as any other instance so the call site stays uniform. The
29
+ * synthesized key is deliberately connection-scoped so a stale
30
+ * legacy unregister can never evict a newer entry.
31
+ */
32
+
33
+ import type { ServerWebSocket } from "bun";
34
+
35
+ import type { ServerMessage } from "../daemon/message-protocol.js";
36
+ import { getLogger } from "../util/logger.js";
37
+
38
+ const log = getLogger("chrome-extension-registry");
39
+
40
+ /** Prefix applied to synthesized instance ids for connections that did not
41
+ * provide a client-supplied `clientInstanceId` at handshake time. Kept
42
+ * distinct from any plausible client-generated value so it never collides
43
+ * with a real install id. */
44
+ const LEGACY_INSTANCE_PREFIX = "legacy:";
45
+
46
+ export interface ChromeExtensionConnection {
47
+ /** Stable identifier for this WebSocket connection (used for unregister). */
48
+ id: string;
49
+ /** Guardian identity this connection is authenticated as. */
50
+ guardianId: string;
51
+ /**
52
+ * Stable per-extension-install identifier (persists across browser
53
+ * restarts, survives service-worker teardown). Absent on older
54
+ * extension builds and on dev-bypass paths — the registry synthesizes
55
+ * a `legacy:<connectionId>` key in that case so sibling multi-instance
56
+ * semantics degrade gracefully to single-instance behavior.
57
+ */
58
+ clientInstanceId?: string;
59
+ /** Underlying Bun WebSocket. */
60
+ ws: ServerWebSocket<unknown>;
61
+ /** Wall-clock timestamp (ms) when the connection was registered. */
62
+ connectedAt: number;
63
+ /**
64
+ * Wall-clock timestamp (ms) of the most recent activity on this
65
+ * connection — updated on register and on each successful `send()`.
66
+ * Used by the default-send routing path to pick the "most recently
67
+ * active" instance when the caller does not pin a specific one.
68
+ */
69
+ lastActiveAt: number;
70
+ /**
71
+ * Monotonic registration sequence number assigned by the registry
72
+ * on each `register()` call. Used as a tuple-secondary tiebreaker
73
+ * after `lastActiveAt` when picking the default active instance, so
74
+ * two sibling instances that share the same millisecond timestamp
75
+ * deterministically resolve to the most recently registered entry.
76
+ *
77
+ * Not used when the registry routes to an explicit instance via
78
+ * `sendToInstance` / `getInstance`. Clients should treat this as an
79
+ * internal field — it's assigned by `register()` and callers don't
80
+ * need to populate it when constructing a connection.
81
+ */
82
+ registrationSeq?: number;
83
+ }
84
+
85
+ /**
86
+ * Module-level registry of active chrome-extension connections keyed by
87
+ * guardianId, then by clientInstanceId. Multiple concurrent connections
88
+ * under the same guardian are supported; reconnects of the *same* install
89
+ * supersede the prior entry for that instance only, leaving sibling
90
+ * instances untouched.
91
+ */
92
+ export class ChromeExtensionRegistry {
93
+ private byGuardian = new Map<
94
+ string,
95
+ Map<string, ChromeExtensionConnection>
96
+ >();
97
+ /**
98
+ * Monotonic counter stamped onto each registration as
99
+ * `registrationSeq`, used as a secondary tiebreaker after
100
+ * `lastActiveAt` in the default routing path. Starts at 0 and
101
+ * increments before stamping so the first registered connection has
102
+ * `registrationSeq === 1`.
103
+ *
104
+ * This exists because `lastActiveAt` is `Date.now()`, which has
105
+ * millisecond resolution at best; two sibling instances that
106
+ * register (or transmit) in the same millisecond would otherwise
107
+ * resolve ties via insertion order of `Map#values()`, which is
108
+ * technically well-defined but is not the "most recently registered"
109
+ * behavior a caller would expect. A monotonic counter fixes that
110
+ * deterministically.
111
+ */
112
+ private seqCounter = 0;
113
+
114
+ /**
115
+ * Resolve the effective instance key for a connection. Prefers the
116
+ * client-supplied `clientInstanceId`; falls back to a
117
+ * connection-scoped `legacy:<connectionId>` placeholder when absent
118
+ * so older clients get stable single-instance semantics without
119
+ * clobbering sibling instances for the same guardian.
120
+ */
121
+ private keyFor(conn: ChromeExtensionConnection): string {
122
+ return conn.clientInstanceId ?? `${LEGACY_INSTANCE_PREFIX}${conn.id}`;
123
+ }
124
+
125
+ /**
126
+ * Register a chrome-extension WebSocket for a guardian + instance.
127
+ * If a prior connection already exists for the same guardianId AND
128
+ * clientInstanceId (i.e. the same install reconnecting), it is closed
129
+ * and replaced with the new one. Sibling instances for the same
130
+ * guardian are left untouched.
131
+ */
132
+ register(conn: ChromeExtensionConnection): void {
133
+ let instances = this.byGuardian.get(conn.guardianId);
134
+ if (!instances) {
135
+ instances = new Map();
136
+ this.byGuardian.set(conn.guardianId, instances);
137
+ }
138
+
139
+ const instanceKey = this.keyFor(conn);
140
+ const prior = instances.get(instanceKey);
141
+ if (prior && prior.id !== conn.id) {
142
+ try {
143
+ prior.ws.close(1000, "superseded by new connection");
144
+ } catch {
145
+ // Best-effort — the prior socket may already be closed.
146
+ }
147
+ }
148
+ // Stamp lastActiveAt on (re-)register so the "most recently active"
149
+ // routing heuristic treats a fresh connection as the current default
150
+ // target for its guardian. Stamp a monotonic registrationSeq
151
+ // alongside it so two registrations that land in the same
152
+ // millisecond resolve deterministically to the newer one.
153
+ conn.lastActiveAt = Date.now();
154
+ conn.registrationSeq = ++this.seqCounter;
155
+ instances.set(instanceKey, conn);
156
+ log.info(
157
+ {
158
+ guardianId: conn.guardianId,
159
+ connectionId: conn.id,
160
+ clientInstanceId: conn.clientInstanceId,
161
+ registrationSeq: conn.registrationSeq,
162
+ instanceCount: instances.size,
163
+ },
164
+ "chrome extension registered",
165
+ );
166
+ }
167
+
168
+ /**
169
+ * Remove the entry with the given connectionId. No-op if no connection
170
+ * with that id is currently registered — the entry may already have been
171
+ * superseded by a newer registration for the same instance, or the
172
+ * guardian may have zero active instances remaining.
173
+ *
174
+ * Importantly, this does not evict sibling instances under the same
175
+ * guardian — multi-instance routing depends on keeping them alive
176
+ * across single-instance reconnects.
177
+ */
178
+ unregister(connectionId: string): void {
179
+ for (const [guardianId, instances] of this.byGuardian) {
180
+ for (const [instanceKey, conn] of instances) {
181
+ if (conn.id === connectionId) {
182
+ instances.delete(instanceKey);
183
+ if (instances.size === 0) {
184
+ this.byGuardian.delete(guardianId);
185
+ }
186
+ log.info(
187
+ {
188
+ guardianId,
189
+ connectionId,
190
+ clientInstanceId: conn.clientInstanceId,
191
+ remaining: instances.size,
192
+ },
193
+ "chrome extension unregistered",
194
+ );
195
+ return;
196
+ }
197
+ }
198
+ }
199
+ }
200
+
201
+ /**
202
+ * Return the default "active" connection for a guardian — the
203
+ * instance with the most recent `lastActiveAt` timestamp. Ties on
204
+ * `lastActiveAt` (common when two sibling instances register or
205
+ * transmit within the same millisecond) are broken by the monotonic
206
+ * `registrationSeq` counter, which deterministically prefers the
207
+ * most recently registered instance. Returns `undefined` when no
208
+ * instances are registered for the guardian.
209
+ *
210
+ * Callers that want to pin a specific instance should use
211
+ * {@link getInstance} instead.
212
+ */
213
+ get(guardianId: string): ChromeExtensionConnection | undefined {
214
+ const instances = this.byGuardian.get(guardianId);
215
+ if (!instances || instances.size === 0) return undefined;
216
+ let best: ChromeExtensionConnection | undefined;
217
+ for (const conn of instances.values()) {
218
+ if (!best) {
219
+ best = conn;
220
+ continue;
221
+ }
222
+ if (conn.lastActiveAt > best.lastActiveAt) {
223
+ best = conn;
224
+ } else if (
225
+ conn.lastActiveAt === best.lastActiveAt &&
226
+ (conn.registrationSeq ?? 0) > (best.registrationSeq ?? 0)
227
+ ) {
228
+ best = conn;
229
+ }
230
+ }
231
+ return best;
232
+ }
233
+
234
+ /**
235
+ * Return the connection for an explicit (guardianId, clientInstanceId)
236
+ * pair, or `undefined` if no such instance is registered. Used by
237
+ * routing callers that need to target a specific extension install
238
+ * (e.g. sending a follow-up frame to the same instance that produced
239
+ * the prior result).
240
+ */
241
+ getInstance(
242
+ guardianId: string,
243
+ clientInstanceId: string,
244
+ ): ChromeExtensionConnection | undefined {
245
+ return this.byGuardian.get(guardianId)?.get(clientInstanceId);
246
+ }
247
+
248
+ /**
249
+ * Return all currently registered connections for a guardian. Order
250
+ * is insertion order of the inner map — callers that care about
251
+ * recency should sort by `lastActiveAt` themselves.
252
+ */
253
+ listInstances(guardianId: string): ChromeExtensionConnection[] {
254
+ const instances = this.byGuardian.get(guardianId);
255
+ if (!instances) return [];
256
+ return Array.from(instances.values());
257
+ }
258
+
259
+ /**
260
+ * Send a ServerMessage to the default active chrome-extension
261
+ * connection for the given guardian. The "default active" instance
262
+ * is the one with the most recent `lastActiveAt` timestamp — i.e.
263
+ * the install the user is currently driving.
264
+ *
265
+ * Returns `true` when a connection exists and the send succeeds;
266
+ * `false` when no connection is registered or when the underlying
267
+ * `ws.send` throws. On a successful send, the connection's
268
+ * `lastActiveAt` is bumped so subsequent default sends stay on the
269
+ * same instance unless another sibling becomes more recent.
270
+ */
271
+ send(guardianId: string, msg: ServerMessage): boolean {
272
+ const conn = this.get(guardianId);
273
+ if (!conn) return false;
274
+ return this.sendTo(conn, msg);
275
+ }
276
+
277
+ /**
278
+ * Send a ServerMessage to an explicit (guardianId, clientInstanceId)
279
+ * pair. Returns `false` when no matching instance is registered or
280
+ * when the underlying `ws.send` throws.
281
+ */
282
+ sendToInstance(
283
+ guardianId: string,
284
+ clientInstanceId: string,
285
+ msg: ServerMessage,
286
+ ): boolean {
287
+ const conn = this.getInstance(guardianId, clientInstanceId);
288
+ if (!conn) return false;
289
+ return this.sendTo(conn, msg);
290
+ }
291
+
292
+ /**
293
+ * Low-level send helper — writes to the socket and bumps
294
+ * `lastActiveAt` on success. Callers should use {@link send} or
295
+ * {@link sendToInstance} unless they already hold a resolved
296
+ * connection handle.
297
+ */
298
+ private sendTo(conn: ChromeExtensionConnection, msg: ServerMessage): boolean {
299
+ try {
300
+ conn.ws.send(JSON.stringify(msg));
301
+ conn.lastActiveAt = Date.now();
302
+ return true;
303
+ } catch (err) {
304
+ log.warn(
305
+ {
306
+ guardianId: conn.guardianId,
307
+ connectionId: conn.id,
308
+ clientInstanceId: conn.clientInstanceId,
309
+ err,
310
+ },
311
+ "failed to send to chrome extension",
312
+ );
313
+ return false;
314
+ }
315
+ }
316
+ }
317
+
318
+ // ── Module-level singleton (same pattern as assistant-event-hub) ──────────
319
+ let instance: ChromeExtensionRegistry | null = null;
320
+
321
+ export function getChromeExtensionRegistry(): ChromeExtensionRegistry {
322
+ if (!instance) instance = new ChromeExtensionRegistry();
323
+ return instance;
324
+ }
325
+
326
+ /**
327
+ * Test helper: reset the module-level singleton so each test starts with a
328
+ * fresh registry. Not exported from any public index — test-only.
329
+ */
330
+ export function __resetChromeExtensionRegistryForTests(): void {
331
+ instance = null;
332
+ }
@@ -19,6 +19,7 @@ import {
19
19
  } from "../memory/canonical-guardian-store.js";
20
20
  import { emitNotificationSignal } from "../notifications/emit-signal.js";
21
21
  import type { NotificationSourceChannel } from "../notifications/signal.js";
22
+ import { isPermissionControlsV2Enabled } from "../permissions/v2-consent-policy.js";
22
23
  import { canonicalizeInboundIdentity } from "../util/canonicalize-identity.js";
23
24
  import { getLogger } from "../util/logger.js";
24
25
  import { DAEMON_INTERNAL_ASSISTANT_ID } from "./assistant-scope.js";
@@ -49,6 +50,7 @@ export type BridgeConfirmationRequestResult =
49
50
  skipped: true;
50
51
  reason:
51
52
  | "not_trusted_contact"
53
+ | "v2_model_mediated"
52
54
  | "no_guardian_binding"
53
55
  | "missing_guardian_identity"
54
56
  | "binding_identity_mismatch";
@@ -84,6 +86,10 @@ export function bridgeConfirmationRequestToGuardian(
84
86
  return { skipped: true, reason: "not_trusted_contact" };
85
87
  }
86
88
 
89
+ if (isPermissionControlsV2Enabled()) {
90
+ return { skipped: true, reason: "v2_model_mediated" };
91
+ }
92
+
87
93
  if (!trustContext.guardianExternalUserId) {
88
94
  log.debug(
89
95
  { conversationId, sourceChannel: trustContext.sourceChannel },
@@ -79,6 +79,13 @@ export const GUARDIAN_DECISION_ACTIONS = {
79
79
  reject: { action: "reject", label: "Reject", description: "Deny this call" },
80
80
  } as const satisfies Record<string, GuardianDecisionAction>;
81
81
 
82
+ export function buildOneTimeDecisionActions(): GuardianDecisionAction[] {
83
+ return [
84
+ GUARDIAN_DECISION_ACTIONS.approve_once,
85
+ GUARDIAN_DECISION_ACTIONS.reject,
86
+ ];
87
+ }
88
+
82
89
  /**
83
90
  * Build the set of `GuardianDecisionAction` items appropriate for a prompt,
84
91
  * respecting whether persistent decisions (approve_always) are allowed.