@vellumai/assistant 0.6.2 → 0.6.4

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 (895) hide show
  1. package/ARCHITECTURE.md +273 -10
  2. package/Dockerfile +2 -3
  3. package/bun.lock +41 -49
  4. package/bunfig.toml +3 -0
  5. package/docs/architecture/memory.md +1 -1
  6. package/docs/backup-troubleshooting.md +52 -0
  7. package/docs/browser-use-architecture-phase2.md +174 -0
  8. package/docs/stt-provider-onboarding.md +120 -0
  9. package/knip.json +12 -2
  10. package/node_modules/@vellumai/ces-contracts/bun.lock +8 -6
  11. package/node_modules/@vellumai/ces-contracts/package.json +3 -3
  12. package/node_modules/@vellumai/ces-contracts/src/rpc.ts +42 -0
  13. package/openapi.yaml +1111 -86
  14. package/package.json +40 -42
  15. package/scripts/generate-openapi.ts +0 -2
  16. package/scripts/test.sh +73 -18
  17. package/src/__tests__/acp-session.test.ts +43 -0
  18. package/src/__tests__/agent-image-optimize.test.ts +28 -0
  19. package/src/__tests__/agent-loop.test.ts +123 -0
  20. package/src/__tests__/anthropic-provider.test.ts +263 -10
  21. package/src/__tests__/app-builder-tool-scripts.test.ts +1 -0
  22. package/src/__tests__/app-executors.test.ts +1 -0
  23. package/src/__tests__/app-source-watcher.test.ts +37 -11
  24. package/src/__tests__/approval-routes-http.test.ts +178 -1
  25. package/src/__tests__/auto-analysis-end-to-end.test.ts +550 -0
  26. package/src/__tests__/auto-analysis-prompt.test.ts +50 -0
  27. package/src/__tests__/browser-fill-credential.test.ts +240 -94
  28. package/src/__tests__/browser-manager.test.ts +40 -27
  29. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +2 -2
  30. package/src/__tests__/browser-skill-endstate.test.ts +31 -7
  31. package/src/__tests__/btw-routes.test.ts +7 -0
  32. package/src/__tests__/call-controller.test.ts +581 -20
  33. package/src/__tests__/catalog-files.test.ts +1000 -0
  34. package/src/__tests__/channel-approvals.test.ts +53 -0
  35. package/src/__tests__/channel-invite-transport.test.ts +2 -2
  36. package/src/__tests__/channel-readiness-routes.test.ts +16 -20
  37. package/src/__tests__/channel-readiness-service.test.ts +12 -7
  38. package/src/__tests__/checker.test.ts +157 -10
  39. package/src/__tests__/clawhub-files.test.ts +347 -0
  40. package/src/__tests__/commit-message-enrichment-service.test.ts +36 -19
  41. package/src/__tests__/config-analysis.test.ts +100 -0
  42. package/src/__tests__/config-managed-gemini-defaults.test.ts +326 -0
  43. package/src/__tests__/config-schema-cmd.test.ts +2 -2
  44. package/src/__tests__/config-schema.test.ts +1248 -224
  45. package/src/__tests__/config-watcher-cleanup-throttle.test.ts +339 -0
  46. package/src/__tests__/config-watcher.test.ts +43 -8
  47. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +23 -0
  48. package/src/__tests__/contact-store-user-file.test.ts +512 -0
  49. package/src/__tests__/contacts-write.test.ts +197 -0
  50. package/src/__tests__/context-overflow-approval.test.ts +16 -1
  51. package/src/__tests__/context-window-manager.test.ts +88 -0
  52. package/src/__tests__/conversation-abort-tool-results.test.ts +2 -0
  53. package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -1
  54. package/src/__tests__/conversation-agent-loop.test.ts +99 -3
  55. package/src/__tests__/conversation-analysis-routes.test.ts +2 -2
  56. package/src/__tests__/conversation-attachments.test.ts +80 -4
  57. package/src/__tests__/conversation-confirmation-signals.test.ts +290 -0
  58. package/src/__tests__/conversation-error.test.ts +70 -0
  59. package/src/__tests__/conversation-fork-crud.test.ts +17 -0
  60. package/src/__tests__/conversation-history-web-search.test.ts +12 -4
  61. package/src/__tests__/conversation-host-access-routes.test.ts +229 -0
  62. package/src/__tests__/conversation-init.benchmark.test.ts +6 -1
  63. package/src/__tests__/conversation-inject-context.test.ts +103 -0
  64. package/src/__tests__/conversation-launcher-skill-regression.test.ts +51 -0
  65. package/src/__tests__/conversation-list-source.test.ts +145 -0
  66. package/src/__tests__/conversation-pre-run-repair.test.ts +2 -0
  67. package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -0
  68. package/src/__tests__/conversation-queue.test.ts +946 -62
  69. package/src/__tests__/conversation-routes-disk-view.test.ts +275 -0
  70. package/src/__tests__/conversation-routes-guardian-reply.test.ts +16 -0
  71. package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
  72. package/src/__tests__/conversation-runtime-assembly.test.ts +324 -46
  73. package/src/__tests__/conversation-skill-tools.test.ts +7 -4
  74. package/src/__tests__/conversation-slash-commands.test.ts +33 -0
  75. package/src/__tests__/conversation-slash-queue.test.ts +89 -18
  76. package/src/__tests__/conversation-slash-unknown.test.ts +2 -0
  77. package/src/__tests__/conversation-starter-routes.test.ts +126 -0
  78. package/src/__tests__/conversation-starters-cadence.test.ts +161 -0
  79. package/src/__tests__/conversation-store.test.ts +195 -0
  80. package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +226 -0
  81. package/src/__tests__/conversation-workspace-cache-state.test.ts +193 -0
  82. package/src/__tests__/conversation-workspace-injection.test.ts +2 -0
  83. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +2 -0
  84. package/src/__tests__/credential-execution-approval-bridge.test.ts +32 -1
  85. package/src/__tests__/credential-health-service.test.ts +352 -0
  86. package/src/__tests__/credential-security-invariants.test.ts +6 -3
  87. package/src/__tests__/credential-vault-unit.test.ts +383 -7
  88. package/src/__tests__/credential-vault.test.ts +152 -13
  89. package/src/__tests__/credentials-cli.test.ts +42 -18
  90. package/src/__tests__/cross-provider-web-search.test.ts +146 -35
  91. package/src/__tests__/date-context.test.ts +4 -4
  92. package/src/__tests__/deterministic-verification-control-plane.test.ts +10 -1
  93. package/src/__tests__/device-id.test.ts +112 -0
  94. package/src/__tests__/docker-signing-key-bootstrap.test.ts +167 -4
  95. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +1 -3
  96. package/src/__tests__/email-html-renderer.test.ts +71 -0
  97. package/src/__tests__/email-invite-adapter.test.ts +36 -32
  98. package/src/__tests__/embedding-managed-proxy-selection.test.ts +256 -0
  99. package/src/__tests__/emit-event-signal.test.ts +71 -0
  100. package/src/__tests__/extension-id-sync-guard.test.ts +222 -0
  101. package/src/__tests__/fixtures/mock-chrome-extension.ts +386 -0
  102. package/src/__tests__/gateway-only-enforcement.test.ts +206 -1
  103. package/src/__tests__/gateway-only-guard.test.ts +2 -0
  104. package/src/__tests__/gemini-provider.test.ts +66 -2
  105. package/src/__tests__/get-skill-detail-audit.test.ts +325 -0
  106. package/src/__tests__/gmail-archive-fallback.test.ts +193 -0
  107. package/src/__tests__/gmail-archive-gate.test.ts +246 -0
  108. package/src/__tests__/gmail-preferences.test.ts +117 -0
  109. package/src/__tests__/guardian-routing-invariants.test.ts +70 -2
  110. package/src/__tests__/headless-browser-interactions.test.ts +738 -359
  111. package/src/__tests__/headless-browser-mode.test.ts +614 -0
  112. package/src/__tests__/headless-browser-navigate.test.ts +528 -49
  113. package/src/__tests__/headless-browser-read-tools.test.ts +274 -100
  114. package/src/__tests__/headless-browser-snapshot.test.ts +250 -77
  115. package/src/__tests__/heartbeat-service.test.ts +70 -17
  116. package/src/__tests__/home-state-routes.test.ts +162 -0
  117. package/src/__tests__/host-bash-proxy.test.ts +145 -1
  118. package/src/__tests__/host-browser-e2e-cloud.test.ts +596 -0
  119. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +286 -0
  120. package/src/__tests__/host-browser-e2e-self-hosted.test.ts +374 -0
  121. package/src/__tests__/host-browser-event-routes.test.ts +350 -0
  122. package/src/__tests__/host-browser-proxy.test.ts +444 -0
  123. package/src/__tests__/host-browser-routes.test.ts +198 -0
  124. package/src/__tests__/host-browser-ws-events-e2e.test.ts +423 -0
  125. package/src/__tests__/host-cu-proxy.test.ts +166 -1
  126. package/src/__tests__/host-file-proxy.test.ts +185 -1
  127. package/src/__tests__/host-file-read-tool.test.ts +52 -0
  128. package/src/__tests__/host-proxy-interface.test.ts +165 -0
  129. package/src/__tests__/host-shell-tool.test.ts +1 -11
  130. package/src/__tests__/http-user-message-parity.test.ts +1 -0
  131. package/src/__tests__/identity-intro-cache.test.ts +40 -10
  132. package/src/__tests__/init-feature-flag-overrides.test.ts +38 -112
  133. package/src/__tests__/integration-status.test.ts +6 -7
  134. package/src/__tests__/jobs-store-upsert-debounced.test.ts +141 -0
  135. package/src/__tests__/list-messages-tool-merge.test.ts +37 -12
  136. package/src/__tests__/llm-context-normalization.test.ts +488 -0
  137. package/src/__tests__/llm-context-route-provider.test.ts +86 -5
  138. package/src/__tests__/llm-usage-store.test.ts +363 -0
  139. package/src/__tests__/mcp-client-auth.test.ts +40 -4
  140. package/src/__tests__/mcp-health-check.test.ts +10 -3
  141. package/src/__tests__/media-stream-output.test.ts +555 -0
  142. package/src/__tests__/media-stream-parser.test.ts +374 -0
  143. package/src/__tests__/media-stream-server-integration.test.ts +1234 -0
  144. package/src/__tests__/media-stream-stt-session.test.ts +588 -0
  145. package/src/__tests__/media-turn-detector.test.ts +440 -0
  146. package/src/__tests__/message-queue.test.ts +125 -0
  147. package/src/__tests__/migration-cross-version-compatibility.test.ts +3 -1
  148. package/src/__tests__/migration-export-http.test.ts +67 -8
  149. package/src/__tests__/migration-export-streaming.test.ts +66 -0
  150. package/src/__tests__/migration-import-commit-http.test.ts +109 -7
  151. package/src/__tests__/migration-import-preflight-http.test.ts +6 -5
  152. package/src/__tests__/migration-validate-http.test.ts +3 -3
  153. package/src/__tests__/mock-gateway-ipc.ts +151 -0
  154. package/src/__tests__/model-intents.test.ts +2 -2
  155. package/src/__tests__/native-host-marker-sync-guard.test.ts +157 -0
  156. package/src/__tests__/oauth-apps-routes.test.ts +18 -12
  157. package/src/__tests__/oauth-cli.test.ts +709 -60
  158. package/src/__tests__/oauth-connect-orchestrator.test.ts +118 -24
  159. package/src/__tests__/oauth-provider-seed-logos.test.ts +23 -0
  160. package/src/__tests__/oauth-provider-serializer.test.ts +147 -10
  161. package/src/__tests__/oauth-provider-visibility.test.ts +19 -21
  162. package/src/__tests__/oauth-providers-routes.test.ts +52 -14
  163. package/src/__tests__/oauth-store.test.ts +1465 -176
  164. package/src/__tests__/oauth2-gateway-transport.test.ts +460 -26
  165. package/src/__tests__/onboarding-template-contract.test.ts +81 -70
  166. package/src/__tests__/openai-provider.test.ts +178 -2
  167. package/src/__tests__/openai-responses-cutover-guard.test.ts +184 -0
  168. package/src/__tests__/openai-responses-provider.test.ts +1105 -0
  169. package/src/__tests__/openrouter-token-estimation.test.ts +100 -0
  170. package/src/__tests__/outlook-categories.test.ts +1 -1
  171. package/src/__tests__/outlook-client-automation.test.ts +1 -1
  172. package/src/__tests__/outlook-compose-tools.test.ts +1 -1
  173. package/src/__tests__/outlook-email-watcher.test.ts +1 -1
  174. package/src/__tests__/outlook-follow-up.test.ts +1 -1
  175. package/src/__tests__/outlook-messaging-provider.test.ts +2 -2
  176. package/src/__tests__/outlook-trash.test.ts +1 -1
  177. package/src/__tests__/outlook-unsubscribe.test.ts +32 -3
  178. package/src/__tests__/permission-checker-host-gate.test.ts +74 -14
  179. package/src/__tests__/permission-mode.test.ts +28 -56
  180. package/src/__tests__/persona-resolver.test.ts +251 -0
  181. package/src/__tests__/platform-bash-auto-approve.test.ts +4 -0
  182. package/src/__tests__/platform-callback-registration.test.ts +19 -0
  183. package/src/__tests__/platform.test.ts +92 -1
  184. package/src/__tests__/post-turn-tool-result-truncation.test.ts +343 -0
  185. package/src/__tests__/prechat-onboarding-contract.test.ts +267 -0
  186. package/src/__tests__/pricing.test.ts +174 -0
  187. package/src/__tests__/proxy-approval-callback.test.ts +18 -0
  188. package/src/__tests__/qdrant-manager.test.ts +29 -8
  189. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +194 -0
  190. package/src/__tests__/relationship-state-contract.test.ts +175 -0
  191. package/src/__tests__/relay-server.test.ts +423 -5
  192. package/src/__tests__/require-fresh-approval.test.ts +40 -1
  193. package/src/__tests__/sanitize-config-for-transfer.test.ts +132 -0
  194. package/src/__tests__/schedule-routes.test.ts +162 -0
  195. package/src/__tests__/search-skills-unified.test.ts +118 -0
  196. package/src/__tests__/secret-detection-handler.test.ts +84 -0
  197. package/src/__tests__/secret-ingress-http.test.ts +1 -0
  198. package/src/__tests__/secret-scanner-executor.test.ts +4 -0
  199. package/src/__tests__/secure-keys.test.ts +107 -0
  200. package/src/__tests__/send-endpoint-busy.test.ts +8 -1
  201. package/src/__tests__/sequence-store.test.ts +1 -1
  202. package/src/__tests__/server-history-render.test.ts +49 -0
  203. package/src/__tests__/set-permission-mode.test.ts +13 -250
  204. package/src/__tests__/settings-routes.test.ts +201 -0
  205. package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
  206. package/src/__tests__/skills-file-content-endpoint.test.ts +801 -0
  207. package/src/__tests__/skills-files-catalog-fallback.test.ts +738 -0
  208. package/src/__tests__/skills.test.ts +5 -2
  209. package/src/__tests__/skillssh-files.test.ts +446 -0
  210. package/src/__tests__/slack-block-formatting.test.ts +110 -0
  211. package/src/__tests__/slack-channel-config.test.ts +576 -16
  212. package/src/__tests__/stt-catalog-parity.test.ts +282 -0
  213. package/src/__tests__/stt-stream-session.test.ts +535 -0
  214. package/src/__tests__/subagent-detail.test.ts +44 -2
  215. package/src/__tests__/subagent-disposal.test.ts +1 -0
  216. package/src/__tests__/subagent-fork-notifications.test.ts +291 -0
  217. package/src/__tests__/subagent-fork-spawn.test.ts +384 -0
  218. package/src/__tests__/subagent-manager-notify.test.ts +1 -0
  219. package/src/__tests__/subagent-notify-parent.test.ts +1 -0
  220. package/src/__tests__/subagent-spawn-tool-fork.test.ts +411 -0
  221. package/src/__tests__/subagent-tools.test.ts +1 -0
  222. package/src/__tests__/subagent-types.test.ts +1 -0
  223. package/src/__tests__/system-prompt-ask-mode.test.ts +27 -71
  224. package/src/__tests__/system-prompt.test.ts +184 -27
  225. package/src/__tests__/task-scheduler.test.ts +32 -6
  226. package/src/__tests__/telegram-config.test.ts +10 -13
  227. package/src/__tests__/telephony-stt-routing.test.ts +329 -0
  228. package/src/__tests__/terminal-tools.test.ts +25 -5
  229. package/src/__tests__/test-preload.ts +18 -0
  230. package/src/__tests__/test-support/browser-skill-harness.ts +4 -1
  231. package/src/__tests__/tool-approval-handler.test.ts +73 -0
  232. package/src/__tests__/tool-executor-lifecycle-events.test.ts +9 -5
  233. package/src/__tests__/tool-executor-shell-integration.test.ts +4 -0
  234. package/src/__tests__/tool-executor.test.ts +33 -24
  235. package/src/__tests__/tool-result-truncation.test.ts +36 -0
  236. package/src/__tests__/tool-side-effects-slack-dm.test.ts +22 -0
  237. package/src/__tests__/top-level-renderer.test.ts +73 -1
  238. package/src/__tests__/transport-hints-queue.test.ts +14 -29
  239. package/src/__tests__/trust-store.test.ts +7 -1
  240. package/src/__tests__/trusted-contact-approval-notifier.test.ts +1 -1
  241. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +109 -0
  242. package/src/__tests__/tts-catalog-parity.test.ts +345 -0
  243. package/src/__tests__/twilio-routes-twiml.test.ts +512 -114
  244. package/src/__tests__/twilio-routes.test.ts +376 -0
  245. package/src/__tests__/unicode.test.ts +293 -0
  246. package/src/__tests__/update-bulletin-format.test.ts +59 -0
  247. package/src/__tests__/update-bulletin.test.ts +206 -5
  248. package/src/__tests__/usage-routes.test.ts +25 -4
  249. package/src/__tests__/user-reference.test.ts +46 -61
  250. package/src/__tests__/v2-consent-policy.test.ts +103 -0
  251. package/src/__tests__/verification-control-plane-policy.test.ts +4 -0
  252. package/src/__tests__/voice-config-update.test.ts +403 -0
  253. package/src/__tests__/voice-quality.test.ts +434 -19
  254. package/src/__tests__/workspace-heartbeat-service.test.ts +7 -0
  255. package/src/__tests__/workspace-migration-033-stt-service-explicit-config.test.ts +547 -0
  256. package/src/__tests__/workspace-migration-034-remove-calls-voice-transcription-provider.test.ts +596 -0
  257. package/src/__tests__/workspace-migration-drop-user-md.test.ts +368 -0
  258. package/src/__tests__/workspace-migration-meets.test.ts +244 -0
  259. package/src/__tests__/workspace-migration-seed-device-id.test.ts +14 -20
  260. package/src/__tests__/workspace-policy.test.ts +2 -0
  261. package/src/acp/client-handler.ts +30 -4
  262. package/src/agent/image-optimize.ts +24 -12
  263. package/src/agent/loop.ts +55 -9
  264. package/src/approvals/guardian-request-resolvers.ts +21 -15
  265. package/src/backup/__tests__/backup-key.test.ts +152 -0
  266. package/src/backup/__tests__/backup-worker.test.ts +767 -0
  267. package/src/backup/__tests__/list-snapshots.test.ts +87 -0
  268. package/src/backup/__tests__/local-writer.test.ts +218 -0
  269. package/src/backup/__tests__/offsite-writer.test.ts +641 -0
  270. package/src/backup/__tests__/paths.test.ts +300 -0
  271. package/src/backup/__tests__/restore.test.ts +498 -0
  272. package/src/backup/__tests__/snapshot-lock.test.ts +352 -0
  273. package/src/backup/__tests__/stream-crypt.test.ts +228 -0
  274. package/src/backup/backup-key.ts +137 -0
  275. package/src/backup/backup-worker.ts +459 -0
  276. package/src/backup/list-snapshots.ts +147 -0
  277. package/src/backup/local-writer.ts +133 -0
  278. package/src/backup/offsite-writer.ts +222 -0
  279. package/src/backup/paths.ts +226 -0
  280. package/src/backup/restore.ts +322 -0
  281. package/src/backup/snapshot-lock.ts +431 -0
  282. package/src/backup/stream-crypt.ts +263 -0
  283. package/src/browser-session/__tests__/manager.test.ts +297 -0
  284. package/src/browser-session/backends/cdp-inspect.ts +30 -0
  285. package/src/browser-session/backends/extension.ts +26 -0
  286. package/src/browser-session/backends/local.ts +24 -0
  287. package/src/browser-session/events.ts +164 -0
  288. package/src/browser-session/index.ts +27 -0
  289. package/src/browser-session/manager.ts +159 -0
  290. package/src/browser-session/types.ts +28 -0
  291. package/src/bundler/package-resolver.ts +4 -0
  292. package/src/calls/audio-store.ts +11 -5
  293. package/src/calls/call-controller.ts +226 -71
  294. package/src/calls/call-domain.ts +9 -0
  295. package/src/calls/call-speech-output.ts +190 -0
  296. package/src/calls/call-transport.ts +77 -0
  297. package/src/calls/media-stream-audio-transcode.ts +173 -0
  298. package/src/calls/media-stream-output.ts +660 -0
  299. package/src/calls/media-stream-parser.ts +300 -0
  300. package/src/calls/media-stream-protocol.ts +166 -0
  301. package/src/calls/media-stream-server.ts +592 -0
  302. package/src/calls/media-stream-stt-session.ts +460 -0
  303. package/src/calls/media-turn-detector.ts +230 -0
  304. package/src/calls/relay-server.ts +90 -75
  305. package/src/calls/resolve-call-tts-provider.ts +136 -0
  306. package/src/calls/telephony-stt-routing.ts +145 -0
  307. package/src/calls/tts-call-strategy.ts +161 -0
  308. package/src/calls/tts-text-sanitizer.ts +32 -16
  309. package/src/calls/twilio-routes.ts +281 -17
  310. package/src/calls/voice-quality.ts +78 -35
  311. package/src/calls/voice-session-bridge.ts +8 -1
  312. package/src/channels/__tests__/types.test.ts +134 -0
  313. package/src/channels/types.ts +69 -3
  314. package/src/cli/__tests__/run-assistant-command.ts +11 -1
  315. package/src/cli/commands/__tests__/backup.test.ts +1165 -0
  316. package/src/cli/commands/__tests__/domain-register.test.ts +234 -0
  317. package/src/cli/commands/__tests__/domain-status.test.ts +132 -0
  318. package/src/cli/commands/__tests__/email-attachment.test.ts +422 -0
  319. package/src/cli/commands/__tests__/email-download.test.ts +16 -1
  320. package/src/cli/commands/__tests__/email-list.test.ts +22 -4
  321. package/src/cli/commands/__tests__/email-register.test.ts +4 -4
  322. package/src/cli/commands/__tests__/email-send.test.ts +37 -4
  323. package/src/cli/commands/__tests__/email-status.test.ts +5 -1
  324. package/src/cli/commands/__tests__/email-unregister.test.ts +34 -5
  325. package/src/cli/commands/backup.ts +993 -0
  326. package/src/cli/commands/conversations.ts +77 -0
  327. package/src/cli/commands/credentials.ts +3 -4
  328. package/src/cli/commands/domain.ts +210 -0
  329. package/src/cli/commands/email.ts +273 -16
  330. package/src/cli/commands/mcp.ts +16 -4
  331. package/src/cli/commands/oauth/__tests__/connect.test.ts +56 -44
  332. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +21 -21
  333. package/src/cli/commands/oauth/__tests__/mode.test.ts +17 -17
  334. package/src/cli/commands/oauth/__tests__/ping.test.ts +16 -16
  335. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +32 -33
  336. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +330 -0
  337. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +117 -12
  338. package/src/cli/commands/oauth/__tests__/status.test.ts +10 -10
  339. package/src/cli/commands/oauth/__tests__/token.test.ts +7 -7
  340. package/src/cli/commands/oauth/apps.ts +7 -4
  341. package/src/cli/commands/oauth/connect.ts +6 -3
  342. package/src/cli/commands/oauth/disconnect.ts +1 -1
  343. package/src/cli/commands/oauth/mode.ts +12 -3
  344. package/src/cli/commands/oauth/providers.ts +215 -36
  345. package/src/cli/commands/oauth/shared.ts +7 -6
  346. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +254 -0
  347. package/src/cli/commands/platform/__tests__/connect.test.ts +6 -0
  348. package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -1
  349. package/src/cli/commands/platform/__tests__/status.test.ts +6 -0
  350. package/src/cli/commands/platform/index.ts +107 -10
  351. package/src/cli/commands/usage.ts +10 -9
  352. package/src/cli/lib/daemon-credential-client.ts +4 -0
  353. package/src/cli/program.ts +30 -4
  354. package/src/config/__tests__/backup-schema.test.ts +134 -0
  355. package/src/config/assistant-feature-flags.ts +61 -62
  356. package/src/config/bundled-skills/app-builder/SKILL.md +26 -249
  357. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +141 -0
  358. package/src/config/bundled-skills/app-builder/references/INTERACTION_HOOKS.md +56 -0
  359. package/src/config/bundled-skills/app-builder/references/WIDGETS.md +125 -0
  360. package/src/config/bundled-skills/browser/SKILL.md +30 -5
  361. package/src/config/bundled-skills/browser/TOOLS.json +123 -0
  362. package/src/config/bundled-skills/browser/tools/browser-attach.ts +12 -0
  363. package/src/config/bundled-skills/browser/tools/browser-detach.ts +12 -0
  364. package/src/config/bundled-skills/browser/tools/browser-status.ts +12 -0
  365. package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +17 -0
  366. package/src/config/bundled-skills/contacts/SKILL.md +5 -2
  367. package/src/config/bundled-skills/document/SKILL.md +4 -0
  368. package/src/config/bundled-skills/gmail/SKILL.md +54 -8
  369. package/src/config/bundled-skills/gmail/TOOLS.json +33 -3
  370. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +116 -9
  371. package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +138 -11
  372. package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +59 -0
  373. package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +82 -0
  374. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +113 -17
  375. package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +2 -2
  376. package/src/config/bundled-skills/media-processing/SKILL.md +3 -9
  377. package/src/config/bundled-skills/media-processing/TOOLS.json +1 -6
  378. package/src/config/bundled-skills/media-processing/__tests__/audio-transcribe.test.ts +125 -0
  379. package/src/config/bundled-skills/media-processing/__tests__/extract-keyframes.test.ts +181 -0
  380. package/src/config/bundled-skills/media-processing/__tests__/preprocess-audio.test.ts +141 -0
  381. package/src/config/bundled-skills/media-processing/services/audio-transcribe.ts +32 -87
  382. package/src/config/bundled-skills/media-processing/services/preprocess.ts +8 -4
  383. package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +0 -10
  384. package/src/config/bundled-skills/messaging/SKILL.md +3 -3
  385. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +2 -2
  386. package/src/config/bundled-skills/outlook/SKILL.md +9 -2
  387. package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +2 -2
  388. package/src/config/bundled-skills/phone-calls/SKILL.md +2 -2
  389. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +27 -18
  390. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +3 -3
  391. package/src/config/bundled-skills/settings/TOOLS.json +3 -3
  392. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +26 -22
  393. package/src/config/bundled-skills/slack/SKILL.md +1 -0
  394. package/src/config/bundled-skills/subagent/SKILL.md +21 -0
  395. package/src/config/bundled-skills/subagent/TOOLS.json +8 -4
  396. package/src/config/bundled-skills/tasks/SKILL.md +5 -0
  397. package/src/config/bundled-skills/transcribe/SKILL.md +9 -14
  398. package/src/config/bundled-skills/transcribe/TOOLS.json +2 -7
  399. package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +256 -0
  400. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +38 -188
  401. package/src/config/bundled-tool-registry.ts +8 -0
  402. package/src/config/env-registry.ts +38 -0
  403. package/src/config/env.ts +49 -4
  404. package/src/config/feature-flag-registry.json +85 -14
  405. package/src/config/loader.ts +82 -13
  406. package/src/config/sanitize-for-transfer.ts +47 -0
  407. package/src/config/schema.ts +81 -15
  408. package/src/config/schemas/__tests__/stt.test.ts +43 -0
  409. package/src/config/schemas/analysis.ts +51 -0
  410. package/src/config/schemas/backup.ts +72 -0
  411. package/src/config/schemas/calls.ts +1 -26
  412. package/src/config/schemas/elevenlabs.ts +0 -59
  413. package/src/config/schemas/filing.ts +47 -7
  414. package/src/config/schemas/heartbeat.ts +27 -5
  415. package/src/config/schemas/host-browser.ts +112 -0
  416. package/src/config/schemas/inference.ts +1 -1
  417. package/src/config/schemas/memory-lifecycle.ts +14 -2
  418. package/src/config/schemas/memory-retrieval.ts +103 -0
  419. package/src/config/schemas/security.ts +0 -6
  420. package/src/config/schemas/services.ts +52 -0
  421. package/src/config/schemas/stt.ts +59 -0
  422. package/src/config/schemas/tts.ts +230 -0
  423. package/src/config/schemas/updates.ts +14 -0
  424. package/src/config/skills.ts +4 -0
  425. package/src/config/types.ts +4 -1
  426. package/src/contacts/contact-store.ts +56 -11
  427. package/src/contacts/contacts-write.ts +38 -1
  428. package/src/context/post-turn-tool-result-truncation.ts +177 -0
  429. package/src/context/tool-result-truncation.ts +2 -1
  430. package/src/context/window-manager.ts +61 -10
  431. package/src/credential-execution/approval-bridge.ts +49 -15
  432. package/src/credential-execution/executable-discovery.ts +12 -2
  433. package/src/credential-execution/process-manager.ts +33 -2
  434. package/src/credential-health/credential-health-service.ts +366 -0
  435. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +324 -0
  436. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +497 -0
  437. package/src/daemon/__tests__/conversation-tool-setup.test.ts +195 -0
  438. package/src/daemon/__tests__/lifecycle-startup-ordering.test.ts +127 -0
  439. package/src/daemon/app-source-watcher.ts +35 -0
  440. package/src/daemon/config-watcher.ts +99 -5
  441. package/src/daemon/context-overflow-approval.ts +5 -0
  442. package/src/daemon/conversation-agent-loop-handlers.ts +23 -2
  443. package/src/daemon/conversation-agent-loop.ts +153 -42
  444. package/src/daemon/conversation-attachments.ts +40 -0
  445. package/src/daemon/conversation-error.ts +11 -0
  446. package/src/daemon/conversation-history.ts +40 -6
  447. package/src/daemon/conversation-launch.ts +220 -0
  448. package/src/daemon/conversation-lifecycle.ts +59 -9
  449. package/src/daemon/conversation-messaging.ts +37 -3
  450. package/src/daemon/conversation-notifiers.ts +5 -0
  451. package/src/daemon/conversation-process.ts +622 -13
  452. package/src/daemon/conversation-queue-manager.ts +24 -0
  453. package/src/daemon/conversation-runtime-assembly.ts +128 -36
  454. package/src/daemon/conversation-slash.ts +36 -0
  455. package/src/daemon/conversation-surfaces.ts +131 -40
  456. package/src/daemon/conversation-tool-setup.ts +99 -8
  457. package/src/daemon/conversation-usage.ts +7 -4
  458. package/src/daemon/conversation-workspace.ts +12 -0
  459. package/src/daemon/conversation.ts +292 -16
  460. package/src/daemon/date-context.ts +10 -10
  461. package/src/daemon/first-greeting.ts +3 -2
  462. package/src/daemon/handlers/config-slack-channel.ts +269 -94
  463. package/src/daemon/handlers/conversations.ts +13 -141
  464. package/src/daemon/handlers/shared.ts +80 -0
  465. package/src/daemon/handlers/skills.ts +483 -44
  466. package/src/daemon/host-bash-proxy.ts +48 -13
  467. package/src/daemon/host-browser-proxy.ts +192 -0
  468. package/src/daemon/host-cu-proxy.ts +36 -11
  469. package/src/daemon/host-file-proxy.ts +57 -9
  470. package/src/daemon/lifecycle.ts +179 -28
  471. package/src/daemon/message-protocol.ts +13 -0
  472. package/src/daemon/message-types/conversations.ts +89 -14
  473. package/src/daemon/message-types/home.ts +40 -0
  474. package/src/daemon/message-types/host-browser.ts +100 -0
  475. package/src/daemon/message-types/meet.ts +143 -0
  476. package/src/daemon/message-types/messages.ts +19 -5
  477. package/src/daemon/message-types/schedules.ts +34 -2
  478. package/src/daemon/message-types/skills.ts +26 -0
  479. package/src/daemon/message-types/subagents.ts +2 -0
  480. package/src/daemon/message-types/surfaces.ts +2 -0
  481. package/src/daemon/server.ts +439 -14
  482. package/src/daemon/shutdown-handlers.ts +32 -4
  483. package/src/daemon/shutdown-registry.ts +40 -0
  484. package/src/daemon/tool-side-effects.ts +15 -0
  485. package/src/daemon/transport-hints.ts +5 -24
  486. package/src/email/html-renderer.ts +76 -0
  487. package/src/heartbeat/heartbeat-service.ts +93 -7
  488. package/src/home/__tests__/assistant-feed-authoring.test.ts +156 -0
  489. package/src/home/__tests__/emit-feed-event.test.ts +169 -0
  490. package/src/home/__tests__/feed-scheduler.test.ts +194 -0
  491. package/src/home/__tests__/feed-types.test.ts +275 -0
  492. package/src/home/__tests__/feed-writer.test.ts +688 -0
  493. package/src/home/__tests__/phase5-exit-criteria.test.ts +212 -0
  494. package/src/home/__tests__/platform-gmail-digest.test.ts +222 -0
  495. package/src/home/__tests__/progress-formula.test.ts +213 -0
  496. package/src/home/__tests__/relationship-state-writer.test.ts +740 -0
  497. package/src/home/__tests__/rollup-producer.test.ts +398 -0
  498. package/src/home/assistant-feed-authoring.ts +124 -0
  499. package/src/home/emit-feed-event.ts +158 -0
  500. package/src/home/feed-scheduler.ts +247 -0
  501. package/src/home/feed-types.ts +181 -0
  502. package/src/home/feed-writer.ts +469 -0
  503. package/src/home/platform-gmail-digest.ts +163 -0
  504. package/src/home/progress-formula.ts +86 -0
  505. package/src/home/relationship-state-writer.ts +824 -0
  506. package/src/home/relationship-state.ts +143 -0
  507. package/src/home/rollup-producer.ts +384 -0
  508. package/src/hooks/runner.ts +7 -0
  509. package/src/inbound/platform-callback-registration.ts +30 -20
  510. package/src/inbound/public-ingress-urls.ts +12 -0
  511. package/src/instrument.ts +1 -1
  512. package/src/ipc/__tests__/cli-ipc.test.ts +200 -0
  513. package/src/ipc/cli-client.ts +151 -0
  514. package/src/ipc/cli-server.ts +234 -0
  515. package/src/ipc/gateway-client.ts +180 -0
  516. package/src/ipc/routes/index.ts +5 -0
  517. package/src/ipc/routes/wake-conversation.ts +19 -0
  518. package/src/mcp/client.ts +59 -24
  519. package/src/memory/__tests__/auto-analysis-enqueue.test.ts +356 -0
  520. package/src/memory/__tests__/auto-analysis-guard.test.ts +57 -0
  521. package/src/memory/__tests__/conversation-analyze-job.test.ts +232 -0
  522. package/src/memory/__tests__/find-analysis-conversation.test.ts +196 -0
  523. package/src/memory/app-store.ts +31 -1
  524. package/src/memory/attachments-store.ts +70 -0
  525. package/src/memory/auto-analysis-enqueue.ts +127 -0
  526. package/src/memory/auto-analysis-guard.ts +27 -0
  527. package/src/memory/cleanup-schedule-state.ts +37 -0
  528. package/src/memory/conversation-analyze-job.ts +73 -0
  529. package/src/memory/conversation-crud.ts +122 -0
  530. package/src/memory/conversation-disk-view.ts +7 -0
  531. package/src/memory/conversation-group-migration.ts +34 -2
  532. package/src/memory/conversation-queries.ts +6 -5
  533. package/src/memory/conversation-starters-cadence.ts +76 -0
  534. package/src/memory/conversation-title-service.ts +5 -2
  535. package/src/memory/db-init.ts +18 -0
  536. package/src/memory/db-maintenance.ts +108 -0
  537. package/src/memory/db.ts +1 -0
  538. package/src/memory/embedding-backend.test.ts +75 -0
  539. package/src/memory/embedding-backend.ts +131 -5
  540. package/src/memory/embedding-gemini.test.ts +54 -0
  541. package/src/memory/embedding-gemini.ts +20 -9
  542. package/src/memory/embedding-local.ts +176 -17
  543. package/src/memory/graph/consolidation.ts +10 -23
  544. package/src/memory/graph/conversation-graph-memory.ts +15 -0
  545. package/src/memory/graph/extraction-job.ts +15 -0
  546. package/src/memory/graph/extraction.test.ts +23 -0
  547. package/src/memory/graph/extraction.ts +8 -0
  548. package/src/memory/graph/retriever.ts +67 -40
  549. package/src/memory/graph/scoring.test.ts +186 -0
  550. package/src/memory/graph/scoring.ts +31 -1
  551. package/src/memory/graph/store.test.ts +7 -3
  552. package/src/memory/graph/store.ts +47 -12
  553. package/src/memory/graph/tools.ts +1 -1
  554. package/src/memory/group-crud.ts +6 -1
  555. package/src/memory/indexer.ts +95 -16
  556. package/src/memory/job-handlers/cleanup.ts +11 -8
  557. package/src/memory/job-handlers/conversation-starters.ts +16 -10
  558. package/src/memory/jobs-store.ts +64 -4
  559. package/src/memory/jobs-worker.ts +22 -9
  560. package/src/memory/llm-usage-store.ts +137 -60
  561. package/src/memory/migrations/213-oauth-providers-scope-separator.ts +13 -0
  562. package/src/memory/migrations/214-oauth-providers-refresh-url.ts +11 -0
  563. package/src/memory/migrations/215-oauth-providers-revoke.ts +14 -0
  564. package/src/memory/migrations/216-oauth-providers-token-auth-method.ts +30 -0
  565. package/src/memory/migrations/217-conversation-host-access.ts +40 -0
  566. package/src/memory/migrations/218-oauth-providers-logo-url.ts +11 -0
  567. package/src/memory/migrations/219-oauth-providers-token-exchange-body-format.ts +15 -0
  568. package/src/memory/migrations/220-normalize-user-file-by-principal.ts +190 -0
  569. package/src/memory/migrations/221-conversations-archived-at.ts +16 -0
  570. package/src/memory/migrations/index.ts +12 -0
  571. package/src/memory/migrations/registry.ts +16 -0
  572. package/src/memory/qdrant-manager.ts +43 -16
  573. package/src/memory/schema/conversations.ts +3 -0
  574. package/src/memory/schema/oauth.ts +21 -13
  575. package/src/memory/usage-buckets.ts +396 -0
  576. package/src/messaging/providers/gmail/client.ts +57 -6
  577. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +282 -0
  578. package/src/messaging/providers/slack/adapter.ts +143 -38
  579. package/src/messaging/providers/slack/client.ts +16 -0
  580. package/src/messaging/providers/slack/types.ts +4 -0
  581. package/src/notifications/decision-engine.ts +3 -3
  582. package/src/notifications/signal.ts +5 -0
  583. package/src/oauth/AGENTS.md +76 -0
  584. package/src/oauth/__tests__/identity-verifier.test.ts +25 -19
  585. package/src/oauth/__tests__/seed-providers-managed.test.ts +32 -0
  586. package/src/oauth/byo-connection.test.ts +26 -9
  587. package/src/oauth/byo-connection.ts +10 -8
  588. package/src/oauth/connect-orchestrator.ts +25 -21
  589. package/src/oauth/connect-types.ts +3 -3
  590. package/src/oauth/connection-resolver.test.ts +17 -4
  591. package/src/oauth/connection-resolver.ts +22 -18
  592. package/src/oauth/connection.ts +3 -1
  593. package/src/oauth/manual-token-connection.ts +13 -13
  594. package/src/oauth/oauth-store.ts +223 -100
  595. package/src/oauth/platform-connection.test.ts +101 -3
  596. package/src/oauth/platform-connection.ts +56 -35
  597. package/src/oauth/provider-serializer.ts +31 -5
  598. package/src/oauth/revoke.ts +76 -0
  599. package/src/oauth/seed-providers.ts +133 -87
  600. package/src/oauth/token-persistence.ts +1 -1
  601. package/src/permissions/checker.ts +16 -6
  602. package/src/permissions/defaults.ts +49 -1
  603. package/src/permissions/permission-mode.ts +4 -11
  604. package/src/permissions/prompter.ts +13 -1
  605. package/src/permissions/trust-store.ts +3 -3
  606. package/src/permissions/v2-consent-policy.ts +87 -0
  607. package/src/permissions/workspace-policy.ts +3 -0
  608. package/src/platform/client.test.ts +10 -0
  609. package/src/platform/sync-identity.ts +129 -0
  610. package/src/prompts/persona-resolver.ts +126 -2
  611. package/src/prompts/system-prompt.ts +76 -38
  612. package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +3 -65
  613. package/src/prompts/templates/BOOTSTRAP.md +59 -105
  614. package/src/prompts/templates/SOUL.md +3 -1
  615. package/src/prompts/templates/UPDATES.md +12 -0
  616. package/src/prompts/templates/channels/slack.md +20 -0
  617. package/src/prompts/update-bulletin-format.ts +26 -9
  618. package/src/prompts/update-bulletin.ts +34 -23
  619. package/src/prompts/user-reference.ts +20 -17
  620. package/src/providers/__tests__/provider-secret-catalog.test.ts +42 -0
  621. package/src/providers/anthropic/client.ts +157 -60
  622. package/src/providers/fireworks/client.ts +2 -2
  623. package/src/providers/gemini/client.ts +9 -1
  624. package/src/providers/model-catalog.ts +6 -0
  625. package/src/providers/model-intents.ts +4 -4
  626. package/src/providers/ollama/client.ts +2 -2
  627. package/src/providers/openai/chat-completions-provider.ts +474 -0
  628. package/src/providers/openai/client.ts +25 -440
  629. package/src/providers/openai/responses-provider.ts +502 -0
  630. package/src/providers/openrouter/client.ts +101 -4
  631. package/src/providers/provider-secret-catalog.ts +139 -0
  632. package/src/providers/registry.ts +2 -2
  633. package/src/providers/retry.ts +14 -3
  634. package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +251 -0
  635. package/src/providers/speech-to-text/__tests__/resolve.test.ts +828 -0
  636. package/src/providers/speech-to-text/deepgram-realtime.test.ts +980 -0
  637. package/src/providers/speech-to-text/deepgram-realtime.ts +767 -0
  638. package/src/providers/speech-to-text/deepgram.test.ts +332 -0
  639. package/src/providers/speech-to-text/deepgram.ts +115 -0
  640. package/src/providers/speech-to-text/google-gemini-live-stream.test.ts +743 -0
  641. package/src/providers/speech-to-text/google-gemini-live-stream.ts +625 -0
  642. package/src/providers/speech-to-text/google-gemini.test.ts +226 -0
  643. package/src/providers/speech-to-text/google-gemini.ts +101 -0
  644. package/src/providers/speech-to-text/openai-whisper-stream.test.ts +564 -0
  645. package/src/providers/speech-to-text/openai-whisper-stream.ts +381 -0
  646. package/src/providers/speech-to-text/openai-whisper.test.ts +1 -37
  647. package/src/providers/speech-to-text/openai-whisper.ts +63 -33
  648. package/src/providers/speech-to-text/provider-catalog.ts +306 -0
  649. package/src/providers/speech-to-text/resolve.ts +386 -6
  650. package/src/providers/types.ts +10 -1
  651. package/src/runtime/AGENTS.md +65 -0
  652. package/src/runtime/__tests__/agent-wake.test.ts +831 -0
  653. package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +715 -0
  654. package/src/runtime/__tests__/capability-tokens.test.ts +258 -0
  655. package/src/runtime/__tests__/chrome-extension-registry.test.ts +518 -0
  656. package/src/runtime/__tests__/runtime-mode.test.ts +62 -0
  657. package/src/runtime/__tests__/slack-block-formatting.test.ts +481 -0
  658. package/src/runtime/agent-wake.ts +512 -0
  659. package/src/runtime/assistant-event-hub.ts +2 -2
  660. package/src/runtime/auth/__tests__/guard-tests.test.ts +1 -0
  661. package/src/runtime/auth/__tests__/middleware.test.ts +116 -1
  662. package/src/runtime/auth/__tests__/route-policy.test.ts +48 -0
  663. package/src/runtime/auth/middleware.ts +98 -0
  664. package/src/runtime/auth/route-policy.ts +33 -9
  665. package/src/runtime/auth/token-service.ts +56 -1
  666. package/src/runtime/btw-sidechain.ts +2 -0
  667. package/src/runtime/capability-tokens.ts +414 -0
  668. package/src/runtime/channel-approvals.ts +18 -5
  669. package/src/runtime/channel-invite-transport.ts +1 -1
  670. package/src/runtime/channel-invite-transports/email.ts +14 -6
  671. package/src/runtime/channel-readiness-service.ts +12 -22
  672. package/src/runtime/chrome-extension-registry.ts +368 -0
  673. package/src/runtime/confirmation-request-guardian-bridge.ts +6 -0
  674. package/src/runtime/guardian-decision-types.ts +7 -0
  675. package/src/runtime/http-server.ts +815 -75
  676. package/src/runtime/http-types.ts +6 -2
  677. package/src/runtime/migrations/__tests__/rebind-secrets-credentials.test.ts +172 -0
  678. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +276 -0
  679. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +198 -0
  680. package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +360 -0
  681. package/src/runtime/migrations/migration-transport.ts +7 -0
  682. package/src/runtime/migrations/migration-wizard.ts +23 -2
  683. package/src/runtime/migrations/rebind-secrets-screen.ts +76 -15
  684. package/src/runtime/migrations/vbundle-builder.ts +145 -38
  685. package/src/runtime/migrations/vbundle-import-analyzer.ts +96 -1
  686. package/src/runtime/migrations/vbundle-importer.ts +89 -5
  687. package/src/runtime/pending-interactions.ts +18 -13
  688. package/src/runtime/routes/__tests__/backup-routes.test.ts +967 -0
  689. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +507 -0
  690. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +208 -0
  691. package/src/runtime/routes/__tests__/stt-routes.test.ts +406 -0
  692. package/src/runtime/routes/__tests__/tts-routes.test.ts +474 -0
  693. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +148 -17
  694. package/src/runtime/routes/app-management-routes.ts +12 -18
  695. package/src/runtime/routes/approval-routes.ts +90 -16
  696. package/src/runtime/routes/attachment-routes.test.ts +9 -3
  697. package/src/runtime/routes/attachment-routes.ts +216 -17
  698. package/src/runtime/routes/backup-routes.ts +519 -0
  699. package/src/runtime/routes/browser-extension-pair-routes.ts +556 -0
  700. package/src/runtime/routes/btw-routes.ts +8 -6
  701. package/src/runtime/routes/contact-routes.test.ts +298 -0
  702. package/src/runtime/routes/contact-routes.ts +132 -5
  703. package/src/runtime/routes/conversation-analysis-routes.ts +22 -141
  704. package/src/runtime/routes/conversation-management-routes.ts +223 -0
  705. package/src/runtime/routes/conversation-routes.ts +598 -103
  706. package/src/runtime/routes/conversation-starter-routes.ts +78 -16
  707. package/src/runtime/routes/filing-routes.ts +93 -0
  708. package/src/runtime/routes/guardian-action-routes.ts +24 -13
  709. package/src/runtime/routes/home-feed-routes.ts +334 -0
  710. package/src/runtime/routes/home-state-routes.ts +138 -0
  711. package/src/runtime/routes/host-browser-routes.ts +268 -0
  712. package/src/runtime/routes/host-file-routes.ts +9 -1
  713. package/src/runtime/routes/identity-intro-cache.ts +7 -3
  714. package/src/runtime/routes/identity-routes.ts +262 -33
  715. package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +46 -39
  716. package/src/runtime/routes/inbound-stages/transcribe-audio.ts +15 -15
  717. package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +137 -0
  718. package/src/runtime/routes/integrations/slack/__tests__/share.test.ts +179 -0
  719. package/src/runtime/routes/integrations/slack/channel.ts +11 -3
  720. package/src/runtime/routes/integrations/slack/share.ts +45 -7
  721. package/src/runtime/routes/llm-context-normalization.ts +303 -0
  722. package/src/runtime/routes/log-export-routes.ts +42 -22
  723. package/src/runtime/routes/memory-item-routes.test.ts +3 -2
  724. package/src/runtime/routes/memory-item-routes.ts +1 -7
  725. package/src/runtime/routes/migration-routes.ts +122 -2
  726. package/src/runtime/routes/oauth-apps.ts +15 -17
  727. package/src/runtime/routes/oauth-providers.ts +4 -0
  728. package/src/runtime/routes/schedule-routes.ts +24 -11
  729. package/src/runtime/routes/settings-routes.ts +31 -102
  730. package/src/runtime/routes/skills-routes.ts +128 -9
  731. package/src/runtime/routes/stt-routes.ts +233 -0
  732. package/src/runtime/routes/subagents-routes.ts +14 -10
  733. package/src/runtime/routes/surface-action-routes.ts +41 -2
  734. package/src/runtime/routes/tts-routes.ts +108 -24
  735. package/src/runtime/routes/usage-routes.ts +38 -9
  736. package/src/runtime/routes/user-route-dispatcher.ts +50 -5
  737. package/src/runtime/routes/user-routes.ts +13 -1
  738. package/src/runtime/routes/work-items-routes.ts +8 -1
  739. package/src/runtime/routes/workspace-routes.test.ts +22 -0
  740. package/src/runtime/routes/workspace-routes.ts +8 -1
  741. package/src/runtime/routes/workspace-utils.ts +2 -0
  742. package/src/runtime/runtime-mode.ts +33 -0
  743. package/src/runtime/services/__tests__/analyze-conversation.test.ts +444 -0
  744. package/src/runtime/services/__tests__/analyze-deps-singleton.test.ts +67 -0
  745. package/src/runtime/services/__tests__/auto-analysis-prompt.test.ts +53 -0
  746. package/src/runtime/services/__tests__/manual-analysis-prompt.test.ts +41 -0
  747. package/src/runtime/services/analyze-conversation.ts +344 -0
  748. package/src/runtime/services/analyze-deps-singleton.ts +32 -0
  749. package/src/runtime/services/auto-analysis-prompt.ts +55 -0
  750. package/src/runtime/skill-route-registry.ts +49 -0
  751. package/src/runtime/slack-block-formatting.ts +437 -10
  752. package/src/schedule/scheduler.ts +57 -5
  753. package/src/security/ces-credential-client.ts +20 -0
  754. package/src/security/ces-rpc-credential-backend.ts +17 -0
  755. package/src/security/credential-backend.ts +5 -0
  756. package/src/security/oauth2.ts +68 -29
  757. package/src/security/secure-keys.ts +143 -27
  758. package/src/security/token-manager.ts +31 -10
  759. package/src/sequence/engine.ts +23 -0
  760. package/src/sequence/types.ts +1 -1
  761. package/src/skills/catalog-files.ts +554 -0
  762. package/src/skills/category-inference.ts +122 -0
  763. package/src/skills/clawhub-files.ts +213 -0
  764. package/src/skills/clawhub.ts +84 -23
  765. package/src/skills/skill-file-provider.ts +40 -0
  766. package/src/skills/skillssh-files.ts +395 -0
  767. package/src/skills/skillssh-registry.ts +4 -4
  768. package/src/stt/__tests__/daemon-batch-transcriber.test.ts +392 -0
  769. package/src/stt/__tests__/types.test.ts +89 -0
  770. package/src/stt/daemon-batch-transcriber.ts +195 -0
  771. package/src/stt/stt-stream-session.ts +499 -0
  772. package/src/stt/types.ts +330 -0
  773. package/src/stt/wav-encoder.test.ts +373 -0
  774. package/src/stt/wav-encoder.ts +175 -0
  775. package/src/subagent/manager.ts +169 -40
  776. package/src/subagent/types.ts +19 -0
  777. package/src/tools/apps/executors.ts +11 -2
  778. package/src/tools/browser/__tests__/auth-detector.test.ts +202 -108
  779. package/src/tools/browser/__tests__/browser-mode.test.ts +119 -0
  780. package/src/tools/browser/__tests__/browser-status.test.ts +123 -0
  781. package/src/tools/browser/auth-detector.ts +43 -12
  782. package/src/tools/browser/browser-execution.ts +1787 -342
  783. package/src/tools/browser/browser-manager.ts +81 -12
  784. package/src/tools/browser/browser-mode-constants.ts +12 -0
  785. package/src/tools/browser/browser-mode.ts +92 -0
  786. package/src/tools/browser/browser-status-constants.ts +33 -0
  787. package/src/tools/browser/cdp-client/__tests__/accessibility-snapshot.test.ts +318 -0
  788. package/src/tools/browser/cdp-client/__tests__/cdp-dom-helpers.test.ts +1175 -0
  789. package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +1263 -0
  790. package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +359 -0
  791. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +1993 -0
  792. package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-nested-frames.json +64 -0
  793. package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-simple.json +69 -0
  794. package/src/tools/browser/cdp-client/__tests__/local-cdp-client.test.ts +310 -0
  795. package/src/tools/browser/cdp-client/__tests__/types.test.ts +96 -0
  796. package/src/tools/browser/cdp-client/accessibility-snapshot.ts +387 -0
  797. package/src/tools/browser/cdp-client/cdp-dom-helpers.ts +695 -0
  798. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/discovery.test.ts +1007 -0
  799. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +580 -0
  800. package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +744 -0
  801. package/src/tools/browser/cdp-client/cdp-inspect/ws-transport.ts +579 -0
  802. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +868 -0
  803. package/src/tools/browser/cdp-client/errors.ts +49 -0
  804. package/src/tools/browser/cdp-client/extension-cdp-client.ts +148 -0
  805. package/src/tools/browser/cdp-client/factory.ts +914 -0
  806. package/src/tools/browser/cdp-client/index.ts +28 -0
  807. package/src/tools/browser/cdp-client/local-cdp-client.ts +187 -0
  808. package/src/tools/browser/cdp-client/types.ts +120 -0
  809. package/src/tools/credentials/vault.ts +35 -6
  810. package/src/tools/filesystem/edit.ts +1 -1
  811. package/src/tools/filesystem/list.ts +1 -1
  812. package/src/tools/filesystem/read.ts +1 -1
  813. package/src/tools/filesystem/write.ts +2 -1
  814. package/src/tools/host-filesystem/edit.ts +1 -1
  815. package/src/tools/host-filesystem/read.ts +12 -15
  816. package/src/tools/host-filesystem/write.ts +1 -1
  817. package/src/tools/host-terminal/host-shell.ts +21 -16
  818. package/src/tools/network/web-fetch.ts +5 -2
  819. package/src/tools/network/web-search.ts +5 -2
  820. package/src/tools/permission-checker.ts +77 -82
  821. package/src/tools/registry.ts +0 -2
  822. package/src/tools/secret-detection-handler.ts +34 -0
  823. package/src/tools/shared/filesystem/image-read.ts +61 -40
  824. package/src/tools/shared/shell-output.ts +3 -1
  825. package/src/tools/side-effects.ts +2 -0
  826. package/src/tools/skills/sandbox-runner.ts +3 -2
  827. package/src/tools/subagent/spawn.ts +47 -3
  828. package/src/tools/subagent/status.ts +2 -0
  829. package/src/tools/system/register.ts +2 -16
  830. package/src/tools/terminal/safe-env.ts +15 -0
  831. package/src/tools/terminal/shell.ts +36 -20
  832. package/src/tools/tool-approval-handler.ts +48 -2
  833. package/src/tools/tool-manifest.ts +21 -0
  834. package/src/tools/types.ts +19 -0
  835. package/src/tools/ui-surface/definitions.ts +6 -1
  836. package/src/tts/__tests__/provider-adapters.test.ts +834 -0
  837. package/src/tts/__tests__/provider-catalog-consistency.test.ts +196 -0
  838. package/src/tts/__tests__/provider-catalog.test.ts +183 -0
  839. package/src/tts/__tests__/provider-registry.test.ts +90 -0
  840. package/src/tts/provider-catalog.ts +201 -0
  841. package/src/tts/provider-registry.ts +73 -0
  842. package/src/tts/providers/deepgram-provider.ts +219 -0
  843. package/src/tts/providers/elevenlabs-provider.ts +211 -0
  844. package/src/tts/providers/fish-audio-provider.ts +183 -0
  845. package/src/tts/providers/index.ts +42 -0
  846. package/src/tts/providers/register-builtins.ts +130 -0
  847. package/src/tts/synthesize-text.ts +110 -0
  848. package/src/tts/tts-config-resolver.ts +78 -0
  849. package/src/tts/types.ts +153 -0
  850. package/src/types/onboarding-context.ts +7 -0
  851. package/src/util/abort-reasons.ts +58 -0
  852. package/src/util/device-id.ts +32 -16
  853. package/src/util/errors.ts +9 -1
  854. package/src/util/platform.ts +63 -24
  855. package/src/util/pricing.ts +66 -3
  856. package/src/util/spawn.ts +1 -1
  857. package/src/util/truncate.ts +4 -2
  858. package/src/util/unicode.ts +201 -0
  859. package/src/version.ts +19 -24
  860. package/src/watcher/engine.ts +23 -0
  861. package/src/watcher/watcher-store.ts +31 -0
  862. package/src/workspace/migrations/003-seed-device-id.ts +9 -3
  863. package/src/workspace/migrations/017-seed-persona-dirs.ts +68 -4
  864. package/src/workspace/migrations/029-seed-pkb.ts +1 -1
  865. package/src/workspace/migrations/031-drop-user-md.ts +317 -0
  866. package/src/workspace/migrations/031-llm-log-retention-zero-to-null.ts +73 -0
  867. package/src/workspace/migrations/032-tts-provider-unification.ts +227 -0
  868. package/src/workspace/migrations/033-stt-service-explicit-config.ts +122 -0
  869. package/src/workspace/migrations/034-remove-calls-voice-transcription-provider.ts +215 -0
  870. package/src/workspace/migrations/035-seed-slack-channel-persona.ts +50 -0
  871. package/src/workspace/migrations/036-update-pkb-index-bar.ts +37 -0
  872. package/src/workspace/migrations/037-create-meets-dir.ts +61 -0
  873. package/src/workspace/migrations/registry.ts +16 -0
  874. package/src/workspace/top-level-renderer.ts +31 -1
  875. package/src/workspace/turn-commit.ts +31 -0
  876. package/src/__tests__/chrome-cdp.test.ts +0 -419
  877. package/src/__tests__/email-cli.test.ts +0 -297
  878. package/src/__tests__/email-service-config-fallback.test.ts +0 -102
  879. package/src/__tests__/permission-mode-sse.test.ts +0 -418
  880. package/src/__tests__/permission-mode-store.test.ts +0 -277
  881. package/src/browser-extension-relay/protocol.ts +0 -63
  882. package/src/browser-extension-relay/server.ts +0 -203
  883. package/src/cli/commands/browser-relay.ts +0 -536
  884. package/src/config/schemas/sandbox.ts +0 -14
  885. package/src/email/guardrails.ts +0 -221
  886. package/src/email/provider.ts +0 -117
  887. package/src/email/providers/agentmail.ts +0 -361
  888. package/src/email/providers/index.ts +0 -65
  889. package/src/email/service.ts +0 -384
  890. package/src/email/types.ts +0 -126
  891. package/src/permissions/permission-mode-store.ts +0 -180
  892. package/src/prompts/templates/USER.md +0 -13
  893. package/src/providers/speech-to-text/types.ts +0 -17
  894. package/src/tools/browser/chrome-cdp.ts +0 -239
  895. package/src/tools/system/set-permission-mode.ts +0 -103
@@ -9,35 +9,93 @@ mock.module("../util/logger.js", () => ({
9
9
  }),
10
10
  }));
11
11
 
12
+ /**
13
+ * Fake CDP session driven by the real `LocalCdpClient` via the mocked
14
+ * `browserManager.getOrCreateSessionPage` below. `sendCalls` records
15
+ * every `session.send(method, params)` so tests can assert the exact
16
+ * sequence of CDP commands issued by `executeBrowserFillCredential`.
17
+ * `sendHandler` is replaced per test to shape responses or throw.
18
+ */
19
+ interface SendCall {
20
+ method: string;
21
+ params: Record<string, unknown> | undefined;
22
+ }
23
+
24
+ let sendCalls: SendCall[];
25
+ let sendHandler: (
26
+ method: string,
27
+ params: Record<string, unknown> | undefined,
28
+ ) => unknown;
29
+ let detachCalls: number;
30
+
31
+ function resetCdpMock() {
32
+ sendCalls = [];
33
+ detachCalls = 0;
34
+ sendHandler = defaultCdpHandler;
35
+ }
36
+
37
+ const fakeCdpSession = {
38
+ send: async (method: string, params?: Record<string, unknown>) => {
39
+ sendCalls.push({ method, params });
40
+ const value = sendHandler(method, params);
41
+ if (value instanceof Error) throw value;
42
+ return value;
43
+ },
44
+ detach: async () => {
45
+ detachCalls += 1;
46
+ },
47
+ };
48
+
49
+ /**
50
+ * Fake Playwright page that LocalCdpClient drives. Only the
51
+ * `context().newCDPSession()` surface is needed — all credential-fill
52
+ * work now flows through CDP.
53
+ */
12
54
  let mockPage: {
13
- click: ReturnType<typeof mock>;
14
- fill: ReturnType<typeof mock>;
15
- press: ReturnType<typeof mock>;
16
- evaluate: ReturnType<typeof mock>;
17
- title: ReturnType<typeof mock>;
18
- url: ReturnType<typeof mock>;
19
- goto: ReturnType<typeof mock>;
20
55
  close: () => Promise<void>;
21
56
  isClosed: () => boolean;
57
+ context: () => {
58
+ newCDPSession: (page: unknown) => Promise<typeof fakeCdpSession>;
59
+ };
22
60
  };
23
61
 
24
- let snapshotMaps: Map<string, Map<string, string>>;
62
+ let snapshotBackendNodeMaps: Map<string, Map<string, number>>;
63
+
64
+ const preferredBackendKinds = new Map<string, string>();
25
65
 
26
66
  mock.module("../tools/browser/browser-manager.js", () => {
27
- snapshotMaps = new Map();
67
+ snapshotBackendNodeMaps = new Map();
68
+ preferredBackendKinds.clear();
28
69
  return {
29
70
  browserManager: {
30
71
  getOrCreateSessionPage: async () => mockPage,
31
72
  closeSessionPage: async () => {},
32
73
  closeAllPages: async () => {},
33
- storeSnapshotMap: (conversationId: string, map: Map<string, string>) => {
34
- snapshotMaps.set(conversationId, map);
74
+ storeSnapshotBackendNodeMap: (
75
+ conversationId: string,
76
+ map: Map<string, number>,
77
+ ) => {
78
+ snapshotBackendNodeMaps.set(conversationId, map);
35
79
  },
36
- resolveSnapshotSelector: (conversationId: string, elementId: string) => {
37
- const map = snapshotMaps.get(conversationId);
80
+ resolveSnapshotBackendNodeId: (
81
+ conversationId: string,
82
+ elementId: string,
83
+ ) => {
84
+ const map = snapshotBackendNodeMaps.get(conversationId);
38
85
  if (!map) return null;
39
86
  return map.get(elementId) ?? null;
40
87
  },
88
+ clearSnapshotBackendNodeMap: (conversationId: string) => {
89
+ snapshotBackendNodeMaps.delete(conversationId);
90
+ },
91
+ getPreferredBackendKind: (conversationId: string) =>
92
+ preferredBackendKinds.get(conversationId) ?? null,
93
+ setPreferredBackendKind: (conversationId: string, kind: string) => {
94
+ preferredBackendKinds.set(conversationId, kind);
95
+ },
96
+ clearPreferredBackendKind: (conversationId: string) => {
97
+ preferredBackendKinds.delete(conversationId);
98
+ },
41
99
  },
42
100
  };
43
101
  });
@@ -82,21 +140,50 @@ const ctx: ToolContext = {
82
140
 
83
141
  function resetMockPage() {
84
142
  mockPage = {
85
- click: mock(async () => {}),
86
- fill: mock(async () => {}),
87
- press: mock(async () => {}),
88
- evaluate: mock(async () => ""),
89
- title: mock(async () => "Test Page"),
90
- url: mock(() => "https://example.com/"),
91
- goto: mock(async () => ({
92
- status: () => 200,
93
- url: () => "https://example.com/",
94
- })),
95
143
  close: async () => {},
96
144
  isClosed: () => false,
145
+ context: () => ({
146
+ newCDPSession: async (_page: unknown) => fakeCdpSession,
147
+ }),
97
148
  };
98
149
  }
99
150
 
151
+ /**
152
+ * Default CDP handler used by every test unless overridden. Returns
153
+ * the minimum plumbing needed for:
154
+ * - `getCurrentUrl` via Runtime.evaluate (for the broker domain check)
155
+ * - `querySelectorBackendNodeId` via DOM.getDocument / querySelector / describeNode
156
+ * - `focusElement` via DOM.focus
157
+ * - `clearAndInsertText` via DOM.resolveNode + Runtime.callFunctionOn + Input.insertText
158
+ * - `dispatchKeyPress` via Input.dispatchKeyEvent
159
+ */
160
+ function defaultCdpHandler(
161
+ method: string,
162
+ _params: Record<string, unknown> | undefined,
163
+ ): unknown {
164
+ switch (method) {
165
+ case "Runtime.evaluate":
166
+ // getCurrentUrl() reads document.location.href via Runtime.evaluate
167
+ return { result: { value: "https://example.com/" } };
168
+ case "DOM.getDocument":
169
+ return { root: { nodeId: 1 } };
170
+ case "DOM.querySelector":
171
+ return { nodeId: 42 };
172
+ case "DOM.describeNode":
173
+ return { node: { backendNodeId: 100 } };
174
+ case "DOM.resolveNode":
175
+ // Used by clearAndInsertText to obtain a remote object on the
176
+ // target element so it can run the value-clearing function.
177
+ return { object: { objectId: "obj-1" } };
178
+ case "Runtime.callFunctionOn":
179
+ // The clear-helper function returns undefined; tests don't
180
+ // depend on the return value.
181
+ return { result: { value: undefined } };
182
+ default:
183
+ return {};
184
+ }
185
+ }
186
+
100
187
  function defaultMetadata(service: string, field: string) {
101
188
  return {
102
189
  credentialId: `${service}:${field}`,
@@ -114,7 +201,8 @@ function defaultMetadata(service: string, field: string) {
114
201
  describe("executeBrowserFillCredential", () => {
115
202
  beforeEach(() => {
116
203
  resetMockPage();
117
- snapshotMaps.clear();
204
+ resetCdpMock();
205
+ snapshotBackendNodeMaps.clear();
118
206
  mockGetSecureKey = mock(() => "super-secret-password");
119
207
  mockGetCredentialMetadata = mock((service: string, field: string) =>
120
208
  defaultMetadata(service, field),
@@ -122,23 +210,79 @@ describe("executeBrowserFillCredential", () => {
122
210
  });
123
211
 
124
212
  test("fills credential into element by element_id", async () => {
125
- snapshotMaps.set(
126
- "test-conversation",
127
- new Map([["e1", '[data-vellum-eid="e1"]']]),
128
- );
213
+ snapshotBackendNodeMaps.set("test-conversation", new Map([["e1", 555]]));
129
214
  const result = await executeBrowserFillCredential(
130
215
  { service: "gmail", field: "password", element_id: "e1" },
131
216
  ctx,
132
217
  );
133
218
  expect(result.isError).toBe(false);
134
219
  expect(result.content).toContain("Filled password for gmail");
135
- expect(mockPage.fill).toHaveBeenCalledWith(
136
- '[data-vellum-eid="e1"]',
137
- "super-secret-password",
138
- );
220
+
221
+ // Backend path now goes through clearAndInsertText:
222
+ // Runtime.evaluate (getCurrentUrl)
223
+ // → DOM.focus
224
+ // → DOM.resolveNode
225
+ // → Runtime.callFunctionOn (clear)
226
+ // → DOM.focus (re-focus)
227
+ // → Input.insertText
228
+ const methods = sendCalls.map((c) => c.method);
229
+ expect(methods).toContain("DOM.focus");
230
+ expect(methods).toContain("DOM.resolveNode");
231
+ expect(methods).toContain("Runtime.callFunctionOn");
232
+ expect(methods).toContain("Input.insertText");
233
+ expect(methods).not.toContain("DOM.querySelector");
234
+
235
+ const focusCall = sendCalls.find((c) => c.method === "DOM.focus")!;
236
+ expect(focusCall.params).toEqual({ backendNodeId: 555 });
237
+
238
+ const insertCall = sendCalls.find((c) => c.method === "Input.insertText")!;
239
+ expect(insertCall.params).toEqual({ text: "super-secret-password" });
240
+
139
241
  expect(mockGetSecureKey).toHaveBeenCalledWith(
140
242
  credentialKey("gmail", "password"),
141
243
  );
244
+
245
+ // CdpClient disposed in finally → session.detach called.
246
+ await new Promise((resolve) => setTimeout(resolve, 0));
247
+ expect(detachCalls).toBe(1);
248
+ });
249
+
250
+ test("clears pre-populated field BEFORE inserting credential text", async () => {
251
+ // Regression: previously, fillCredential called focus + insertText
252
+ // directly, which APPENDED the credential to any existing value
253
+ // (autofill, prior typing, etc.) — corrupting the password and
254
+ // leaking partial state. The fix routes through the shared
255
+ // clearAndInsertText helper.
256
+ snapshotBackendNodeMaps.set("test-conversation", new Map([["e1", 555]]));
257
+ await executeBrowserFillCredential(
258
+ { service: "gmail", field: "password", element_id: "e1" },
259
+ ctx,
260
+ );
261
+
262
+ // The clear must happen BEFORE the insertText. Specifically, the
263
+ // Runtime.callFunctionOn that runs the clearing function declaration
264
+ // must precede Input.insertText.
265
+ const methodSeq = sendCalls.map((c) => c.method);
266
+ const clearIdx = methodSeq.indexOf("Runtime.callFunctionOn");
267
+ const insertIdx = methodSeq.indexOf("Input.insertText");
268
+ expect(clearIdx).toBeGreaterThanOrEqual(0);
269
+ expect(insertIdx).toBeGreaterThan(clearIdx);
270
+
271
+ // The clearing function must reset both `value` and
272
+ // `textContent` so input/textarea AND contenteditable targets
273
+ // are handled.
274
+ const clearCall = sendCalls[clearIdx]!;
275
+ const fnDecl = (clearCall.params as { functionDeclaration: string })
276
+ .functionDeclaration;
277
+ expect(fnDecl).toContain('this.value = ""');
278
+ expect(fnDecl).toContain("this.textContent");
279
+ expect(fnDecl).toContain('new Event("input"');
280
+
281
+ // After the clear, the helper re-focuses the element (some sites
282
+ // blur on programmatic value reset) before inserting text — so we
283
+ // expect at least 2 DOM.focus calls in total.
284
+ const focusCount = methodSeq.filter((m) => m === "DOM.focus").length;
285
+ expect(focusCount).toBeGreaterThanOrEqual(2);
142
286
  });
143
287
 
144
288
  test("fills credential by CSS selector", async () => {
@@ -148,18 +292,27 @@ describe("executeBrowserFillCredential", () => {
148
292
  );
149
293
  expect(result.isError).toBe(false);
150
294
  expect(result.content).toContain("Filled token for github");
151
- expect(mockPage.fill).toHaveBeenCalledWith(
152
- 'input[name="password"]',
153
- "super-secret-password",
154
- );
295
+
296
+ // Selector path must resolve the backendNodeId via DOM.querySelector
297
+ // before focusing + inserting text.
298
+ const methods = sendCalls.map((c) => c.method);
299
+ expect(methods).toContain("DOM.getDocument");
300
+ expect(methods).toContain("DOM.querySelector");
301
+ expect(methods).toContain("DOM.describeNode");
302
+ expect(methods).toContain("DOM.focus");
303
+ expect(methods).toContain("Input.insertText");
304
+
305
+ // DOM.focus uses the backendNodeId (100) returned by DOM.describeNode
306
+ const focusCall = sendCalls.find((c) => c.method === "DOM.focus")!;
307
+ expect(focusCall.params).toEqual({ backendNodeId: 100 });
308
+
309
+ const insertCall = sendCalls.find((c) => c.method === "Input.insertText")!;
310
+ expect(insertCall.params).toEqual({ text: "super-secret-password" });
155
311
  });
156
312
 
157
313
  test("returns error when credential not found", async () => {
158
314
  mockGetCredentialMetadata = mock(() => undefined);
159
- snapshotMaps.set(
160
- "test-conversation",
161
- new Map([["e1", '[data-vellum-eid="e1"]']]),
162
- );
315
+ snapshotBackendNodeMaps.set("test-conversation", new Map([["e1", 555]]));
163
316
  const result = await executeBrowserFillCredential(
164
317
  { service: "slack", field: "api_key", element_id: "e1" },
165
318
  ctx,
@@ -167,15 +320,15 @@ describe("executeBrowserFillCredential", () => {
167
320
  expect(result.isError).toBe(true);
168
321
  expect(result.content).toContain("No credential stored for slack/api_key");
169
322
  expect(result.content).toContain("credential_store");
170
- expect(mockPage.fill).not.toHaveBeenCalled();
323
+ // The broker short-circuits before DOM.focus is dispatched.
324
+ const methods = sendCalls.map((c) => c.method);
325
+ expect(methods).not.toContain("DOM.focus");
326
+ expect(methods).not.toContain("Input.insertText");
171
327
  });
172
328
 
173
329
  test("returns error when metadata exists but no stored value", async () => {
174
330
  mockGetSecureKey = mock(() => undefined);
175
- snapshotMaps.set(
176
- "test-conversation",
177
- new Map([["e1", '[data-vellum-eid="e1"]']]),
178
- );
331
+ snapshotBackendNodeMaps.set("test-conversation", new Map([["e1", 555]]));
179
332
  const result = await executeBrowserFillCredential(
180
333
  { service: "slack", field: "api_key", element_id: "e1" },
181
334
  ctx,
@@ -183,7 +336,8 @@ describe("executeBrowserFillCredential", () => {
183
336
  expect(result.isError).toBe(true);
184
337
  expect(result.content).toContain("No credential stored for slack/api_key");
185
338
  expect(result.content).toContain("credential_store");
186
- expect(mockPage.fill).not.toHaveBeenCalled();
339
+ const methods = sendCalls.map((c) => c.method);
340
+ expect(methods).not.toContain("Input.insertText");
187
341
  });
188
342
 
189
343
  test("returns error when element not found", async () => {
@@ -194,13 +348,13 @@ describe("executeBrowserFillCredential", () => {
194
348
  expect(result.isError).toBe(true);
195
349
  expect(result.content).toContain('element_id "e99" not found');
196
350
  expect(result.content).toContain("browser_snapshot");
351
+ // Element resolution fails before any CDP session is opened.
352
+ expect(sendCalls).toHaveLength(0);
353
+ expect(detachCalls).toBe(0);
197
354
  });
198
355
 
199
356
  test("presses Enter after fill when press_enter is true", async () => {
200
- snapshotMaps.set(
201
- "test-conversation",
202
- new Map([["e2", '[data-vellum-eid="e2"]']]),
203
- );
357
+ snapshotBackendNodeMaps.set("test-conversation", new Map([["e2", 222]]));
204
358
  const result = await executeBrowserFillCredential(
205
359
  {
206
360
  service: "gmail",
@@ -211,21 +365,34 @@ describe("executeBrowserFillCredential", () => {
211
365
  ctx,
212
366
  );
213
367
  expect(result.isError).toBe(false);
214
- expect(mockPage.fill).toHaveBeenCalledWith(
215
- '[data-vellum-eid="e2"]',
216
- "super-secret-password",
368
+ const methods = sendCalls.map((c) => c.method);
369
+ expect(methods).toContain("Input.insertText");
370
+ // dispatchKeyPress for "Enter" dispatches keyDown + char + keyUp
371
+ // (Enter has text "\r" so it now produces a char event too).
372
+ const keyEvents = sendCalls.filter(
373
+ (c) => c.method === "Input.dispatchKeyEvent",
217
374
  );
218
- expect(mockPage.press).toHaveBeenCalledWith(
219
- '[data-vellum-eid="e2"]',
375
+ expect(keyEvents).toHaveLength(3);
376
+ expect((keyEvents[0]!.params as { type: string; key: string }).type).toBe(
377
+ "keyDown",
378
+ );
379
+ expect((keyEvents[0]!.params as { type: string; key: string }).key).toBe(
220
380
  "Enter",
221
381
  );
382
+ expect((keyEvents[1]!.params as { type: string }).type).toBe("char");
383
+ expect((keyEvents[2]!.params as { type: string }).type).toBe("keyUp");
384
+ // Enter must come AFTER Input.insertText.
385
+ const insertIdx = sendCalls.findIndex(
386
+ (c) => c.method === "Input.insertText",
387
+ );
388
+ const firstKeyIdx = sendCalls.findIndex(
389
+ (c) => c.method === "Input.dispatchKeyEvent",
390
+ );
391
+ expect(firstKeyIdx).toBeGreaterThan(insertIdx);
222
392
  });
223
393
 
224
394
  test("credential value NEVER appears in result content", async () => {
225
- snapshotMaps.set(
226
- "test-conversation",
227
- new Map([["e1", '[data-vellum-eid="e1"]']]),
228
- );
395
+ snapshotBackendNodeMaps.set("test-conversation", new Map([["e1", 555]]));
229
396
  const result = await executeBrowserFillCredential(
230
397
  { service: "gmail", field: "password", element_id: "e1" },
231
398
  ctx,
@@ -235,10 +402,7 @@ describe("executeBrowserFillCredential", () => {
235
402
  });
236
403
 
237
404
  test("returns error when service is missing", async () => {
238
- snapshotMaps.set(
239
- "test-conversation",
240
- new Map([["e1", '[data-vellum-eid="e1"]']]),
241
- );
405
+ snapshotBackendNodeMaps.set("test-conversation", new Map([["e1", 555]]));
242
406
  const result = await executeBrowserFillCredential(
243
407
  { field: "password", element_id: "e1" },
244
408
  ctx,
@@ -248,10 +412,7 @@ describe("executeBrowserFillCredential", () => {
248
412
  });
249
413
 
250
414
  test("returns error when field is missing", async () => {
251
- snapshotMaps.set(
252
- "test-conversation",
253
- new Map([["e1", '[data-vellum-eid="e1"]']]),
254
- );
415
+ snapshotBackendNodeMaps.set("test-conversation", new Map([["e1", 555]]));
255
416
  const result = await executeBrowserFillCredential(
256
417
  { service: "gmail", element_id: "e1" },
257
418
  ctx,
@@ -265,10 +426,7 @@ describe("executeBrowserFillCredential", () => {
265
426
  // -----------------------------------------------------------------------
266
427
  describe("broker integration", () => {
267
428
  test("fill succeeds with no domain or tool-policy checks", async () => {
268
- snapshotMaps.set(
269
- "test-conversation",
270
- new Map([["e1", '[data-vellum-eid="e1"]']]),
271
- );
429
+ snapshotBackendNodeMaps.set("test-conversation", new Map([["e1", 555]]));
272
430
  const result = await executeBrowserFillCredential(
273
431
  { service: "gmail", field: "password", element_id: "e1" },
274
432
  ctx,
@@ -279,10 +437,7 @@ describe("executeBrowserFillCredential", () => {
279
437
  });
280
438
 
281
439
  test("credential access goes through broker (metadata + value checked)", async () => {
282
- snapshotMaps.set(
283
- "test-conversation",
284
- new Map([["e1", '[data-vellum-eid="e1"]']]),
285
- );
440
+ snapshotBackendNodeMaps.set("test-conversation", new Map([["e1", 555]]));
286
441
  await executeBrowserFillCredential(
287
442
  { service: "gmail", field: "password", element_id: "e1" },
288
443
  ctx,
@@ -302,10 +457,7 @@ describe("executeBrowserFillCredential", () => {
302
457
  ...defaultMetadata(service, field),
303
458
  allowedTools: ["some_other_tool"],
304
459
  }));
305
- snapshotMaps.set(
306
- "test-conversation",
307
- new Map([["e1", '[data-vellum-eid="e1"]']]),
308
- );
460
+ snapshotBackendNodeMaps.set("test-conversation", new Map([["e1", 555]]));
309
461
  const result = await executeBrowserFillCredential(
310
462
  { service: "gmail", field: "password", element_id: "e1" },
311
463
  ctx,
@@ -314,7 +466,9 @@ describe("executeBrowserFillCredential", () => {
314
466
  expect(result.content).toContain("Policy denied");
315
467
  expect(result.content).toContain("not allowed to use credential");
316
468
  expect(result.content).toContain("credential_store");
317
- expect(mockPage.fill).not.toHaveBeenCalled();
469
+ // The broker short-circuits before Input.insertText fires.
470
+ const methods = sendCalls.map((c) => c.method);
471
+ expect(methods).not.toContain("Input.insertText");
318
472
  });
319
473
 
320
474
  test("returns domain policy denial with actionable message", async () => {
@@ -322,10 +476,7 @@ describe("executeBrowserFillCredential", () => {
322
476
  ...defaultMetadata(service, field),
323
477
  allowedDomains: ["other-site.com"],
324
478
  }));
325
- snapshotMaps.set(
326
- "test-conversation",
327
- new Map([["e1", '[data-vellum-eid="e1"]']]),
328
- );
479
+ snapshotBackendNodeMaps.set("test-conversation", new Map([["e1", 555]]));
329
480
  const result = await executeBrowserFillCredential(
330
481
  { service: "gmail", field: "password", element_id: "e1" },
331
482
  ctx,
@@ -333,7 +484,8 @@ describe("executeBrowserFillCredential", () => {
333
484
  expect(result.isError).toBe(true);
334
485
  expect(result.content).toContain("Domain policy denied");
335
486
  expect(result.content).toContain("Navigate to an allowed domain");
336
- expect(mockPage.fill).not.toHaveBeenCalled();
487
+ const methods = sendCalls.map((c) => c.method);
488
+ expect(methods).not.toContain("Input.insertText");
337
489
  });
338
490
 
339
491
  test("passes current page domain to broker", async () => {
@@ -341,15 +493,12 @@ describe("executeBrowserFillCredential", () => {
341
493
  ...defaultMetadata(service, field),
342
494
  allowedDomains: ["example.com"],
343
495
  }));
344
- snapshotMaps.set(
345
- "test-conversation",
346
- new Map([["e1", '[data-vellum-eid="e1"]']]),
347
- );
496
+ snapshotBackendNodeMaps.set("test-conversation", new Map([["e1", 555]]));
348
497
  const result = await executeBrowserFillCredential(
349
498
  { service: "gmail", field: "password", element_id: "e1" },
350
499
  ctx,
351
500
  );
352
- // Page URL is https://example.com/ which matches allowedDomains
501
+ // Default handler returns https://example.com/ matches allowedDomains
353
502
  expect(result.isError).toBe(false);
354
503
  expect(result.content).toContain("Filled password for gmail");
355
504
  });
@@ -359,10 +508,7 @@ describe("executeBrowserFillCredential", () => {
359
508
  ...defaultMetadata(service, field),
360
509
  allowedTools: ["other_tool"],
361
510
  }));
362
- snapshotMaps.set(
363
- "test-conversation",
364
- new Map([["e1", '[data-vellum-eid="e1"]']]),
365
- );
511
+ snapshotBackendNodeMaps.set("test-conversation", new Map([["e1", 555]]));
366
512
  const result = await executeBrowserFillCredential(
367
513
  { service: "gmail", field: "password", element_id: "e1" },
368
514
  ctx,
@@ -165,13 +165,15 @@ describe("BrowserManager", () => {
165
165
  // Should not throw
166
166
  });
167
167
 
168
- test("clears snapshot map for the session", async () => {
168
+ test("clears snapshot backendNodeId map for the session", async () => {
169
169
  await browserManager.getOrCreateSessionPage("s1");
170
- browserManager.storeSnapshotMap("s1", new Map([["e1", "#btn"]]));
171
- expect(browserManager.resolveSnapshotSelector("s1", "e1")).toBe("#btn");
170
+ browserManager.storeSnapshotBackendNodeMap("s1", new Map([["e1", 42]]));
171
+ expect(browserManager.resolveSnapshotBackendNodeId("s1", "e1")).toBe(42);
172
172
 
173
173
  await browserManager.closeSessionPage("s1");
174
- expect(browserManager.resolveSnapshotSelector("s1", "e1")).toBeNull();
174
+ expect(
175
+ browserManager.resolveSnapshotBackendNodeId("s1", "e1"),
176
+ ).toBeNull();
175
177
  });
176
178
  });
177
179
 
@@ -195,52 +197,63 @@ describe("BrowserManager", () => {
195
197
  // Should not throw
196
198
  });
197
199
 
198
- test("clears all snapshot maps", async () => {
200
+ test("clears all snapshot backendNodeId maps", async () => {
199
201
  await browserManager.getOrCreateSessionPage("s1");
200
202
  await browserManager.getOrCreateSessionPage("s2");
201
- browserManager.storeSnapshotMap("s1", new Map([["e1", "#a"]]));
202
- browserManager.storeSnapshotMap("s2", new Map([["e2", "#b"]]));
203
+ browserManager.storeSnapshotBackendNodeMap("s1", new Map([["e1", 11]]));
204
+ browserManager.storeSnapshotBackendNodeMap("s2", new Map([["e2", 22]]));
203
205
 
204
206
  await browserManager.closeAllPages();
205
207
 
206
- expect(browserManager.resolveSnapshotSelector("s1", "e1")).toBeNull();
207
- expect(browserManager.resolveSnapshotSelector("s2", "e2")).toBeNull();
208
+ expect(
209
+ browserManager.resolveSnapshotBackendNodeId("s1", "e1"),
210
+ ).toBeNull();
211
+ expect(
212
+ browserManager.resolveSnapshotBackendNodeId("s2", "e2"),
213
+ ).toBeNull();
208
214
  });
209
215
  });
210
216
 
211
- // ── snapshot map ─────────────────────────────────────────────
217
+ // ── snapshot backendNodeId map ───────────────────────────────
212
218
 
213
- describe("snapshot map", () => {
214
- test("stores and resolves element selectors", () => {
219
+ describe("snapshot backendNodeId map", () => {
220
+ test("stores and resolves element backendNodeIds", () => {
215
221
  const map = new Map([
216
- ["e1", "#submit-btn"],
217
- ["e2", 'input[name="email"]'],
222
+ ["e1", 101],
223
+ ["e2", 202],
218
224
  ]);
219
- browserManager.storeSnapshotMap("s1", map);
225
+ browserManager.storeSnapshotBackendNodeMap("s1", map);
220
226
 
221
- expect(browserManager.resolveSnapshotSelector("s1", "e1")).toBe(
222
- "#submit-btn",
223
- );
224
- expect(browserManager.resolveSnapshotSelector("s1", "e2")).toBe(
225
- 'input[name="email"]',
226
- );
227
+ expect(browserManager.resolveSnapshotBackendNodeId("s1", "e1")).toBe(101);
228
+ expect(browserManager.resolveSnapshotBackendNodeId("s1", "e2")).toBe(202);
227
229
  });
228
230
 
229
231
  test("returns null for unknown element id", () => {
230
- browserManager.storeSnapshotMap("s1", new Map([["e1", "#btn"]]));
231
- expect(browserManager.resolveSnapshotSelector("s1", "e999")).toBeNull();
232
+ browserManager.storeSnapshotBackendNodeMap("s1", new Map([["e1", 42]]));
233
+ expect(
234
+ browserManager.resolveSnapshotBackendNodeId("s1", "e999"),
235
+ ).toBeNull();
232
236
  });
233
237
 
234
238
  test("returns null for unknown session", () => {
235
239
  expect(
236
- browserManager.resolveSnapshotSelector("unknown", "e1"),
240
+ browserManager.resolveSnapshotBackendNodeId("unknown", "e1"),
237
241
  ).toBeNull();
238
242
  });
239
243
 
240
244
  test("overwrites previous snapshot map for same session", () => {
241
- browserManager.storeSnapshotMap("s1", new Map([["e1", "#old"]]));
242
- browserManager.storeSnapshotMap("s1", new Map([["e1", "#new"]]));
243
- expect(browserManager.resolveSnapshotSelector("s1", "e1")).toBe("#new");
245
+ browserManager.storeSnapshotBackendNodeMap("s1", new Map([["e1", 1]]));
246
+ browserManager.storeSnapshotBackendNodeMap("s1", new Map([["e1", 999]]));
247
+ expect(browserManager.resolveSnapshotBackendNodeId("s1", "e1")).toBe(999);
248
+ });
249
+
250
+ test("clearSnapshotBackendNodeMap drops the map for a session", () => {
251
+ browserManager.storeSnapshotBackendNodeMap("s1", new Map([["e1", 42]]));
252
+ expect(browserManager.resolveSnapshotBackendNodeId("s1", "e1")).toBe(42);
253
+ browserManager.clearSnapshotBackendNodeMap("s1");
254
+ expect(
255
+ browserManager.resolveSnapshotBackendNodeId("s1", "e1"),
256
+ ).toBeNull();
244
257
  });
245
258
  });
246
259
  });
@@ -41,12 +41,12 @@ describe("browser skill cutover — startup tool payload", () => {
41
41
  }
42
42
  });
43
43
 
44
- test("total tool definition count reflects removal of 14 browser tools", () => {
44
+ test("total tool definition count reflects removal of browser tools", () => {
45
45
  const definitions = getAllToolDefinitions();
46
46
  // Startup has ~20 definitions after moving scaffold/settings/skill-management
47
47
  // tools to bundled skills (no browser tools).
48
48
  // Allow wider drift for unrelated tool additions while still failing if
49
- // browser tools are reintroduced at startup (+14 definitions).
49
+ // browser tools are reintroduced at startup (+many definitions).
50
50
  expect(definitions.length).toBeGreaterThanOrEqual(15);
51
51
  expect(definitions.length).toBeLessThanOrEqual(50);
52
52
  });