@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
@@ -10,6 +10,7 @@ import { shouldAutoStartDaemon } from "../../daemon/connection-policy.js";
10
10
  import { healthCheckHost, isHttpHealthy } from "../../daemon/daemon-control.js";
11
11
  import { ensureDaemonRunning } from "../../daemon/lifecycle.js";
12
12
  import { formatJson, formatMarkdown } from "../../export/formatter.js";
13
+ import { cliIpcCall } from "../../ipc/cli-client.js";
13
14
  import {
14
15
  clearAll as clearAllConversations,
15
16
  countConversationsByScheduleJobId,
@@ -388,4 +389,80 @@ Examples:
388
389
  `cancelled ${result.cancelledJobCount} jobs.`,
389
390
  );
390
391
  });
392
+
393
+ conversations
394
+ .command("wake <conversationId>")
395
+ .description(
396
+ "Wake the agent on an existing conversation with an internal hint",
397
+ )
398
+ .requiredOption(
399
+ "--hint <text>",
400
+ "Hint message visible to the LLM (not persisted to transcript)",
401
+ )
402
+ .option(
403
+ "--source <label>",
404
+ "Source label for logging (e.g. github-notification)",
405
+ "cli",
406
+ )
407
+ .option("--json", "Output result as JSON")
408
+ .addHelpText(
409
+ "after",
410
+ `
411
+ Arguments:
412
+ conversationId Conversation ID to wake.
413
+
414
+ Wake the assistant's agent loop on an existing conversation without a user
415
+ message. The hint is injected as a non-persisted internal message visible
416
+ only to the LLM — it never appears in the transcript or SSE feed. If the
417
+ agent produces output (text or tool calls), it is persisted and emitted to
418
+ connected clients. Otherwise the wake is a silent no-op.
419
+
420
+ Requires the assistant to be running. Communicates via IPC socket.
421
+
422
+ Examples:
423
+ $ assistant conversations wake abc123 --hint "PR #25933 received a review requesting changes"
424
+ $ assistant conversations wake abc123 --hint "CI failed on commit abc" --source github-ci
425
+ $ assistant conversations wake abc123 --hint "New Slack DM from Vargas" --source slack --json`,
426
+ )
427
+ .action(
428
+ async (
429
+ conversationId: string,
430
+ opts: { hint: string; source: string; json?: boolean },
431
+ ) => {
432
+ const result = await cliIpcCall<{
433
+ invoked: boolean;
434
+ producedToolCalls: boolean;
435
+ }>("wake_conversation", {
436
+ conversationId,
437
+ hint: opts.hint,
438
+ source: opts.source,
439
+ });
440
+
441
+ if (!result.ok) {
442
+ if (opts.json) {
443
+ log.info(JSON.stringify({ ok: false, error: result.error }));
444
+ } else {
445
+ log.error(`Error: ${result.error}`);
446
+ }
447
+ process.exitCode = 1;
448
+ return;
449
+ }
450
+
451
+ const wake = result.result!;
452
+ if (opts.json) {
453
+ log.info(JSON.stringify({ ok: true, ...wake }));
454
+ } else if (wake.invoked) {
455
+ log.info(
456
+ wake.producedToolCalls
457
+ ? `Wake produced output on conversation ${conversationId}`
458
+ : `Wake invoked on ${conversationId} (no output produced)`,
459
+ );
460
+ } else {
461
+ log.error(
462
+ `Could not wake conversation ${conversationId} — conversation not found`,
463
+ );
464
+ process.exitCode = 1;
465
+ }
466
+ },
467
+ );
391
468
  }
@@ -248,7 +248,6 @@ storage convention used internally (credential/{service}/{field}):
248
248
  --service telegram --field bot_token Telegram bot token
249
249
  --service slack_channel --field bot_token Slack channel bot token
250
250
  --service github --field token GitHub personal access token
251
- --service agentmail --field api_key AgentMail API key
252
251
 
253
252
  Secrets are stored in AES-256-GCM encrypted storage. Metadata (policy,
254
253
  timestamps, labels) is tracked separately and never contains secret values.
@@ -0,0 +1,210 @@
1
+ import type { Command } from "commander";
2
+
3
+ import { getAssistantDomain } from "../../config/env.js";
4
+ import { VellumPlatformClient } from "../../platform/client.js";
5
+ import { getCliLogger } from "../logger.js";
6
+ import { shouldOutputJson, writeOutput } from "../output.js";
7
+
8
+ const log = getCliLogger("domain");
9
+
10
+ export function registerDomainCommand(program: Command): void {
11
+ const baseDomain = getAssistantDomain();
12
+ const domain = program
13
+ .command("domain")
14
+ .description(
15
+ `Register and manage this assistant's custom subdomain on ${baseDomain}`,
16
+ )
17
+ .option("--json", "Machine-readable compact JSON output");
18
+
19
+ domain.addHelpText(
20
+ "after",
21
+ `
22
+ Each assistant can register its own subdomain (e.g. velly.${baseDomain})
23
+ for email and web presence. DNS managed by the Vellum platform.
24
+
25
+ Examples:
26
+ $ assistant domain register velly
27
+ $ assistant domain register --json
28
+ $ assistant domain status`,
29
+ );
30
+
31
+ domain
32
+ .command("register [subdomain]")
33
+ .description(
34
+ `Register a custom subdomain on ${baseDomain} for this assistant`,
35
+ )
36
+ .addHelpText(
37
+ "after",
38
+ `
39
+ Arguments:
40
+ subdomain The subdomain to register (e.g. "velly" → velly.${baseDomain}).
41
+ If omitted, the platform derives it from the assistant's name.
42
+
43
+ Registers a subdomain at <subdomain>.${baseDomain}. DNS managed by the
44
+ Vellum platform — no manual DNS changes needed.
45
+
46
+ Examples:
47
+ $ assistant domain register velly
48
+ ✓ Registered velly.${baseDomain}
49
+
50
+ $ assistant domain register
51
+ ✓ Registered my-assistant.${baseDomain}
52
+
53
+ $ assistant domain register velly --json
54
+ {"domain":"velly.${baseDomain}","id":"...","status":"active","verified":true}`,
55
+ )
56
+ .action(
57
+ async (subdomain: string | undefined, _opts: unknown, cmd: Command) => {
58
+ try {
59
+ const client = await VellumPlatformClient.create();
60
+ if (!client) {
61
+ throw new Error(
62
+ "Platform credentials not configured. Run: assistant platform connect",
63
+ );
64
+ }
65
+ if (!client.platformAssistantId) {
66
+ throw new Error(
67
+ "Assistant ID not configured. Set PLATFORM_ASSISTANT_ID or run: assistant platform connect",
68
+ );
69
+ }
70
+
71
+ const body: Record<string, string> = {};
72
+ if (subdomain) {
73
+ body.subdomain = subdomain;
74
+ }
75
+
76
+ const response = await client.fetch(
77
+ `/v1/assistants/${client.platformAssistantId}/domains/`,
78
+ {
79
+ method: "POST",
80
+ headers: { "Content-Type": "application/json" },
81
+ body: JSON.stringify(body),
82
+ },
83
+ );
84
+
85
+ if (!response.ok) {
86
+ const respBody = (await response
87
+ .json()
88
+ .catch(() => ({}))) as Record<string, unknown>;
89
+ const detail =
90
+ respBody.detail ??
91
+ (Array.isArray(respBody.subdomain)
92
+ ? respBody.subdomain[0]
93
+ : undefined) ??
94
+ `HTTP ${response.status}`;
95
+ throw new Error(String(detail));
96
+ }
97
+
98
+ const data = (await response.json()) as {
99
+ id: string;
100
+ domain: string;
101
+ status: string;
102
+ verified: boolean;
103
+ created_at: string;
104
+ };
105
+
106
+ if (shouldOutputJson(cmd)) {
107
+ writeOutput(cmd, data);
108
+ } else {
109
+ log.info(`✓ Registered ${data.domain}`);
110
+ if (!data.verified) {
111
+ log.info(
112
+ " ⚠ Domain verification pending — this usually resolves within a few seconds.",
113
+ );
114
+ }
115
+ }
116
+ } catch (err) {
117
+ const message = err instanceof Error ? err.message : String(err);
118
+ if (shouldOutputJson(cmd)) {
119
+ writeOutput(cmd, { error: message });
120
+ } else {
121
+ log.error(`Error: ${message}`);
122
+ }
123
+ process.exitCode = 1;
124
+ }
125
+ },
126
+ );
127
+
128
+ domain
129
+ .command("status")
130
+ .description("Show this assistant's domain registration and health")
131
+ .addHelpText(
132
+ "after",
133
+ `
134
+ Shows the domain currently registered for this assistant, including
135
+ verification status and DNS health.
136
+
137
+ Examples:
138
+ $ assistant domain status
139
+ Domain: velly.${baseDomain}
140
+ Status: active
141
+ Verified: yes
142
+ Created: 2026-04-15
143
+
144
+ $ assistant domain status --json
145
+ {"domain":"velly.${baseDomain}","status":"active","verified":true,...}`,
146
+ )
147
+ .action(async (_opts: unknown, cmd: Command) => {
148
+ try {
149
+ const client = await VellumPlatformClient.create();
150
+ if (!client) {
151
+ throw new Error(
152
+ "Platform credentials not configured. Run: assistant platform connect",
153
+ );
154
+ }
155
+ if (!client.platformAssistantId) {
156
+ throw new Error(
157
+ "Assistant ID not configured. Set PLATFORM_ASSISTANT_ID or run: assistant platform connect",
158
+ );
159
+ }
160
+
161
+ const response = await client.fetch(
162
+ `/v1/assistants/${client.platformAssistantId}/domains/`,
163
+ );
164
+
165
+ if (!response.ok) {
166
+ const respBody = (await response.json().catch(() => ({}))) as Record<
167
+ string,
168
+ unknown
169
+ >;
170
+ const detail = respBody.detail ?? `HTTP ${response.status}`;
171
+ throw new Error(String(detail));
172
+ }
173
+
174
+ const data = (await response.json()) as {
175
+ results: {
176
+ id: string;
177
+ domain: string;
178
+ status: string;
179
+ verified: boolean;
180
+ created_at: string;
181
+ }[];
182
+ };
183
+
184
+ const domains = data.results ?? [];
185
+
186
+ if (shouldOutputJson(cmd)) {
187
+ writeOutput(cmd, data);
188
+ } else if (domains.length === 0) {
189
+ log.info(
190
+ "No domain registered for this assistant. Run: assistant domain register [subdomain]",
191
+ );
192
+ } else {
193
+ for (const d of domains) {
194
+ log.info(`Domain: ${d.domain}`);
195
+ log.info(`Status: ${d.status}`);
196
+ log.info(`Verified: ${d.verified ? "yes" : "no"}`);
197
+ log.info(`Created: ${d.created_at.split("T")[0]}`);
198
+ }
199
+ }
200
+ } catch (err) {
201
+ const message = err instanceof Error ? err.message : String(err);
202
+ if (shouldOutputJson(cmd)) {
203
+ writeOutput(cmd, { error: message });
204
+ } else {
205
+ log.error(`Error: ${message}`);
206
+ }
207
+ process.exitCode = 1;
208
+ }
209
+ });
210
+ }
@@ -1,8 +1,12 @@
1
- import { readFileSync, writeFileSync } from "node:fs";
1
+ import { createWriteStream, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { basename, join } from "node:path";
3
+ import type { Readable } from "node:stream";
4
+ import { pipeline } from "node:stream/promises";
2
5
 
3
6
  import type { Command } from "commander";
4
7
 
5
8
  import { getAssistantDomain } from "../../config/env.js";
9
+ import { markdownToEmailHtml } from "../../email/html-renderer.js";
6
10
  import { VellumPlatformClient } from "../../platform/client.js";
7
11
  import { getCliLogger } from "../logger.js";
8
12
  import { shouldOutputJson, writeOutput } from "../output.js";
@@ -30,6 +34,8 @@ Examples:
30
34
  $ assistant email send user@example.com -s "Hello" -b "Hi there"
31
35
  $ assistant email status
32
36
  $ assistant email list
37
+ $ assistant email attachment msg_abc1 --list
38
+ $ assistant email attachment msg_abc1 att_xyz1
33
39
  $ assistant email register mybot --json`,
34
40
  );
35
41
 
@@ -569,6 +575,10 @@ Examples:
569
575
  .option("-b, --body <text>", "Email body (plain text)")
570
576
  .option("-f, --file <path>", "Read body from file")
571
577
  .option("--html <path>", "HTML body file (optional)")
578
+ .option(
579
+ "--reply-to <email_id>",
580
+ "Reply to an email by its ID (auto-resolves threading headers and subject)",
581
+ )
572
582
  .addHelpText(
573
583
  "after",
574
584
  `
@@ -581,13 +591,20 @@ from the assistant's registered email address.
581
591
 
582
592
  Body source priority: --body flag > --file flag > stdin (if not a TTY).
583
593
 
594
+ When --reply-to is provided, the platform auto-resolves In-Reply-To,
595
+ References, and Subject headers from the referenced email. You can
596
+ still override subject with -s.
597
+
584
598
  Examples:
585
599
  $ assistant email send user@example.com -s "Hello" -b "Hi there"
586
600
  ✓ Sent to user@example.com (delivery_id: abc123)
587
601
 
588
- $ echo "Body text" | assistant email send user@example.com -s "Hello"
602
+ $ assistant email send user@example.com -b "Thanks!" --reply-to 019d96e4-e5d2-7201-890e-04a21e8f95bb
589
603
  ✓ Sent to user@example.com (delivery_id: def456)
590
604
 
605
+ $ echo "Body text" | assistant email send user@example.com -s "Hello"
606
+ ✓ Sent to user@example.com (delivery_id: ghi789)
607
+
591
608
  $ assistant email send user@example.com -s "Hello" -b "Hi" --json
592
609
  {"delivery_id":"abc123","status":"accepted"}`,
593
610
  )
@@ -599,6 +616,7 @@ Examples:
599
616
  body?: string;
600
617
  file?: string;
601
618
  html?: string;
619
+ replyTo?: string;
602
620
  },
603
621
  cmd: Command,
604
622
  ) => {
@@ -653,10 +671,13 @@ Examples:
653
671
  );
654
672
  }
655
673
 
656
- // 3. Resolve optional HTML body from file
674
+ // 3. Resolve HTML body: explicit file > auto-generate from text
657
675
  let html: string | undefined;
658
676
  if (opts.html) {
659
677
  html = readFileSync(opts.html, "utf-8");
678
+ } else {
679
+ // Auto-generate HTML from the text body (markdown → email HTML).
680
+ html = markdownToEmailHtml(text);
660
681
  }
661
682
 
662
683
  // 4. Build payload
@@ -667,6 +688,7 @@ Examples:
667
688
  };
668
689
  if (opts.subject) payload.subject = opts.subject;
669
690
  if (html) payload.html = html;
691
+ if (opts.replyTo) payload.reply_to = opts.replyTo;
670
692
 
671
693
  // 5. Send via runtime proxy
672
694
  const response = await client.fetch("/v1/runtime-proxy/email/send/", {
@@ -705,4 +727,234 @@ Examples:
705
727
  }
706
728
  },
707
729
  );
730
+
731
+ email
732
+ .command("attachment <message-id> [attachment-id]")
733
+ .description("Download email attachments")
734
+ .option("--all", "Download all attachments for the message")
735
+ .option(
736
+ "-o, --output <dir>",
737
+ "Output directory (default: current directory)",
738
+ ".",
739
+ )
740
+ .option("--list", "List attachments without downloading")
741
+ .addHelpText(
742
+ "after",
743
+ `
744
+ Arguments:
745
+ message-id Email message ID (from \`assistant email list --json\`)
746
+ attachment-id Attachment ID (optional — required unless --all or --list)
747
+
748
+ Download one or all attachments from a specific email message. Use
749
+ --list to see available attachments without downloading.
750
+
751
+ Examples:
752
+ $ assistant email attachment msg_abc1 --list
753
+ $ assistant email attachment msg_abc1 att_xyz1
754
+ $ assistant email attachment msg_abc1 att_xyz1 -o ./downloads/
755
+ $ assistant email attachment msg_abc1 --all
756
+ $ assistant email attachment msg_abc1 --all -o ./attachments/
757
+ $ assistant email attachment msg_abc1 --list --json`,
758
+ )
759
+ .action(
760
+ async (
761
+ messageId: string,
762
+ attachmentId: string | undefined,
763
+ opts: {
764
+ all?: boolean;
765
+ output?: string;
766
+ list?: boolean;
767
+ },
768
+ cmd: Command,
769
+ ) => {
770
+ try {
771
+ const client = await VellumPlatformClient.create();
772
+ if (!client) {
773
+ throw new Error(
774
+ "Platform credentials not configured. Run: assistant platform connect",
775
+ );
776
+ }
777
+ if (!client.platformAssistantId) {
778
+ throw new Error(
779
+ "Assistant ID not configured. Set PLATFORM_ASSISTANT_ID or run: assistant platform connect",
780
+ );
781
+ }
782
+
783
+ const assistantId = client.platformAssistantId;
784
+ const basePath = `/v1/assistants/${assistantId}/emails/${messageId}/attachments`;
785
+
786
+ if (opts.list) {
787
+ // List mode — show attachment metadata without downloading
788
+ const response = await client.fetch(`${basePath}/`);
789
+ if (!response.ok) {
790
+ const body = (await response
791
+ .json()
792
+ .catch(() => ({}))) as Record<string, unknown>;
793
+ const detail = body.detail ?? `HTTP ${response.status}`;
794
+ throw new Error(String(detail));
795
+ }
796
+
797
+ const data = (await response.json()) as {
798
+ results: AttachmentMeta[];
799
+ };
800
+
801
+ if (shouldOutputJson(cmd)) {
802
+ writeOutput(cmd, data);
803
+ } else {
804
+ const attachments = data.results ?? [];
805
+ if (attachments.length === 0) {
806
+ log.info("No attachments for this message.");
807
+ } else {
808
+ for (const att of attachments) {
809
+ log.info(
810
+ ` ${att.id} ${att.filename} (${att.content_type}, ${formatBytes(att.size_bytes)})`,
811
+ );
812
+ }
813
+ log.info(`\n${attachments.length} attachment(s)`);
814
+ }
815
+ }
816
+ return;
817
+ }
818
+
819
+ if (!opts.all && !attachmentId) {
820
+ throw new Error(
821
+ "Specify an attachment ID, or use --all to download all attachments. Use --list to see available attachments.",
822
+ );
823
+ }
824
+
825
+ // Ensure output directory exists
826
+ const outDir = opts.output ?? ".";
827
+ mkdirSync(outDir, { recursive: true });
828
+
829
+ if (opts.all) {
830
+ // Download all attachments
831
+ const listResponse = await client.fetch(`${basePath}/`);
832
+ if (!listResponse.ok) {
833
+ const body = (await listResponse
834
+ .json()
835
+ .catch(() => ({}))) as Record<string, unknown>;
836
+ const detail = body.detail ?? `HTTP ${listResponse.status}`;
837
+ throw new Error(String(detail));
838
+ }
839
+
840
+ const listData = (await listResponse.json()) as {
841
+ results: AttachmentMeta[];
842
+ };
843
+
844
+ const attachments = listData.results ?? [];
845
+ if (attachments.length === 0) {
846
+ throw new Error("No attachments for this message.");
847
+ }
848
+
849
+ const downloaded: { filename: string; size_bytes: number }[] = [];
850
+ for (const att of attachments) {
851
+ const dest = join(outDir, safeFilename(att.filename));
852
+ await downloadAttachment(client, basePath, att.id, dest);
853
+ downloaded.push({
854
+ filename: att.filename,
855
+ size_bytes: att.size_bytes,
856
+ });
857
+ }
858
+
859
+ if (shouldOutputJson(cmd)) {
860
+ writeOutput(cmd, {
861
+ downloaded: downloaded.length,
862
+ directory: outDir,
863
+ files: downloaded,
864
+ });
865
+ } else {
866
+ log.info(
867
+ `✓ Downloaded ${downloaded.length} attachment(s) to ${outDir}`,
868
+ );
869
+ for (const f of downloaded) {
870
+ log.info(` - ${f.filename} (${formatBytes(f.size_bytes)})`);
871
+ }
872
+ }
873
+ } else {
874
+ // Download single attachment — first get metadata for the filename
875
+ const metaResponse = await client.fetch(
876
+ `${basePath}/${attachmentId}/`,
877
+ );
878
+ if (!metaResponse.ok) {
879
+ const body = (await metaResponse
880
+ .json()
881
+ .catch(() => ({}))) as Record<string, unknown>;
882
+ const detail = body.detail ?? `HTTP ${metaResponse.status}`;
883
+ throw new Error(String(detail));
884
+ }
885
+
886
+ const meta = (await metaResponse.json()) as AttachmentMeta;
887
+ const dest = join(outDir, safeFilename(meta.filename));
888
+ await downloadAttachment(client, basePath, meta.id, dest);
889
+
890
+ if (shouldOutputJson(cmd)) {
891
+ writeOutput(cmd, {
892
+ filename: meta.filename,
893
+ size_bytes: meta.size_bytes,
894
+ saved: dest,
895
+ });
896
+ } else {
897
+ log.info(
898
+ `✓ Downloaded ${meta.filename} (${formatBytes(meta.size_bytes)})`,
899
+ );
900
+ }
901
+ }
902
+ } catch (err) {
903
+ const message = err instanceof Error ? err.message : String(err);
904
+ if (shouldOutputJson(cmd)) {
905
+ writeOutput(cmd, { error: message });
906
+ } else {
907
+ log.error(`Error: ${message}`);
908
+ }
909
+ process.exitCode = 1;
910
+ }
911
+ },
912
+ );
913
+ }
914
+
915
+ interface AttachmentMeta {
916
+ id: string;
917
+ filename: string;
918
+ content_type: string;
919
+ size_bytes: number;
920
+ content_id: string;
921
+ created_at: string;
922
+ }
923
+
924
+ function formatBytes(bytes: number): string {
925
+ if (bytes < 1024) return `${bytes} B`;
926
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
927
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
928
+ }
929
+
930
+ function safeFilename(name: string): string {
931
+ // Strip path separators and null bytes — keep the basename only
932
+ return basename(name).replace(/[\x00/\\]/g, "_") || "attachment";
933
+ }
934
+
935
+ async function downloadAttachment(
936
+ client: VellumPlatformClient,
937
+ basePath: string,
938
+ attachmentId: string,
939
+ dest: string,
940
+ ): Promise<void> {
941
+ const response = await client.fetch(
942
+ `${basePath}/${attachmentId}/download/`,
943
+ );
944
+
945
+ if (!response.ok) {
946
+ const body = (await response.json().catch(() => ({}))) as Record<
947
+ string,
948
+ unknown
949
+ >;
950
+ const detail = body.detail ?? `HTTP ${response.status}`;
951
+ throw new Error(`Failed to download attachment: ${detail}`);
952
+ }
953
+
954
+ if (!response.body) {
955
+ throw new Error("Empty response body from download endpoint.");
956
+ }
957
+
958
+ const fileStream = createWriteStream(dest);
959
+ await pipeline(response.body as unknown as Readable, fileStream);
708
960
  }