@vellumai/assistant 0.6.3 → 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 (667) hide show
  1. package/ARCHITECTURE.md +273 -10
  2. package/Dockerfile +2 -3
  3. package/bun.lock +5 -13
  4. package/docs/backup-troubleshooting.md +52 -0
  5. package/docs/browser-use-architecture-phase2.md +174 -0
  6. package/docs/stt-provider-onboarding.md +120 -0
  7. package/knip.json +12 -2
  8. package/node_modules/@vellumai/ces-contracts/bun.lock +8 -6
  9. package/node_modules/@vellumai/ces-contracts/package.json +3 -3
  10. package/openapi.yaml +982 -72
  11. package/package.json +4 -6
  12. package/scripts/generate-openapi.ts +0 -1
  13. package/scripts/test.sh +73 -18
  14. package/src/__tests__/agent-image-optimize.test.ts +28 -0
  15. package/src/__tests__/agent-loop.test.ts +123 -0
  16. package/src/__tests__/anthropic-provider.test.ts +263 -10
  17. package/src/__tests__/auto-analysis-end-to-end.test.ts +550 -0
  18. package/src/__tests__/auto-analysis-prompt.test.ts +50 -0
  19. package/src/__tests__/browser-fill-credential.test.ts +11 -0
  20. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +2 -2
  21. package/src/__tests__/browser-skill-endstate.test.ts +31 -7
  22. package/src/__tests__/btw-routes.test.ts +7 -0
  23. package/src/__tests__/call-controller.test.ts +581 -20
  24. package/src/__tests__/catalog-files.test.ts +138 -0
  25. package/src/__tests__/channel-invite-transport.test.ts +2 -2
  26. package/src/__tests__/channel-readiness-routes.test.ts +16 -20
  27. package/src/__tests__/channel-readiness-service.test.ts +12 -7
  28. package/src/__tests__/checker.test.ts +157 -10
  29. package/src/__tests__/clawhub-files.test.ts +347 -0
  30. package/src/__tests__/commit-message-enrichment-service.test.ts +36 -19
  31. package/src/__tests__/config-analysis.test.ts +100 -0
  32. package/src/__tests__/config-schema.test.ts +1013 -66
  33. package/src/__tests__/config-watcher-cleanup-throttle.test.ts +339 -0
  34. package/src/__tests__/config-watcher.test.ts +43 -8
  35. package/src/__tests__/contact-store-user-file.test.ts +512 -0
  36. package/src/__tests__/contacts-write.test.ts +197 -0
  37. package/src/__tests__/context-window-manager.test.ts +88 -0
  38. package/src/__tests__/conversation-abort-tool-results.test.ts +2 -0
  39. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
  40. package/src/__tests__/conversation-agent-loop.test.ts +98 -2
  41. package/src/__tests__/conversation-confirmation-signals.test.ts +135 -0
  42. package/src/__tests__/conversation-error.test.ts +70 -0
  43. package/src/__tests__/conversation-history-web-search.test.ts +11 -4
  44. package/src/__tests__/conversation-init.benchmark.test.ts +6 -1
  45. package/src/__tests__/conversation-launcher-skill-regression.test.ts +51 -0
  46. package/src/__tests__/conversation-list-source.test.ts +145 -0
  47. package/src/__tests__/conversation-pre-run-repair.test.ts +2 -0
  48. package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -0
  49. package/src/__tests__/conversation-queue.test.ts +901 -60
  50. package/src/__tests__/conversation-routes-disk-view.test.ts +270 -0
  51. package/src/__tests__/conversation-runtime-assembly.test.ts +55 -0
  52. package/src/__tests__/conversation-skill-tools.test.ts +7 -4
  53. package/src/__tests__/conversation-slash-commands.test.ts +33 -0
  54. package/src/__tests__/conversation-slash-queue.test.ts +89 -18
  55. package/src/__tests__/conversation-slash-unknown.test.ts +2 -0
  56. package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +226 -0
  57. package/src/__tests__/conversation-workspace-injection.test.ts +2 -0
  58. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +2 -0
  59. package/src/__tests__/credential-health-service.test.ts +352 -0
  60. package/src/__tests__/credential-security-invariants.test.ts +5 -3
  61. package/src/__tests__/credential-vault-unit.test.ts +379 -3
  62. package/src/__tests__/credentials-cli.test.ts +40 -16
  63. package/src/__tests__/cross-provider-web-search.test.ts +146 -35
  64. package/src/__tests__/deterministic-verification-control-plane.test.ts +10 -1
  65. package/src/__tests__/device-id.test.ts +112 -0
  66. package/src/__tests__/docker-signing-key-bootstrap.test.ts +167 -4
  67. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +1 -3
  68. package/src/__tests__/email-html-renderer.test.ts +71 -0
  69. package/src/__tests__/email-invite-adapter.test.ts +36 -32
  70. package/src/__tests__/emit-event-signal.test.ts +71 -0
  71. package/src/__tests__/extension-id-sync-guard.test.ts +75 -8
  72. package/src/__tests__/fixtures/mock-chrome-extension.ts +11 -0
  73. package/src/__tests__/gateway-only-enforcement.test.ts +206 -1
  74. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  75. package/src/__tests__/gemini-provider.test.ts +64 -0
  76. package/src/__tests__/get-skill-detail-audit.test.ts +325 -0
  77. package/src/__tests__/gmail-archive-fallback.test.ts +193 -0
  78. package/src/__tests__/gmail-archive-gate.test.ts +246 -0
  79. package/src/__tests__/gmail-preferences.test.ts +117 -0
  80. package/src/__tests__/headless-browser-interactions.test.ts +43 -0
  81. package/src/__tests__/headless-browser-mode.test.ts +614 -0
  82. package/src/__tests__/headless-browser-navigate.test.ts +142 -5
  83. package/src/__tests__/headless-browser-read-tools.test.ts +11 -0
  84. package/src/__tests__/headless-browser-snapshot.test.ts +10 -0
  85. package/src/__tests__/heartbeat-service.test.ts +70 -17
  86. package/src/__tests__/home-state-routes.test.ts +162 -0
  87. package/src/__tests__/host-bash-proxy.test.ts +0 -5
  88. package/src/__tests__/host-browser-e2e-cloud.test.ts +138 -4
  89. package/src/__tests__/host-browser-e2e-self-hosted.test.ts +4 -4
  90. package/src/__tests__/host-browser-ws-events-e2e.test.ts +103 -0
  91. package/src/__tests__/host-cu-proxy.test.ts +0 -5
  92. package/src/__tests__/identity-intro-cache.test.ts +40 -10
  93. package/src/__tests__/init-feature-flag-overrides.test.ts +38 -112
  94. package/src/__tests__/jobs-store-upsert-debounced.test.ts +141 -0
  95. package/src/__tests__/llm-context-normalization.test.ts +488 -0
  96. package/src/__tests__/llm-context-route-provider.test.ts +86 -5
  97. package/src/__tests__/llm-usage-store.test.ts +363 -0
  98. package/src/__tests__/media-stream-output.test.ts +555 -0
  99. package/src/__tests__/media-stream-parser.test.ts +374 -0
  100. package/src/__tests__/media-stream-server-integration.test.ts +1234 -0
  101. package/src/__tests__/media-stream-stt-session.test.ts +588 -0
  102. package/src/__tests__/media-turn-detector.test.ts +440 -0
  103. package/src/__tests__/message-queue.test.ts +125 -0
  104. package/src/__tests__/migration-export-http.test.ts +6 -6
  105. package/src/__tests__/migration-import-commit-http.test.ts +8 -6
  106. package/src/__tests__/migration-import-preflight-http.test.ts +6 -5
  107. package/src/__tests__/migration-validate-http.test.ts +3 -3
  108. package/src/__tests__/mock-gateway-ipc.ts +151 -0
  109. package/src/__tests__/model-intents.test.ts +2 -2
  110. package/src/__tests__/oauth-apps-routes.test.ts +1 -0
  111. package/src/__tests__/oauth-cli.test.ts +2 -0
  112. package/src/__tests__/oauth-connect-orchestrator.test.ts +2 -0
  113. package/src/__tests__/oauth-provider-serializer.test.ts +1 -0
  114. package/src/__tests__/oauth-providers-routes.test.ts +2 -0
  115. package/src/__tests__/oauth-store.test.ts +85 -0
  116. package/src/__tests__/oauth2-gateway-transport.test.ts +249 -6
  117. package/src/__tests__/onboarding-template-contract.test.ts +6 -13
  118. package/src/__tests__/openai-provider.test.ts +176 -0
  119. package/src/__tests__/openai-responses-cutover-guard.test.ts +184 -0
  120. package/src/__tests__/openai-responses-provider.test.ts +1105 -0
  121. package/src/__tests__/openrouter-token-estimation.test.ts +100 -0
  122. package/src/__tests__/outlook-unsubscribe.test.ts +31 -2
  123. package/src/__tests__/persona-resolver.test.ts +251 -0
  124. package/src/__tests__/platform-bash-auto-approve.test.ts +4 -0
  125. package/src/__tests__/platform.test.ts +92 -1
  126. package/src/__tests__/post-turn-tool-result-truncation.test.ts +47 -0
  127. package/src/__tests__/prechat-onboarding-contract.test.ts +267 -0
  128. package/src/__tests__/pricing.test.ts +174 -0
  129. package/src/__tests__/qdrant-manager.test.ts +29 -8
  130. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +194 -0
  131. package/src/__tests__/relationship-state-contract.test.ts +175 -0
  132. package/src/__tests__/relay-server.test.ts +423 -5
  133. package/src/__tests__/search-skills-unified.test.ts +118 -0
  134. package/src/__tests__/secret-scanner-executor.test.ts +4 -0
  135. package/src/__tests__/secure-keys.test.ts +107 -0
  136. package/src/__tests__/send-endpoint-busy.test.ts +5 -1
  137. package/src/__tests__/sequence-store.test.ts +1 -1
  138. package/src/__tests__/server-history-render.test.ts +49 -0
  139. package/src/__tests__/settings-routes.test.ts +201 -0
  140. package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
  141. package/src/__tests__/skills-file-content-endpoint.test.ts +276 -145
  142. package/src/__tests__/skills-files-catalog-fallback.test.ts +381 -93
  143. package/src/__tests__/skills.test.ts +5 -2
  144. package/src/__tests__/skillssh-files.test.ts +446 -0
  145. package/src/__tests__/slack-block-formatting.test.ts +110 -0
  146. package/src/__tests__/slack-channel-config.test.ts +564 -1
  147. package/src/__tests__/stt-catalog-parity.test.ts +282 -0
  148. package/src/__tests__/stt-stream-session.test.ts +535 -0
  149. package/src/__tests__/system-prompt.test.ts +112 -26
  150. package/src/__tests__/telephony-stt-routing.test.ts +329 -0
  151. package/src/__tests__/terminal-tools.test.ts +18 -7
  152. package/src/__tests__/test-preload.ts +18 -0
  153. package/src/__tests__/test-support/browser-skill-harness.ts +4 -1
  154. package/src/__tests__/tool-executor-lifecycle-events.test.ts +9 -5
  155. package/src/__tests__/tool-executor-shell-integration.test.ts +4 -0
  156. package/src/__tests__/tool-executor.test.ts +33 -24
  157. package/src/__tests__/tool-result-truncation.test.ts +36 -0
  158. package/src/__tests__/trust-store.test.ts +7 -1
  159. package/src/__tests__/trusted-contact-approval-notifier.test.ts +1 -1
  160. package/src/__tests__/tts-catalog-parity.test.ts +345 -0
  161. package/src/__tests__/twilio-routes-twiml.test.ts +512 -114
  162. package/src/__tests__/twilio-routes.test.ts +376 -0
  163. package/src/__tests__/unicode.test.ts +293 -0
  164. package/src/__tests__/update-bulletin-format.test.ts +59 -0
  165. package/src/__tests__/update-bulletin.test.ts +206 -5
  166. package/src/__tests__/usage-routes.test.ts +25 -4
  167. package/src/__tests__/user-reference.test.ts +46 -61
  168. package/src/__tests__/verification-control-plane-policy.test.ts +4 -0
  169. package/src/__tests__/voice-config-update.test.ts +403 -0
  170. package/src/__tests__/voice-quality.test.ts +434 -19
  171. package/src/__tests__/workspace-heartbeat-service.test.ts +7 -0
  172. package/src/__tests__/workspace-migration-033-stt-service-explicit-config.test.ts +547 -0
  173. package/src/__tests__/workspace-migration-034-remove-calls-voice-transcription-provider.test.ts +596 -0
  174. package/src/__tests__/workspace-migration-drop-user-md.test.ts +368 -0
  175. package/src/__tests__/workspace-migration-meets.test.ts +244 -0
  176. package/src/__tests__/workspace-migration-seed-device-id.test.ts +14 -20
  177. package/src/__tests__/workspace-policy.test.ts +2 -0
  178. package/src/agent/image-optimize.ts +24 -12
  179. package/src/agent/loop.ts +43 -3
  180. package/src/backup/__tests__/backup-key.test.ts +152 -0
  181. package/src/backup/__tests__/backup-worker.test.ts +767 -0
  182. package/src/backup/__tests__/list-snapshots.test.ts +87 -0
  183. package/src/backup/__tests__/local-writer.test.ts +218 -0
  184. package/src/backup/__tests__/offsite-writer.test.ts +641 -0
  185. package/src/backup/__tests__/paths.test.ts +300 -0
  186. package/src/backup/__tests__/restore.test.ts +498 -0
  187. package/src/backup/__tests__/snapshot-lock.test.ts +352 -0
  188. package/src/backup/__tests__/stream-crypt.test.ts +228 -0
  189. package/src/backup/backup-key.ts +137 -0
  190. package/src/backup/backup-worker.ts +459 -0
  191. package/src/backup/list-snapshots.ts +147 -0
  192. package/src/backup/local-writer.ts +133 -0
  193. package/src/backup/offsite-writer.ts +222 -0
  194. package/src/backup/paths.ts +226 -0
  195. package/src/backup/restore.ts +322 -0
  196. package/src/backup/snapshot-lock.ts +431 -0
  197. package/src/backup/stream-crypt.ts +263 -0
  198. package/src/bundler/package-resolver.ts +4 -0
  199. package/src/calls/audio-store.ts +11 -5
  200. package/src/calls/call-controller.ts +226 -71
  201. package/src/calls/call-domain.ts +9 -0
  202. package/src/calls/call-speech-output.ts +190 -0
  203. package/src/calls/call-transport.ts +77 -0
  204. package/src/calls/media-stream-audio-transcode.ts +173 -0
  205. package/src/calls/media-stream-output.ts +660 -0
  206. package/src/calls/media-stream-parser.ts +300 -0
  207. package/src/calls/media-stream-protocol.ts +166 -0
  208. package/src/calls/media-stream-server.ts +592 -0
  209. package/src/calls/media-stream-stt-session.ts +460 -0
  210. package/src/calls/media-turn-detector.ts +230 -0
  211. package/src/calls/relay-server.ts +90 -75
  212. package/src/calls/resolve-call-tts-provider.ts +136 -0
  213. package/src/calls/telephony-stt-routing.ts +145 -0
  214. package/src/calls/tts-call-strategy.ts +161 -0
  215. package/src/calls/tts-text-sanitizer.ts +32 -16
  216. package/src/calls/twilio-routes.ts +281 -17
  217. package/src/calls/voice-quality.ts +78 -35
  218. package/src/calls/voice-session-bridge.ts +8 -1
  219. package/src/channels/types.ts +16 -0
  220. package/src/cli/__tests__/run-assistant-command.ts +11 -1
  221. package/src/cli/commands/__tests__/backup.test.ts +1165 -0
  222. package/src/cli/commands/__tests__/domain-register.test.ts +234 -0
  223. package/src/cli/commands/__tests__/domain-status.test.ts +132 -0
  224. package/src/cli/commands/__tests__/email-attachment.test.ts +422 -0
  225. package/src/cli/commands/__tests__/email-download.test.ts +16 -1
  226. package/src/cli/commands/__tests__/email-list.test.ts +22 -4
  227. package/src/cli/commands/__tests__/email-register.test.ts +4 -4
  228. package/src/cli/commands/__tests__/email-send.test.ts +37 -4
  229. package/src/cli/commands/__tests__/email-status.test.ts +5 -1
  230. package/src/cli/commands/__tests__/email-unregister.test.ts +34 -5
  231. package/src/cli/commands/backup.ts +993 -0
  232. package/src/cli/commands/conversations.ts +77 -0
  233. package/src/cli/commands/credentials.ts +0 -1
  234. package/src/cli/commands/domain.ts +210 -0
  235. package/src/cli/commands/email.ts +255 -3
  236. package/src/cli/commands/oauth/__tests__/connect.test.ts +12 -0
  237. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +1 -0
  238. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +1 -0
  239. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +1 -0
  240. package/src/cli/commands/oauth/mode.ts +12 -3
  241. package/src/cli/commands/oauth/providers.ts +15 -0
  242. package/src/cli/commands/oauth/shared.ts +2 -1
  243. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +4 -9
  244. package/src/cli/commands/platform/__tests__/connect.test.ts +6 -0
  245. package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -1
  246. package/src/cli/commands/platform/__tests__/status.test.ts +6 -0
  247. package/src/cli/program.ts +30 -4
  248. package/src/config/__tests__/backup-schema.test.ts +134 -0
  249. package/src/config/assistant-feature-flags.ts +61 -62
  250. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +37 -1
  251. package/src/config/bundled-skills/browser/SKILL.md +30 -5
  252. package/src/config/bundled-skills/browser/TOOLS.json +123 -0
  253. package/src/config/bundled-skills/browser/tools/browser-attach.ts +12 -0
  254. package/src/config/bundled-skills/browser/tools/browser-detach.ts +12 -0
  255. package/src/config/bundled-skills/browser/tools/browser-status.ts +12 -0
  256. package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +17 -0
  257. package/src/config/bundled-skills/contacts/SKILL.md +2 -2
  258. package/src/config/bundled-skills/gmail/SKILL.md +53 -7
  259. package/src/config/bundled-skills/gmail/TOOLS.json +33 -3
  260. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +116 -9
  261. package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +138 -11
  262. package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +59 -0
  263. package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +82 -0
  264. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +113 -17
  265. package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +2 -2
  266. package/src/config/bundled-skills/media-processing/SKILL.md +3 -9
  267. package/src/config/bundled-skills/media-processing/TOOLS.json +1 -6
  268. package/src/config/bundled-skills/media-processing/__tests__/audio-transcribe.test.ts +125 -0
  269. package/src/config/bundled-skills/media-processing/__tests__/extract-keyframes.test.ts +181 -0
  270. package/src/config/bundled-skills/media-processing/__tests__/preprocess-audio.test.ts +141 -0
  271. package/src/config/bundled-skills/media-processing/services/audio-transcribe.ts +32 -87
  272. package/src/config/bundled-skills/media-processing/services/preprocess.ts +8 -4
  273. package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +0 -10
  274. package/src/config/bundled-skills/messaging/SKILL.md +3 -3
  275. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +2 -2
  276. package/src/config/bundled-skills/outlook/SKILL.md +2 -2
  277. package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +2 -2
  278. package/src/config/bundled-skills/phone-calls/SKILL.md +2 -2
  279. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +27 -18
  280. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +3 -3
  281. package/src/config/bundled-skills/settings/TOOLS.json +3 -3
  282. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +26 -22
  283. package/src/config/bundled-skills/slack/SKILL.md +1 -0
  284. package/src/config/bundled-skills/transcribe/SKILL.md +9 -14
  285. package/src/config/bundled-skills/transcribe/TOOLS.json +2 -7
  286. package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +256 -0
  287. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +38 -188
  288. package/src/config/bundled-tool-registry.ts +8 -0
  289. package/src/config/env-registry.ts +24 -0
  290. package/src/config/env.ts +34 -10
  291. package/src/config/feature-flag-registry.json +46 -14
  292. package/src/config/loader.ts +26 -12
  293. package/src/config/schema.ts +35 -10
  294. package/src/config/schemas/__tests__/stt.test.ts +43 -0
  295. package/src/config/schemas/analysis.ts +51 -0
  296. package/src/config/schemas/backup.ts +72 -0
  297. package/src/config/schemas/calls.ts +1 -26
  298. package/src/config/schemas/elevenlabs.ts +0 -59
  299. package/src/config/schemas/filing.ts +47 -7
  300. package/src/config/schemas/heartbeat.ts +27 -5
  301. package/src/config/schemas/host-browser.ts +47 -1
  302. package/src/config/schemas/inference.ts +1 -1
  303. package/src/config/schemas/memory-lifecycle.ts +14 -2
  304. package/src/config/schemas/services.ts +44 -0
  305. package/src/config/schemas/stt.ts +59 -0
  306. package/src/config/schemas/tts.ts +230 -0
  307. package/src/config/schemas/updates.ts +14 -0
  308. package/src/config/skills.ts +4 -0
  309. package/src/config/types.ts +4 -0
  310. package/src/contacts/contact-store.ts +56 -11
  311. package/src/contacts/contacts-write.ts +38 -1
  312. package/src/context/post-turn-tool-result-truncation.ts +3 -2
  313. package/src/context/tool-result-truncation.ts +2 -1
  314. package/src/context/window-manager.ts +45 -12
  315. package/src/credential-execution/executable-discovery.ts +12 -2
  316. package/src/credential-execution/process-manager.ts +33 -2
  317. package/src/credential-health/credential-health-service.ts +366 -0
  318. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +324 -0
  319. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +497 -0
  320. package/src/daemon/__tests__/conversation-tool-setup.test.ts +17 -8
  321. package/src/daemon/__tests__/lifecycle-startup-ordering.test.ts +127 -0
  322. package/src/daemon/config-watcher.ts +99 -5
  323. package/src/daemon/conversation-agent-loop-handlers.ts +6 -0
  324. package/src/daemon/conversation-agent-loop.ts +101 -24
  325. package/src/daemon/conversation-error.ts +11 -0
  326. package/src/daemon/conversation-history.ts +40 -6
  327. package/src/daemon/conversation-launch.ts +220 -0
  328. package/src/daemon/conversation-lifecycle.ts +59 -9
  329. package/src/daemon/conversation-messaging.ts +37 -3
  330. package/src/daemon/conversation-notifiers.ts +5 -0
  331. package/src/daemon/conversation-process.ts +581 -19
  332. package/src/daemon/conversation-queue-manager.ts +24 -0
  333. package/src/daemon/conversation-runtime-assembly.ts +11 -1
  334. package/src/daemon/conversation-slash.ts +36 -0
  335. package/src/daemon/conversation-surfaces.ts +94 -4
  336. package/src/daemon/conversation-tool-setup.ts +25 -0
  337. package/src/daemon/conversation-usage.ts +7 -4
  338. package/src/daemon/conversation.ts +86 -28
  339. package/src/daemon/handlers/config-slack-channel.ts +269 -94
  340. package/src/daemon/handlers/conversations.ts +4 -1
  341. package/src/daemon/handlers/shared.ts +22 -0
  342. package/src/daemon/handlers/skills.ts +321 -77
  343. package/src/daemon/host-browser-proxy.ts +2 -1
  344. package/src/daemon/lifecycle.ts +122 -25
  345. package/src/daemon/message-protocol.ts +6 -0
  346. package/src/daemon/message-types/conversations.ts +34 -1
  347. package/src/daemon/message-types/home.ts +40 -0
  348. package/src/daemon/message-types/meet.ts +143 -0
  349. package/src/daemon/message-types/messages.ts +14 -0
  350. package/src/daemon/message-types/schedules.ts +34 -2
  351. package/src/daemon/message-types/skills.ts +16 -0
  352. package/src/daemon/message-types/surfaces.ts +2 -0
  353. package/src/daemon/server.ts +347 -2
  354. package/src/daemon/shutdown-handlers.ts +32 -4
  355. package/src/daemon/shutdown-registry.ts +40 -0
  356. package/src/daemon/tool-side-effects.ts +9 -0
  357. package/src/email/html-renderer.ts +76 -0
  358. package/src/heartbeat/heartbeat-service.ts +93 -7
  359. package/src/home/__tests__/assistant-feed-authoring.test.ts +156 -0
  360. package/src/home/__tests__/emit-feed-event.test.ts +169 -0
  361. package/src/home/__tests__/feed-scheduler.test.ts +194 -0
  362. package/src/home/__tests__/feed-types.test.ts +275 -0
  363. package/src/home/__tests__/feed-writer.test.ts +688 -0
  364. package/src/home/__tests__/phase5-exit-criteria.test.ts +212 -0
  365. package/src/home/__tests__/platform-gmail-digest.test.ts +222 -0
  366. package/src/home/__tests__/progress-formula.test.ts +213 -0
  367. package/src/home/__tests__/relationship-state-writer.test.ts +740 -0
  368. package/src/home/__tests__/rollup-producer.test.ts +398 -0
  369. package/src/home/assistant-feed-authoring.ts +124 -0
  370. package/src/home/emit-feed-event.ts +158 -0
  371. package/src/home/feed-scheduler.ts +247 -0
  372. package/src/home/feed-types.ts +181 -0
  373. package/src/home/feed-writer.ts +469 -0
  374. package/src/home/platform-gmail-digest.ts +163 -0
  375. package/src/home/progress-formula.ts +86 -0
  376. package/src/home/relationship-state-writer.ts +824 -0
  377. package/src/home/relationship-state.ts +143 -0
  378. package/src/home/rollup-producer.ts +384 -0
  379. package/src/hooks/runner.ts +7 -0
  380. package/src/inbound/platform-callback-registration.ts +12 -3
  381. package/src/inbound/public-ingress-urls.ts +12 -0
  382. package/src/instrument.ts +1 -1
  383. package/src/ipc/__tests__/cli-ipc.test.ts +200 -0
  384. package/src/ipc/cli-client.ts +151 -0
  385. package/src/ipc/cli-server.ts +234 -0
  386. package/src/ipc/gateway-client.ts +180 -0
  387. package/src/ipc/routes/index.ts +5 -0
  388. package/src/ipc/routes/wake-conversation.ts +19 -0
  389. package/src/memory/__tests__/auto-analysis-enqueue.test.ts +356 -0
  390. package/src/memory/__tests__/auto-analysis-guard.test.ts +57 -0
  391. package/src/memory/__tests__/conversation-analyze-job.test.ts +232 -0
  392. package/src/memory/__tests__/find-analysis-conversation.test.ts +196 -0
  393. package/src/memory/app-store.ts +1 -1
  394. package/src/memory/attachments-store.ts +70 -0
  395. package/src/memory/auto-analysis-enqueue.ts +127 -0
  396. package/src/memory/auto-analysis-guard.ts +27 -0
  397. package/src/memory/cleanup-schedule-state.ts +37 -0
  398. package/src/memory/conversation-analyze-job.ts +73 -0
  399. package/src/memory/conversation-crud.ts +99 -0
  400. package/src/memory/conversation-disk-view.ts +7 -0
  401. package/src/memory/conversation-group-migration.ts +34 -2
  402. package/src/memory/conversation-queries.ts +6 -5
  403. package/src/memory/db-init.ts +6 -0
  404. package/src/memory/db-maintenance.ts +108 -0
  405. package/src/memory/db.ts +1 -0
  406. package/src/memory/graph/conversation-graph-memory.ts +15 -0
  407. package/src/memory/graph/extraction.test.ts +23 -0
  408. package/src/memory/graph/extraction.ts +8 -0
  409. package/src/memory/graph/retriever.ts +27 -18
  410. package/src/memory/graph/scoring.test.ts +186 -0
  411. package/src/memory/graph/scoring.ts +31 -1
  412. package/src/memory/graph/tools.ts +1 -1
  413. package/src/memory/group-crud.ts +6 -1
  414. package/src/memory/indexer.ts +95 -16
  415. package/src/memory/job-handlers/cleanup.ts +11 -8
  416. package/src/memory/job-handlers/conversation-starters.ts +16 -10
  417. package/src/memory/jobs-store.ts +64 -4
  418. package/src/memory/jobs-worker.ts +22 -9
  419. package/src/memory/llm-usage-store.ts +92 -56
  420. package/src/memory/migrations/219-oauth-providers-token-exchange-body-format.ts +15 -0
  421. package/src/memory/migrations/220-normalize-user-file-by-principal.ts +190 -0
  422. package/src/memory/migrations/221-conversations-archived-at.ts +16 -0
  423. package/src/memory/migrations/index.ts +6 -0
  424. package/src/memory/migrations/registry.ts +8 -0
  425. package/src/memory/qdrant-manager.ts +43 -16
  426. package/src/memory/schema/conversations.ts +2 -0
  427. package/src/memory/schema/oauth.ts +3 -0
  428. package/src/memory/usage-buckets.ts +396 -0
  429. package/src/messaging/providers/gmail/client.ts +57 -6
  430. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +282 -0
  431. package/src/messaging/providers/slack/adapter.ts +143 -38
  432. package/src/messaging/providers/slack/client.ts +16 -0
  433. package/src/messaging/providers/slack/types.ts +4 -0
  434. package/src/notifications/decision-engine.ts +3 -3
  435. package/src/notifications/signal.ts +5 -0
  436. package/src/oauth/__tests__/identity-verifier.test.ts +1 -0
  437. package/src/oauth/byo-connection.test.ts +18 -1
  438. package/src/oauth/byo-connection.ts +3 -1
  439. package/src/oauth/connect-orchestrator.ts +2 -0
  440. package/src/oauth/connection-resolver.ts +6 -2
  441. package/src/oauth/connection.ts +2 -0
  442. package/src/oauth/oauth-store.ts +9 -0
  443. package/src/oauth/platform-connection.test.ts +98 -0
  444. package/src/oauth/platform-connection.ts +52 -31
  445. package/src/oauth/seed-providers.ts +7 -0
  446. package/src/permissions/checker.ts +16 -6
  447. package/src/permissions/defaults.ts +49 -1
  448. package/src/permissions/trust-store.ts +3 -3
  449. package/src/permissions/workspace-policy.ts +3 -0
  450. package/src/platform/client.test.ts +10 -0
  451. package/src/platform/sync-identity.ts +129 -0
  452. package/src/prompts/persona-resolver.ts +126 -2
  453. package/src/prompts/system-prompt.ts +59 -18
  454. package/src/prompts/templates/BOOTSTRAP.md +5 -5
  455. package/src/prompts/templates/SOUL.md +3 -1
  456. package/src/prompts/templates/UPDATES.md +12 -0
  457. package/src/prompts/templates/channels/slack.md +20 -0
  458. package/src/prompts/update-bulletin-format.ts +26 -9
  459. package/src/prompts/update-bulletin.ts +34 -23
  460. package/src/prompts/user-reference.ts +20 -17
  461. package/src/providers/__tests__/provider-secret-catalog.test.ts +42 -0
  462. package/src/providers/anthropic/client.ts +157 -61
  463. package/src/providers/fireworks/client.ts +2 -2
  464. package/src/providers/gemini/client.ts +9 -1
  465. package/src/providers/model-catalog.ts +6 -0
  466. package/src/providers/model-intents.ts +4 -4
  467. package/src/providers/ollama/client.ts +2 -2
  468. package/src/providers/openai/chat-completions-provider.ts +474 -0
  469. package/src/providers/openai/client.ts +25 -440
  470. package/src/providers/openai/responses-provider.ts +502 -0
  471. package/src/providers/openrouter/client.ts +101 -4
  472. package/src/providers/provider-secret-catalog.ts +139 -0
  473. package/src/providers/registry.ts +2 -2
  474. package/src/providers/retry.ts +14 -3
  475. package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +251 -0
  476. package/src/providers/speech-to-text/__tests__/resolve.test.ts +828 -0
  477. package/src/providers/speech-to-text/deepgram-realtime.test.ts +980 -0
  478. package/src/providers/speech-to-text/deepgram-realtime.ts +767 -0
  479. package/src/providers/speech-to-text/deepgram.test.ts +332 -0
  480. package/src/providers/speech-to-text/deepgram.ts +115 -0
  481. package/src/providers/speech-to-text/google-gemini-live-stream.test.ts +743 -0
  482. package/src/providers/speech-to-text/google-gemini-live-stream.ts +625 -0
  483. package/src/providers/speech-to-text/google-gemini.test.ts +226 -0
  484. package/src/providers/speech-to-text/google-gemini.ts +101 -0
  485. package/src/providers/speech-to-text/openai-whisper-stream.test.ts +564 -0
  486. package/src/providers/speech-to-text/openai-whisper-stream.ts +381 -0
  487. package/src/providers/speech-to-text/openai-whisper.test.ts +1 -37
  488. package/src/providers/speech-to-text/openai-whisper.ts +63 -33
  489. package/src/providers/speech-to-text/provider-catalog.ts +306 -0
  490. package/src/providers/speech-to-text/resolve.ts +386 -6
  491. package/src/providers/types.ts +9 -0
  492. package/src/runtime/AGENTS.md +43 -1
  493. package/src/runtime/__tests__/agent-wake.test.ts +831 -0
  494. package/src/runtime/__tests__/runtime-mode.test.ts +62 -0
  495. package/src/runtime/__tests__/slack-block-formatting.test.ts +481 -0
  496. package/src/runtime/agent-wake.ts +512 -0
  497. package/src/runtime/auth/__tests__/route-policy.test.ts +40 -0
  498. package/src/runtime/auth/route-policy.ts +30 -5
  499. package/src/runtime/auth/token-service.ts +56 -1
  500. package/src/runtime/btw-sidechain.ts +2 -0
  501. package/src/runtime/capability-tokens.ts +10 -10
  502. package/src/runtime/channel-invite-transport.ts +1 -1
  503. package/src/runtime/channel-invite-transports/email.ts +14 -6
  504. package/src/runtime/channel-readiness-service.ts +12 -22
  505. package/src/runtime/chrome-extension-registry.ts +38 -2
  506. package/src/runtime/http-server.ts +395 -10
  507. package/src/runtime/http-types.ts +6 -2
  508. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +36 -0
  509. package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +360 -0
  510. package/src/runtime/migrations/migration-transport.ts +1 -0
  511. package/src/runtime/migrations/migration-wizard.ts +1 -0
  512. package/src/runtime/migrations/vbundle-import-analyzer.ts +77 -1
  513. package/src/runtime/migrations/vbundle-importer.ts +34 -0
  514. package/src/runtime/pending-interactions.ts +0 -11
  515. package/src/runtime/routes/__tests__/backup-routes.test.ts +967 -0
  516. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +507 -0
  517. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +208 -0
  518. package/src/runtime/routes/__tests__/stt-routes.test.ts +406 -0
  519. package/src/runtime/routes/__tests__/tts-routes.test.ts +474 -0
  520. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +148 -17
  521. package/src/runtime/routes/app-management-routes.ts +12 -18
  522. package/src/runtime/routes/attachment-routes.test.ts +9 -3
  523. package/src/runtime/routes/attachment-routes.ts +216 -17
  524. package/src/runtime/routes/backup-routes.ts +519 -0
  525. package/src/runtime/routes/browser-extension-pair-routes.ts +82 -23
  526. package/src/runtime/routes/btw-routes.ts +8 -6
  527. package/src/runtime/routes/contact-routes.test.ts +298 -0
  528. package/src/runtime/routes/contact-routes.ts +132 -5
  529. package/src/runtime/routes/conversation-analysis-routes.ts +22 -142
  530. package/src/runtime/routes/conversation-management-routes.ts +115 -0
  531. package/src/runtime/routes/conversation-routes.ts +367 -146
  532. package/src/runtime/routes/filing-routes.ts +93 -0
  533. package/src/runtime/routes/home-feed-routes.ts +334 -0
  534. package/src/runtime/routes/home-state-routes.ts +138 -0
  535. package/src/runtime/routes/host-browser-routes.ts +3 -14
  536. package/src/runtime/routes/identity-intro-cache.ts +7 -3
  537. package/src/runtime/routes/identity-routes.ts +3 -17
  538. package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +46 -39
  539. package/src/runtime/routes/inbound-stages/transcribe-audio.ts +15 -15
  540. package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +137 -0
  541. package/src/runtime/routes/integrations/slack/__tests__/share.test.ts +179 -0
  542. package/src/runtime/routes/integrations/slack/channel.ts +11 -3
  543. package/src/runtime/routes/integrations/slack/share.ts +45 -7
  544. package/src/runtime/routes/llm-context-normalization.ts +303 -0
  545. package/src/runtime/routes/memory-item-routes.test.ts +3 -2
  546. package/src/runtime/routes/migration-routes.ts +40 -5
  547. package/src/runtime/routes/settings-routes.ts +22 -5
  548. package/src/runtime/routes/skills-routes.ts +76 -7
  549. package/src/runtime/routes/stt-routes.ts +233 -0
  550. package/src/runtime/routes/surface-action-routes.ts +41 -2
  551. package/src/runtime/routes/tts-routes.ts +108 -24
  552. package/src/runtime/routes/usage-routes.ts +30 -2
  553. package/src/runtime/routes/user-route-dispatcher.ts +50 -5
  554. package/src/runtime/routes/user-routes.ts +13 -1
  555. package/src/runtime/routes/work-items-routes.ts +8 -1
  556. package/src/runtime/runtime-mode.ts +33 -0
  557. package/src/runtime/services/__tests__/analyze-conversation.test.ts +444 -0
  558. package/src/runtime/services/__tests__/analyze-deps-singleton.test.ts +67 -0
  559. package/src/runtime/services/__tests__/auto-analysis-prompt.test.ts +53 -0
  560. package/src/runtime/services/__tests__/manual-analysis-prompt.test.ts +41 -0
  561. package/src/runtime/services/analyze-conversation.ts +344 -0
  562. package/src/runtime/services/analyze-deps-singleton.ts +32 -0
  563. package/src/runtime/services/auto-analysis-prompt.ts +55 -0
  564. package/src/runtime/skill-route-registry.ts +49 -0
  565. package/src/runtime/slack-block-formatting.ts +437 -10
  566. package/src/schedule/scheduler.ts +50 -0
  567. package/src/security/oauth2.ts +26 -4
  568. package/src/security/secure-keys.ts +25 -2
  569. package/src/security/token-manager.ts +8 -0
  570. package/src/sequence/engine.ts +23 -0
  571. package/src/sequence/types.ts +1 -1
  572. package/src/skills/catalog-files.ts +64 -2
  573. package/src/skills/category-inference.ts +122 -0
  574. package/src/skills/clawhub-files.ts +213 -0
  575. package/src/skills/clawhub.ts +84 -23
  576. package/src/skills/skill-file-provider.ts +40 -0
  577. package/src/skills/skillssh-files.ts +395 -0
  578. package/src/skills/skillssh-registry.ts +4 -4
  579. package/src/stt/__tests__/daemon-batch-transcriber.test.ts +392 -0
  580. package/src/stt/__tests__/types.test.ts +89 -0
  581. package/src/stt/daemon-batch-transcriber.ts +195 -0
  582. package/src/stt/stt-stream-session.ts +499 -0
  583. package/src/stt/types.ts +330 -0
  584. package/src/stt/wav-encoder.test.ts +373 -0
  585. package/src/stt/wav-encoder.ts +175 -0
  586. package/src/subagent/manager.ts +38 -14
  587. package/src/tools/browser/__tests__/browser-mode.test.ts +119 -0
  588. package/src/tools/browser/__tests__/browser-status.test.ts +123 -0
  589. package/src/tools/browser/browser-execution.ts +1163 -23
  590. package/src/tools/browser/browser-manager.ts +45 -0
  591. package/src/tools/browser/browser-mode-constants.ts +12 -0
  592. package/src/tools/browser/browser-mode.ts +92 -0
  593. package/src/tools/browser/browser-status-constants.ts +33 -0
  594. package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +393 -0
  595. package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +29 -0
  596. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +1648 -32
  597. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/discovery.test.ts +264 -0
  598. package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +183 -17
  599. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +254 -21
  600. package/src/tools/browser/cdp-client/errors.ts +15 -0
  601. package/src/tools/browser/cdp-client/extension-cdp-client.ts +39 -16
  602. package/src/tools/browser/cdp-client/factory.ts +797 -87
  603. package/src/tools/browser/cdp-client/index.ts +16 -2
  604. package/src/tools/browser/cdp-client/types.ts +68 -0
  605. package/src/tools/credentials/vault.ts +35 -6
  606. package/src/tools/network/web-fetch.ts +5 -2
  607. package/src/tools/network/web-search.ts +5 -2
  608. package/src/tools/shared/shell-output.ts +3 -1
  609. package/src/tools/side-effects.ts +2 -0
  610. package/src/tools/skills/sandbox-runner.ts +3 -2
  611. package/src/tools/terminal/safe-env.ts +10 -2
  612. package/src/tools/terminal/shell.ts +15 -4
  613. package/src/tools/tool-manifest.ts +21 -0
  614. package/src/tools/types.ts +17 -0
  615. package/src/tools/ui-surface/definitions.ts +6 -1
  616. package/src/tts/__tests__/provider-adapters.test.ts +834 -0
  617. package/src/tts/__tests__/provider-catalog-consistency.test.ts +196 -0
  618. package/src/tts/__tests__/provider-catalog.test.ts +183 -0
  619. package/src/tts/__tests__/provider-registry.test.ts +90 -0
  620. package/src/tts/provider-catalog.ts +201 -0
  621. package/src/tts/provider-registry.ts +73 -0
  622. package/src/tts/providers/deepgram-provider.ts +219 -0
  623. package/src/tts/providers/elevenlabs-provider.ts +211 -0
  624. package/src/tts/providers/fish-audio-provider.ts +183 -0
  625. package/src/tts/providers/index.ts +42 -0
  626. package/src/tts/providers/register-builtins.ts +130 -0
  627. package/src/tts/synthesize-text.ts +110 -0
  628. package/src/tts/tts-config-resolver.ts +78 -0
  629. package/src/tts/types.ts +153 -0
  630. package/src/types/onboarding-context.ts +7 -0
  631. package/src/util/abort-reasons.ts +58 -0
  632. package/src/util/device-id.ts +32 -16
  633. package/src/util/errors.ts +9 -1
  634. package/src/util/platform.ts +54 -10
  635. package/src/util/pricing.ts +66 -3
  636. package/src/util/spawn.ts +1 -1
  637. package/src/util/truncate.ts +4 -2
  638. package/src/util/unicode.ts +201 -0
  639. package/src/version.ts +19 -24
  640. package/src/watcher/engine.ts +23 -0
  641. package/src/watcher/watcher-store.ts +31 -0
  642. package/src/workspace/migrations/003-seed-device-id.ts +9 -3
  643. package/src/workspace/migrations/017-seed-persona-dirs.ts +68 -4
  644. package/src/workspace/migrations/029-seed-pkb.ts +1 -1
  645. package/src/workspace/migrations/031-drop-user-md.ts +317 -0
  646. package/src/workspace/migrations/031-llm-log-retention-zero-to-null.ts +73 -0
  647. package/src/workspace/migrations/032-tts-provider-unification.ts +227 -0
  648. package/src/workspace/migrations/033-stt-service-explicit-config.ts +122 -0
  649. package/src/workspace/migrations/034-remove-calls-voice-transcription-provider.ts +215 -0
  650. package/src/workspace/migrations/035-seed-slack-channel-persona.ts +50 -0
  651. package/src/workspace/migrations/036-update-pkb-index-bar.ts +37 -0
  652. package/src/workspace/migrations/037-create-meets-dir.ts +61 -0
  653. package/src/workspace/migrations/registry.ts +16 -0
  654. package/src/workspace/top-level-renderer.ts +13 -1
  655. package/src/workspace/turn-commit.ts +31 -0
  656. package/src/__tests__/email-cli.test.ts +0 -297
  657. package/src/__tests__/email-service-config-fallback.test.ts +0 -102
  658. package/src/cli/commands/browser-relay.ts +0 -466
  659. package/src/email/guardrails.ts +0 -221
  660. package/src/email/provider.ts +0 -117
  661. package/src/email/providers/agentmail.ts +0 -361
  662. package/src/email/providers/index.ts +0 -65
  663. package/src/email/service.ts +0 -384
  664. package/src/email/types.ts +0 -126
  665. package/src/prompts/templates/USER.md +0 -13
  666. package/src/providers/speech-to-text/types.ts +0 -17
  667. package/src/runtime/routes/browser-cdp-routes.ts +0 -229
@@ -5,7 +5,7 @@
5
5
  * `meta/feature-flags/feature-flag-registry.json` and resolves the effective
6
6
  * enabled/disabled state for each declared assistant-scope flag by consulting
7
7
  * (in priority order):
8
- * 1. Override values from the gateway HTTP API (or local file fallback)
8
+ * 1. Override values from the gateway IPC socket (or local file fallback)
9
9
  * 2. Remote values from `feature-flags-remote.json` (platform-pushed,
10
10
  * cached locally; only used in local mode — containerized mode gets
11
11
  * remote values via the gateway)
@@ -17,9 +17,10 @@
17
17
  */
18
18
 
19
19
  import { existsSync, readFileSync } from "node:fs";
20
- import { homedir } from "node:os";
21
20
  import { dirname, join } from "node:path";
22
21
 
22
+ import { ipcGetFeatureFlags } from "../ipc/gateway-client.js";
23
+ import { getProtectedDir } from "../util/platform.js";
23
24
  import type { AssistantConfig } from "./schema.js";
24
25
 
25
26
  // ---------------------------------------------------------------------------
@@ -110,7 +111,7 @@ function parseRegistryToDefaults(parsed: unknown): FeatureFlagDefaultsRegistry {
110
111
  }
111
112
 
112
113
  // ---------------------------------------------------------------------------
113
- // Override loading — reads from gateway HTTP API or local file
114
+ // Override loading — reads from gateway IPC socket or local file
114
115
  // ---------------------------------------------------------------------------
115
116
 
116
117
  /**
@@ -119,6 +120,14 @@ function parseRegistryToDefaults(parsed: unknown): FeatureFlagDefaultsRegistry {
119
120
  */
120
121
  let cachedOverrides: Record<string, boolean> | null = null;
121
122
 
123
+ /**
124
+ * True when `cachedOverrides` was populated by the gateway IPC fetch (or
125
+ * preseeded by a test). False/unset when the cache was populated by the sync
126
+ * file fallback in `loadOverrides()`, which must not prevent a subsequent
127
+ * authoritative gateway fetch from running.
128
+ */
129
+ let cachedOverridesFromGateway = false;
130
+
122
131
  /**
123
132
  * File format for the local feature-flags.json override file, matching the
124
133
  * gateway's feature-flag-store.ts schema.
@@ -132,14 +141,15 @@ interface FeatureFlagFileData {
132
141
  * Resolve the path to the feature flag overrides file.
133
142
  *
134
143
  * Docker: `GATEWAY_SECURITY_DIR/feature-flags.json`
135
- * Local: `~/.vellum/` + gateway security subdir + `feature-flags.json`
144
+ * Local: `<protectedDir>/feature-flags.json` — resolved via `getProtectedDir()`
145
+ * so it honors `BASE_DATA_DIR` for per-instance setups.
136
146
  */
137
147
  function getFeatureFlagOverridesPath(): string {
138
148
  const securityDir = process.env.GATEWAY_SECURITY_DIR;
139
149
  if (securityDir) {
140
150
  return join(securityDir, "feature-flags.json");
141
151
  }
142
- return join(homedir(), ".vellum", "protected", "feature-flags.json");
152
+ return join(getProtectedDir(), "feature-flags.json");
143
153
  }
144
154
 
145
155
  /**
@@ -172,60 +182,16 @@ function loadOverridesFromFile(): Record<string, boolean> {
172
182
  }
173
183
 
174
184
  /**
175
- * Fetch override values from the gateway via async HTTP.
185
+ * Fetch override values from the gateway via IPC (Unix domain socket).
176
186
  *
177
187
  * Returns the gateway's merged feature flag map (persisted > remote >
178
- * registry), or an empty record on any failure (network, auth, parse).
188
+ * registry), or an empty record on any failure (socket not found,
189
+ * timeout, parse error). No auth needed — the IPC socket is
190
+ * access-controlled by file-system permissions on the shared volume.
179
191
  */
180
192
  async function fetchOverridesFromGateway(): Promise<Record<string, boolean>> {
181
193
  try {
182
- // Lazy-import to avoid circular dependency and keep this module
183
- // importable from bootstrap code when not in containerized mode.
184
- const { getGatewayInternalBaseUrl } =
185
- // eslint-disable-next-line @typescript-eslint/no-require-imports
186
- require("./env.js") as typeof import("./env.js");
187
- const {
188
- mintEdgeRelayToken,
189
- isSigningKeyInitialized,
190
- initAuthSigningKey,
191
- resolveSigningKey,
192
- } =
193
- // eslint-disable-next-line @typescript-eslint/no-require-imports
194
- require("../runtime/auth/token-service.js") as typeof import("../runtime/auth/token-service.js");
195
-
196
- // CLI subprocesses don't run daemon startup, so the signing key
197
- // may not be initialized yet. Initialize it now so mintEdgeRelayToken
198
- // can produce a valid JWT for the gateway request.
199
- if (!isSigningKeyInitialized()) {
200
- initAuthSigningKey(resolveSigningKey());
201
- }
202
-
203
- const url = `${getGatewayInternalBaseUrl()}/v1/feature-flags`;
204
- const token = mintEdgeRelayToken();
205
-
206
- const response = await fetch(url, {
207
- method: "GET",
208
- headers: {
209
- Authorization: `Bearer ${token}`,
210
- Accept: "application/json",
211
- },
212
- signal: AbortSignal.timeout(10_000),
213
- });
214
-
215
- if (!response.ok) return {};
216
-
217
- const parsed = (await response.json()) as {
218
- flags?: Array<{ key: string; enabled: boolean }>;
219
- };
220
- if (!Array.isArray(parsed.flags)) return {};
221
-
222
- const result: Record<string, boolean> = {};
223
- for (const entry of parsed.flags) {
224
- if (typeof entry.key === "string" && typeof entry.enabled === "boolean") {
225
- result[entry.key] = entry.enabled;
226
- }
227
- }
228
- return result;
194
+ return await ipcGetFeatureFlags();
229
195
  } catch {
230
196
  return {};
231
197
  }
@@ -242,17 +208,25 @@ async function fetchOverridesFromGateway(): Promise<Record<string, boolean>> {
242
208
  * On failure, the cache is left unset so subsequent sync calls fall
243
209
  * through to the file-based fallback rather than caching an empty map
244
210
  * that masks all overrides for the process lifetime.
211
+ *
212
+ * No-ops when the cache is already populated — callers that want to
213
+ * refresh must call `clearFeatureFlagOverridesCache()` first. This lets
214
+ * tests preseed flag state via `_setOverridesForTesting()` without the
215
+ * gateway IPC call clobbering their setup.
245
216
  */
246
217
  export async function initFeatureFlagOverrides(): Promise<void> {
218
+ if (cachedOverridesFromGateway) return;
219
+
247
220
  const gatewayOverrides = await fetchOverridesFromGateway();
248
221
  if (Object.keys(gatewayOverrides).length > 0) {
249
222
  cachedOverrides = gatewayOverrides;
223
+ cachedOverridesFromGateway = true;
250
224
  return;
251
225
  }
252
226
 
253
- // Gateway returned empty or failed. Leave the cache unset so
254
- // loadOverrides() falls through to file on the next sync read,
255
- // regardless of containerized vs local mode.
227
+ // Gateway returned empty or failed. If the cache was populated from the
228
+ // file fallback, leave it in place for the next sync read. Otherwise leave
229
+ // unset so `loadOverrides()` falls through to file on first sync read.
256
230
  }
257
231
 
258
232
  /**
@@ -265,9 +239,6 @@ export async function initFeatureFlagOverrides(): Promise<void> {
265
239
  function loadOverrides(): Record<string, boolean> {
266
240
  if (cachedOverrides != null) return cachedOverrides;
267
241
 
268
- // Cache not yet populated (initFeatureFlagOverrides wasn't called or
269
- // hasn't finished). Fall back to the local file so the resolver still
270
- // works, just without gateway data.
271
242
  cachedOverrides = loadOverridesFromFile();
272
243
  return cachedOverrides;
273
244
  }
@@ -333,6 +304,7 @@ function loadRemoteValues(): Record<string, boolean> {
333
304
  */
334
305
  export function clearFeatureFlagOverridesCache(): void {
335
306
  cachedOverrides = null;
307
+ cachedOverridesFromGateway = false;
336
308
  cachedRemoteValues = null;
337
309
  }
338
310
 
@@ -343,12 +315,19 @@ export function clearFeatureFlagOverridesCache(): void {
343
315
  * flag state without writing to disk. Production code should never call this;
344
316
  * use `clearFeatureFlagOverridesCache()` instead and let the resolver
345
317
  * re-read from the appropriate source.
318
+ *
319
+ * Forces `cachedRemoteValues` to an empty record (not `null`) so the resolver
320
+ * does not fall through to reading `feature-flags-remote.json` from disk. This
321
+ * matters because a developer's local remote-cache file can leak platform-set
322
+ * values into the test environment (e.g. `email-channel: true`), defeating
323
+ * test isolation.
346
324
  */
347
325
  export function _setOverridesForTesting(
348
326
  overrides: Record<string, boolean>,
349
327
  ): void {
350
328
  cachedOverrides = { ...overrides };
351
- cachedRemoteValues = null;
329
+ cachedOverridesFromGateway = true;
330
+ cachedRemoteValues = {};
352
331
  }
353
332
 
354
333
  // ---------------------------------------------------------------------------
@@ -359,7 +338,7 @@ export function _setOverridesForTesting(
359
338
  * Resolve whether an assistant feature flag is enabled.
360
339
  *
361
340
  * Resolution order:
362
- * 1. Override from gateway HTTP API (or local file fallback)
341
+ * 1. Override from gateway IPC socket (or local file fallback)
363
342
  * 2. Remote value from `feature-flags-remote.json` (platform-pushed,
364
343
  * cached locally)
365
344
  * 3. defaults registry `defaultEnabled` (for declared assistant-scope keys)
@@ -395,3 +374,23 @@ export function isAssistantFeatureFlagEnabled(
395
374
  export function getAssistantFeatureFlagDefaults(): FeatureFlagDefaultsRegistry {
396
375
  return loadDefaultsRegistry();
397
376
  }
377
+
378
+ // ---------------------------------------------------------------------------
379
+ // Named flag helpers
380
+ // ---------------------------------------------------------------------------
381
+
382
+ /**
383
+ * Canonical key for the `home-feed` flag — gates the activity feed section on
384
+ * the macOS Home page (nudges, digests, actions, threads). Requires the
385
+ * `home-tab` flag to also be enabled. Declared in
386
+ * `meta/feature-flags/feature-flag-registry.json` with scope `macos`.
387
+ */
388
+ export const HOME_FEED_FLAG = "home-feed";
389
+
390
+ /**
391
+ * Resolve whether the `home-feed` flag is enabled for the current assistant
392
+ * config. Wraps `isAssistantFeatureFlagEnabled` with the canonical key.
393
+ */
394
+ export function isHomeFeedEnabled(config: AssistantConfig): boolean {
395
+ return isAssistantFeatureFlagEnabled(HOME_FEED_FLAG, config);
396
+ }
@@ -6,7 +6,7 @@ When the app needs server-side persistence, custom API logic, or workspace file
6
6
 
7
7
  ## Handler file convention
8
8
 
9
- Each handler file exports named functions for the HTTP methods it supports (`GET`, `POST`, `PUT`, `PATCH`, `DELETE`). Handlers use the standard Web API `Request`/`Response` signature.
9
+ Each handler file exports named functions for the HTTP methods it supports (`GET`, `POST`, `PUT`, `PATCH`, `DELETE`). Handlers receive two arguments: the standard Web API `Request` and an optional `context` object with runtime singletons.
10
10
 
11
11
  ```
12
12
  {workspaceDir}/routes/
@@ -76,6 +76,42 @@ const createRes = await window.vellum.fetch("/v1/x/items", {
76
76
  if (!createRes.ok) throw new Error(`HTTP ${createRes.status}`);
77
77
  ```
78
78
 
79
+ ## Runtime context
80
+
81
+ Every handler receives a frozen `context` object as its second argument. This provides access to daemon singletons that are otherwise unreachable from dynamically imported route modules.
82
+
83
+ ```typescript
84
+ export async function POST(request: Request, context): Promise<Response> {
85
+ // context.assistantEventHub — publish events to connected SSE clients
86
+ // context.assistantId — the daemon's logical assistant ID ("self")
87
+ }
88
+ ```
89
+
90
+ ### Publishing events to the client
91
+
92
+ Use `context.assistantEventHub` to push real-time events to connected desktop/mobile clients. This is how route handlers can trigger client-side navigation, update UI, or deliver notifications.
93
+
94
+ ```typescript
95
+ // routes/open-conversation.ts
96
+ export async function POST(request: Request, context): Promise<Response> {
97
+ const { conversationId } = await request.json();
98
+
99
+ await context.assistantEventHub.publish({
100
+ id: crypto.randomUUID(),
101
+ assistantId: context.assistantId,
102
+ conversationId,
103
+ emittedAt: new Date().toISOString(),
104
+ message: { type: "open_conversation", conversationId },
105
+ });
106
+
107
+ return Response.json({ ok: true });
108
+ }
109
+ ```
110
+
111
+ The context object is **immutable** — attempting to reassign its properties will throw in strict mode (ESM). This prevents user route handlers from accidentally corrupting shared state.
112
+
113
+ Legacy handlers that only accept `(request)` continue to work — the context is passed positionally but ignored if the handler doesn't declare the parameter.
114
+
79
115
  ## Key rules
80
116
 
81
117
  - Always create the route handler files via `file_write` before calling `app_refresh`
@@ -13,10 +13,12 @@ metadata:
13
13
 
14
14
  Use this skill to browse the web. After loading this skill, the following browser tools become available:
15
15
 
16
+ - `browser_attach` - Attach the Chrome debugger to the active tab
16
17
  - `browser_navigate` - Navigate to a URL
17
18
  - `browser_snapshot` - List interactive elements on the current page
18
19
  - `browser_screenshot` - Take a visual screenshot
19
20
  - `browser_close` - Close the browser page
21
+ - `browser_detach` - Detach the Chrome debugger from the active tab
20
22
  - `browser_click` - Click an element
21
23
  - `browser_type` - Type text into an input
22
24
  - `browser_press_key` - Press a keyboard key
@@ -27,18 +29,41 @@ Use this skill to browse the web. After loading this skill, the following browse
27
29
  - `browser_extract` - Extract page text content
28
30
  - `browser_wait_for_download` - Wait for a file download to complete
29
31
  - `browser_fill_credential` - Fill a stored credential into a form field
32
+ - `browser_status` - Diagnose browser backend readiness and setup steps
30
33
 
31
34
  ## Capabilities
32
35
 
33
36
  This browser runs **full Chromium with JavaScript enabled**. It can handle SPAs, React/Vue/Angular apps, dynamic content, date pickers, booking systems, reservation flows, and any JavaScript-heavy interactive site. Never tell the user you "can't handle interactive JavaScript" - you can.
34
37
 
38
+ ## Browser Mode
39
+
40
+ Every browser tool accepts an optional `browser_mode` parameter that controls which backend executes the command:
41
+
42
+ | Value | Backend | Description |
43
+ |---|---|---|
44
+ | `auto` | Automatic | Default. The assistant picks the best available backend based on context (extension > cdp-inspect > local). |
45
+ | `extension` | Chrome extension | Routes through the user's Chrome browser via the extension debugger. |
46
+ | `cdp-inspect` | CDP inspect | Connects to an already-running Chrome instance via the DevTools protocol. Alias: `cdp-debugger`. |
47
+ | `local` | Playwright | Drives a dedicated Playwright-managed Chromium instance. Alias: `playwright`. |
48
+
49
+ **When to use `auto`**: Prefer `auto` (or omit `browser_mode` entirely) unless you have a specific reason to pin. The automatic backend selection handles extension availability, fallback, and session reuse.
50
+
51
+ **When to pin a mode**: Pin explicitly when:
52
+ - The user requests interaction with their own browser (use `extension` or `cdp-inspect`).
53
+ - A tool only works on a specific backend (e.g. `browser_wait_for_download` requires `local`).
54
+ - You want to avoid fallback behavior for diagnostic clarity.
55
+
56
+ **Unsupported mode errors**: Some tools restrict which modes they support. For example, `browser_wait_for_download` only supports `auto` and `local` because file downloads require the Playwright backend. Passing an unsupported mode returns a clear error with the accepted alternatives.
57
+
35
58
  ## Typical Workflow
36
59
 
37
- 1. `browser_navigate` to load a page
38
- 2. `browser_snapshot` to discover interactive elements
39
- 3. Use `browser_click`, `browser_type`, `browser_press_key`, `browser_scroll`, `browser_select_option`, or `browser_hover` to interact
40
- 4. `browser_extract` or `browser_screenshot` to capture results
41
- 5. `browser_close` when done
60
+ 1. (Optional) `browser_status` to diagnose backend availability and remediation when setup is unclear
61
+ 2. `browser_attach` to establish the debugger session (extension path; optional on other backends)
62
+ 3. `browser_navigate` to load a page
63
+ 4. `browser_snapshot` to discover interactive elements
64
+ 5. Use `browser_click`, `browser_type`, `browser_press_key`, `browser_scroll`, `browser_select_option`, or `browser_hover` to interact
65
+ 6. `browser_extract` or `browser_screenshot` to capture results
66
+ 7. `browser_detach` to end the debugger session, or `browser_close` to close the page entirely
42
67
 
43
68
  ## Interaction Strategies
44
69
 
@@ -17,6 +17,10 @@
17
17
  "type": "boolean",
18
18
  "description": "If true, allows navigation to localhost/private-network hosts. Disabled by default for SSRF safety."
19
19
  },
20
+ "browser_mode": {
21
+ "type": "string",
22
+ "description": "Override backend selection. Values: auto (default), extension, cdp-inspect (alias: cdp-debugger), local (alias: playwright). Omit or use auto to let the assistant choose."
23
+ },
20
24
  "activity": {
21
25
  "type": "string",
22
26
  "description": "Brief non-technical explanation of why this tool is being called"
@@ -35,6 +39,10 @@
35
39
  "input_schema": {
36
40
  "type": "object",
37
41
  "properties": {
42
+ "browser_mode": {
43
+ "type": "string",
44
+ "description": "Override backend selection. Values: auto (default), extension, cdp-inspect (alias: cdp-debugger), local (alias: playwright). Omit or use auto to let the assistant choose."
45
+ },
38
46
  "activity": {
39
47
  "type": "string",
40
48
  "description": "Brief non-technical explanation of why this tool is being called"
@@ -56,6 +64,10 @@
56
64
  "type": "boolean",
57
65
  "description": "Capture the full scrollable page instead of just the viewport."
58
66
  },
67
+ "browser_mode": {
68
+ "type": "string",
69
+ "description": "Override backend selection. Values: auto (default), extension, cdp-inspect (alias: cdp-debugger), local (alias: playwright). Omit or use auto to let the assistant choose."
70
+ },
59
71
  "activity": {
60
72
  "type": "string",
61
73
  "description": "Brief non-technical explanation of why this tool is being called"
@@ -77,6 +89,10 @@
77
89
  "type": "boolean",
78
90
  "description": "If true, close all browser pages and the browser context. Default: false (close only the current conversation page)."
79
91
  },
92
+ "browser_mode": {
93
+ "type": "string",
94
+ "description": "Override backend selection. Values: auto (default), extension, cdp-inspect (alias: cdp-debugger), local (alias: playwright). Omit or use auto to let the assistant choose."
95
+ },
80
96
  "activity": {
81
97
  "type": "string",
82
98
  "description": "Brief non-technical explanation of why this tool is being called"
@@ -86,6 +102,48 @@
86
102
  "executor": "tools/browser-close.ts",
87
103
  "execution_target": "host"
88
104
  },
105
+ {
106
+ "name": "browser_attach",
107
+ "description": "Explicitly attach the Chrome debugger to the active browser tab. Use at the start of a browser session to establish the debugging connection before navigating or interacting. On the extension path this attaches the debugger; on other backends this is a no-op that returns success.",
108
+ "category": "browser",
109
+ "risk": "low",
110
+ "input_schema": {
111
+ "type": "object",
112
+ "properties": {
113
+ "browser_mode": {
114
+ "type": "string",
115
+ "description": "Override backend selection. Values: auto (default), extension, cdp-inspect (alias: cdp-debugger), local (alias: playwright). Omit or use auto to let the assistant choose."
116
+ },
117
+ "activity": {
118
+ "type": "string",
119
+ "description": "Brief non-technical explanation of why this tool is being called"
120
+ }
121
+ }
122
+ },
123
+ "executor": "tools/browser-attach.ts",
124
+ "execution_target": "host"
125
+ },
126
+ {
127
+ "name": "browser_detach",
128
+ "description": "Explicitly detach the Chrome debugger from the active browser tab. Use when done with browser interaction to cleanly end the debugging session. On the extension path this detaches the debugger and clears the Chrome debugging banner; on other backends this clears stale snapshot state.",
129
+ "category": "browser",
130
+ "risk": "low",
131
+ "input_schema": {
132
+ "type": "object",
133
+ "properties": {
134
+ "browser_mode": {
135
+ "type": "string",
136
+ "description": "Override backend selection. Values: auto (default), extension, cdp-inspect (alias: cdp-debugger), local (alias: playwright). Omit or use auto to let the assistant choose."
137
+ },
138
+ "activity": {
139
+ "type": "string",
140
+ "description": "Brief non-technical explanation of why this tool is being called"
141
+ }
142
+ }
143
+ },
144
+ "executor": "tools/browser-detach.ts",
145
+ "execution_target": "host"
146
+ },
89
147
  {
90
148
  "name": "browser_click",
91
149
  "description": "Click an element on the page. Always use element_id from browser_snapshot \u2014 do not fabricate CSS selectors. For native <select> elements, use browser_select_option instead. For ARIA/custom dropdowns (mat-select, role=listbox, or any dropdown whose options appear as role=\"option\" in browser_snapshot), click to open, take a new browser_snapshot, then click the desired option by element_id. For autocomplete inputs where options don't appear in the snapshot, use browser_press_key with ArrowDown/ArrowUp + Enter.",
@@ -102,6 +160,10 @@
102
160
  "type": "string",
103
161
  "description": "A CSS selector to target. Used as fallback when element_id is not available."
104
162
  },
163
+ "browser_mode": {
164
+ "type": "string",
165
+ "description": "Override backend selection. Values: auto (default), extension, cdp-inspect (alias: cdp-debugger), local (alias: playwright). Omit or use auto to let the assistant choose."
166
+ },
105
167
  "activity": {
106
168
  "type": "string",
107
169
  "description": "Brief non-technical explanation of why this tool is being called"
@@ -139,6 +201,10 @@
139
201
  "type": "boolean",
140
202
  "description": "If true, press Enter after typing the text."
141
203
  },
204
+ "browser_mode": {
205
+ "type": "string",
206
+ "description": "Override backend selection. Values: auto (default), extension, cdp-inspect (alias: cdp-debugger), local (alias: playwright). Omit or use auto to let the assistant choose."
207
+ },
142
208
  "activity": {
143
209
  "type": "string",
144
210
  "description": "Brief non-technical explanation of why this tool is being called"
@@ -169,6 +235,10 @@
169
235
  "type": "string",
170
236
  "description": "Optional CSS selector to target."
171
237
  },
238
+ "browser_mode": {
239
+ "type": "string",
240
+ "description": "Override backend selection. Values: auto (default), extension, cdp-inspect (alias: cdp-debugger), local (alias: playwright). Omit or use auto to let the assistant choose."
241
+ },
172
242
  "activity": {
173
243
  "type": "string",
174
244
  "description": "Brief non-technical explanation of why this tool is being called"
@@ -204,6 +274,10 @@
204
274
  "type": "string",
205
275
  "description": "Optional CSS selector of element to scroll within."
206
276
  },
277
+ "browser_mode": {
278
+ "type": "string",
279
+ "description": "Override backend selection. Values: auto (default), extension, cdp-inspect (alias: cdp-debugger), local (alias: playwright). Omit or use auto to let the assistant choose."
280
+ },
207
281
  "activity": {
208
282
  "type": "string",
209
283
  "description": "Brief non-technical explanation of why this tool is being called"
@@ -242,6 +316,10 @@
242
316
  "type": "number",
243
317
  "description": "The zero-based index of the <option> to select."
244
318
  },
319
+ "browser_mode": {
320
+ "type": "string",
321
+ "description": "Override backend selection. Values: auto (default), extension, cdp-inspect (alias: cdp-debugger), local (alias: playwright). Omit or use auto to let the assistant choose."
322
+ },
245
323
  "activity": {
246
324
  "type": "string",
247
325
  "description": "Brief non-technical explanation of why this tool is being called"
@@ -267,6 +345,10 @@
267
345
  "type": "string",
268
346
  "description": "A CSS selector to target. Used as fallback when element_id is not available."
269
347
  },
348
+ "browser_mode": {
349
+ "type": "string",
350
+ "description": "Override backend selection. Values: auto (default), extension, cdp-inspect (alias: cdp-debugger), local (alias: playwright). Omit or use auto to let the assistant choose."
351
+ },
270
352
  "activity": {
271
353
  "type": "string",
272
354
  "description": "Brief non-technical explanation of why this tool is being called"
@@ -300,6 +382,10 @@
300
382
  "type": "number",
301
383
  "description": "Maximum wait time in milliseconds (default and max: 30000)."
302
384
  },
385
+ "browser_mode": {
386
+ "type": "string",
387
+ "description": "Override backend selection. Values: auto (default), extension, cdp-inspect (alias: cdp-debugger), local (alias: playwright). Omit or use auto to let the assistant choose."
388
+ },
303
389
  "activity": {
304
390
  "type": "string",
305
391
  "description": "Brief non-technical explanation of why this tool is being called"
@@ -321,6 +407,10 @@
321
407
  "type": "boolean",
322
408
  "description": "If true, include a list of links found on the page (up to 200)."
323
409
  },
410
+ "browser_mode": {
411
+ "type": "string",
412
+ "description": "Override backend selection. Values: auto (default), extension, cdp-inspect (alias: cdp-debugger), local (alias: playwright). Omit or use auto to let the assistant choose."
413
+ },
324
414
  "activity": {
325
415
  "type": "string",
326
416
  "description": "Brief non-technical explanation of why this tool is being called"
@@ -342,6 +432,10 @@
342
432
  "type": "number",
343
433
  "description": "Maximum wait time in milliseconds (default: 30000, max: 120000)."
344
434
  },
435
+ "browser_mode": {
436
+ "type": "string",
437
+ "description": "Override backend selection. Only auto (default) and local (alias: playwright) are supported for this tool — file downloads require the local Playwright backend. Other modes (extension, cdp-inspect) are not supported and will be rejected."
438
+ },
345
439
  "activity": {
346
440
  "type": "string",
347
441
  "description": "Brief non-technical explanation of why this tool is being called"
@@ -379,6 +473,10 @@
379
473
  "type": "boolean",
380
474
  "description": "Press Enter after filling"
381
475
  },
476
+ "browser_mode": {
477
+ "type": "string",
478
+ "description": "Override backend selection. Values: auto (default), extension, cdp-inspect (alias: cdp-debugger), local (alias: playwright). Omit or use auto to let the assistant choose."
479
+ },
382
480
  "activity": {
383
481
  "type": "string",
384
482
  "description": "Brief non-technical explanation of why this tool is being called"
@@ -388,6 +486,31 @@
388
486
  },
389
487
  "executor": "tools/browser-fill-credential.ts",
390
488
  "execution_target": "host"
489
+ },
490
+ {
491
+ "name": "browser_status",
492
+ "description": "Check browser backend readiness and remediation guidance. Reports per-mode availability, verification method, setup steps, and trade-offs for extension, cdp-inspect, and local Playwright modes.",
493
+ "category": "browser",
494
+ "risk": "low",
495
+ "input_schema": {
496
+ "type": "object",
497
+ "properties": {
498
+ "browser_mode": {
499
+ "type": "string",
500
+ "description": "Optional scope override for this status check. Use auto (default) to check all modes, or set extension/cdp-inspect/local to check only one mode. Aliases: cdp-debugger -> cdp-inspect, playwright -> local."
501
+ },
502
+ "check_local_launch": {
503
+ "type": "boolean",
504
+ "description": "If true, run an active local Playwright launch probe. Default false (preflight-only) to avoid creating a new local browser page during diagnostics."
505
+ },
506
+ "activity": {
507
+ "type": "string",
508
+ "description": "Brief non-technical explanation of why this tool is being called"
509
+ }
510
+ }
511
+ },
512
+ "executor": "tools/browser-status.ts",
513
+ "execution_target": "host"
391
514
  }
392
515
  ]
393
516
  }
@@ -0,0 +1,12 @@
1
+ import { executeBrowserAttach } from "../../../../tools/browser/browser-execution.js";
2
+ import type {
3
+ ToolContext,
4
+ ToolExecutionResult,
5
+ } from "../../../../tools/types.js";
6
+
7
+ export async function run(
8
+ input: Record<string, unknown>,
9
+ context: ToolContext,
10
+ ): Promise<ToolExecutionResult> {
11
+ return executeBrowserAttach(input, context);
12
+ }
@@ -0,0 +1,12 @@
1
+ import { executeBrowserDetach } from "../../../../tools/browser/browser-execution.js";
2
+ import type {
3
+ ToolContext,
4
+ ToolExecutionResult,
5
+ } from "../../../../tools/types.js";
6
+
7
+ export async function run(
8
+ input: Record<string, unknown>,
9
+ context: ToolContext,
10
+ ): Promise<ToolExecutionResult> {
11
+ return executeBrowserDetach(input, context);
12
+ }
@@ -0,0 +1,12 @@
1
+ import { executeBrowserStatus } from "../../../../tools/browser/browser-execution.js";
2
+ import type {
3
+ ToolContext,
4
+ ToolExecutionResult,
5
+ } from "../../../../tools/types.js";
6
+
7
+ export async function run(
8
+ input: Record<string, unknown>,
9
+ context: ToolContext,
10
+ ): Promise<ToolExecutionResult> {
11
+ return executeBrowserStatus(input, context);
12
+ }
@@ -1,4 +1,5 @@
1
1
  import { browserManager } from "../../../../tools/browser/browser-manager.js";
2
+ import { normalizeBrowserMode } from "../../../../tools/browser/browser-mode.js";
2
3
  import type {
3
4
  ToolContext,
4
5
  ToolExecutionResult,
@@ -8,6 +9,22 @@ export async function run(
8
9
  input: Record<string, unknown>,
9
10
  context: ToolContext,
10
11
  ): Promise<ToolExecutionResult> {
12
+ // Validate browser_mode: only auto/local are supported for downloads.
13
+ const modeResult = normalizeBrowserMode(input.browser_mode);
14
+ if ("error" in modeResult) {
15
+ return { content: `Error: ${modeResult.error}`, isError: true };
16
+ }
17
+ const { mode } = modeResult;
18
+ if (mode !== "auto" && mode !== "local") {
19
+ return {
20
+ content:
21
+ `Error: browser_wait_for_download does not support browser_mode "${mode}". ` +
22
+ `File downloads require the local Playwright backend. ` +
23
+ `Use browser_mode "auto" or "local" instead.`,
24
+ isError: true,
25
+ };
26
+ }
27
+
11
28
  const timeout =
12
29
  typeof input.timeout === "number"
13
30
  ? Math.min(Math.max(input.timeout, 1000), 120_000)
@@ -308,7 +308,7 @@ The response contains `{ ok: true, invite: { id, token, inviteCode, guardianInst
308
308
 
309
309
  - `inviteCode` is the 6-digit code the invitee must send to redeem the invite. It is only returned at creation time.
310
310
  - `guardianInstruction` is a generated instruction telling the guardian how to share the invite.
311
- - `channelHandle` is the assistant's email address (e.g. `hello@domain.agentmail.to`).
311
+ - `channelHandle` is the assistant's email address (e.g. `hello@vellum.me`).
312
312
 
313
313
  **Presenting to the guardian**: Give the guardian the invite code and the assistant's email address:
314
314
 
@@ -320,7 +320,7 @@ The response contains `{ ok: true, invite: { id, token, inviteCode, guardianInst
320
320
  >
321
321
  > This code can be used <maxUses> time(s)<and expires in X hours/days if applicable>.
322
322
 
323
- If the assistant's email address is not available (AgentMail not configured), tell the guardian they need to set up email integration first.
323
+ If the assistant's email address is not available, tell the guardian they need to register one with `assistant email register <username>`.
324
324
 
325
325
  ### Create a WhatsApp invite
326
326