cowork-os 0.3.21

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 (526) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1638 -0
  3. package/bin/cowork.js +42 -0
  4. package/build/entitlements.mac.plist +16 -0
  5. package/build/icon.icns +0 -0
  6. package/build/icon.png +0 -0
  7. package/dist/electron/electron/activity/ActivityRepository.js +190 -0
  8. package/dist/electron/electron/agent/browser/browser-service.js +639 -0
  9. package/dist/electron/electron/agent/context-manager.js +225 -0
  10. package/dist/electron/electron/agent/custom-skill-loader.js +566 -0
  11. package/dist/electron/electron/agent/daemon.js +975 -0
  12. package/dist/electron/electron/agent/executor.js +3561 -0
  13. package/dist/electron/electron/agent/llm/anthropic-provider.js +155 -0
  14. package/dist/electron/electron/agent/llm/bedrock-provider.js +202 -0
  15. package/dist/electron/electron/agent/llm/gemini-provider.js +375 -0
  16. package/dist/electron/electron/agent/llm/index.js +34 -0
  17. package/dist/electron/electron/agent/llm/ollama-provider.js +263 -0
  18. package/dist/electron/electron/agent/llm/openai-oauth.js +101 -0
  19. package/dist/electron/electron/agent/llm/openai-provider.js +657 -0
  20. package/dist/electron/electron/agent/llm/openrouter-provider.js +232 -0
  21. package/dist/electron/electron/agent/llm/pricing.js +160 -0
  22. package/dist/electron/electron/agent/llm/provider-factory.js +880 -0
  23. package/dist/electron/electron/agent/llm/types.js +178 -0
  24. package/dist/electron/electron/agent/queue-manager.js +378 -0
  25. package/dist/electron/electron/agent/sandbox/docker-sandbox.js +402 -0
  26. package/dist/electron/electron/agent/sandbox/macos-sandbox.js +407 -0
  27. package/dist/electron/electron/agent/sandbox/runner.js +410 -0
  28. package/dist/electron/electron/agent/sandbox/sandbox-factory.js +228 -0
  29. package/dist/electron/electron/agent/sandbox/security-utils.js +258 -0
  30. package/dist/electron/electron/agent/search/brave-provider.js +119 -0
  31. package/dist/electron/electron/agent/search/google-provider.js +100 -0
  32. package/dist/electron/electron/agent/search/index.js +28 -0
  33. package/dist/electron/electron/agent/search/provider-factory.js +395 -0
  34. package/dist/electron/electron/agent/search/serpapi-provider.js +112 -0
  35. package/dist/electron/electron/agent/search/tavily-provider.js +90 -0
  36. package/dist/electron/electron/agent/search/types.js +40 -0
  37. package/dist/electron/electron/agent/security/index.js +12 -0
  38. package/dist/electron/electron/agent/security/input-sanitizer.js +303 -0
  39. package/dist/electron/electron/agent/security/output-filter.js +217 -0
  40. package/dist/electron/electron/agent/skill-eligibility.js +281 -0
  41. package/dist/electron/electron/agent/skill-registry.js +396 -0
  42. package/dist/electron/electron/agent/skills/document.js +878 -0
  43. package/dist/electron/electron/agent/skills/image-generator.js +225 -0
  44. package/dist/electron/electron/agent/skills/organizer.js +141 -0
  45. package/dist/electron/electron/agent/skills/presentation.js +367 -0
  46. package/dist/electron/electron/agent/skills/spreadsheet.js +165 -0
  47. package/dist/electron/electron/agent/tools/browser-tools.js +523 -0
  48. package/dist/electron/electron/agent/tools/builtin-settings.js +384 -0
  49. package/dist/electron/electron/agent/tools/canvas-tools.js +530 -0
  50. package/dist/electron/electron/agent/tools/cron-tools.js +577 -0
  51. package/dist/electron/electron/agent/tools/edit-tools.js +194 -0
  52. package/dist/electron/electron/agent/tools/file-tools.js +719 -0
  53. package/dist/electron/electron/agent/tools/glob-tools.js +283 -0
  54. package/dist/electron/electron/agent/tools/grep-tools.js +387 -0
  55. package/dist/electron/electron/agent/tools/image-tools.js +111 -0
  56. package/dist/electron/electron/agent/tools/mention-tools.js +282 -0
  57. package/dist/electron/electron/agent/tools/node-tools.js +476 -0
  58. package/dist/electron/electron/agent/tools/registry.js +2719 -0
  59. package/dist/electron/electron/agent/tools/search-tools.js +91 -0
  60. package/dist/electron/electron/agent/tools/shell-tools.js +574 -0
  61. package/dist/electron/electron/agent/tools/skill-tools.js +274 -0
  62. package/dist/electron/electron/agent/tools/system-tools.js +578 -0
  63. package/dist/electron/electron/agent/tools/web-fetch-tools.js +444 -0
  64. package/dist/electron/electron/agent/tools/x-tools.js +264 -0
  65. package/dist/electron/electron/agents/AgentRoleRepository.js +420 -0
  66. package/dist/electron/electron/agents/HeartbeatService.js +356 -0
  67. package/dist/electron/electron/agents/MentionRepository.js +197 -0
  68. package/dist/electron/electron/agents/TaskSubscriptionRepository.js +168 -0
  69. package/dist/electron/electron/agents/WorkingStateRepository.js +229 -0
  70. package/dist/electron/electron/canvas/canvas-manager.js +714 -0
  71. package/dist/electron/electron/canvas/canvas-preload.js +53 -0
  72. package/dist/electron/electron/canvas/canvas-protocol.js +195 -0
  73. package/dist/electron/electron/canvas/canvas-store.js +174 -0
  74. package/dist/electron/electron/canvas/index.js +13 -0
  75. package/dist/electron/electron/control-plane/client.js +364 -0
  76. package/dist/electron/electron/control-plane/handlers.js +572 -0
  77. package/dist/electron/electron/control-plane/index.js +41 -0
  78. package/dist/electron/electron/control-plane/node-manager.js +264 -0
  79. package/dist/electron/electron/control-plane/protocol.js +194 -0
  80. package/dist/electron/electron/control-plane/remote-client.js +437 -0
  81. package/dist/electron/electron/control-plane/server.js +640 -0
  82. package/dist/electron/electron/control-plane/settings.js +369 -0
  83. package/dist/electron/electron/control-plane/ssh-tunnel.js +549 -0
  84. package/dist/electron/electron/cron/index.js +30 -0
  85. package/dist/electron/electron/cron/schedule.js +190 -0
  86. package/dist/electron/electron/cron/service.js +614 -0
  87. package/dist/electron/electron/cron/store.js +155 -0
  88. package/dist/electron/electron/cron/types.js +82 -0
  89. package/dist/electron/electron/cron/webhook.js +258 -0
  90. package/dist/electron/electron/database/SecureSettingsRepository.js +444 -0
  91. package/dist/electron/electron/database/TaskLabelRepository.js +120 -0
  92. package/dist/electron/electron/database/repositories.js +1781 -0
  93. package/dist/electron/electron/database/schema.js +978 -0
  94. package/dist/electron/electron/extensions/index.js +33 -0
  95. package/dist/electron/electron/extensions/loader.js +313 -0
  96. package/dist/electron/electron/extensions/registry.js +485 -0
  97. package/dist/electron/electron/extensions/types.js +11 -0
  98. package/dist/electron/electron/gateway/channel-registry.js +1102 -0
  99. package/dist/electron/electron/gateway/channels/bluebubbles-client.js +479 -0
  100. package/dist/electron/electron/gateway/channels/bluebubbles.js +432 -0
  101. package/dist/electron/electron/gateway/channels/discord.js +975 -0
  102. package/dist/electron/electron/gateway/channels/email-client.js +593 -0
  103. package/dist/electron/electron/gateway/channels/email.js +443 -0
  104. package/dist/electron/electron/gateway/channels/google-chat.js +631 -0
  105. package/dist/electron/electron/gateway/channels/imessage-client.js +363 -0
  106. package/dist/electron/electron/gateway/channels/imessage.js +465 -0
  107. package/dist/electron/electron/gateway/channels/index.js +36 -0
  108. package/dist/electron/electron/gateway/channels/line-client.js +470 -0
  109. package/dist/electron/electron/gateway/channels/line.js +479 -0
  110. package/dist/electron/electron/gateway/channels/matrix-client.js +432 -0
  111. package/dist/electron/electron/gateway/channels/matrix.js +592 -0
  112. package/dist/electron/electron/gateway/channels/mattermost-client.js +394 -0
  113. package/dist/electron/electron/gateway/channels/mattermost.js +496 -0
  114. package/dist/electron/electron/gateway/channels/signal-client.js +500 -0
  115. package/dist/electron/electron/gateway/channels/signal.js +582 -0
  116. package/dist/electron/electron/gateway/channels/slack.js +415 -0
  117. package/dist/electron/electron/gateway/channels/teams.js +596 -0
  118. package/dist/electron/electron/gateway/channels/telegram.js +1390 -0
  119. package/dist/electron/electron/gateway/channels/twitch-client.js +502 -0
  120. package/dist/electron/electron/gateway/channels/twitch.js +396 -0
  121. package/dist/electron/electron/gateway/channels/types.js +8 -0
  122. package/dist/electron/electron/gateway/channels/whatsapp.js +953 -0
  123. package/dist/electron/electron/gateway/context-policy.js +268 -0
  124. package/dist/electron/electron/gateway/index.js +1063 -0
  125. package/dist/electron/electron/gateway/infrastructure.js +496 -0
  126. package/dist/electron/electron/gateway/router.js +2700 -0
  127. package/dist/electron/electron/gateway/security.js +375 -0
  128. package/dist/electron/electron/gateway/session.js +115 -0
  129. package/dist/electron/electron/gateway/tunnel.js +503 -0
  130. package/dist/electron/electron/guardrails/guardrail-manager.js +348 -0
  131. package/dist/electron/electron/hooks/gmail-watcher.js +300 -0
  132. package/dist/electron/electron/hooks/index.js +46 -0
  133. package/dist/electron/electron/hooks/mappings.js +381 -0
  134. package/dist/electron/electron/hooks/server.js +480 -0
  135. package/dist/electron/electron/hooks/settings.js +447 -0
  136. package/dist/electron/electron/hooks/types.js +41 -0
  137. package/dist/electron/electron/ipc/canvas-handlers.js +158 -0
  138. package/dist/electron/electron/ipc/handlers.js +3138 -0
  139. package/dist/electron/electron/ipc/mission-control-handlers.js +141 -0
  140. package/dist/electron/electron/main.js +448 -0
  141. package/dist/electron/electron/mcp/client/MCPClientManager.js +330 -0
  142. package/dist/electron/electron/mcp/client/MCPServerConnection.js +437 -0
  143. package/dist/electron/electron/mcp/client/transports/SSETransport.js +304 -0
  144. package/dist/electron/electron/mcp/client/transports/StdioTransport.js +307 -0
  145. package/dist/electron/electron/mcp/client/transports/WebSocketTransport.js +329 -0
  146. package/dist/electron/electron/mcp/host/MCPHostServer.js +354 -0
  147. package/dist/electron/electron/mcp/host/ToolAdapter.js +100 -0
  148. package/dist/electron/electron/mcp/registry/MCPRegistryManager.js +497 -0
  149. package/dist/electron/electron/mcp/settings.js +446 -0
  150. package/dist/electron/electron/mcp/types.js +59 -0
  151. package/dist/electron/electron/memory/MemoryService.js +435 -0
  152. package/dist/electron/electron/notifications/index.js +17 -0
  153. package/dist/electron/electron/notifications/service.js +118 -0
  154. package/dist/electron/electron/notifications/store.js +144 -0
  155. package/dist/electron/electron/preload.js +842 -0
  156. package/dist/electron/electron/reports/StandupReportService.js +272 -0
  157. package/dist/electron/electron/security/concurrency.js +293 -0
  158. package/dist/electron/electron/security/index.js +15 -0
  159. package/dist/electron/electron/security/policy-manager.js +435 -0
  160. package/dist/electron/electron/settings/appearance-manager.js +193 -0
  161. package/dist/electron/electron/settings/personality-manager.js +724 -0
  162. package/dist/electron/electron/settings/x-manager.js +58 -0
  163. package/dist/electron/electron/tailscale/exposure.js +188 -0
  164. package/dist/electron/electron/tailscale/index.js +28 -0
  165. package/dist/electron/electron/tailscale/settings.js +205 -0
  166. package/dist/electron/electron/tailscale/tailscale.js +355 -0
  167. package/dist/electron/electron/tray/QuickInputWindow.js +568 -0
  168. package/dist/electron/electron/tray/TrayManager.js +895 -0
  169. package/dist/electron/electron/tray/index.js +9 -0
  170. package/dist/electron/electron/updater/index.js +6 -0
  171. package/dist/electron/electron/updater/update-manager.js +418 -0
  172. package/dist/electron/electron/utils/env-migration.js +209 -0
  173. package/dist/electron/electron/utils/process.js +102 -0
  174. package/dist/electron/electron/utils/rate-limiter.js +104 -0
  175. package/dist/electron/electron/utils/validation.js +419 -0
  176. package/dist/electron/electron/utils/x-cli.js +177 -0
  177. package/dist/electron/electron/voice/VoiceService.js +507 -0
  178. package/dist/electron/electron/voice/index.js +14 -0
  179. package/dist/electron/electron/voice/voice-settings-manager.js +359 -0
  180. package/dist/electron/shared/channelMessages.js +170 -0
  181. package/dist/electron/shared/types.js +1185 -0
  182. package/package.json +159 -0
  183. package/resources/skills/1password.json +10 -0
  184. package/resources/skills/add-documentation.json +31 -0
  185. package/resources/skills/analyze-csv.json +17 -0
  186. package/resources/skills/apple-notes.json +10 -0
  187. package/resources/skills/apple-reminders.json +10 -0
  188. package/resources/skills/auto-commenter.json +10 -0
  189. package/resources/skills/bear-notes.json +10 -0
  190. package/resources/skills/bird.json +35 -0
  191. package/resources/skills/blogwatcher.json +10 -0
  192. package/resources/skills/blucli.json +10 -0
  193. package/resources/skills/bluebubbles.json +10 -0
  194. package/resources/skills/camsnap.json +10 -0
  195. package/resources/skills/clean-imports.json +18 -0
  196. package/resources/skills/code-review.json +18 -0
  197. package/resources/skills/coding-agent.json +10 -0
  198. package/resources/skills/compare-files.json +23 -0
  199. package/resources/skills/convert-code.json +34 -0
  200. package/resources/skills/create-changelog.json +24 -0
  201. package/resources/skills/debug-error.json +17 -0
  202. package/resources/skills/dependency-check.json +10 -0
  203. package/resources/skills/discord.json +10 -0
  204. package/resources/skills/eightctl.json +10 -0
  205. package/resources/skills/explain-code.json +29 -0
  206. package/resources/skills/extract-todos.json +18 -0
  207. package/resources/skills/food-order.json +10 -0
  208. package/resources/skills/gemini.json +10 -0
  209. package/resources/skills/generate-readme.json +10 -0
  210. package/resources/skills/gifgrep.json +10 -0
  211. package/resources/skills/git-commit.json +10 -0
  212. package/resources/skills/github.json +10 -0
  213. package/resources/skills/gog.json +10 -0
  214. package/resources/skills/goplaces.json +10 -0
  215. package/resources/skills/himalaya.json +10 -0
  216. package/resources/skills/imsg.json +10 -0
  217. package/resources/skills/karpathy-guidelines.json +12 -0
  218. package/resources/skills/last30days.json +26 -0
  219. package/resources/skills/local-places.json +10 -0
  220. package/resources/skills/mcporter.json +10 -0
  221. package/resources/skills/model-usage.json +10 -0
  222. package/resources/skills/nano-banana-pro.json +10 -0
  223. package/resources/skills/nano-pdf.json +10 -0
  224. package/resources/skills/notion.json +10 -0
  225. package/resources/skills/obsidian.json +10 -0
  226. package/resources/skills/openai-image-gen.json +10 -0
  227. package/resources/skills/openai-whisper-api.json +10 -0
  228. package/resources/skills/openai-whisper.json +10 -0
  229. package/resources/skills/openhue.json +10 -0
  230. package/resources/skills/oracle.json +10 -0
  231. package/resources/skills/ordercli.json +10 -0
  232. package/resources/skills/peekaboo.json +10 -0
  233. package/resources/skills/project-structure.json +10 -0
  234. package/resources/skills/proofread.json +17 -0
  235. package/resources/skills/refactor-code.json +31 -0
  236. package/resources/skills/rename-symbol.json +23 -0
  237. package/resources/skills/sag.json +10 -0
  238. package/resources/skills/security-audit.json +18 -0
  239. package/resources/skills/session-logs.json +10 -0
  240. package/resources/skills/sherpa-onnx-tts.json +10 -0
  241. package/resources/skills/skill-creator.json +15 -0
  242. package/resources/skills/skill-hub.json +29 -0
  243. package/resources/skills/slack.json +10 -0
  244. package/resources/skills/songsee.json +10 -0
  245. package/resources/skills/sonoscli.json +10 -0
  246. package/resources/skills/spotify-player.json +10 -0
  247. package/resources/skills/startup-cfo.json +55 -0
  248. package/resources/skills/summarize-folder.json +18 -0
  249. package/resources/skills/summarize.json +10 -0
  250. package/resources/skills/things-mac.json +10 -0
  251. package/resources/skills/tmux.json +10 -0
  252. package/resources/skills/translate.json +36 -0
  253. package/resources/skills/trello.json +10 -0
  254. package/resources/skills/video-frames.json +10 -0
  255. package/resources/skills/voice-call.json +10 -0
  256. package/resources/skills/wacli.json +10 -0
  257. package/resources/skills/weather.json +10 -0
  258. package/resources/skills/write-tests.json +31 -0
  259. package/src/electron/activity/ActivityRepository.ts +238 -0
  260. package/src/electron/agent/browser/browser-service.ts +721 -0
  261. package/src/electron/agent/context-manager.ts +257 -0
  262. package/src/electron/agent/custom-skill-loader.ts +634 -0
  263. package/src/electron/agent/daemon.ts +1097 -0
  264. package/src/electron/agent/executor.ts +4017 -0
  265. package/src/electron/agent/llm/anthropic-provider.ts +175 -0
  266. package/src/electron/agent/llm/bedrock-provider.ts +236 -0
  267. package/src/electron/agent/llm/gemini-provider.ts +422 -0
  268. package/src/electron/agent/llm/index.ts +9 -0
  269. package/src/electron/agent/llm/ollama-provider.ts +347 -0
  270. package/src/electron/agent/llm/openai-oauth.ts +127 -0
  271. package/src/electron/agent/llm/openai-provider.ts +686 -0
  272. package/src/electron/agent/llm/openrouter-provider.ts +273 -0
  273. package/src/electron/agent/llm/pricing.ts +180 -0
  274. package/src/electron/agent/llm/provider-factory.ts +971 -0
  275. package/src/electron/agent/llm/types.ts +291 -0
  276. package/src/electron/agent/queue-manager.ts +408 -0
  277. package/src/electron/agent/sandbox/docker-sandbox.ts +453 -0
  278. package/src/electron/agent/sandbox/macos-sandbox.ts +426 -0
  279. package/src/electron/agent/sandbox/runner.ts +453 -0
  280. package/src/electron/agent/sandbox/sandbox-factory.ts +337 -0
  281. package/src/electron/agent/sandbox/security-utils.ts +251 -0
  282. package/src/electron/agent/search/brave-provider.ts +141 -0
  283. package/src/electron/agent/search/google-provider.ts +131 -0
  284. package/src/electron/agent/search/index.ts +6 -0
  285. package/src/electron/agent/search/provider-factory.ts +450 -0
  286. package/src/electron/agent/search/serpapi-provider.ts +138 -0
  287. package/src/electron/agent/search/tavily-provider.ts +108 -0
  288. package/src/electron/agent/search/types.ts +118 -0
  289. package/src/electron/agent/security/index.ts +20 -0
  290. package/src/electron/agent/security/input-sanitizer.ts +380 -0
  291. package/src/electron/agent/security/output-filter.ts +259 -0
  292. package/src/electron/agent/skill-eligibility.ts +334 -0
  293. package/src/electron/agent/skill-registry.ts +457 -0
  294. package/src/electron/agent/skills/document.ts +1070 -0
  295. package/src/electron/agent/skills/image-generator.ts +272 -0
  296. package/src/electron/agent/skills/organizer.ts +131 -0
  297. package/src/electron/agent/skills/presentation.ts +418 -0
  298. package/src/electron/agent/skills/spreadsheet.ts +166 -0
  299. package/src/electron/agent/tools/browser-tools.ts +546 -0
  300. package/src/electron/agent/tools/builtin-settings.ts +422 -0
  301. package/src/electron/agent/tools/canvas-tools.ts +572 -0
  302. package/src/electron/agent/tools/cron-tools.ts +723 -0
  303. package/src/electron/agent/tools/edit-tools.ts +196 -0
  304. package/src/electron/agent/tools/file-tools.ts +811 -0
  305. package/src/electron/agent/tools/glob-tools.ts +303 -0
  306. package/src/electron/agent/tools/grep-tools.ts +432 -0
  307. package/src/electron/agent/tools/image-tools.ts +126 -0
  308. package/src/electron/agent/tools/mention-tools.ts +371 -0
  309. package/src/electron/agent/tools/node-tools.ts +550 -0
  310. package/src/electron/agent/tools/registry.ts +3052 -0
  311. package/src/electron/agent/tools/search-tools.ts +111 -0
  312. package/src/electron/agent/tools/shell-tools.ts +651 -0
  313. package/src/electron/agent/tools/skill-tools.ts +340 -0
  314. package/src/electron/agent/tools/system-tools.ts +665 -0
  315. package/src/electron/agent/tools/web-fetch-tools.ts +528 -0
  316. package/src/electron/agent/tools/x-tools.ts +267 -0
  317. package/src/electron/agents/AgentRoleRepository.ts +557 -0
  318. package/src/electron/agents/HeartbeatService.ts +469 -0
  319. package/src/electron/agents/MentionRepository.ts +242 -0
  320. package/src/electron/agents/TaskSubscriptionRepository.ts +231 -0
  321. package/src/electron/agents/WorkingStateRepository.ts +278 -0
  322. package/src/electron/canvas/canvas-manager.ts +818 -0
  323. package/src/electron/canvas/canvas-preload.ts +102 -0
  324. package/src/electron/canvas/canvas-protocol.ts +174 -0
  325. package/src/electron/canvas/canvas-store.ts +200 -0
  326. package/src/electron/canvas/index.ts +8 -0
  327. package/src/electron/control-plane/client.ts +527 -0
  328. package/src/electron/control-plane/handlers.ts +723 -0
  329. package/src/electron/control-plane/index.ts +51 -0
  330. package/src/electron/control-plane/node-manager.ts +322 -0
  331. package/src/electron/control-plane/protocol.ts +269 -0
  332. package/src/electron/control-plane/remote-client.ts +517 -0
  333. package/src/electron/control-plane/server.ts +853 -0
  334. package/src/electron/control-plane/settings.ts +401 -0
  335. package/src/electron/control-plane/ssh-tunnel.ts +624 -0
  336. package/src/electron/cron/index.ts +9 -0
  337. package/src/electron/cron/schedule.ts +217 -0
  338. package/src/electron/cron/service.ts +743 -0
  339. package/src/electron/cron/store.ts +165 -0
  340. package/src/electron/cron/types.ts +291 -0
  341. package/src/electron/cron/webhook.ts +303 -0
  342. package/src/electron/database/SecureSettingsRepository.ts +514 -0
  343. package/src/electron/database/TaskLabelRepository.ts +148 -0
  344. package/src/electron/database/repositories.ts +2397 -0
  345. package/src/electron/database/schema.ts +1017 -0
  346. package/src/electron/extensions/index.ts +18 -0
  347. package/src/electron/extensions/loader.ts +336 -0
  348. package/src/electron/extensions/registry.ts +546 -0
  349. package/src/electron/extensions/types.ts +372 -0
  350. package/src/electron/gateway/channel-registry.ts +1267 -0
  351. package/src/electron/gateway/channels/bluebubbles-client.ts +641 -0
  352. package/src/electron/gateway/channels/bluebubbles.ts +509 -0
  353. package/src/electron/gateway/channels/discord.ts +1150 -0
  354. package/src/electron/gateway/channels/email-client.ts +708 -0
  355. package/src/electron/gateway/channels/email.ts +516 -0
  356. package/src/electron/gateway/channels/google-chat.ts +760 -0
  357. package/src/electron/gateway/channels/imessage-client.ts +473 -0
  358. package/src/electron/gateway/channels/imessage.ts +520 -0
  359. package/src/electron/gateway/channels/index.ts +21 -0
  360. package/src/electron/gateway/channels/line-client.ts +598 -0
  361. package/src/electron/gateway/channels/line.ts +559 -0
  362. package/src/electron/gateway/channels/matrix-client.ts +632 -0
  363. package/src/electron/gateway/channels/matrix.ts +655 -0
  364. package/src/electron/gateway/channels/mattermost-client.ts +526 -0
  365. package/src/electron/gateway/channels/mattermost.ts +550 -0
  366. package/src/electron/gateway/channels/signal-client.ts +722 -0
  367. package/src/electron/gateway/channels/signal.ts +666 -0
  368. package/src/electron/gateway/channels/slack.ts +458 -0
  369. package/src/electron/gateway/channels/teams.ts +681 -0
  370. package/src/electron/gateway/channels/telegram.ts +1727 -0
  371. package/src/electron/gateway/channels/twitch-client.ts +665 -0
  372. package/src/electron/gateway/channels/twitch.ts +468 -0
  373. package/src/electron/gateway/channels/types.ts +1002 -0
  374. package/src/electron/gateway/channels/whatsapp.ts +1101 -0
  375. package/src/electron/gateway/context-policy.ts +382 -0
  376. package/src/electron/gateway/index.ts +1274 -0
  377. package/src/electron/gateway/infrastructure.ts +645 -0
  378. package/src/electron/gateway/router.ts +3206 -0
  379. package/src/electron/gateway/security.ts +422 -0
  380. package/src/electron/gateway/session.ts +144 -0
  381. package/src/electron/gateway/tunnel.ts +626 -0
  382. package/src/electron/guardrails/guardrail-manager.ts +380 -0
  383. package/src/electron/hooks/gmail-watcher.ts +355 -0
  384. package/src/electron/hooks/index.ts +30 -0
  385. package/src/electron/hooks/mappings.ts +404 -0
  386. package/src/electron/hooks/server.ts +574 -0
  387. package/src/electron/hooks/settings.ts +466 -0
  388. package/src/electron/hooks/types.ts +245 -0
  389. package/src/electron/ipc/canvas-handlers.ts +223 -0
  390. package/src/electron/ipc/handlers.ts +3661 -0
  391. package/src/electron/ipc/mission-control-handlers.ts +182 -0
  392. package/src/electron/main.ts +496 -0
  393. package/src/electron/mcp/client/MCPClientManager.ts +406 -0
  394. package/src/electron/mcp/client/MCPServerConnection.ts +514 -0
  395. package/src/electron/mcp/client/transports/SSETransport.ts +360 -0
  396. package/src/electron/mcp/client/transports/StdioTransport.ts +355 -0
  397. package/src/electron/mcp/client/transports/WebSocketTransport.ts +384 -0
  398. package/src/electron/mcp/host/MCPHostServer.ts +388 -0
  399. package/src/electron/mcp/host/ToolAdapter.ts +140 -0
  400. package/src/electron/mcp/registry/MCPRegistryManager.ts +565 -0
  401. package/src/electron/mcp/settings.ts +468 -0
  402. package/src/electron/mcp/types.ts +371 -0
  403. package/src/electron/memory/MemoryService.ts +523 -0
  404. package/src/electron/notifications/index.ts +16 -0
  405. package/src/electron/notifications/service.ts +161 -0
  406. package/src/electron/notifications/store.ts +163 -0
  407. package/src/electron/preload.ts +2845 -0
  408. package/src/electron/reports/StandupReportService.ts +356 -0
  409. package/src/electron/security/concurrency.ts +333 -0
  410. package/src/electron/security/index.ts +17 -0
  411. package/src/electron/security/policy-manager.ts +539 -0
  412. package/src/electron/settings/appearance-manager.ts +182 -0
  413. package/src/electron/settings/personality-manager.ts +800 -0
  414. package/src/electron/settings/x-manager.ts +62 -0
  415. package/src/electron/tailscale/exposure.ts +262 -0
  416. package/src/electron/tailscale/index.ts +34 -0
  417. package/src/electron/tailscale/settings.ts +218 -0
  418. package/src/electron/tailscale/tailscale.ts +379 -0
  419. package/src/electron/tray/QuickInputWindow.ts +609 -0
  420. package/src/electron/tray/TrayManager.ts +1005 -0
  421. package/src/electron/tray/index.ts +6 -0
  422. package/src/electron/updater/index.ts +1 -0
  423. package/src/electron/updater/update-manager.ts +447 -0
  424. package/src/electron/utils/env-migration.ts +203 -0
  425. package/src/electron/utils/process.ts +124 -0
  426. package/src/electron/utils/rate-limiter.ts +130 -0
  427. package/src/electron/utils/validation.ts +493 -0
  428. package/src/electron/utils/x-cli.ts +198 -0
  429. package/src/electron/voice/VoiceService.ts +583 -0
  430. package/src/electron/voice/index.ts +9 -0
  431. package/src/electron/voice/voice-settings-manager.ts +403 -0
  432. package/src/renderer/App.tsx +775 -0
  433. package/src/renderer/components/ActivityFeed.tsx +407 -0
  434. package/src/renderer/components/ActivityFeedItem.tsx +285 -0
  435. package/src/renderer/components/AgentRoleCard.tsx +343 -0
  436. package/src/renderer/components/AgentRoleEditor.tsx +805 -0
  437. package/src/renderer/components/AgentSquadSettings.tsx +295 -0
  438. package/src/renderer/components/AgentWorkingStatePanel.tsx +411 -0
  439. package/src/renderer/components/AppearanceSettings.tsx +122 -0
  440. package/src/renderer/components/ApprovalDialog.tsx +100 -0
  441. package/src/renderer/components/BlueBubblesSettings.tsx +505 -0
  442. package/src/renderer/components/BuiltinToolsSettings.tsx +307 -0
  443. package/src/renderer/components/CanvasPreview.tsx +1189 -0
  444. package/src/renderer/components/CommandOutput.tsx +202 -0
  445. package/src/renderer/components/ContextPolicySettings.tsx +523 -0
  446. package/src/renderer/components/ControlPlaneSettings.tsx +1134 -0
  447. package/src/renderer/components/DisclaimerModal.tsx +124 -0
  448. package/src/renderer/components/DiscordSettings.tsx +436 -0
  449. package/src/renderer/components/EmailSettings.tsx +606 -0
  450. package/src/renderer/components/ExtensionsSettings.tsx +542 -0
  451. package/src/renderer/components/FileViewer.tsx +224 -0
  452. package/src/renderer/components/GoogleChatSettings.tsx +535 -0
  453. package/src/renderer/components/GuardrailSettings.tsx +487 -0
  454. package/src/renderer/components/HooksSettings.tsx +581 -0
  455. package/src/renderer/components/ImessageSettings.tsx +484 -0
  456. package/src/renderer/components/LineSettings.tsx +483 -0
  457. package/src/renderer/components/MCPRegistryBrowser.tsx +386 -0
  458. package/src/renderer/components/MCPSettings.tsx +943 -0
  459. package/src/renderer/components/MainContent.tsx +2433 -0
  460. package/src/renderer/components/MatrixSettings.tsx +510 -0
  461. package/src/renderer/components/MattermostSettings.tsx +473 -0
  462. package/src/renderer/components/MemorySettings.tsx +247 -0
  463. package/src/renderer/components/MentionBadge.tsx +87 -0
  464. package/src/renderer/components/MentionInput.tsx +409 -0
  465. package/src/renderer/components/MentionList.tsx +476 -0
  466. package/src/renderer/components/MissionControlPanel.tsx +1995 -0
  467. package/src/renderer/components/NodesSettings.tsx +316 -0
  468. package/src/renderer/components/NotificationPanel.tsx +481 -0
  469. package/src/renderer/components/Onboarding/AwakeningOrb.tsx +44 -0
  470. package/src/renderer/components/Onboarding/Onboarding.tsx +443 -0
  471. package/src/renderer/components/Onboarding/TypewriterText.tsx +102 -0
  472. package/src/renderer/components/Onboarding/index.ts +3 -0
  473. package/src/renderer/components/OnboardingModal.tsx +698 -0
  474. package/src/renderer/components/PairingCodeDisplay.tsx +324 -0
  475. package/src/renderer/components/PersonalitySettings.tsx +597 -0
  476. package/src/renderer/components/QueueSettings.tsx +119 -0
  477. package/src/renderer/components/QuickTaskFAB.tsx +71 -0
  478. package/src/renderer/components/RightPanel.tsx +413 -0
  479. package/src/renderer/components/ScheduledTasksSettings.tsx +1328 -0
  480. package/src/renderer/components/SearchSettings.tsx +328 -0
  481. package/src/renderer/components/Settings.tsx +1504 -0
  482. package/src/renderer/components/Sidebar.tsx +344 -0
  483. package/src/renderer/components/SignalSettings.tsx +673 -0
  484. package/src/renderer/components/SkillHubBrowser.tsx +458 -0
  485. package/src/renderer/components/SkillParameterModal.tsx +185 -0
  486. package/src/renderer/components/SkillsSettings.tsx +451 -0
  487. package/src/renderer/components/SlackSettings.tsx +442 -0
  488. package/src/renderer/components/StandupReportViewer.tsx +614 -0
  489. package/src/renderer/components/TaskBoard.tsx +498 -0
  490. package/src/renderer/components/TaskBoardCard.tsx +357 -0
  491. package/src/renderer/components/TaskBoardColumn.tsx +211 -0
  492. package/src/renderer/components/TaskLabelManager.tsx +472 -0
  493. package/src/renderer/components/TaskQueuePanel.tsx +144 -0
  494. package/src/renderer/components/TaskQuickActions.tsx +492 -0
  495. package/src/renderer/components/TaskTimeline.tsx +216 -0
  496. package/src/renderer/components/TaskView.tsx +162 -0
  497. package/src/renderer/components/TeamsSettings.tsx +518 -0
  498. package/src/renderer/components/TelegramSettings.tsx +421 -0
  499. package/src/renderer/components/Toast.tsx +76 -0
  500. package/src/renderer/components/TraySettings.tsx +189 -0
  501. package/src/renderer/components/TwitchSettings.tsx +511 -0
  502. package/src/renderer/components/UpdateSettings.tsx +295 -0
  503. package/src/renderer/components/VoiceIndicator.tsx +270 -0
  504. package/src/renderer/components/VoiceSettings.tsx +867 -0
  505. package/src/renderer/components/WhatsAppSettings.tsx +721 -0
  506. package/src/renderer/components/WorkingStateEditor.tsx +309 -0
  507. package/src/renderer/components/WorkingStateHistory.tsx +481 -0
  508. package/src/renderer/components/WorkspaceSelector.tsx +150 -0
  509. package/src/renderer/components/XSettings.tsx +311 -0
  510. package/src/renderer/global.d.ts +9 -0
  511. package/src/renderer/hooks/useAgentContext.ts +153 -0
  512. package/src/renderer/hooks/useOnboardingFlow.ts +548 -0
  513. package/src/renderer/hooks/useVoiceInput.ts +268 -0
  514. package/src/renderer/index.html +12 -0
  515. package/src/renderer/main.tsx +10 -0
  516. package/src/renderer/public/cowork-os-logo.png +0 -0
  517. package/src/renderer/quick-input.html +164 -0
  518. package/src/renderer/styles/index.css +14504 -0
  519. package/src/renderer/utils/agentMessages.ts +749 -0
  520. package/src/renderer/utils/voice-directives.ts +169 -0
  521. package/src/shared/channelMessages.ts +213 -0
  522. package/src/shared/types.ts +3608 -0
  523. package/tsconfig.electron.json +26 -0
  524. package/tsconfig.json +26 -0
  525. package/tsconfig.node.json +10 -0
  526. package/vite.config.ts +23 -0
@@ -0,0 +1,583 @@
1
+ /**
2
+ * Voice Service - Text-to-Speech and Speech-to-Text
3
+ *
4
+ * Provides voice interaction capabilities using ElevenLabs for TTS
5
+ * and OpenAI Whisper for STT.
6
+ *
7
+ * NOTE: This service runs in the Electron main process.
8
+ * Audio playback must be handled by the renderer process.
9
+ */
10
+
11
+ import { EventEmitter } from 'events';
12
+ import {
13
+ VoiceSettings,
14
+ VoiceState,
15
+ ElevenLabsVoice,
16
+ DEFAULT_VOICE_SETTINGS,
17
+ } from '../../shared/types';
18
+
19
+ // ElevenLabs API configuration
20
+ const ELEVENLABS_API_BASE = 'https://api.elevenlabs.io/v1';
21
+ const OPENAI_API_BASE = 'https://api.openai.com/v1';
22
+
23
+ // Default ElevenLabs voice (Rachel - conversational)
24
+ const DEFAULT_ELEVENLABS_VOICE_ID = '21m00Tcm4TlvDq8ikWAM';
25
+
26
+ export interface VoiceServiceOptions {
27
+ settings?: Partial<VoiceSettings>;
28
+ onStateChange?: (state: VoiceState) => void;
29
+ }
30
+
31
+ export class VoiceService extends EventEmitter {
32
+ private settings: VoiceSettings;
33
+ private state: VoiceState;
34
+
35
+ constructor(options: VoiceServiceOptions = {}) {
36
+ super();
37
+ this.settings = { ...DEFAULT_VOICE_SETTINGS, ...options.settings };
38
+ this.state = {
39
+ isActive: false,
40
+ isListening: false,
41
+ isSpeaking: false,
42
+ isProcessing: false,
43
+ audioLevel: 0,
44
+ };
45
+
46
+ if (options.onStateChange) {
47
+ this.on('stateChange', options.onStateChange);
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Initialize the voice service
53
+ */
54
+ async initialize(): Promise<void> {
55
+ console.log('[VoiceService] Initializing...');
56
+ this.updateState({ isActive: this.settings.enabled });
57
+ console.log('[VoiceService] Initialized with settings:', {
58
+ enabled: this.settings.enabled,
59
+ ttsProvider: this.settings.ttsProvider,
60
+ sttProvider: this.settings.sttProvider,
61
+ });
62
+ }
63
+
64
+ /**
65
+ * Update settings
66
+ */
67
+ updateSettings(settings: Partial<VoiceSettings>): void {
68
+ this.settings = { ...this.settings, ...settings };
69
+ this.updateState({ isActive: this.settings.enabled });
70
+ this.emit('settingsChange', this.settings);
71
+ }
72
+
73
+ /**
74
+ * Get current settings
75
+ */
76
+ getSettings(): VoiceSettings {
77
+ return { ...this.settings };
78
+ }
79
+
80
+ /**
81
+ * Get current state
82
+ */
83
+ getState(): VoiceState {
84
+ return { ...this.state };
85
+ }
86
+
87
+ /**
88
+ * Check if speech-to-text transcription is available
89
+ * Returns true if an STT provider with valid API keys is configured
90
+ */
91
+ isTranscriptionAvailable(): boolean {
92
+ const { sttProvider, openaiApiKey, azureApiKey, azureEndpoint } = this.settings;
93
+
94
+ switch (sttProvider) {
95
+ case 'openai':
96
+ return !!openaiApiKey;
97
+ case 'azure':
98
+ return !!(azureApiKey && azureEndpoint);
99
+ case 'elevenlabs':
100
+ // ElevenLabs uses OpenAI or Azure for STT
101
+ return !!openaiApiKey || !!(azureApiKey && azureEndpoint);
102
+ case 'local':
103
+ return false; // Not available in main process
104
+ default:
105
+ return false;
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Text-to-Speech: Convert text to audio data
111
+ * Returns audio data as Buffer for the renderer to play
112
+ */
113
+ async speak(text: string): Promise<Buffer | null> {
114
+ if (!this.settings.enabled) {
115
+ console.log('[VoiceService] Voice mode disabled, skipping TTS');
116
+ return null;
117
+ }
118
+
119
+ if (!text || text.trim().length === 0) {
120
+ return null;
121
+ }
122
+
123
+ console.log('[VoiceService] Generating TTS:', text.substring(0, 100) + (text.length > 100 ? '...' : ''));
124
+
125
+ try {
126
+ // Clear any previous error
127
+ this.updateState({ isSpeaking: true, isProcessing: true, error: undefined });
128
+ this.emit('speakingStart', text);
129
+
130
+ let audioBuffer: ArrayBuffer;
131
+
132
+ switch (this.settings.ttsProvider) {
133
+ case 'elevenlabs':
134
+ audioBuffer = await this.elevenLabsTTS(text);
135
+ break;
136
+ case 'openai':
137
+ audioBuffer = await this.openaiTTS(text);
138
+ break;
139
+ case 'azure':
140
+ audioBuffer = await this.azureTTS(text);
141
+ break;
142
+ case 'local':
143
+ // Local TTS requires browser APIs - not available in main process
144
+ throw new Error('Local TTS is not available in the main process. Please use ElevenLabs, OpenAI, or Azure.');
145
+ default:
146
+ throw new Error(`Unknown TTS provider: ${this.settings.ttsProvider}`);
147
+ }
148
+
149
+ this.updateState({ isProcessing: false });
150
+
151
+ // Return audio data as Buffer for renderer to play
152
+ return Buffer.from(audioBuffer);
153
+ } catch (error) {
154
+ console.error('[VoiceService] TTS error:', error);
155
+ this.updateState({ error: (error as Error).message, isSpeaking: false, isProcessing: false });
156
+ this.emit('error', error);
157
+ throw error;
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Mark speaking as finished (called by renderer after audio playback)
163
+ */
164
+ finishSpeaking(): void {
165
+ this.updateState({ isSpeaking: false });
166
+ this.emit('speakingEnd');
167
+ }
168
+
169
+ /**
170
+ * Stop current speech
171
+ */
172
+ stopSpeaking(): void {
173
+ this.updateState({ isSpeaking: false });
174
+ this.emit('speakingEnd');
175
+ }
176
+
177
+ /**
178
+ * Speech-to-Text: Transcribe audio to text
179
+ * Accepts audio data as Buffer from the renderer
180
+ * @param audioData - Audio data as Buffer
181
+ * @param options - Optional settings
182
+ * @param options.force - If true, bypass the enabled check (useful for channel audio messages)
183
+ */
184
+ async transcribe(audioData: Buffer, options?: { force?: boolean }): Promise<string> {
185
+ if (!this.settings.enabled && !options?.force) {
186
+ throw new Error('Voice mode is disabled');
187
+ }
188
+
189
+ console.log('[VoiceService] Transcribing audio...');
190
+ // Clear any previous error
191
+ this.updateState({ isProcessing: true, error: undefined });
192
+
193
+ try {
194
+ let transcript: string;
195
+
196
+ switch (this.settings.sttProvider) {
197
+ case 'openai':
198
+ transcript = await this.openaiSTT(audioData);
199
+ break;
200
+ case 'azure':
201
+ transcript = await this.azureSTT(audioData);
202
+ break;
203
+ case 'local':
204
+ // Local STT requires browser APIs - not available in main process
205
+ throw new Error('Local STT is not available in the main process. Please use OpenAI Whisper or Azure.');
206
+ case 'elevenlabs':
207
+ // ElevenLabs doesn't have an STT API - redirect to OpenAI if key available
208
+ if (this.settings.openaiApiKey) {
209
+ transcript = await this.openaiSTT(audioData);
210
+ } else if (this.settings.azureEndpoint && this.settings.azureApiKey) {
211
+ transcript = await this.azureSTT(audioData);
212
+ } else {
213
+ throw new Error('ElevenLabs does not provide speech-to-text. Please use OpenAI Whisper, Azure, or configure an API key.');
214
+ }
215
+ break;
216
+ default:
217
+ throw new Error(`Unknown STT provider: ${this.settings.sttProvider}`);
218
+ }
219
+
220
+ this.emit('transcript', transcript);
221
+ return transcript;
222
+ } catch (error) {
223
+ console.error('[VoiceService] STT error:', error);
224
+ this.updateState({ error: (error as Error).message });
225
+ this.emit('error', error);
226
+ throw error;
227
+ } finally {
228
+ this.updateState({ isProcessing: false });
229
+ }
230
+ }
231
+
232
+ /**
233
+ * Get available ElevenLabs voices
234
+ */
235
+ async getElevenLabsVoices(): Promise<ElevenLabsVoice[]> {
236
+ const apiKey = this.settings.elevenLabsApiKey;
237
+ if (!apiKey) {
238
+ throw new Error('ElevenLabs API key not configured');
239
+ }
240
+
241
+ const response = await fetch(`${ELEVENLABS_API_BASE}/voices`, {
242
+ headers: {
243
+ 'xi-api-key': apiKey,
244
+ },
245
+ });
246
+
247
+ if (!response.ok) {
248
+ const error = await response.text();
249
+ throw new Error(`Failed to fetch voices: ${error}`);
250
+ }
251
+
252
+ const data = await response.json() as { voices?: ElevenLabsVoice[] };
253
+ return data.voices || [];
254
+ }
255
+
256
+ /**
257
+ * Test ElevenLabs connection
258
+ */
259
+ async testElevenLabsConnection(): Promise<{ success: boolean; voiceCount?: number; error?: string }> {
260
+ try {
261
+ const voices = await this.getElevenLabsVoices();
262
+ return { success: true, voiceCount: voices.length };
263
+ } catch (error) {
264
+ return { success: false, error: (error as Error).message };
265
+ }
266
+ }
267
+
268
+ /**
269
+ * Test OpenAI voice connection
270
+ */
271
+ async testOpenAIConnection(): Promise<{ success: boolean; error?: string }> {
272
+ const apiKey = this.settings.openaiApiKey;
273
+ if (!apiKey) {
274
+ return { success: false, error: 'OpenAI API key not configured' };
275
+ }
276
+
277
+ try {
278
+ // Test with a minimal TTS request
279
+ const response = await fetch(`${OPENAI_API_BASE}/audio/speech`, {
280
+ method: 'POST',
281
+ headers: {
282
+ 'Authorization': `Bearer ${apiKey}`,
283
+ 'Content-Type': 'application/json',
284
+ },
285
+ body: JSON.stringify({
286
+ model: 'tts-1',
287
+ input: 'Test',
288
+ voice: 'alloy',
289
+ }),
290
+ });
291
+
292
+ if (!response.ok) {
293
+ const error = await response.text();
294
+ return { success: false, error };
295
+ }
296
+
297
+ return { success: true };
298
+ } catch (error) {
299
+ return { success: false, error: (error as Error).message };
300
+ }
301
+ }
302
+
303
+ /**
304
+ * Test Azure OpenAI voice connection
305
+ */
306
+ async testAzureConnection(): Promise<{ success: boolean; error?: string }> {
307
+ const endpoint = this.settings.azureEndpoint;
308
+ const apiKey = this.settings.azureApiKey;
309
+ const deploymentName = this.settings.azureTtsDeploymentName;
310
+
311
+ if (!endpoint) {
312
+ return { success: false, error: 'Azure OpenAI endpoint not configured' };
313
+ }
314
+ if (!apiKey) {
315
+ return { success: false, error: 'Azure OpenAI API key not configured' };
316
+ }
317
+ if (!deploymentName) {
318
+ return { success: false, error: 'Azure OpenAI TTS deployment name not configured' };
319
+ }
320
+
321
+ try {
322
+ const apiVersion = this.settings.azureApiVersion || '2024-02-15-preview';
323
+ const url = `${endpoint}/openai/deployments/${deploymentName}/audio/speech?api-version=${apiVersion}`;
324
+
325
+ const response = await fetch(url, {
326
+ method: 'POST',
327
+ headers: {
328
+ 'api-key': apiKey,
329
+ 'Content-Type': 'application/json',
330
+ },
331
+ body: JSON.stringify({
332
+ model: deploymentName,
333
+ input: 'Test',
334
+ voice: 'alloy',
335
+ }),
336
+ });
337
+
338
+ if (!response.ok) {
339
+ const error = await response.text();
340
+ return { success: false, error };
341
+ }
342
+
343
+ return { success: true };
344
+ } catch (error) {
345
+ return { success: false, error: (error as Error).message };
346
+ }
347
+ }
348
+
349
+ /**
350
+ * Cleanup resources
351
+ */
352
+ dispose(): void {
353
+ this.stopSpeaking();
354
+ this.removeAllListeners();
355
+ }
356
+
357
+ // ============ Private Methods ============
358
+
359
+ private updateState(partial: Partial<VoiceState>): void {
360
+ this.state = { ...this.state, ...partial };
361
+ this.emit('stateChange', this.state);
362
+ }
363
+
364
+ /**
365
+ * ElevenLabs Text-to-Speech
366
+ */
367
+ private async elevenLabsTTS(text: string): Promise<ArrayBuffer> {
368
+ const apiKey = this.settings.elevenLabsApiKey;
369
+ if (!apiKey) {
370
+ throw new Error('ElevenLabs API key not configured');
371
+ }
372
+
373
+ const voiceId = this.settings.elevenLabsVoiceId || DEFAULT_ELEVENLABS_VOICE_ID;
374
+
375
+ const response = await fetch(`${ELEVENLABS_API_BASE}/text-to-speech/${voiceId}`, {
376
+ method: 'POST',
377
+ headers: {
378
+ 'Accept': 'audio/mpeg',
379
+ 'xi-api-key': apiKey,
380
+ 'Content-Type': 'application/json',
381
+ },
382
+ body: JSON.stringify({
383
+ text,
384
+ model_id: 'eleven_monolingual_v1',
385
+ voice_settings: {
386
+ stability: 0.5,
387
+ similarity_boost: 0.75,
388
+ style: 0.0,
389
+ use_speaker_boost: true,
390
+ },
391
+ }),
392
+ });
393
+
394
+ if (!response.ok) {
395
+ const errorText = await response.text();
396
+ throw new Error(`ElevenLabs TTS failed: ${errorText}`);
397
+ }
398
+
399
+ return response.arrayBuffer();
400
+ }
401
+
402
+ /**
403
+ * OpenAI Text-to-Speech
404
+ */
405
+ private async openaiTTS(text: string): Promise<ArrayBuffer> {
406
+ const apiKey = this.settings.openaiApiKey;
407
+ if (!apiKey) {
408
+ throw new Error('OpenAI API key not configured');
409
+ }
410
+
411
+ const voice = this.settings.openaiVoice || 'nova';
412
+
413
+ const response = await fetch(`${OPENAI_API_BASE}/audio/speech`, {
414
+ method: 'POST',
415
+ headers: {
416
+ 'Authorization': `Bearer ${apiKey}`,
417
+ 'Content-Type': 'application/json',
418
+ },
419
+ body: JSON.stringify({
420
+ model: 'tts-1',
421
+ input: text,
422
+ voice,
423
+ speed: this.settings.speechRate,
424
+ }),
425
+ });
426
+
427
+ if (!response.ok) {
428
+ const errorText = await response.text();
429
+ throw new Error(`OpenAI TTS failed: ${errorText}`);
430
+ }
431
+
432
+ return response.arrayBuffer();
433
+ }
434
+
435
+ /**
436
+ * OpenAI Whisper Speech-to-Text
437
+ */
438
+ private async openaiSTT(audioData: Buffer): Promise<string> {
439
+ const apiKey = this.settings.openaiApiKey;
440
+ if (!apiKey) {
441
+ throw new Error('OpenAI API key not configured');
442
+ }
443
+
444
+ // Create a Blob-like object for Node.js fetch
445
+ // Convert Buffer to Uint8Array for BlobPart compatibility
446
+ const uint8Array = new Uint8Array(audioData.buffer as ArrayBuffer, audioData.byteOffset, audioData.byteLength);
447
+ const blob = new Blob([uint8Array], { type: 'audio/webm' });
448
+
449
+ const formData = new FormData();
450
+ formData.append('file', blob, 'audio.webm');
451
+ formData.append('model', 'whisper-1');
452
+ formData.append('language', this.settings.language.split('-')[0]); // e.g., 'en' from 'en-US'
453
+
454
+ const response = await fetch(`${OPENAI_API_BASE}/audio/transcriptions`, {
455
+ method: 'POST',
456
+ headers: {
457
+ 'Authorization': `Bearer ${apiKey}`,
458
+ },
459
+ body: formData,
460
+ });
461
+
462
+ if (!response.ok) {
463
+ const errorText = await response.text();
464
+ throw new Error(`OpenAI STT failed: ${errorText}`);
465
+ }
466
+
467
+ const data = await response.json() as { text: string };
468
+ return data.text;
469
+ }
470
+
471
+ /**
472
+ * Azure OpenAI Text-to-Speech
473
+ */
474
+ private async azureTTS(text: string): Promise<ArrayBuffer> {
475
+ const endpoint = this.settings.azureEndpoint;
476
+ const apiKey = this.settings.azureApiKey;
477
+ const deploymentName = this.settings.azureTtsDeploymentName;
478
+
479
+ if (!endpoint) {
480
+ throw new Error('Azure OpenAI endpoint not configured');
481
+ }
482
+ if (!apiKey) {
483
+ throw new Error('Azure OpenAI API key not configured');
484
+ }
485
+ if (!deploymentName) {
486
+ throw new Error('Azure OpenAI TTS deployment name not configured');
487
+ }
488
+
489
+ const voice = this.settings.azureVoice || 'nova';
490
+ const apiVersion = this.settings.azureApiVersion || '2024-02-15-preview';
491
+ const url = `${endpoint}/openai/deployments/${deploymentName}/audio/speech?api-version=${apiVersion}`;
492
+
493
+ const response = await fetch(url, {
494
+ method: 'POST',
495
+ headers: {
496
+ 'api-key': apiKey,
497
+ 'Content-Type': 'application/json',
498
+ },
499
+ body: JSON.stringify({
500
+ model: deploymentName,
501
+ input: text,
502
+ voice,
503
+ speed: this.settings.speechRate,
504
+ }),
505
+ });
506
+
507
+ if (!response.ok) {
508
+ const errorText = await response.text();
509
+ throw new Error(`Azure OpenAI TTS failed: ${errorText}`);
510
+ }
511
+
512
+ return response.arrayBuffer();
513
+ }
514
+
515
+ /**
516
+ * Azure OpenAI Whisper Speech-to-Text
517
+ */
518
+ private async azureSTT(audioData: Buffer): Promise<string> {
519
+ const endpoint = this.settings.azureEndpoint;
520
+ const apiKey = this.settings.azureApiKey;
521
+ const deploymentName = this.settings.azureSttDeploymentName;
522
+
523
+ if (!endpoint) {
524
+ throw new Error('Azure OpenAI endpoint not configured');
525
+ }
526
+ if (!apiKey) {
527
+ throw new Error('Azure OpenAI API key not configured');
528
+ }
529
+ if (!deploymentName) {
530
+ throw new Error('Azure OpenAI STT deployment name not configured');
531
+ }
532
+
533
+ const apiVersion = this.settings.azureApiVersion || '2024-02-15-preview';
534
+ const url = `${endpoint}/openai/deployments/${deploymentName}/audio/transcriptions?api-version=${apiVersion}`;
535
+
536
+ // Create a Blob-like object for Node.js fetch
537
+ const uint8Array = new Uint8Array(audioData.buffer as ArrayBuffer, audioData.byteOffset, audioData.byteLength);
538
+ const blob = new Blob([uint8Array], { type: 'audio/webm' });
539
+
540
+ const formData = new FormData();
541
+ formData.append('file', blob, 'audio.webm');
542
+ formData.append('language', this.settings.language.split('-')[0]);
543
+
544
+ const response = await fetch(url, {
545
+ method: 'POST',
546
+ headers: {
547
+ 'api-key': apiKey,
548
+ },
549
+ body: formData,
550
+ });
551
+
552
+ if (!response.ok) {
553
+ const errorText = await response.text();
554
+ throw new Error(`Azure OpenAI STT failed: ${errorText}`);
555
+ }
556
+
557
+ const data = await response.json() as { text: string };
558
+ return data.text;
559
+ }
560
+ }
561
+
562
+ // Singleton instance
563
+ let voiceServiceInstance: VoiceService | null = null;
564
+
565
+ /**
566
+ * Get or create the VoiceService singleton
567
+ */
568
+ export function getVoiceService(options?: VoiceServiceOptions): VoiceService {
569
+ if (!voiceServiceInstance) {
570
+ voiceServiceInstance = new VoiceService(options);
571
+ }
572
+ return voiceServiceInstance;
573
+ }
574
+
575
+ /**
576
+ * Reset the VoiceService singleton (for testing)
577
+ */
578
+ export function resetVoiceService(): void {
579
+ if (voiceServiceInstance) {
580
+ voiceServiceInstance.dispose();
581
+ voiceServiceInstance = null;
582
+ }
583
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Voice Module Exports
3
+ *
4
+ * Provides voice interaction capabilities with TTS/STT support.
5
+ */
6
+
7
+ export { VoiceService, getVoiceService, resetVoiceService } from './VoiceService';
8
+ export type { VoiceServiceOptions } from './VoiceService';
9
+ export { VoiceSettingsManager } from './voice-settings-manager';