@vellumai/assistant 0.6.4 → 0.6.5

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 (717) hide show
  1. package/.prettierignore +5 -0
  2. package/ARCHITECTURE.md +32 -36
  3. package/Dockerfile +12 -0
  4. package/README.md +3 -4
  5. package/bun.lock +8 -3
  6. package/docs/architecture/integrations.md +1 -20
  7. package/docs/architecture/security.md +16 -16
  8. package/docs/error-handling.md +111 -0
  9. package/docs/skills.md +10 -10
  10. package/docs/stt-provider-onboarding.md +2 -1
  11. package/knip.json +9 -2
  12. package/node_modules/@vellumai/ces-contracts/package.json +2 -1
  13. package/node_modules/@vellumai/ces-contracts/src/__tests__/trust-rules.test.ts +471 -0
  14. package/node_modules/@vellumai/ces-contracts/src/trust-rules.ts +398 -4
  15. package/node_modules/@vellumai/credential-storage/bun.lock +2 -2
  16. package/node_modules/@vellumai/credential-storage/package.json +2 -2
  17. package/node_modules/@vellumai/credential-storage/src/oauth-runtime.ts +20 -2
  18. package/node_modules/@vellumai/egress-proxy/bun.lock +2 -2
  19. package/node_modules/@vellumai/egress-proxy/package.json +2 -2
  20. package/openapi.yaml +123 -11
  21. package/package.json +6 -3
  22. package/scripts/generate-openapi.ts +50 -11
  23. package/src/__tests__/agent-loop-callsite-precedence.test.ts +318 -0
  24. package/src/__tests__/agent-loop-sentry-hygiene.test.ts +137 -0
  25. package/src/__tests__/agent-loop.test.ts +112 -1
  26. package/src/__tests__/anthropic-error-formatting.test.ts +98 -0
  27. package/src/__tests__/anthropic-provider.test.ts +171 -2
  28. package/src/__tests__/approval-cascade.test.ts +31 -10
  29. package/src/__tests__/approval-routes-http.test.ts +134 -10
  30. package/src/__tests__/assistant-attachments.test.ts +44 -0
  31. package/src/__tests__/assistant-feature-flags-integration.test.ts +29 -0
  32. package/src/__tests__/browser-fill-credential.test.ts +1 -1
  33. package/src/__tests__/browser-identifier-parity-guard.test.ts +53 -0
  34. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +23 -33
  35. package/src/__tests__/browser-skill-endstate.test.ts +51 -182
  36. package/src/__tests__/btw-routes.test.ts +47 -1
  37. package/src/__tests__/call-controller.test.ts +1 -2
  38. package/src/__tests__/call-site-routing-provider.test.ts +214 -0
  39. package/src/__tests__/catalog-cache.test.ts +27 -4
  40. package/src/__tests__/channel-approval-routes.test.ts +4 -4
  41. package/src/__tests__/channel-reply-delivery.test.ts +300 -2
  42. package/src/__tests__/checker.test.ts +428 -501
  43. package/src/__tests__/cli-command-risk-guard.test.ts +30 -33
  44. package/src/__tests__/compaction-circuit-breaker.test.ts +336 -0
  45. package/src/__tests__/compaction.benchmark.test.ts +1 -1
  46. package/src/__tests__/config-analysis.test.ts +11 -28
  47. package/src/__tests__/config-loader-backfill.test.ts +174 -0
  48. package/src/__tests__/config-loader-corrupt.test.ts +183 -0
  49. package/src/__tests__/config-loader-quarantine-bulletin.test.ts +202 -0
  50. package/src/__tests__/config-schema-cmd.test.ts +11 -5
  51. package/src/__tests__/config-schema.test.ts +427 -114
  52. package/src/__tests__/config-watcher.test.ts +2 -2
  53. package/src/__tests__/contact-store-user-file.test.ts +72 -73
  54. package/src/__tests__/contacts-write.test.ts +4 -4
  55. package/src/__tests__/context-token-estimator.test.ts +191 -1
  56. package/src/__tests__/context-window-manager.test.ts +530 -2
  57. package/src/__tests__/conversation-abort-tool-results.test.ts +30 -16
  58. package/src/__tests__/conversation-agent-loop-overflow.test.ts +61 -17
  59. package/src/__tests__/conversation-agent-loop.test.ts +412 -82
  60. package/src/__tests__/conversation-attachments.test.ts +1 -1
  61. package/src/__tests__/conversation-confirmation-signals.test.ts +30 -9
  62. package/src/__tests__/conversation-error.test.ts +37 -6
  63. package/src/__tests__/conversation-history-web-search.test.ts +6 -0
  64. package/src/__tests__/conversation-init.benchmark.test.ts +36 -0
  65. package/src/__tests__/conversation-lifecycle.test.ts +336 -0
  66. package/src/__tests__/conversation-load-history-repair.test.ts +27 -10
  67. package/src/__tests__/conversation-pre-run-repair.test.ts +30 -16
  68. package/src/__tests__/conversation-process-callsite.test.ts +306 -0
  69. package/src/__tests__/conversation-provider-retry-repair.test.ts +30 -16
  70. package/src/__tests__/conversation-queue.test.ts +41 -26
  71. package/src/__tests__/conversation-routes-disk-view.test.ts +29 -1
  72. package/src/__tests__/conversation-routes-slash-commands.test.ts +31 -3
  73. package/src/__tests__/conversation-runtime-assembly.test.ts +2735 -55
  74. package/src/__tests__/conversation-runtime-workspace.test.ts +12 -12
  75. package/src/__tests__/conversation-skill-tools.test.ts +12 -146
  76. package/src/__tests__/conversation-slash-queue.test.ts +34 -19
  77. package/src/__tests__/conversation-slash-unknown.test.ts +30 -16
  78. package/src/__tests__/conversation-speed-override.test.ts +30 -11
  79. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +1035 -0
  80. package/src/__tests__/conversation-surfaces-standalone.test.ts +630 -0
  81. package/src/__tests__/conversation-title-service.test.ts +2 -2
  82. package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +1 -1
  83. package/src/__tests__/conversation-unread-route.test.ts +2 -2
  84. package/src/__tests__/conversation-usage.test.ts +3 -1
  85. package/src/__tests__/conversation-workspace-cache-state.test.ts +31 -10
  86. package/src/__tests__/conversation-workspace-injection.test.ts +43 -15
  87. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +44 -16
  88. package/src/__tests__/credential-broker-browser-fill.test.ts +110 -0
  89. package/src/__tests__/credential-security-invariants.test.ts +3 -0
  90. package/src/__tests__/credential-storage-oauth-compat.test.ts +18 -0
  91. package/src/__tests__/credential-storage-static-compat.test.ts +28 -0
  92. package/src/__tests__/credential-vault-unit.test.ts +135 -19
  93. package/src/__tests__/credentials-cli.test.ts +1 -9
  94. package/src/__tests__/cross-provider-web-search.test.ts +84 -0
  95. package/src/__tests__/daemon-server-persist-and-process-callsite.test.ts +92 -0
  96. package/src/__tests__/delete-propagation.test.ts +437 -0
  97. package/src/__tests__/dm-backfill.test.ts +417 -0
  98. package/src/__tests__/dm-persistence.test.ts +227 -0
  99. package/src/__tests__/edit-propagation.test.ts +280 -0
  100. package/src/__tests__/ephemeral-permissions.test.ts +93 -3
  101. package/src/__tests__/estimator-calibration-integration.test.ts +208 -0
  102. package/src/__tests__/estimator-calibration.test.ts +213 -0
  103. package/src/__tests__/extension-id-sync-guard.test.ts +26 -7
  104. package/src/__tests__/file-write-tool.test.ts +151 -1
  105. package/src/__tests__/filing-service.test.ts +255 -0
  106. package/src/__tests__/gemini-provider.test.ts +0 -3
  107. package/src/__tests__/guardian-grant-minting.test.ts +8 -0
  108. package/src/__tests__/headless-browser-interactions.test.ts +1 -1
  109. package/src/__tests__/heartbeat-service.test.ts +96 -15
  110. package/src/__tests__/host-shell-tool.test.ts +124 -18
  111. package/src/__tests__/http-user-message-parity.test.ts +29 -1
  112. package/src/__tests__/inbound-slack-persistence.test.ts +340 -0
  113. package/src/__tests__/intent-routing.test.ts +1 -40
  114. package/src/__tests__/llm-catalog-parity.test.ts +174 -0
  115. package/src/__tests__/llm-context-normalization.test.ts +121 -0
  116. package/src/__tests__/llm-resolver.test.ts +214 -0
  117. package/src/__tests__/llm-schema.test.ts +223 -0
  118. package/src/__tests__/managed-proxy-context.test.ts +6 -2
  119. package/src/__tests__/messaging-skill-split.test.ts +3 -34
  120. package/src/__tests__/migration-import-from-url.test.ts +684 -0
  121. package/src/__tests__/model-intents.test.ts +9 -83
  122. package/src/__tests__/notification-decision-fallback.test.ts +0 -10
  123. package/src/__tests__/notification-decision-identity.test.ts +0 -9
  124. package/src/__tests__/notification-decision-recipient-context.test.ts +0 -9
  125. package/src/__tests__/oauth-store.test.ts +10 -7
  126. package/src/__tests__/oauth2-gateway-transport.test.ts +8 -3
  127. package/src/__tests__/oauth2-refresh-retry.test.ts +279 -0
  128. package/src/__tests__/openai-provider.test.ts +7 -0
  129. package/src/__tests__/openai-responses-provider.test.ts +396 -0
  130. package/src/__tests__/openrouter-provider-only.test.ts +135 -0
  131. package/src/__tests__/outbound-slack-persistence.test.ts +293 -0
  132. package/src/__tests__/permission-checker-host-gate.test.ts +1 -1
  133. package/src/__tests__/permission-mode.test.ts +16 -0
  134. package/src/__tests__/permission-types.test.ts +0 -1
  135. package/src/__tests__/persona-resolver.test.ts +13 -13
  136. package/src/__tests__/pkb-autoinject.test.ts +37 -1
  137. package/src/__tests__/platform-bash-auto-approve.test.ts +1 -1
  138. package/src/__tests__/pricing.test.ts +50 -3
  139. package/src/__tests__/profiler-routes.test.ts +1 -1
  140. package/src/__tests__/provider-commit-message-generator.test.ts +14 -84
  141. package/src/__tests__/provider-env-vars-scope.test.ts +52 -0
  142. package/src/__tests__/provider-error-scenarios.test.ts +135 -6
  143. package/src/__tests__/provider-managed-proxy-integration.test.ts +42 -11
  144. package/src/__tests__/provider-registry-ollama.test.ts +1 -2
  145. package/src/__tests__/proxy-approval-callback.test.ts +0 -1
  146. package/src/__tests__/reaction-persistence.test.ts +560 -0
  147. package/src/__tests__/relay-server.test.ts +1 -1
  148. package/src/__tests__/require-fresh-approval.test.ts +1 -1
  149. package/src/__tests__/retry-openrouter-only-normalization.test.ts +136 -0
  150. package/src/__tests__/retry-thinking-tool-choice.test.ts +226 -0
  151. package/src/__tests__/risk-classifier-parity.test.ts +230 -0
  152. package/src/__tests__/sanitize-config-for-transfer.test.ts +78 -1
  153. package/src/__tests__/secret-ingress-http.test.ts +28 -0
  154. package/src/__tests__/secret-prompter-channel-fallback.test.ts +125 -0
  155. package/src/__tests__/secret-routes-managed-proxy.test.ts +2 -3
  156. package/src/__tests__/secret-scanner-executor.test.ts +1 -1
  157. package/src/__tests__/send-endpoint-busy.test.ts +29 -1
  158. package/src/__tests__/server-history-render.test.ts +31 -0
  159. package/src/__tests__/shell-parser-property.test.ts +13 -13
  160. package/src/__tests__/skill-cache-store.test.ts +182 -0
  161. package/src/__tests__/skills.test.ts +19 -33
  162. package/src/__tests__/slack-app-setup-skill-regression.test.ts +3 -1
  163. package/src/__tests__/slack-skill.test.ts +3 -8
  164. package/src/__tests__/starter-bundle.test.ts +35 -0
  165. package/src/__tests__/subagent-call-site-routing.test.ts +280 -0
  166. package/src/__tests__/suggestion-routes.test.ts +160 -3
  167. package/src/__tests__/system-prompt.test.ts +22 -35
  168. package/src/__tests__/task-runner.test.ts +3 -1
  169. package/src/__tests__/tcc-sandbox-deny.test.ts +198 -0
  170. package/src/__tests__/terminal-tools.test.ts +8 -0
  171. package/src/__tests__/test-support/browser-skill-harness.ts +2 -52
  172. package/src/__tests__/thread-backfill.test.ts +941 -0
  173. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -2
  174. package/src/__tests__/tool-executor-lifecycle-events.test.ts +2 -2
  175. package/src/__tests__/tool-executor.test.ts +60 -94
  176. package/src/__tests__/trust-store.test.ts +442 -109
  177. package/src/__tests__/update-bulletin-job.test.ts +389 -0
  178. package/src/__tests__/usage-cache-backfill-migration.test.ts +3 -1
  179. package/src/__tests__/verification-control-plane-policy.test.ts +1 -22
  180. package/src/__tests__/voice-session-bridge.test.ts +39 -0
  181. package/src/__tests__/volume-security-guard.test.ts +3 -2
  182. package/src/__tests__/web-search-history.test.ts +337 -0
  183. package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +343 -0
  184. package/src/__tests__/workspace-migration-043-release-notes-latex-rendering.test.ts +202 -0
  185. package/src/__tests__/workspace-migration-045-release-notes-meet-avatar.test.ts +210 -0
  186. package/src/__tests__/workspace-migration-drop-user-md.test.ts +11 -11
  187. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +841 -0
  188. package/src/__tests__/workspace-policy.test.ts +1 -13
  189. package/src/acp/client-handler.ts +1 -2
  190. package/src/agent/loop.ts +209 -17
  191. package/src/avatar/resvg-lazy.test.ts +136 -0
  192. package/src/avatar/resvg-lazy.ts +82 -9
  193. package/src/avatar/traits-png-sync.ts +21 -1
  194. package/src/browser/__tests__/operations.test.ts +163 -0
  195. package/src/browser/identifiers.ts +51 -0
  196. package/src/browser/operations.ts +660 -0
  197. package/src/browser/types.ts +81 -0
  198. package/src/calls/guardian-question-copy.ts +2 -2
  199. package/src/calls/telephony-stt-routing.ts +1 -1
  200. package/src/calls/voice-session-bridge.ts +1 -0
  201. package/src/cli/AGENTS.md +1 -1
  202. package/src/cli/commands/__tests__/attachment.test.ts +438 -0
  203. package/src/cli/commands/__tests__/browser.test.ts +554 -0
  204. package/src/cli/commands/__tests__/cache.test.ts +623 -0
  205. package/src/cli/commands/__tests__/email-list.test.ts +6 -0
  206. package/src/cli/commands/__tests__/email-send.test.ts +93 -1
  207. package/src/cli/commands/__tests__/image-generation.test.ts +666 -0
  208. package/src/cli/commands/__tests__/inference-send.test.ts +451 -0
  209. package/src/cli/commands/__tests__/stt-transcribe.test.ts +454 -0
  210. package/src/cli/commands/__tests__/task.test.ts +913 -0
  211. package/src/cli/commands/__tests__/tts-synthesize.test.ts +594 -0
  212. package/src/cli/commands/__tests__/ui-confirm.test.ts +650 -0
  213. package/src/cli/commands/__tests__/ui.test.ts +1215 -0
  214. package/src/cli/commands/__tests__/watchers.test.ts +716 -0
  215. package/src/cli/commands/attachment.ts +182 -0
  216. package/src/cli/commands/browser.ts +350 -0
  217. package/src/cli/commands/cache.ts +341 -0
  218. package/src/cli/commands/completions.ts +0 -3
  219. package/src/cli/commands/config.ts +6 -6
  220. package/src/cli/commands/conversations-import.ts +347 -0
  221. package/src/cli/commands/conversations.ts +14 -1
  222. package/src/cli/commands/email.ts +234 -194
  223. package/src/cli/commands/image-generation.ts +300 -0
  224. package/src/cli/commands/inference.ts +200 -0
  225. package/src/cli/commands/memory.ts +127 -17
  226. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -1
  227. package/src/cli/commands/platform/__tests__/connect.test.ts +0 -1
  228. package/src/cli/commands/platform/__tests__/disconnect.test.ts +0 -1
  229. package/src/cli/commands/platform/__tests__/status.test.ts +0 -1
  230. package/src/cli/commands/stt.ts +339 -0
  231. package/src/cli/commands/task.ts +795 -0
  232. package/src/cli/commands/trust.ts +50 -19
  233. package/src/cli/commands/tts.ts +273 -0
  234. package/src/cli/commands/ui.ts +670 -0
  235. package/src/cli/commands/watchers.ts +509 -0
  236. package/src/cli/lib/daemon-credential-client.ts +0 -19
  237. package/src/cli/program.ts +23 -4
  238. package/src/cli.ts +0 -37
  239. package/src/config/bundled-skills/conversations/tools/rename-conversation.ts +23 -1
  240. package/src/config/bundled-skills/media-processing/services/reduce.ts +1 -1
  241. package/src/config/bundled-skills/messaging/SKILL.md +2 -2
  242. package/src/config/bundled-skills/messaging/TOOLS.json +4 -0
  243. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +8 -1
  244. package/src/config/bundled-skills/messaging/tools/messaging-read.ts +15 -1
  245. package/src/config/bundled-skills/messaging/tools/messaging-search.ts +21 -1
  246. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +11 -12
  247. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +9 -8
  248. package/src/config/bundled-skills/settings/TOOLS.json +3 -3
  249. package/src/config/bundled-tool-registry.ts +0 -175
  250. package/src/config/env.ts +7 -2
  251. package/src/config/feature-flag-registry.json +25 -9
  252. package/src/config/llm-resolver.ts +128 -0
  253. package/src/config/loader.ts +194 -10
  254. package/src/config/raw-config-utils.ts +30 -2
  255. package/src/config/sanitize-for-transfer.ts +35 -0
  256. package/src/config/schema.ts +30 -41
  257. package/src/config/schemas/analysis.ts +3 -22
  258. package/src/config/schemas/calls.ts +0 -4
  259. package/src/config/schemas/filing.ts +2 -7
  260. package/src/config/schemas/heartbeat.ts +0 -5
  261. package/src/config/schemas/inference.ts +3 -23
  262. package/src/config/schemas/llm.ts +318 -0
  263. package/src/config/schemas/memory-processing.ts +1 -9
  264. package/src/config/schemas/notifications.ts +4 -11
  265. package/src/config/schemas/platform.ts +3 -9
  266. package/src/config/schemas/security.ts +33 -0
  267. package/src/config/schemas/services.ts +9 -4
  268. package/src/config/schemas/stt.ts +1 -0
  269. package/src/config/schemas/tts.ts +53 -0
  270. package/src/config/schemas/updates.ts +1 -1
  271. package/src/config/schemas/workspace-git.ts +3 -40
  272. package/src/config/skills.ts +2 -2
  273. package/src/context/__tests__/compact-prompt.test.ts +45 -0
  274. package/src/context/__tests__/microcompact.test.ts +805 -0
  275. package/src/context/estimator-calibration.ts +136 -0
  276. package/src/context/microcompact.ts +443 -0
  277. package/src/context/prompts/compact.md +12 -0
  278. package/src/context/token-estimator.ts +61 -3
  279. package/src/context/window-manager.ts +229 -25
  280. package/src/credential-execution/approval-bridge.ts +0 -1
  281. package/src/credential-execution/executable-discovery.ts +19 -8
  282. package/src/credential-execution/process-manager.test.ts +109 -0
  283. package/src/credential-execution/process-manager.ts +65 -2
  284. package/src/daemon/approval-generators.ts +29 -4
  285. package/src/daemon/assistant-attachments.ts +24 -13
  286. package/src/daemon/classifier.ts +2 -2
  287. package/src/daemon/config-watcher.ts +0 -1
  288. package/src/daemon/context-overflow-reducer.ts +4 -1
  289. package/src/daemon/conversation-agent-loop-handlers.ts +79 -12
  290. package/src/daemon/conversation-agent-loop.ts +462 -80
  291. package/src/daemon/conversation-attachments.ts +2 -6
  292. package/src/daemon/conversation-error.ts +36 -1
  293. package/src/daemon/conversation-lifecycle.ts +30 -6
  294. package/src/daemon/conversation-messaging.ts +73 -4
  295. package/src/daemon/conversation-process.ts +10 -4
  296. package/src/daemon/conversation-queue-manager.ts +3 -0
  297. package/src/daemon/conversation-runtime-assembly.ts +760 -29
  298. package/src/daemon/conversation-slash.ts +2 -2
  299. package/src/daemon/conversation-surfaces.ts +389 -1
  300. package/src/daemon/conversation-tool-setup.ts +10 -5
  301. package/src/daemon/conversation-usage.ts +1 -1
  302. package/src/daemon/conversation.ts +118 -30
  303. package/src/daemon/external-skills-bootstrap.ts +41 -0
  304. package/src/daemon/guardian-action-generators.ts +34 -14
  305. package/src/daemon/handlers/config-model.test.ts +86 -0
  306. package/src/daemon/handlers/config-model.ts +54 -12
  307. package/src/daemon/handlers/conversations.ts +9 -2
  308. package/src/daemon/handlers/shared.ts +39 -11
  309. package/src/daemon/handlers/skills.ts +2 -2
  310. package/src/daemon/handlers/slack-channel-oauth-install.ts +197 -0
  311. package/src/daemon/lifecycle.ts +76 -14
  312. package/src/daemon/message-types/conversations.ts +14 -0
  313. package/src/daemon/message-types/messages.ts +9 -1
  314. package/src/daemon/message-types/trust.ts +0 -2
  315. package/src/daemon/parse-actual-tokens-from-error.test.ts +57 -1
  316. package/src/daemon/parse-actual-tokens-from-error.ts +66 -0
  317. package/src/daemon/pkb-context-tracker.test.ts +169 -0
  318. package/src/daemon/pkb-context-tracker.ts +125 -0
  319. package/src/daemon/pkb-reminder-builder.test.ts +70 -0
  320. package/src/daemon/pkb-reminder-builder.ts +31 -0
  321. package/src/daemon/providers-setup.ts +6 -0
  322. package/src/daemon/server.ts +117 -9
  323. package/src/daemon/tool-side-effects.ts +0 -9
  324. package/src/daemon/watch-handler.ts +4 -4
  325. package/src/daemon/web-search-history.ts +126 -0
  326. package/src/events/domain-events.ts +0 -1
  327. package/src/filing/filing-service.ts +9 -10
  328. package/src/heartbeat/heartbeat-service.ts +76 -28
  329. package/src/home/__tests__/feed-scheduler.test.ts +39 -11
  330. package/src/home/__tests__/rollup-producer.test.ts +44 -0
  331. package/src/home/assistant-feed-authoring.ts +4 -0
  332. package/src/home/emit-feed-event.ts +4 -0
  333. package/src/home/feed-scheduler.ts +20 -4
  334. package/src/home/feed-types.ts +56 -2
  335. package/src/home/relationship-state-writer.ts +2 -2
  336. package/src/home/rollup-producer.ts +34 -5
  337. package/src/home/suggested-prompts.ts +101 -0
  338. package/src/ipc/__tests__/attachment-ipc.test.ts +213 -0
  339. package/src/ipc/__tests__/browser-ipc.test.ts +339 -0
  340. package/src/ipc/__tests__/cache-ipc.test.ts +266 -0
  341. package/src/ipc/__tests__/socket-path.test.ts +73 -0
  342. package/src/ipc/__tests__/task-ipc.test.ts +577 -0
  343. package/src/ipc/__tests__/ui-request-route.test.ts +495 -0
  344. package/src/ipc/__tests__/watcher-ipc.test.ts +295 -0
  345. package/src/ipc/cli-client.ts +2 -1
  346. package/src/ipc/cli-server.ts +26 -8
  347. package/src/ipc/gateway-client.ts +4 -4
  348. package/src/ipc/routes/attachment.ts +114 -0
  349. package/src/ipc/routes/browser-context.ts +61 -0
  350. package/src/ipc/routes/browser.ts +96 -0
  351. package/src/ipc/routes/cache.ts +96 -0
  352. package/src/ipc/routes/index.ts +17 -1
  353. package/src/ipc/routes/task-queue.ts +226 -0
  354. package/src/ipc/routes/task.ts +173 -0
  355. package/src/ipc/routes/ui-request.ts +50 -0
  356. package/src/ipc/routes/watcher.ts +203 -0
  357. package/src/ipc/socket-path.ts +100 -0
  358. package/src/memory/__tests__/conversation-analyze-job.test.ts +9 -8
  359. package/src/memory/__tests__/conversation-group-migration.test.ts +99 -0
  360. package/src/memory/admin.ts +18 -0
  361. package/src/memory/conversation-analyze-job.ts +14 -13
  362. package/src/memory/conversation-attention-store.ts +13 -6
  363. package/src/memory/conversation-crud.ts +103 -3
  364. package/src/memory/conversation-group-migration.ts +38 -6
  365. package/src/memory/conversation-title-service.ts +7 -4
  366. package/src/memory/db-init.ts +2 -0
  367. package/src/memory/embedding-backend.ts +1 -1
  368. package/src/memory/graph/compaction.ts +299 -0
  369. package/src/memory/graph/consolidation.ts +4 -4
  370. package/src/memory/graph/conversation-graph-memory.ts +89 -29
  371. package/src/memory/graph/extraction.test.ts +272 -2
  372. package/src/memory/graph/extraction.ts +173 -51
  373. package/src/memory/graph/graph-search.test.ts +92 -0
  374. package/src/memory/graph/graph-search.ts +4 -1
  375. package/src/memory/graph/narrative.ts +2 -2
  376. package/src/memory/graph/pattern-scan.ts +2 -2
  377. package/src/memory/graph/retriever.test.ts +459 -0
  378. package/src/memory/graph/retriever.ts +230 -48
  379. package/src/memory/graph/store.ts +41 -0
  380. package/src/memory/graph/tool-handlers.ts +27 -0
  381. package/src/memory/graph/tools.ts +6 -1
  382. package/src/memory/indexer.ts +5 -5
  383. package/src/memory/job-handlers/conversation-starters.ts +23 -20
  384. package/src/memory/job-handlers/summarization.ts +2 -2
  385. package/src/memory/job-utils.ts +7 -1
  386. package/src/memory/jobs/embed-pkb-file.test.ts +168 -0
  387. package/src/memory/jobs/embed-pkb-file.ts +54 -0
  388. package/src/memory/jobs-store.ts +44 -3
  389. package/src/memory/jobs-worker.ts +4 -0
  390. package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +1 -1
  391. package/src/memory/migrations/220-normalize-user-file-by-principal.ts +2 -2
  392. package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +82 -0
  393. package/src/memory/migrations/index.ts +1 -0
  394. package/src/memory/pkb/pkb-index.test.ts +368 -0
  395. package/src/memory/pkb/pkb-index.ts +255 -0
  396. package/src/memory/pkb/pkb-reconcile.test.ts +251 -0
  397. package/src/memory/pkb/pkb-reconcile.ts +148 -0
  398. package/src/memory/pkb/pkb-search.test.ts +438 -0
  399. package/src/memory/pkb/pkb-search.ts +137 -0
  400. package/src/memory/pkb/types.ts +53 -0
  401. package/src/memory/qdrant-client.ts +122 -1
  402. package/src/memory/slack-thread-store.ts +37 -0
  403. package/src/messaging/providers/gmail/adapter.ts +6 -16
  404. package/src/messaging/providers/gmail/client.ts +22 -0
  405. package/src/messaging/providers/gmail/types.ts +7 -0
  406. package/src/messaging/providers/slack/adapter.ts +14 -2
  407. package/src/messaging/providers/slack/backfill.test.ts +257 -0
  408. package/src/messaging/providers/slack/backfill.ts +101 -0
  409. package/src/messaging/providers/slack/message-metadata.test.ts +316 -0
  410. package/src/messaging/providers/slack/message-metadata.ts +123 -0
  411. package/src/messaging/providers/slack/render-transcript.test.ts +1373 -0
  412. package/src/messaging/providers/slack/render-transcript.ts +443 -0
  413. package/src/messaging/style-analyzer.ts +5 -2
  414. package/src/notifications/README.md +9 -5
  415. package/src/notifications/decision-engine.ts +3 -9
  416. package/src/notifications/preference-extractor.ts +2 -6
  417. package/src/oauth/oauth-store.ts +1 -0
  418. package/src/oauth/platform-connection.test.ts +47 -0
  419. package/src/oauth/platform-connection.ts +15 -5
  420. package/src/oauth/seed-providers.ts +4 -2
  421. package/src/permissions/approval-policy.test.ts +948 -0
  422. package/src/permissions/approval-policy.ts +257 -0
  423. package/src/permissions/bash-risk-classifier.test.ts +1208 -0
  424. package/src/permissions/bash-risk-classifier.ts +707 -0
  425. package/src/permissions/checker.ts +217 -708
  426. package/src/permissions/command-registry.test.ts +535 -0
  427. package/src/permissions/command-registry.ts +825 -0
  428. package/src/permissions/defaults.ts +26 -78
  429. package/src/permissions/file-risk-classifier.test.ts +535 -0
  430. package/src/permissions/file-risk-classifier.ts +274 -0
  431. package/src/permissions/risk-types.ts +205 -0
  432. package/src/permissions/secret-prompter.ts +53 -2
  433. package/src/permissions/skill-risk-classifier.test.ts +311 -0
  434. package/src/permissions/skill-risk-classifier.ts +214 -0
  435. package/src/permissions/trust-client.ts +52 -25
  436. package/src/permissions/trust-store-interface.ts +1 -6
  437. package/src/permissions/trust-store.ts +161 -62
  438. package/src/permissions/types.ts +23 -14
  439. package/src/permissions/web-risk-classifier.test.ts +170 -0
  440. package/src/permissions/web-risk-classifier.ts +89 -0
  441. package/src/permissions/workspace-policy.ts +1 -16
  442. package/src/platform/client.ts +19 -1
  443. package/src/prompts/persona-resolver.ts +3 -3
  444. package/src/prompts/system-prompt.ts +19 -20
  445. package/src/prompts/templates/SOUL.md +2 -2
  446. package/src/prompts/update-bulletin-job.ts +190 -0
  447. package/src/providers/__tests__/context-overflow-error.test.ts +328 -0
  448. package/src/providers/__tests__/provider-env-vars.test.ts +102 -0
  449. package/src/providers/__tests__/retry-callsite.test.ts +424 -0
  450. package/src/providers/anthropic/client.ts +183 -14
  451. package/src/providers/call-site-routing.ts +71 -0
  452. package/src/providers/gemini/client.ts +65 -2
  453. package/src/providers/managed-proxy/constants.ts +2 -1
  454. package/src/providers/model-catalog.ts +501 -33
  455. package/src/providers/model-intents.ts +4 -4
  456. package/src/providers/openai/chat-completions-provider.ts +57 -1
  457. package/src/providers/openai/responses-provider.ts +86 -9
  458. package/src/providers/openrouter/client.ts +76 -9
  459. package/src/providers/provider-env-vars.ts +56 -0
  460. package/src/providers/provider-send-message.ts +22 -5
  461. package/src/providers/ratelimit.ts +4 -0
  462. package/src/providers/registry.ts +19 -8
  463. package/src/providers/retry.ts +174 -39
  464. package/src/providers/speech-to-text/__tests__/resolve.test.ts +55 -0
  465. package/src/providers/speech-to-text/google-gemini-live-stream.ts +4 -4
  466. package/src/providers/speech-to-text/provider-catalog.ts +17 -0
  467. package/src/providers/speech-to-text/resolve.ts +7 -0
  468. package/src/providers/speech-to-text/xai-realtime.test.ts +578 -0
  469. package/src/providers/speech-to-text/xai-realtime.ts +796 -0
  470. package/src/providers/speech-to-text/xai.test.ts +155 -0
  471. package/src/providers/speech-to-text/xai.ts +97 -0
  472. package/src/providers/types.ts +93 -3
  473. package/src/runtime/AGENTS.md +2 -2
  474. package/src/runtime/__tests__/agent-wake.test.ts +43 -2
  475. package/src/runtime/__tests__/interactive-ui.test.ts +673 -0
  476. package/src/runtime/agent-wake.ts +63 -22
  477. package/src/runtime/auth/route-policy.ts +4 -0
  478. package/src/runtime/btw-sidechain.ts +13 -3
  479. package/src/runtime/channel-reply-delivery.ts +106 -2
  480. package/src/runtime/decision-token.ts +116 -0
  481. package/src/runtime/gateway-client.ts +2 -2
  482. package/src/runtime/http-router.ts +32 -0
  483. package/src/runtime/http-server.ts +52 -1
  484. package/src/runtime/http-types.ts +23 -1
  485. package/src/runtime/interactive-ui.ts +362 -0
  486. package/src/runtime/invite-instruction-generator.ts +2 -2
  487. package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +176 -0
  488. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +390 -0
  489. package/src/runtime/migrations/__tests__/vbundle-metadata-merge.test.ts +221 -0
  490. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +1540 -0
  491. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +453 -0
  492. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +222 -0
  493. package/src/runtime/migrations/gcs-signed-url.ts +162 -0
  494. package/src/runtime/migrations/vbundle-importer.ts +154 -9
  495. package/src/runtime/migrations/vbundle-metadata-merge.ts +124 -0
  496. package/src/runtime/migrations/vbundle-streaming-importer.ts +2522 -0
  497. package/src/runtime/migrations/vbundle-streaming-validator.ts +244 -0
  498. package/src/runtime/migrations/vbundle-tar-stream.ts +217 -0
  499. package/src/runtime/migrations/vbundle-validator.ts +15 -6
  500. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +111 -0
  501. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +114 -75
  502. package/src/runtime/routes/__tests__/migration-vellum-metadata-reconcile.test.ts +246 -0
  503. package/src/runtime/routes/approval-prompt-ts-tracker.ts +58 -0
  504. package/src/runtime/routes/approval-routes.ts +12 -17
  505. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +9 -0
  506. package/src/runtime/routes/avatar-routes.ts +20 -4
  507. package/src/runtime/routes/btw-routes.ts +1 -4
  508. package/src/runtime/routes/conversation-management-routes.ts +20 -2
  509. package/src/runtime/routes/conversation-routes.ts +133 -27
  510. package/src/runtime/routes/debug-routes.ts +1 -1
  511. package/src/runtime/routes/diagnostics-routes.ts +6 -4
  512. package/src/runtime/routes/events-routes.ts +16 -0
  513. package/src/runtime/routes/guardian-approval-interception.ts +33 -3
  514. package/src/runtime/routes/guardian-approval-prompt.ts +13 -3
  515. package/src/runtime/routes/home-feed-routes.ts +120 -2
  516. package/src/runtime/routes/inbound-message-handler.ts +912 -2
  517. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +113 -2
  518. package/src/runtime/routes/inbound-stages/background-dispatch.ts +61 -3
  519. package/src/runtime/routes/inbound-stages/edit-intercept.ts +129 -6
  520. package/src/runtime/routes/integrations/slack/channel.ts +25 -3
  521. package/src/runtime/routes/llm-context-normalization.ts +23 -1
  522. package/src/runtime/routes/migration-routes.ts +720 -124
  523. package/src/runtime/routes/settings-routes.ts +4 -2
  524. package/src/runtime/routes/trust-rules-routes.ts +30 -14
  525. package/src/runtime/routes/work-items-routes.test.ts +1 -1
  526. package/src/runtime/routes/work-items-routes.ts +3 -2
  527. package/src/runtime/services/__tests__/analyze-conversation.test.ts +25 -43
  528. package/src/runtime/services/analyze-conversation.ts +12 -16
  529. package/src/runtime/skill-route-registry.ts +28 -6
  530. package/src/schedule/scheduler.ts +8 -0
  531. package/src/security/__tests__/provider-key-env-fallback.test.ts +119 -0
  532. package/src/security/__tests__/untrusted-content.test.ts +109 -0
  533. package/src/security/oauth2.ts +98 -35
  534. package/src/security/secure-keys.ts +7 -8
  535. package/src/security/token-manager.ts +27 -13
  536. package/src/security/untrusted-content.ts +102 -0
  537. package/src/skills/catalog-cache.ts +26 -7
  538. package/src/skills/catalog-install.ts +31 -3
  539. package/src/skills/skill-cache-store.ts +97 -0
  540. package/src/stt/__tests__/daemon-batch-transcriber.test.ts +76 -0
  541. package/src/stt/daemon-batch-transcriber.ts +33 -0
  542. package/src/stt/stt-stream-session.ts +8 -1
  543. package/src/stt/types.ts +5 -1
  544. package/src/subagent/manager.ts +41 -13
  545. package/src/tasks/ephemeral-permissions.ts +9 -4
  546. package/src/telemetry/usage-telemetry-reporter.ts +27 -5
  547. package/src/tools/browser/__tests__/browser-status.test.ts +45 -2
  548. package/src/tools/browser/browser-execution.ts +65 -38
  549. package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +22 -0
  550. package/src/tools/credentials/tool-policy.ts +39 -5
  551. package/src/tools/credentials/vault.ts +9 -4
  552. package/src/tools/executor.ts +4 -0
  553. package/src/tools/filesystem/write.ts +52 -0
  554. package/src/tools/host-terminal/host-shell.ts +45 -5
  555. package/src/tools/memory/register.test.ts +185 -0
  556. package/src/tools/memory/register.ts +3 -1
  557. package/src/tools/network/web-fetch.ts +20 -10
  558. package/src/tools/network/web-search.ts +19 -4
  559. package/src/tools/permission-checker.ts +36 -15
  560. package/src/tools/policy-context.ts +25 -8
  561. package/src/tools/registry.ts +55 -3
  562. package/src/tools/side-effects.ts +0 -11
  563. package/src/tools/skills/execute.ts +2 -2
  564. package/src/tools/skills/sandbox-runner.ts +5 -2
  565. package/src/tools/terminal/backends/native.ts +51 -2
  566. package/src/tools/terminal/safe-env.ts +3 -2
  567. package/src/tools/terminal/shell.ts +1 -0
  568. package/src/tools/tool-manifest.ts +6 -21
  569. package/src/tools/types.ts +12 -3
  570. package/src/tools/verification-control-plane-policy.ts +1 -1
  571. package/src/tts/__tests__/provider-adapters.test.ts +240 -13
  572. package/src/tts/provider-catalog.ts +18 -0
  573. package/src/tts/providers/index.ts +2 -0
  574. package/src/tts/providers/xai-provider.ts +224 -0
  575. package/src/tts/types.ts +46 -0
  576. package/src/types/tar-stream.d.ts +66 -0
  577. package/src/util/json.ts +17 -0
  578. package/src/util/platform.ts +2 -2
  579. package/src/util/pricing.ts +15 -5
  580. package/src/watcher/engine.ts +1 -1
  581. package/src/watcher/providers/google-calendar.ts +134 -8
  582. package/src/watcher/providers/outlook-calendar.ts +42 -2
  583. package/src/workspace/git-service.ts +23 -4
  584. package/src/workspace/migrations/038-unify-llm-callsite-configs.ts +516 -0
  585. package/src/workspace/migrations/039-drop-legacy-llm-keys.ts +171 -0
  586. package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +154 -0
  587. package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +57 -0
  588. package/src/workspace/migrations/042-fix-backfill-google-gmail-settings-scope.ts +70 -0
  589. package/src/workspace/migrations/043-release-notes-latex-rendering.ts +75 -0
  590. package/src/workspace/migrations/044-bump-stale-provider-stream-timeout.ts +51 -0
  591. package/src/workspace/migrations/045-release-notes-meet-avatar.ts +130 -0
  592. package/src/workspace/migrations/AGENTS.md +1 -1
  593. package/src/workspace/migrations/registry.ts +16 -0
  594. package/src/workspace/provider-commit-message-generator.ts +19 -38
  595. package/src/__tests__/gmail-archive-fallback.test.ts +0 -193
  596. package/src/__tests__/gmail-archive-gate.test.ts +0 -246
  597. package/src/__tests__/gmail-preferences.test.ts +0 -117
  598. package/src/__tests__/outlook-attachments.test.ts +0 -301
  599. package/src/__tests__/outlook-automation-tools.test.ts +0 -425
  600. package/src/__tests__/outlook-categories.test.ts +0 -212
  601. package/src/__tests__/outlook-compose-tools.test.ts +0 -325
  602. package/src/__tests__/outlook-declutter-tools.test.ts +0 -585
  603. package/src/__tests__/outlook-follow-up.test.ts +0 -196
  604. package/src/__tests__/outlook-trash.test.ts +0 -77
  605. package/src/__tests__/outlook-unsubscribe.test.ts +0 -279
  606. package/src/__tests__/update-bulletin-format.test.ts +0 -181
  607. package/src/__tests__/update-bulletin-state.test.ts +0 -135
  608. package/src/__tests__/update-bulletin.test.ts +0 -478
  609. package/src/__tests__/update-template-contract.test.ts +0 -29
  610. package/src/cli/commands/doctor.ts +0 -341
  611. package/src/config/bundled-skills/browser/SKILL.md +0 -88
  612. package/src/config/bundled-skills/browser/TOOLS.json +0 -516
  613. package/src/config/bundled-skills/browser/tools/browser-attach.ts +0 -12
  614. package/src/config/bundled-skills/browser/tools/browser-click.ts +0 -12
  615. package/src/config/bundled-skills/browser/tools/browser-close.ts +0 -12
  616. package/src/config/bundled-skills/browser/tools/browser-detach.ts +0 -12
  617. package/src/config/bundled-skills/browser/tools/browser-extract.ts +0 -12
  618. package/src/config/bundled-skills/browser/tools/browser-fill-credential.ts +0 -12
  619. package/src/config/bundled-skills/browser/tools/browser-hover.ts +0 -12
  620. package/src/config/bundled-skills/browser/tools/browser-navigate.ts +0 -12
  621. package/src/config/bundled-skills/browser/tools/browser-press-key.ts +0 -12
  622. package/src/config/bundled-skills/browser/tools/browser-screenshot.ts +0 -12
  623. package/src/config/bundled-skills/browser/tools/browser-scroll.ts +0 -12
  624. package/src/config/bundled-skills/browser/tools/browser-select-option.ts +0 -12
  625. package/src/config/bundled-skills/browser/tools/browser-snapshot.ts +0 -12
  626. package/src/config/bundled-skills/browser/tools/browser-status.ts +0 -12
  627. package/src/config/bundled-skills/browser/tools/browser-type.ts +0 -12
  628. package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +0 -49
  629. package/src/config/bundled-skills/browser/tools/browser-wait-for.ts +0 -12
  630. package/src/config/bundled-skills/chatgpt-import/SKILL.md +0 -27
  631. package/src/config/bundled-skills/chatgpt-import/TOOLS.json +0 -27
  632. package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +0 -378
  633. package/src/config/bundled-skills/gmail/SKILL.md +0 -221
  634. package/src/config/bundled-skills/gmail/TOOLS.json +0 -588
  635. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +0 -256
  636. package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +0 -112
  637. package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +0 -44
  638. package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +0 -81
  639. package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +0 -108
  640. package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +0 -146
  641. package/src/config/bundled-skills/gmail/tools/gmail-label.ts +0 -53
  642. package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +0 -347
  643. package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +0 -59
  644. package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +0 -82
  645. package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +0 -26
  646. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +0 -347
  647. package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +0 -29
  648. package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +0 -122
  649. package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +0 -67
  650. package/src/config/bundled-skills/gmail/tools/scan-result-store.ts +0 -100
  651. package/src/config/bundled-skills/gmail/tools/shared.ts +0 -47
  652. package/src/config/bundled-skills/google-calendar/SKILL.md +0 -51
  653. package/src/config/bundled-skills/google-calendar/TOOLS.json +0 -226
  654. package/src/config/bundled-skills/google-calendar/calendar-client.ts +0 -223
  655. package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +0 -27
  656. package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +0 -48
  657. package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +0 -19
  658. package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +0 -36
  659. package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +0 -58
  660. package/src/config/bundled-skills/google-calendar/tools/shared.ts +0 -17
  661. package/src/config/bundled-skills/google-calendar/types.ts +0 -97
  662. package/src/config/bundled-skills/outlook/SKILL.md +0 -196
  663. package/src/config/bundled-skills/outlook/TOOLS.json +0 -530
  664. package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +0 -85
  665. package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +0 -77
  666. package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +0 -84
  667. package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +0 -94
  668. package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +0 -49
  669. package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +0 -237
  670. package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +0 -161
  671. package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +0 -32
  672. package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +0 -272
  673. package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +0 -29
  674. package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +0 -129
  675. package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +0 -87
  676. package/src/config/bundled-skills/outlook/tools/shared.ts +0 -20
  677. package/src/config/bundled-skills/outlook-calendar/SKILL.md +0 -51
  678. package/src/config/bundled-skills/outlook-calendar/TOOLS.json +0 -221
  679. package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +0 -252
  680. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +0 -53
  681. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +0 -74
  682. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +0 -18
  683. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +0 -46
  684. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +0 -36
  685. package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +0 -17
  686. package/src/config/bundled-skills/outlook-calendar/types.ts +0 -120
  687. package/src/config/bundled-skills/slack/SKILL.md +0 -108
  688. package/src/config/bundled-skills/tasks/SKILL.md +0 -37
  689. package/src/config/bundled-skills/tasks/TOOLS.json +0 -353
  690. package/src/config/bundled-skills/tasks/icon.svg +0 -34
  691. package/src/config/bundled-skills/tasks/tools/task-delete.ts +0 -12
  692. package/src/config/bundled-skills/tasks/tools/task-list-add.ts +0 -12
  693. package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +0 -12
  694. package/src/config/bundled-skills/tasks/tools/task-list-show.ts +0 -12
  695. package/src/config/bundled-skills/tasks/tools/task-list-update.ts +0 -12
  696. package/src/config/bundled-skills/tasks/tools/task-list.ts +0 -12
  697. package/src/config/bundled-skills/tasks/tools/task-queue-run.ts +0 -12
  698. package/src/config/bundled-skills/tasks/tools/task-run.ts +0 -12
  699. package/src/config/bundled-skills/tasks/tools/task-save.ts +0 -12
  700. package/src/config/bundled-skills/watcher/SKILL.md +0 -31
  701. package/src/config/bundled-skills/watcher/TOOLS.json +0 -167
  702. package/src/config/bundled-skills/watcher/tools/watcher-create.ts +0 -12
  703. package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +0 -12
  704. package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +0 -12
  705. package/src/config/bundled-skills/watcher/tools/watcher-list.ts +0 -12
  706. package/src/config/bundled-skills/watcher/tools/watcher-update.ts +0 -12
  707. package/src/prompts/templates/UPDATES.md +0 -50
  708. package/src/prompts/update-bulletin-format.ts +0 -85
  709. package/src/prompts/update-bulletin-state.ts +0 -58
  710. package/src/prompts/update-bulletin-template-path.ts +0 -13
  711. package/src/prompts/update-bulletin.ts +0 -139
  712. package/src/shared/provider-env-vars.ts +0 -19
  713. package/src/tools/watcher/create.ts +0 -86
  714. package/src/tools/watcher/delete.ts +0 -36
  715. package/src/tools/watcher/digest.ts +0 -54
  716. package/src/tools/watcher/list.ts +0 -83
  717. package/src/tools/watcher/update.ts +0 -71
@@ -35,6 +35,14 @@ let mockDeepgramConfig = {
35
35
  format: "mp3" as "mp3" | "wav" | "opus",
36
36
  };
37
37
 
38
+ let mockXaiConfig = {
39
+ voiceId: "eve",
40
+ language: "auto",
41
+ format: "mp3" as "mp3" | "wav",
42
+ sampleRate: 24000,
43
+ bitRate: 128000,
44
+ };
45
+
38
46
  mock.module("../../config/loader.js", () => ({
39
47
  getConfig: () => ({
40
48
  services: {
@@ -43,6 +51,7 @@ mock.module("../../config/loader.js", () => ({
43
51
  elevenlabs: mockElevenLabsConfig,
44
52
  "fish-audio": mockFishAudioConfig,
45
53
  deepgram: mockDeepgramConfig,
54
+ xai: mockXaiConfig,
46
55
  },
47
56
  },
48
57
  },
@@ -53,9 +62,13 @@ mock.module("../../config/loader.js", () => ({
53
62
 
54
63
  let mockApiKey: string | null = "test-elevenlabs-api-key";
55
64
  let mockDeepgramApiKey: string | null = "test-deepgram-api-key";
65
+ let mockXaiApiKey: string | null = "test-xai-api-key";
56
66
 
57
67
  mock.module("../../security/secure-keys.js", () => ({
58
- getSecureKeyAsync: async () => mockApiKey,
68
+ getSecureKeyAsync: async (key?: string) => {
69
+ if (key === "credential/xai/api_key") return mockXaiApiKey;
70
+ return mockApiKey;
71
+ },
59
72
  getProviderKeyAsync: async (provider: string) => {
60
73
  if (provider === "deepgram") return mockDeepgramApiKey;
61
74
  return mockApiKey;
@@ -110,6 +123,7 @@ import {
110
123
  _resetBuiltinRegistration,
111
124
  registerBuiltinTtsProviders,
112
125
  } from "../providers/register-builtins.js";
126
+ import { createXaiProvider, XaiTtsError } from "../providers/xai-provider.js";
113
127
  import type { TtsSynthesisRequest } from "../types.js";
114
128
 
115
129
  // ---------------------------------------------------------------------------
@@ -141,6 +155,14 @@ beforeEach(() => {
141
155
  model: "aura-asteria-en",
142
156
  format: "mp3",
143
157
  };
158
+ mockXaiApiKey = "test-xai-api-key";
159
+ mockXaiConfig = {
160
+ voiceId: "eve",
161
+ language: "auto",
162
+ format: "mp3",
163
+ sampleRate: 24000,
164
+ bitRate: 128000,
165
+ };
144
166
  mockSynthesizeWithFishAudio.mockClear();
145
167
  });
146
168
 
@@ -759,32 +781,237 @@ describe("Deepgram TTS provider adapter", () => {
759
781
  });
760
782
  });
761
783
 
784
+ // ===========================================================================
785
+ // xAI TTS provider adapter
786
+ // ===========================================================================
787
+
788
+ describe("xAI TTS provider adapter", () => {
789
+ // -- Interface conformance -----------------------------------------------
790
+
791
+ test("has correct provider ID", () => {
792
+ const provider = createXaiProvider();
793
+ expect(provider.id).toBe("xai");
794
+ });
795
+
796
+ test("advertises mp3 and wav format support without streaming", () => {
797
+ const provider = createXaiProvider();
798
+ expect(provider.capabilities).toEqual({
799
+ supportsStreaming: false,
800
+ supportedFormats: ["mp3", "wav"],
801
+ });
802
+ });
803
+
804
+ // -- Request mapping -----------------------------------------------------
805
+
806
+ test("synthesize posts to /v1/tts with correct auth and default body", async () => {
807
+ const audioPayload = new Uint8Array([0x49, 0x44, 0x33]);
808
+ let capturedUrl = "";
809
+ let capturedHeaders: Headers | null = null;
810
+ let capturedBody = "";
811
+
812
+ globalThis.fetch = mock(
813
+ async (input: RequestInfo | URL, init?: RequestInit) => {
814
+ capturedUrl = typeof input === "string" ? input : input.toString();
815
+ capturedHeaders = new Headers(init?.headers);
816
+ capturedBody = init?.body as string;
817
+ return new Response(audioPayload, {
818
+ status: 200,
819
+ headers: { "Content-Type": "audio/mpeg" },
820
+ });
821
+ },
822
+ ) as unknown as typeof globalThis.fetch;
823
+
824
+ const provider = createXaiProvider();
825
+ await provider.synthesize(makeRequest());
826
+
827
+ expect(capturedUrl).toBe("https://api.x.ai/v1/tts");
828
+ expect(capturedHeaders!.get("Authorization")).toBe(
829
+ "Bearer test-xai-api-key",
830
+ );
831
+ expect(capturedHeaders!.get("Content-Type")).toBe("application/json");
832
+
833
+ const body = JSON.parse(capturedBody);
834
+ expect(body.text).toBe("Hello world");
835
+ expect(body.voice_id).toBe("eve");
836
+ expect(body.language).toBe("auto");
837
+ expect(body.output_format).toEqual({
838
+ codec: "mp3",
839
+ sample_rate: 24000,
840
+ bit_rate: 128000,
841
+ });
842
+ });
843
+
844
+ test("request voiceId overrides config voiceId", async () => {
845
+ const audioPayload = new Uint8Array([0x49, 0x44, 0x33]);
846
+ let capturedBody = "";
847
+
848
+ globalThis.fetch = mock(
849
+ async (_input: RequestInfo | URL, init?: RequestInit) => {
850
+ capturedBody = init?.body as string;
851
+ return new Response(audioPayload, { status: 200 });
852
+ },
853
+ ) as unknown as typeof globalThis.fetch;
854
+
855
+ const provider = createXaiProvider();
856
+ await provider.synthesize(makeRequest({ voiceId: "rex" }));
857
+
858
+ const body = JSON.parse(capturedBody);
859
+ expect(body.voice_id).toBe("rex");
860
+ });
861
+
862
+ test("uses configured voiceId when request has none", async () => {
863
+ mockXaiConfig.voiceId = "ara";
864
+ const audioPayload = new Uint8Array([0x49, 0x44, 0x33]);
865
+ let capturedBody = "";
866
+
867
+ globalThis.fetch = mock(
868
+ async (_input: RequestInfo | URL, init?: RequestInit) => {
869
+ capturedBody = init?.body as string;
870
+ return new Response(audioPayload, { status: 200 });
871
+ },
872
+ ) as unknown as typeof globalThis.fetch;
873
+
874
+ const provider = createXaiProvider();
875
+ await provider.synthesize(makeRequest());
876
+
877
+ const body = JSON.parse(capturedBody);
878
+ expect(body.voice_id).toBe("ara");
879
+ });
880
+
881
+ test("wav config format produces codec=wav without bit_rate", async () => {
882
+ mockXaiConfig.format = "wav";
883
+ const audioPayload = new Uint8Array([0x52, 0x49, 0x46, 0x46]);
884
+ let capturedBody = "";
885
+
886
+ globalThis.fetch = mock(
887
+ async (_input: RequestInfo | URL, init?: RequestInit) => {
888
+ capturedBody = init?.body as string;
889
+ return new Response(audioPayload, { status: 200 });
890
+ },
891
+ ) as unknown as typeof globalThis.fetch;
892
+
893
+ const provider = createXaiProvider();
894
+ const result = await provider.synthesize(makeRequest());
895
+
896
+ const body = JSON.parse(capturedBody);
897
+ expect(body.output_format).toEqual({
898
+ codec: "wav",
899
+ sample_rate: 24000,
900
+ });
901
+ expect(body.output_format.bit_rate).toBeUndefined();
902
+ expect(result.contentType).toBe("audio/wav");
903
+ });
904
+
905
+ test("outputFormat=pcm uses codec=pcm and 16 kHz sample rate", async () => {
906
+ const audioPayload = new Uint8Array([0x00, 0x01, 0x02]);
907
+ let capturedBody = "";
908
+
909
+ globalThis.fetch = mock(
910
+ async (_input: RequestInfo | URL, init?: RequestInit) => {
911
+ capturedBody = init?.body as string;
912
+ return new Response(audioPayload, { status: 200 });
913
+ },
914
+ ) as unknown as typeof globalThis.fetch;
915
+
916
+ const provider = createXaiProvider();
917
+ const result = await provider.synthesize(
918
+ makeRequest({ outputFormat: "pcm" }),
919
+ );
920
+
921
+ const body = JSON.parse(capturedBody);
922
+ expect(body.output_format).toEqual({
923
+ codec: "pcm",
924
+ sample_rate: 16000,
925
+ });
926
+ expect(body.output_format.bit_rate).toBeUndefined();
927
+ expect(result.contentType).toBe("audio/pcm");
928
+ });
929
+
930
+ // -- Content type / format -----------------------------------------------
931
+
932
+ test("returns audio/mpeg content type for mp3 format", async () => {
933
+ const audioPayload = new Uint8Array([0x49, 0x44, 0x33]);
934
+ mockFetchReturning(audioPayload);
935
+
936
+ const provider = createXaiProvider();
937
+ const result = await provider.synthesize(makeRequest());
938
+
939
+ expect(result.contentType).toBe("audio/mpeg");
940
+ expect(result.audio.byteLength).toBeGreaterThan(0);
941
+ });
942
+
943
+ // -- Required config validation ------------------------------------------
944
+
945
+ test("throws XAI_TTS_NO_API_KEY when API key is missing", async () => {
946
+ mockXaiApiKey = null;
947
+
948
+ const provider = createXaiProvider();
949
+
950
+ try {
951
+ await provider.synthesize(makeRequest());
952
+ throw new Error("Expected synthesize to throw");
953
+ } catch (err) {
954
+ expect(err).toBeInstanceOf(XaiTtsError);
955
+ expect((err as XaiTtsError).code).toBe("XAI_TTS_NO_API_KEY");
956
+ expect((err as XaiTtsError).message).toContain("API key not configured");
957
+ }
958
+ });
959
+
960
+ // -- Error handling ------------------------------------------------------
961
+
962
+ test("throws XAI_TTS_HTTP_ERROR on non-200 response", async () => {
963
+ mockFetchError(401, "Unauthorized");
964
+
965
+ const provider = createXaiProvider();
966
+
967
+ try {
968
+ await provider.synthesize(makeRequest());
969
+ throw new Error("Expected synthesize to throw");
970
+ } catch (err) {
971
+ expect(err).toBeInstanceOf(XaiTtsError);
972
+ expect((err as XaiTtsError).code).toBe("XAI_TTS_HTTP_ERROR");
973
+ expect((err as XaiTtsError).statusCode).toBe(401);
974
+ expect((err as XaiTtsError).message).toContain("Unauthorized");
975
+ }
976
+ });
977
+
978
+ test("throws XAI_TTS_EMPTY_RESPONSE on empty audio body", async () => {
979
+ mockFetchReturning(new Uint8Array(0));
980
+
981
+ const provider = createXaiProvider();
982
+
983
+ try {
984
+ await provider.synthesize(makeRequest());
985
+ throw new Error("Expected synthesize to throw");
986
+ } catch (err) {
987
+ expect(err).toBeInstanceOf(XaiTtsError);
988
+ expect((err as XaiTtsError).code).toBe("XAI_TTS_EMPTY_RESPONSE");
989
+ }
990
+ });
991
+ });
992
+
762
993
  // ===========================================================================
763
994
  // Built-in registration
764
995
  // ===========================================================================
765
996
 
766
997
  describe("registerBuiltinTtsProviders", () => {
767
- test("registers elevenlabs, fish-audio, and deepgram providers", () => {
998
+ test("registers every catalog provider ID", () => {
768
999
  registerBuiltinTtsProviders();
769
1000
 
770
1001
  const providers = listTtsProviders();
771
1002
  const ids = providers.map((p) => p.id);
772
- expect(ids).toContain("elevenlabs");
773
- expect(ids).toContain("fish-audio");
774
- expect(ids).toContain("deepgram");
1003
+ for (const id of listCatalogProviderIds()) {
1004
+ expect(ids).toContain(id);
1005
+ }
775
1006
  });
776
1007
 
777
1008
  test("providers are discoverable via getTtsProvider after registration", () => {
778
1009
  registerBuiltinTtsProviders();
779
1010
 
780
- const el = getTtsProvider("elevenlabs");
781
- expect(el.id).toBe("elevenlabs");
782
-
783
- const fa = getTtsProvider("fish-audio");
784
- expect(fa.id).toBe("fish-audio");
785
-
786
- const dg = getTtsProvider("deepgram");
787
- expect(dg.id).toBe("deepgram");
1011
+ for (const id of listCatalogProviderIds()) {
1012
+ const provider = getTtsProvider(id);
1013
+ expect(provider.id).toBe(id);
1014
+ }
788
1015
  });
789
1016
 
790
1017
  test("idempotent — calling twice does not throw", () => {
@@ -158,6 +158,24 @@ const CATALOG: readonly TtsProviderCatalogEntry[] = [
158
158
  },
159
159
  ],
160
160
  },
161
+ {
162
+ id: "xai",
163
+ displayName: "xAI",
164
+ callMode: "synthesized-play",
165
+ allowNativeFallback: false,
166
+ capabilities: {
167
+ supportsStreaming: false,
168
+ supportedFormats: ["mp3", "wav"],
169
+ },
170
+ secretRequirements: [
171
+ {
172
+ credentialStoreKey: "credential/xai/api_key",
173
+ displayName: "xAI API Key",
174
+ setCommand:
175
+ "assistant credentials set --service xai --field api_key <key>",
176
+ },
177
+ ],
178
+ },
161
179
  ] as const;
162
180
 
163
181
  /** Index for O(1) lookup by provider ID. */
@@ -13,6 +13,7 @@ import type { TtsProvider, TtsProviderId } from "../types.js";
13
13
  import { createDeepgramProvider } from "./deepgram-provider.js";
14
14
  import { createElevenLabsProvider } from "./elevenlabs-provider.js";
15
15
  import { createFishAudioProvider } from "./fish-audio-provider.js";
16
+ import { createXaiProvider } from "./xai-provider.js";
16
17
 
17
18
  // ---------------------------------------------------------------------------
18
19
  // Factory type
@@ -39,4 +40,5 @@ export const providerFactories: ReadonlyMap<TtsProviderId, TtsProviderFactory> =
39
40
  ["elevenlabs", createElevenLabsProvider],
40
41
  ["fish-audio", createFishAudioProvider],
41
42
  ["deepgram", createDeepgramProvider],
43
+ ["xai", createXaiProvider],
42
44
  ]);
@@ -0,0 +1,224 @@
1
+ /**
2
+ * xAI TTS provider adapter.
3
+ *
4
+ * Wraps the xAI REST text-to-speech API (`/v1/tts`) behind the uniform
5
+ * {@link TtsProvider} interface. Reads the API key from the secure credential
6
+ * store under `credential/xai/api_key` and the model configuration from the
7
+ * `services.tts.providers.xai` config section.
8
+ */
9
+
10
+ import { getConfig } from "../../config/loader.js";
11
+ import type { TtsXaiProviderConfig } from "../../config/schemas/tts.js";
12
+ import { credentialKey } from "../../security/credential-key.js";
13
+ import { getSecureKeyAsync } from "../../security/secure-keys.js";
14
+ import { getLogger } from "../../util/logger.js";
15
+ import type {
16
+ TtsProvider,
17
+ TtsProviderCapabilities,
18
+ TtsSynthesisRequest,
19
+ TtsSynthesisResult,
20
+ } from "../types.js";
21
+
22
+ const log = getLogger("tts:xai");
23
+
24
+ // ---------------------------------------------------------------------------
25
+ // Error types
26
+ // ---------------------------------------------------------------------------
27
+
28
+ export type XaiTtsErrorCode =
29
+ | "XAI_TTS_NO_API_KEY"
30
+ | "XAI_TTS_HTTP_ERROR"
31
+ | "XAI_TTS_EMPTY_RESPONSE"
32
+ | "XAI_TTS_REQUEST_FAILED";
33
+
34
+ export class XaiTtsError extends Error {
35
+ readonly code: XaiTtsErrorCode;
36
+ readonly statusCode?: number;
37
+
38
+ constructor(code: XaiTtsErrorCode, message: string, statusCode?: number) {
39
+ super(message);
40
+ this.name = "XaiTtsError";
41
+ this.code = code;
42
+ this.statusCode = statusCode;
43
+ }
44
+ }
45
+
46
+ // ---------------------------------------------------------------------------
47
+ // Constants
48
+ // ---------------------------------------------------------------------------
49
+
50
+ const XAI_API_BASE = "https://api.x.ai";
51
+
52
+ /** Map from xAI codec names to MIME content types. */
53
+ const FORMAT_CONTENT_TYPE: Record<string, string> = {
54
+ mp3: "audio/mpeg",
55
+ wav: "audio/wav",
56
+ pcm: "audio/pcm",
57
+ };
58
+
59
+ // ---------------------------------------------------------------------------
60
+ // Provider implementation
61
+ // ---------------------------------------------------------------------------
62
+
63
+ /** Parameters for xAI's `/v1/tts` output_format payload. */
64
+ interface XaiOutputParams {
65
+ /** xAI codec name (`mp3`, `wav`, or `pcm`). */
66
+ codec: string;
67
+ /** Sample rate in Hz. */
68
+ sample_rate: number;
69
+ /** MP3 bit rate. Omitted for non-MP3 codecs. */
70
+ bit_rate?: number;
71
+ /** Content-type key for the FORMAT_CONTENT_TYPE lookup. */
72
+ contentTypeKey: string;
73
+ }
74
+
75
+ /**
76
+ * Resolve the xAI output codec, sample rate, and bit rate based on the
77
+ * synthesis request and provider config.
78
+ *
79
+ * **PCM path** (`outputFormat: "pcm"`):
80
+ * The media-stream transport needs raw headerless PCM for mu-law transcoding.
81
+ * We request `codec=pcm&sample_rate=16000` — matching the ElevenLabs /
82
+ * Deepgram 16 kHz PCM convention and the downstream `audioBufferToFrames`
83
+ * expectation (16 kHz -> 8 kHz downsample).
84
+ *
85
+ * **MP3 path** (`config.format === "mp3"`):
86
+ * Uses the configured sample rate and bit rate.
87
+ *
88
+ * **WAV path** (`config.format === "wav"`):
89
+ * Uses the configured sample rate; bit rate is not meaningful for WAV.
90
+ */
91
+ function resolveOutputParams(
92
+ request: TtsSynthesisRequest,
93
+ config: TtsXaiProviderConfig,
94
+ ): XaiOutputParams {
95
+ if (request.outputFormat === "pcm") {
96
+ return {
97
+ codec: "pcm",
98
+ sample_rate: 16_000,
99
+ contentTypeKey: "pcm",
100
+ };
101
+ }
102
+
103
+ if (config.format === "mp3") {
104
+ return {
105
+ codec: "mp3",
106
+ sample_rate: config.sampleRate,
107
+ bit_rate: config.bitRate,
108
+ contentTypeKey: "mp3",
109
+ };
110
+ }
111
+
112
+ return {
113
+ codec: "wav",
114
+ sample_rate: config.sampleRate,
115
+ contentTypeKey: "wav",
116
+ };
117
+ }
118
+
119
+ /** Resolve the voice ID: request override > config > default. */
120
+ function resolveVoiceId(
121
+ request: TtsSynthesisRequest,
122
+ config: TtsXaiProviderConfig,
123
+ ): string {
124
+ return request.voiceId?.trim() || config.voiceId || "eve";
125
+ }
126
+
127
+ export function createXaiProvider(): TtsProvider {
128
+ const capabilities: TtsProviderCapabilities = {
129
+ supportsStreaming: false,
130
+ supportedFormats: ["mp3", "wav"],
131
+ };
132
+
133
+ return {
134
+ id: "xai",
135
+ capabilities,
136
+
137
+ async synthesize(
138
+ request: TtsSynthesisRequest,
139
+ ): Promise<TtsSynthesisResult> {
140
+ const apiKey = await getSecureKeyAsync(credentialKey("xai", "api_key"));
141
+ if (!apiKey) {
142
+ throw new XaiTtsError(
143
+ "XAI_TTS_NO_API_KEY",
144
+ "xAI API key not configured. " +
145
+ "Add it via: assistant credentials set --service xai --field api_key <key>",
146
+ );
147
+ }
148
+
149
+ const config = getConfig().services.tts.providers.xai;
150
+ const output = resolveOutputParams(request, config);
151
+ const voiceId = resolveVoiceId(request, config);
152
+
153
+ const body = {
154
+ text: request.text,
155
+ voice_id: voiceId,
156
+ language: config.language,
157
+ output_format: {
158
+ codec: output.codec,
159
+ sample_rate: output.sample_rate,
160
+ ...(output.bit_rate ? { bit_rate: output.bit_rate } : {}),
161
+ },
162
+ };
163
+
164
+ log.info(
165
+ {
166
+ voiceId,
167
+ codec: output.codec,
168
+ sampleRate: output.sample_rate,
169
+ textLength: request.text.length,
170
+ },
171
+ "Starting xAI TTS synthesis",
172
+ );
173
+
174
+ let response: Response;
175
+ try {
176
+ response = await fetch(`${XAI_API_BASE}/v1/tts`, {
177
+ method: "POST",
178
+ headers: {
179
+ "Content-Type": "application/json",
180
+ Authorization: `Bearer ${apiKey}`,
181
+ },
182
+ body: JSON.stringify(body),
183
+ signal: request.signal,
184
+ });
185
+ } catch (err) {
186
+ if (err instanceof Error && err.name === "AbortError") throw err;
187
+ throw new XaiTtsError(
188
+ "XAI_TTS_REQUEST_FAILED",
189
+ `xAI TTS request failed: ${err instanceof Error ? err.message : String(err)}`,
190
+ );
191
+ }
192
+
193
+ if (!response.ok) {
194
+ const errorText = await response.text().catch(() => "");
195
+ throw new XaiTtsError(
196
+ "XAI_TTS_HTTP_ERROR",
197
+ `xAI TTS returned ${response.status}: ${errorText}`,
198
+ response.status,
199
+ );
200
+ }
201
+
202
+ const arrayBuffer = await response.arrayBuffer();
203
+ if (arrayBuffer.byteLength === 0) {
204
+ throw new XaiTtsError(
205
+ "XAI_TTS_EMPTY_RESPONSE",
206
+ "xAI TTS returned an empty audio response",
207
+ );
208
+ }
209
+
210
+ const contentType =
211
+ FORMAT_CONTENT_TYPE[output.contentTypeKey] ?? "audio/mpeg";
212
+
213
+ log.debug(
214
+ { bytes: arrayBuffer.byteLength },
215
+ "xAI TTS synthesis complete",
216
+ );
217
+
218
+ return {
219
+ audio: Buffer.from(arrayBuffer),
220
+ contentType,
221
+ };
222
+ },
223
+ };
224
+ }
package/src/tts/types.ts CHANGED
@@ -20,6 +20,7 @@ export type TtsProviderId =
20
20
  | "elevenlabs"
21
21
  | "fish-audio"
22
22
  | "deepgram"
23
+ | "xai"
23
24
  | (string & {});
24
25
 
25
26
  // ---------------------------------------------------------------------------
@@ -99,6 +100,35 @@ export interface TtsSynthesisResult {
99
100
  contentType: string;
100
101
  }
101
102
 
103
+ // ---------------------------------------------------------------------------
104
+ // Alignment / viseme events
105
+ // ---------------------------------------------------------------------------
106
+
107
+ /**
108
+ * Per-phoneme alignment event emitted by TTS providers that expose
109
+ * character- or phoneme-level alignment metadata alongside the audio
110
+ * stream (e.g. ElevenLabs Turbo with alignment).
111
+ *
112
+ * Consumers (e.g. the Meet avatar lip-sync path) map these events to
113
+ * blendshape weights at the rendered timestamp. Providers that do not
114
+ * expose alignment metadata simply never invoke the callback; the
115
+ * caller is expected to fall back to an amplitude-envelope approximation
116
+ * derived from the PCM stream.
117
+ */
118
+ export interface TtsAlignmentEvent {
119
+ /**
120
+ * Phoneme label or character — free-form string that the consumer maps
121
+ * to renderer-specific blendshape weights. Providers typically emit
122
+ * IPA-style phoneme labels, viseme codes, or individual characters
123
+ * depending on their alignment granularity.
124
+ */
125
+ phoneme: string;
126
+ /** Normalized intensity in the range [0, 1]. */
127
+ weight: number;
128
+ /** Milliseconds from the start of the synthesized utterance. */
129
+ timestamp: number;
130
+ }
131
+
102
132
  // ---------------------------------------------------------------------------
103
133
  // Provider capabilities
104
134
  // ---------------------------------------------------------------------------
@@ -110,6 +140,15 @@ export interface TtsProviderCapabilities {
110
140
 
111
141
  /** Audio formats the provider can produce (e.g. `["mp3", "wav", "opus"]`). */
112
142
  supportedFormats: string[];
143
+
144
+ /**
145
+ * Whether the provider can emit {@link TtsAlignmentEvent}s via the optional
146
+ * `onAlignment` callback of `synthesizeStream`. Consumers use this to pick
147
+ * between a viseme-driven lip-sync path and an RMS-amplitude fallback.
148
+ *
149
+ * Optional for backwards compatibility — treat `undefined` as `false`.
150
+ */
151
+ alignment?: boolean;
113
152
  }
114
153
 
115
154
  // ---------------------------------------------------------------------------
@@ -145,9 +184,16 @@ export interface TtsProvider {
145
184
  * The `onChunk` callback is invoked with each audio chunk as it arrives
146
185
  * from the upstream provider. The returned promise resolves with the
147
186
  * complete concatenated result once all chunks have been delivered.
187
+ *
188
+ * Providers that advertise `capabilities.alignment === true` also invoke
189
+ * the optional `onAlignment` callback with per-phoneme alignment events
190
+ * interleaved with the audio chunks. Providers that don't support
191
+ * alignment simply never call it; callers must tolerate a silent
192
+ * channel and fall back to amplitude-based heuristics.
148
193
  */
149
194
  synthesizeStream?(
150
195
  request: TtsSynthesisRequest,
151
196
  onChunk: (chunk: Uint8Array) => void,
197
+ onAlignment?: (event: TtsAlignmentEvent) => void,
152
198
  ): Promise<TtsSynthesisResult>;
153
199
  }