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,360 @@
1
+ /**
2
+ * SSETransport - MCP transport over Server-Sent Events (SSE)
3
+ *
4
+ * Uses SSE (EventSource) for server-to-client messages and
5
+ * HTTP POST requests for client-to-server messages.
6
+ * This enables web-based MCP servers.
7
+ */
8
+
9
+ import { EventEmitter } from 'events';
10
+ import { EventSource } from 'eventsource';
11
+ import {
12
+ MCPTransport,
13
+ MCPServerConfig,
14
+ JSONRPCRequest,
15
+ JSONRPCResponse,
16
+ JSONRPCNotification,
17
+ } from '../../types';
18
+
19
+ interface PendingRequest {
20
+ resolve: (result: any) => void;
21
+ reject: (error: Error) => void;
22
+ timeout: ReturnType<typeof setTimeout>;
23
+ }
24
+
25
+ export class SSETransport extends EventEmitter implements MCPTransport {
26
+ private config: MCPServerConfig;
27
+ private eventSource: EventSource | null = null;
28
+ private messageHandler: ((message: JSONRPCResponse | JSONRPCNotification) => void) | null = null;
29
+ private closeHandler: ((error?: Error) => void) | null = null;
30
+ private errorHandler: ((error: Error) => void) | null = null;
31
+ private pendingRequests: Map<string | number, PendingRequest> = new Map();
32
+ private connected = false;
33
+ private requestId = 0;
34
+ private abortController: AbortController | null = null;
35
+
36
+ constructor(config: MCPServerConfig) {
37
+ super();
38
+ this.config = config;
39
+ }
40
+
41
+ /**
42
+ * Connect to the MCP server via SSE
43
+ */
44
+ async connect(): Promise<void> {
45
+ if (this.connected || this.eventSource) {
46
+ throw new Error('Already connected');
47
+ }
48
+
49
+ const { url } = this.config;
50
+
51
+ if (!url) {
52
+ throw new Error('No URL specified for SSE transport');
53
+ }
54
+
55
+ return new Promise((resolve, reject) => {
56
+ const timeout = setTimeout(() => {
57
+ this.cleanup();
58
+ reject(new Error(`Connection timeout: server did not respond within ${this.config.connectionTimeout || 30000}ms`));
59
+ }, this.config.connectionTimeout || 30000);
60
+
61
+ try {
62
+ // Build SSE URL with auth headers if needed
63
+ const sseUrl = this.buildUrl(url, '/sse');
64
+ console.log(`[MCP SSETransport] Connecting to: ${sseUrl}`);
65
+
66
+ // Create EventSource for server-to-client messages
67
+ // Note: EventSource doesn't support custom headers, so we use URL params for auth
68
+ this.eventSource = new EventSource(sseUrl);
69
+
70
+ this.eventSource.onopen = () => {
71
+ clearTimeout(timeout);
72
+ this.connected = true;
73
+ console.log(`[MCP SSETransport] Connected successfully`);
74
+ resolve();
75
+ };
76
+
77
+ this.eventSource.onmessage = (event) => {
78
+ this.handleMessage(event.data);
79
+ };
80
+
81
+ this.eventSource.onerror = (error) => {
82
+ console.error(`[MCP SSETransport] EventSource error:`, error);
83
+ if (!this.connected) {
84
+ clearTimeout(timeout);
85
+ reject(new Error('Failed to connect to SSE endpoint'));
86
+ } else {
87
+ this.errorHandler?.(new Error('SSE connection error'));
88
+ this.closeHandler?.(new Error('SSE connection lost'));
89
+ }
90
+ this.cleanup();
91
+ };
92
+
93
+ // Handle named events (some servers use event types)
94
+ this.eventSource.addEventListener('message', (event) => {
95
+ this.handleMessage(event.data);
96
+ });
97
+
98
+ this.eventSource.addEventListener('error', () => {
99
+ if (this.connected) {
100
+ this.closeHandler?.(new Error('SSE stream closed'));
101
+ this.cleanup();
102
+ }
103
+ });
104
+
105
+ } catch (error) {
106
+ clearTimeout(timeout);
107
+ console.error(`[MCP SSETransport] Failed to connect:`, error);
108
+ reject(error);
109
+ }
110
+ });
111
+ }
112
+
113
+ /**
114
+ * Disconnect from the MCP server
115
+ */
116
+ async disconnect(): Promise<void> {
117
+ console.log(`[MCP SSETransport] Disconnecting...`);
118
+
119
+ // Abort any pending requests
120
+ this.abortController?.abort();
121
+
122
+ // Reject all pending requests
123
+ for (const [id, pending] of this.pendingRequests) {
124
+ clearTimeout(pending.timeout);
125
+ pending.reject(new Error('Transport disconnected'));
126
+ }
127
+ this.pendingRequests.clear();
128
+
129
+ this.cleanup();
130
+ }
131
+
132
+ /**
133
+ * Send a JSON-RPC request via HTTP POST and wait for response
134
+ */
135
+ async sendRequest(method: string, params?: Record<string, any>): Promise<any> {
136
+ if (!this.connected) {
137
+ throw new Error('Not connected');
138
+ }
139
+
140
+ const id = ++this.requestId;
141
+ const request: JSONRPCRequest = {
142
+ jsonrpc: '2.0',
143
+ id,
144
+ method,
145
+ params,
146
+ };
147
+
148
+ return new Promise((resolve, reject) => {
149
+ const timeout = setTimeout(() => {
150
+ this.pendingRequests.delete(id);
151
+ reject(new Error(`Request timeout for method: ${method}`));
152
+ }, this.config.requestTimeout || 60000);
153
+
154
+ this.pendingRequests.set(id, { resolve, reject, timeout });
155
+
156
+ // Send via HTTP POST
157
+ this.postMessage(request).catch((error) => {
158
+ this.pendingRequests.delete(id);
159
+ clearTimeout(timeout);
160
+ reject(error);
161
+ });
162
+ });
163
+ }
164
+
165
+ /**
166
+ * Send a JSON-RPC message (request or notification)
167
+ */
168
+ async send(message: JSONRPCRequest | JSONRPCNotification): Promise<void> {
169
+ if (!this.connected) {
170
+ throw new Error('Not connected');
171
+ }
172
+
173
+ await this.postMessage(message);
174
+ }
175
+
176
+ /**
177
+ * Post a message to the server via HTTP
178
+ */
179
+ private async postMessage(message: JSONRPCRequest | JSONRPCNotification): Promise<void> {
180
+ const { url } = this.config;
181
+ if (!url) {
182
+ throw new Error('No URL configured');
183
+ }
184
+
185
+ const postUrl = this.buildUrl(url, '/message');
186
+ this.abortController = new AbortController();
187
+
188
+ try {
189
+ const headers: Record<string, string> = {
190
+ 'Content-Type': 'application/json',
191
+ ...this.config.headers,
192
+ };
193
+
194
+ // Add auth headers
195
+ this.addAuthHeaders(headers);
196
+
197
+ const response = await fetch(postUrl, {
198
+ method: 'POST',
199
+ headers,
200
+ body: JSON.stringify(message),
201
+ signal: this.abortController.signal,
202
+ });
203
+
204
+ if (!response.ok) {
205
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
206
+ }
207
+
208
+ // Some servers return the response in the HTTP response body
209
+ const contentType = response.headers.get('content-type');
210
+ if (contentType?.includes('application/json')) {
211
+ const responseData = await response.json();
212
+ if (responseData && typeof responseData === 'object' && 'id' in responseData) {
213
+ this.handleJsonRpcResponse(responseData);
214
+ }
215
+ }
216
+ } catch (error: any) {
217
+ if (error.name === 'AbortError') {
218
+ throw new Error('Request aborted');
219
+ }
220
+ throw error;
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Register message handler
226
+ */
227
+ onMessage(handler: (message: JSONRPCResponse | JSONRPCNotification) => void): void {
228
+ this.messageHandler = handler;
229
+ }
230
+
231
+ /**
232
+ * Register close handler
233
+ */
234
+ onClose(handler: (error?: Error) => void): void {
235
+ this.closeHandler = handler;
236
+ }
237
+
238
+ /**
239
+ * Register error handler
240
+ */
241
+ onError(handler: (error: Error) => void): void {
242
+ this.errorHandler = handler;
243
+ }
244
+
245
+ /**
246
+ * Check if transport is connected
247
+ */
248
+ isConnected(): boolean {
249
+ // EventSource readyState: 0=CONNECTING, 1=OPEN, 2=CLOSED
250
+ return this.connected && this.eventSource?.readyState === 1;
251
+ }
252
+
253
+ /**
254
+ * Handle incoming SSE message
255
+ */
256
+ private handleMessage(data: string): void {
257
+ try {
258
+ const message = JSON.parse(data);
259
+ this.handleJsonRpcResponse(message);
260
+ } catch (error) {
261
+ console.error(`[MCP SSETransport] Failed to parse message: ${data}`);
262
+ }
263
+ }
264
+
265
+ /**
266
+ * Handle a parsed JSON-RPC message
267
+ */
268
+ private handleJsonRpcResponse(message: any): void {
269
+ // Check if this is a response to a pending request
270
+ if ('id' in message && message.id !== null) {
271
+ const pending = this.pendingRequests.get(message.id);
272
+ if (pending) {
273
+ this.pendingRequests.delete(message.id);
274
+ clearTimeout(pending.timeout);
275
+
276
+ if ('error' in message && message.error) {
277
+ pending.reject(new Error(message.error.message || 'Unknown error'));
278
+ } else {
279
+ pending.resolve(message.result);
280
+ }
281
+ return;
282
+ }
283
+ }
284
+
285
+ // Otherwise, pass to message handler (notifications)
286
+ this.messageHandler?.(message as JSONRPCResponse | JSONRPCNotification);
287
+ }
288
+
289
+ /**
290
+ * Build URL with optional path
291
+ */
292
+ private buildUrl(baseUrl: string, path: string): string {
293
+ const url = new URL(baseUrl);
294
+
295
+ // Append path if base URL doesn't already have it
296
+ if (!url.pathname.endsWith(path)) {
297
+ url.pathname = url.pathname.replace(/\/$/, '') + path;
298
+ }
299
+
300
+ // Add auth params for SSE (since EventSource doesn't support headers)
301
+ if (this.config.auth) {
302
+ if (this.config.auth.type === 'bearer' && this.config.auth.token) {
303
+ url.searchParams.set('token', this.config.auth.token);
304
+ } else if (this.config.auth.type === 'api-key' && this.config.auth.apiKey) {
305
+ url.searchParams.set('api_key', this.config.auth.apiKey);
306
+ }
307
+ }
308
+
309
+ return url.toString();
310
+ }
311
+
312
+ /**
313
+ * Add authentication headers
314
+ */
315
+ private addAuthHeaders(headers: Record<string, string>): void {
316
+ if (!this.config.auth) return;
317
+
318
+ switch (this.config.auth.type) {
319
+ case 'bearer':
320
+ if (this.config.auth.token) {
321
+ headers['Authorization'] = `Bearer ${this.config.auth.token}`;
322
+ }
323
+ break;
324
+ case 'api-key':
325
+ if (this.config.auth.apiKey) {
326
+ const headerName = this.config.auth.headerName || 'X-API-Key';
327
+ headers[headerName] = this.config.auth.apiKey;
328
+ }
329
+ break;
330
+ case 'basic':
331
+ if (this.config.auth.username && this.config.auth.password) {
332
+ const credentials = Buffer.from(
333
+ `${this.config.auth.username}:${this.config.auth.password}`
334
+ ).toString('base64');
335
+ headers['Authorization'] = `Basic ${credentials}`;
336
+ }
337
+ break;
338
+ }
339
+ }
340
+
341
+ /**
342
+ * Cleanup resources
343
+ */
344
+ private cleanup(): void {
345
+ this.connected = false;
346
+
347
+ // Clear all pending requests
348
+ for (const [, pending] of this.pendingRequests) {
349
+ clearTimeout(pending.timeout);
350
+ }
351
+ this.pendingRequests.clear();
352
+
353
+ if (this.eventSource) {
354
+ this.eventSource.close();
355
+ this.eventSource = null;
356
+ }
357
+
358
+ this.abortController = null;
359
+ }
360
+ }
@@ -0,0 +1,355 @@
1
+ /**
2
+ * StdioTransport - MCP transport over stdio (stdin/stdout)
3
+ *
4
+ * This is the primary transport for MCP servers that are launched as
5
+ * child processes and communicate via JSON-RPC over stdin/stdout.
6
+ */
7
+
8
+ import { spawn, ChildProcess } from 'child_process';
9
+ import { EventEmitter } from 'events';
10
+ import {
11
+ MCPTransport,
12
+ MCPServerConfig,
13
+ JSONRPCRequest,
14
+ JSONRPCResponse,
15
+ JSONRPCNotification,
16
+ } from '../../types';
17
+
18
+ interface PendingRequest {
19
+ resolve: (result: any) => void;
20
+ reject: (error: Error) => void;
21
+ timeout: ReturnType<typeof setTimeout>;
22
+ }
23
+
24
+ export class StdioTransport extends EventEmitter implements MCPTransport {
25
+ private process: ChildProcess | null = null;
26
+ private config: MCPServerConfig;
27
+ private messageHandler: ((message: JSONRPCResponse | JSONRPCNotification) => void) | null = null;
28
+ private closeHandler: ((error?: Error) => void) | null = null;
29
+ private errorHandler: ((error: Error) => void) | null = null;
30
+ private pendingRequests: Map<string | number, PendingRequest> = new Map();
31
+ private buffer = '';
32
+ private stderrBuffer = ''; // Capture stderr for better error messages
33
+ private connected = false;
34
+ private requestId = 0;
35
+
36
+ constructor(config: MCPServerConfig) {
37
+ super();
38
+ this.config = config;
39
+ }
40
+
41
+ /**
42
+ * Connect to the MCP server by spawning the process
43
+ */
44
+ async connect(): Promise<void> {
45
+ if (this.connected || this.process) {
46
+ throw new Error('Already connected');
47
+ }
48
+
49
+ const { command, args = [], env, cwd } = this.config;
50
+
51
+ if (!command) {
52
+ throw new Error('No command specified for stdio transport');
53
+ }
54
+
55
+ return new Promise((resolve, reject) => {
56
+ const timeout = setTimeout(() => {
57
+ this.cleanup();
58
+ reject(new Error(`Connection timeout: server did not respond within ${this.config.connectionTimeout || 30000}ms`));
59
+ }, this.config.connectionTimeout || 30000);
60
+
61
+ try {
62
+ // Merge environment variables
63
+ const processEnv = {
64
+ ...process.env,
65
+ ...env,
66
+ };
67
+
68
+ console.log(`[MCP StdioTransport] Spawning: ${command} ${args.join(' ')}`);
69
+
70
+ this.process = spawn(command, args, {
71
+ cwd: cwd || process.cwd(),
72
+ env: processEnv,
73
+ stdio: ['pipe', 'pipe', 'pipe'],
74
+ shell: false,
75
+ });
76
+
77
+ // Handle stdout (JSON-RPC messages from server)
78
+ this.process.stdout?.on('data', (data: Buffer) => {
79
+ this.handleData(data);
80
+ });
81
+
82
+ // Handle stderr (logging/errors from server)
83
+ this.process.stderr?.on('data', (data: Buffer) => {
84
+ const text = data.toString();
85
+ console.log(`[MCP StdioTransport] Server stderr: ${text}`);
86
+ // Capture stderr for better error messages (limit to last 1000 chars)
87
+ this.stderrBuffer += text;
88
+ if (this.stderrBuffer.length > 1000) {
89
+ this.stderrBuffer = this.stderrBuffer.slice(-1000);
90
+ }
91
+ });
92
+
93
+ // Handle process errors
94
+ this.process.on('error', (error) => {
95
+ clearTimeout(timeout);
96
+ console.error(`[MCP StdioTransport] Process error:`, error);
97
+ this.errorHandler?.(error);
98
+ if (!this.connected) {
99
+ reject(error);
100
+ }
101
+ this.cleanup();
102
+ });
103
+
104
+ // Handle process exit
105
+ this.process.on('exit', (code, signal) => {
106
+ clearTimeout(timeout);
107
+ // Build error message including stderr output for better diagnostics
108
+ let message = `Process exited with code ${code}`;
109
+ if (signal) {
110
+ message += `, signal ${signal}`;
111
+ }
112
+ // Include stderr in error message if there was an error exit
113
+ if (code !== 0 && this.stderrBuffer.trim()) {
114
+ const stderrSnippet = this.stderrBuffer.trim().slice(-500); // Last 500 chars
115
+ message += `: ${stderrSnippet}`;
116
+ }
117
+ console.log(`[MCP StdioTransport] ${message}`);
118
+
119
+ if (!this.connected) {
120
+ reject(new Error(message));
121
+ } else {
122
+ this.closeHandler?.(code !== 0 ? new Error(message) : undefined);
123
+ }
124
+ this.cleanup();
125
+ });
126
+
127
+ // Handle process close
128
+ this.process.on('close', (code) => {
129
+ if (this.connected) {
130
+ let message = `Process closed with code ${code}`;
131
+ if (code !== 0 && this.stderrBuffer.trim()) {
132
+ const stderrSnippet = this.stderrBuffer.trim().slice(-500);
133
+ message += `: ${stderrSnippet}`;
134
+ }
135
+ this.closeHandler?.(code !== 0 ? new Error(message) : undefined);
136
+ }
137
+ this.cleanup();
138
+ });
139
+
140
+ // Mark as connected once process is spawned
141
+ // The actual MCP handshake will be done by MCPServerConnection
142
+ this.connected = true;
143
+ clearTimeout(timeout);
144
+ console.log(`[MCP StdioTransport] Process spawned successfully`);
145
+ resolve();
146
+
147
+ } catch (error) {
148
+ clearTimeout(timeout);
149
+ console.error(`[MCP StdioTransport] Failed to spawn process:`, error);
150
+ reject(error);
151
+ }
152
+ });
153
+ }
154
+
155
+ /**
156
+ * Disconnect from the MCP server
157
+ */
158
+ async disconnect(): Promise<void> {
159
+ if (!this.process) {
160
+ return;
161
+ }
162
+
163
+ console.log(`[MCP StdioTransport] Disconnecting...`);
164
+
165
+ // Reject all pending requests
166
+ for (const [id, pending] of this.pendingRequests) {
167
+ clearTimeout(pending.timeout);
168
+ pending.reject(new Error('Transport disconnected'));
169
+ }
170
+ this.pendingRequests.clear();
171
+
172
+ // Try graceful shutdown first
173
+ if (this.process.stdin?.writable) {
174
+ try {
175
+ this.process.stdin.end();
176
+ } catch {
177
+ // Ignore errors during shutdown
178
+ }
179
+ }
180
+
181
+ // Give process time to exit gracefully
182
+ await new Promise<void>((resolve) => {
183
+ const forceKillTimeout = setTimeout(() => {
184
+ if (this.process && !this.process.killed) {
185
+ console.log(`[MCP StdioTransport] Force killing process`);
186
+ this.process.kill('SIGKILL');
187
+ }
188
+ resolve();
189
+ }, 5000);
190
+
191
+ if (this.process) {
192
+ this.process.once('exit', () => {
193
+ clearTimeout(forceKillTimeout);
194
+ resolve();
195
+ });
196
+
197
+ // Send SIGTERM first
198
+ this.process.kill('SIGTERM');
199
+ } else {
200
+ clearTimeout(forceKillTimeout);
201
+ resolve();
202
+ }
203
+ });
204
+
205
+ this.cleanup();
206
+ }
207
+
208
+ /**
209
+ * Send a JSON-RPC request and wait for response
210
+ */
211
+ async sendRequest(method: string, params?: Record<string, any>): Promise<any> {
212
+ if (!this.connected || !this.process?.stdin?.writable) {
213
+ throw new Error('Not connected');
214
+ }
215
+
216
+ const id = ++this.requestId;
217
+ const request: JSONRPCRequest = {
218
+ jsonrpc: '2.0',
219
+ id,
220
+ method,
221
+ params,
222
+ };
223
+
224
+ return new Promise((resolve, reject) => {
225
+ const timeout = setTimeout(() => {
226
+ this.pendingRequests.delete(id);
227
+ reject(new Error(`Request timeout for method: ${method}`));
228
+ }, this.config.requestTimeout || 60000);
229
+
230
+ this.pendingRequests.set(id, { resolve, reject, timeout });
231
+
232
+ try {
233
+ const message = JSON.stringify(request) + '\n';
234
+ this.process!.stdin!.write(message);
235
+ } catch (error) {
236
+ this.pendingRequests.delete(id);
237
+ clearTimeout(timeout);
238
+ reject(error);
239
+ }
240
+ });
241
+ }
242
+
243
+ /**
244
+ * Send a JSON-RPC message (request or notification)
245
+ */
246
+ async send(message: JSONRPCRequest | JSONRPCNotification): Promise<void> {
247
+ if (!this.connected || !this.process?.stdin?.writable) {
248
+ throw new Error('Not connected');
249
+ }
250
+
251
+ try {
252
+ const data = JSON.stringify(message) + '\n';
253
+ this.process.stdin.write(data);
254
+ } catch (error) {
255
+ throw new Error(`Failed to send message: ${error}`);
256
+ }
257
+ }
258
+
259
+ /**
260
+ * Register message handler
261
+ */
262
+ onMessage(handler: (message: JSONRPCResponse | JSONRPCNotification) => void): void {
263
+ this.messageHandler = handler;
264
+ }
265
+
266
+ /**
267
+ * Register close handler
268
+ */
269
+ onClose(handler: (error?: Error) => void): void {
270
+ this.closeHandler = handler;
271
+ }
272
+
273
+ /**
274
+ * Register error handler
275
+ */
276
+ onError(handler: (error: Error) => void): void {
277
+ this.errorHandler = handler;
278
+ }
279
+
280
+ /**
281
+ * Check if transport is connected
282
+ */
283
+ isConnected(): boolean {
284
+ return this.connected && !!this.process && !this.process.killed;
285
+ }
286
+
287
+ /**
288
+ * Handle incoming data from stdout
289
+ */
290
+ private handleData(data: Buffer): void {
291
+ this.buffer += data.toString();
292
+
293
+ // Process complete lines (JSON-RPC messages are newline-delimited)
294
+ let newlineIndex: number;
295
+ while ((newlineIndex = this.buffer.indexOf('\n')) !== -1) {
296
+ const line = this.buffer.slice(0, newlineIndex).trim();
297
+ this.buffer = this.buffer.slice(newlineIndex + 1);
298
+
299
+ if (line) {
300
+ try {
301
+ const message = JSON.parse(line);
302
+ this.handleMessage(message);
303
+ } catch (error) {
304
+ console.error(`[MCP StdioTransport] Failed to parse message: ${line}`);
305
+ }
306
+ }
307
+ }
308
+ }
309
+
310
+ /**
311
+ * Handle a parsed JSON-RPC message
312
+ */
313
+ private handleMessage(message: any): void {
314
+ // Check if this is a response to a pending request
315
+ if ('id' in message && message.id !== null) {
316
+ const pending = this.pendingRequests.get(message.id);
317
+ if (pending) {
318
+ this.pendingRequests.delete(message.id);
319
+ clearTimeout(pending.timeout);
320
+
321
+ if ('error' in message && message.error) {
322
+ pending.reject(new Error(message.error.message || 'Unknown error'));
323
+ } else {
324
+ pending.resolve(message.result);
325
+ }
326
+ return;
327
+ }
328
+ }
329
+
330
+ // Otherwise, pass to message handler (notifications)
331
+ this.messageHandler?.(message as JSONRPCResponse | JSONRPCNotification);
332
+ }
333
+
334
+ /**
335
+ * Cleanup resources
336
+ */
337
+ private cleanup(): void {
338
+ this.connected = false;
339
+ this.buffer = '';
340
+ this.stderrBuffer = '';
341
+
342
+ // Clear all pending requests
343
+ for (const [, pending] of this.pendingRequests) {
344
+ clearTimeout(pending.timeout);
345
+ }
346
+ this.pendingRequests.clear();
347
+
348
+ if (this.process) {
349
+ this.process.removeAllListeners();
350
+ this.process.stdout?.removeAllListeners();
351
+ this.process.stderr?.removeAllListeners();
352
+ this.process = null;
353
+ }
354
+ }
355
+ }