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,626 @@
1
+ /**
2
+ * Webhook Tunnel Manager
3
+ *
4
+ * Provides automatic tunnel creation for webhook-based channel adapters.
5
+ * Supports multiple tunnel providers:
6
+ * - ngrok: Popular tunneling service (requires account for persistent URLs)
7
+ * - Tailscale Funnel: Private networking with public endpoints
8
+ * - Cloudflare Tunnel: Enterprise-grade tunneling (cloudflared)
9
+ *
10
+ * Usage:
11
+ * const tunnel = new TunnelManager({ provider: 'ngrok', port: 3000 });
12
+ * const url = await tunnel.start();
13
+ * // Use url for webhook configuration
14
+ * await tunnel.stop();
15
+ */
16
+
17
+ import { spawn, ChildProcess, execSync } from 'child_process';
18
+ import { EventEmitter } from 'events';
19
+ import * as net from 'net';
20
+ import * as http from 'http';
21
+ import * as https from 'https';
22
+
23
+ /**
24
+ * Tunnel provider types
25
+ */
26
+ export type TunnelProvider = 'ngrok' | 'tailscale' | 'cloudflare' | 'localtunnel';
27
+
28
+ /**
29
+ * Tunnel status
30
+ */
31
+ export type TunnelStatus = 'stopped' | 'starting' | 'running' | 'error';
32
+
33
+ /**
34
+ * Tunnel configuration
35
+ */
36
+ export interface TunnelConfig {
37
+ /** Tunnel provider to use */
38
+ provider: TunnelProvider;
39
+
40
+ /** Local port to tunnel */
41
+ port: number;
42
+
43
+ /** Local host (default: localhost) */
44
+ host?: string;
45
+
46
+ /** ngrok auth token (optional, enables more features) */
47
+ ngrokAuthToken?: string;
48
+
49
+ /** ngrok region (default: us) */
50
+ ngrokRegion?: 'us' | 'eu' | 'ap' | 'au' | 'sa' | 'jp' | 'in';
51
+
52
+ /** ngrok subdomain (requires paid plan) */
53
+ ngrokSubdomain?: string;
54
+
55
+ /** Tailscale funnel hostname */
56
+ tailscaleHostname?: string;
57
+
58
+ /** Cloudflare tunnel name */
59
+ cloudflareTunnelName?: string;
60
+
61
+ /** Cloudflare credentials file */
62
+ cloudflareCredentialsFile?: string;
63
+
64
+ /** Protocol (default: https for ngrok/tailscale, http for localtunnel) */
65
+ protocol?: 'http' | 'https';
66
+
67
+ /** Path prefix for webhook endpoint */
68
+ pathPrefix?: string;
69
+
70
+ /** Enable verbose logging */
71
+ verbose?: boolean;
72
+
73
+ /** Auto-restart on failure */
74
+ autoRestart?: boolean;
75
+
76
+ /** Restart delay in ms (default: 5000) */
77
+ restartDelay?: number;
78
+ }
79
+
80
+ /**
81
+ * Tunnel information
82
+ */
83
+ export interface TunnelInfo {
84
+ /** Public URL */
85
+ url: string;
86
+
87
+ /** Tunnel provider */
88
+ provider: TunnelProvider;
89
+
90
+ /** Local port */
91
+ port: number;
92
+
93
+ /** Tunnel status */
94
+ status: TunnelStatus;
95
+
96
+ /** Started at timestamp */
97
+ startedAt?: Date;
98
+
99
+ /** Error message (if status is error) */
100
+ error?: string;
101
+
102
+ /** Additional provider-specific info */
103
+ extra?: Record<string, unknown>;
104
+ }
105
+
106
+ /**
107
+ * Tunnel Manager
108
+ */
109
+ export class TunnelManager extends EventEmitter {
110
+ private config: Required<TunnelConfig>;
111
+ private process?: ChildProcess;
112
+ private _status: TunnelStatus = 'stopped';
113
+ private _url?: string;
114
+ private _startedAt?: Date;
115
+ private _error?: string;
116
+ private restartTimer?: NodeJS.Timeout;
117
+
118
+ constructor(config: TunnelConfig) {
119
+ super();
120
+
121
+ this.config = {
122
+ host: 'localhost',
123
+ protocol: config.provider === 'localtunnel' ? 'http' : 'https',
124
+ pathPrefix: '',
125
+ verbose: false,
126
+ autoRestart: true,
127
+ restartDelay: 5000,
128
+ ngrokRegion: 'us',
129
+ ...config,
130
+ } as Required<TunnelConfig>;
131
+ }
132
+
133
+ /**
134
+ * Get current status
135
+ */
136
+ get status(): TunnelStatus {
137
+ return this._status;
138
+ }
139
+
140
+ /**
141
+ * Get tunnel URL
142
+ */
143
+ get url(): string | undefined {
144
+ return this._url;
145
+ }
146
+
147
+ /**
148
+ * Get tunnel info
149
+ */
150
+ getInfo(): TunnelInfo {
151
+ return {
152
+ url: this._url || '',
153
+ provider: this.config.provider,
154
+ port: this.config.port,
155
+ status: this._status,
156
+ startedAt: this._startedAt,
157
+ error: this._error,
158
+ };
159
+ }
160
+
161
+ /**
162
+ * Start the tunnel
163
+ */
164
+ async start(): Promise<string> {
165
+ if (this._status === 'running') {
166
+ return this._url!;
167
+ }
168
+
169
+ if (this._status === 'starting') {
170
+ // Wait for startup to complete
171
+ return new Promise((resolve, reject) => {
172
+ const onRunning = () => {
173
+ this.off('error', onError);
174
+ resolve(this._url!);
175
+ };
176
+ const onError = (error: Error) => {
177
+ this.off('running', onRunning);
178
+ reject(error);
179
+ };
180
+ this.once('running', onRunning);
181
+ this.once('error', onError);
182
+ });
183
+ }
184
+
185
+ this._status = 'starting';
186
+ this._error = undefined;
187
+ this.emit('starting');
188
+
189
+ try {
190
+ // Check if provider is available
191
+ await this.checkProviderInstalled();
192
+
193
+ // Start the tunnel
194
+ switch (this.config.provider) {
195
+ case 'ngrok':
196
+ this._url = await this.startNgrok();
197
+ break;
198
+ case 'tailscale':
199
+ this._url = await this.startTailscale();
200
+ break;
201
+ case 'cloudflare':
202
+ this._url = await this.startCloudflare();
203
+ break;
204
+ case 'localtunnel':
205
+ this._url = await this.startLocaltunnel();
206
+ break;
207
+ default:
208
+ throw new Error(`Unsupported tunnel provider: ${this.config.provider}`);
209
+ }
210
+
211
+ this._status = 'running';
212
+ this._startedAt = new Date();
213
+ this.emit('running', this._url);
214
+
215
+ if (this.config.verbose) {
216
+ console.log(`Tunnel started: ${this._url}`);
217
+ }
218
+
219
+ return this._url;
220
+ } catch (error) {
221
+ this._status = 'error';
222
+ this._error = error instanceof Error ? error.message : String(error);
223
+ this.emit('error', error);
224
+ throw error;
225
+ }
226
+ }
227
+
228
+ /**
229
+ * Stop the tunnel
230
+ */
231
+ async stop(): Promise<void> {
232
+ if (this.restartTimer) {
233
+ clearTimeout(this.restartTimer);
234
+ this.restartTimer = undefined;
235
+ }
236
+
237
+ if (this.process) {
238
+ this.process.kill('SIGTERM');
239
+ this.process = undefined;
240
+ }
241
+
242
+ this._status = 'stopped';
243
+ this._url = undefined;
244
+ this._startedAt = undefined;
245
+ this.emit('stopped');
246
+
247
+ if (this.config.verbose) {
248
+ console.log('Tunnel stopped');
249
+ }
250
+ }
251
+
252
+ /**
253
+ * Restart the tunnel
254
+ */
255
+ async restart(): Promise<string> {
256
+ await this.stop();
257
+ return this.start();
258
+ }
259
+
260
+ /**
261
+ * Check if the provider is installed
262
+ */
263
+ private async checkProviderInstalled(): Promise<void> {
264
+ const commands: Record<TunnelProvider, string> = {
265
+ ngrok: 'ngrok version',
266
+ tailscale: 'tailscale version',
267
+ cloudflare: 'cloudflared version',
268
+ localtunnel: 'lt --version',
269
+ };
270
+
271
+ const command = commands[this.config.provider];
272
+
273
+ try {
274
+ execSync(command, { encoding: 'utf-8', stdio: 'pipe' });
275
+ } catch {
276
+ const installInstructions: Record<TunnelProvider, string> = {
277
+ ngrok: 'Install ngrok: brew install ngrok (macOS) or download from https://ngrok.com',
278
+ tailscale: 'Install Tailscale: https://tailscale.com/download',
279
+ cloudflare: 'Install cloudflared: brew install cloudflare/cloudflare/cloudflared',
280
+ localtunnel: 'Install localtunnel: npm install -g localtunnel',
281
+ };
282
+
283
+ throw new Error(`${this.config.provider} is not installed. ${installInstructions[this.config.provider]}`);
284
+ }
285
+ }
286
+
287
+ /**
288
+ * Start ngrok tunnel
289
+ */
290
+ private async startNgrok(): Promise<string> {
291
+ // If auth token provided, configure it first
292
+ if (this.config.ngrokAuthToken) {
293
+ try {
294
+ execSync(`ngrok config add-authtoken ${this.config.ngrokAuthToken}`, {
295
+ encoding: 'utf-8',
296
+ stdio: 'pipe',
297
+ });
298
+ } catch {
299
+ // Ignore if already configured
300
+ }
301
+ }
302
+
303
+ const args = ['http', `${this.config.host}:${this.config.port}`];
304
+
305
+ if (this.config.ngrokRegion) {
306
+ args.push('--region', this.config.ngrokRegion);
307
+ }
308
+
309
+ if (this.config.ngrokSubdomain) {
310
+ args.push('--subdomain', this.config.ngrokSubdomain);
311
+ }
312
+
313
+ // Start ngrok process
314
+ this.process = spawn('ngrok', args, {
315
+ stdio: ['ignore', 'pipe', 'pipe'],
316
+ });
317
+
318
+ this.setupProcessHandlers();
319
+
320
+ // Wait for ngrok to start and get URL from API
321
+ return this.waitForNgrokUrl();
322
+ }
323
+
324
+ /**
325
+ * Wait for ngrok to start and get URL from local API
326
+ */
327
+ private async waitForNgrokUrl(): Promise<string> {
328
+ const maxAttempts = 30;
329
+ const delay = 500;
330
+
331
+ for (let i = 0; i < maxAttempts; i++) {
332
+ try {
333
+ const response = await this.httpGet('http://127.0.0.1:4040/api/tunnels');
334
+ const data = JSON.parse(response);
335
+
336
+ if (data.tunnels && data.tunnels.length > 0) {
337
+ const tunnel = data.tunnels.find((t: { proto: string }) => t.proto === 'https') || data.tunnels[0];
338
+ return tunnel.public_url;
339
+ }
340
+ } catch {
341
+ // ngrok API not ready yet
342
+ }
343
+
344
+ await this.sleep(delay);
345
+ }
346
+
347
+ throw new Error('Timeout waiting for ngrok to start');
348
+ }
349
+
350
+ /**
351
+ * Start Tailscale Funnel
352
+ */
353
+ private async startTailscale(): Promise<string> {
354
+ // Check if Tailscale is connected
355
+ try {
356
+ const status = execSync('tailscale status --json', { encoding: 'utf-8' });
357
+ const statusData = JSON.parse(status);
358
+
359
+ if (!statusData.Self?.Online) {
360
+ throw new Error('Tailscale is not connected. Run: tailscale up');
361
+ }
362
+ } catch (error) {
363
+ if (error instanceof Error && error.message.includes('not connected')) {
364
+ throw error;
365
+ }
366
+ throw new Error('Failed to check Tailscale status');
367
+ }
368
+
369
+ // Enable funnel for the port
370
+ const args = ['funnel', `${this.config.port}`];
371
+
372
+ this.process = spawn('tailscale', args, {
373
+ stdio: ['ignore', 'pipe', 'pipe'],
374
+ });
375
+
376
+ this.setupProcessHandlers();
377
+
378
+ // Get the funnel URL
379
+ return this.getTailscaleFunnelUrl();
380
+ }
381
+
382
+ /**
383
+ * Get Tailscale Funnel URL
384
+ */
385
+ private async getTailscaleFunnelUrl(): Promise<string> {
386
+ try {
387
+ const status = execSync('tailscale status --json', { encoding: 'utf-8' });
388
+ const statusData = JSON.parse(status);
389
+ const hostname = statusData.Self?.DNSName?.replace(/\.$/, '') || this.config.tailscaleHostname;
390
+
391
+ if (!hostname) {
392
+ throw new Error('Could not determine Tailscale hostname');
393
+ }
394
+
395
+ return `https://${hostname}:${this.config.port}`;
396
+ } catch {
397
+ throw new Error('Failed to get Tailscale Funnel URL');
398
+ }
399
+ }
400
+
401
+ /**
402
+ * Start Cloudflare Tunnel
403
+ */
404
+ private async startCloudflare(): Promise<string> {
405
+ const args = ['tunnel'];
406
+
407
+ if (this.config.cloudflareCredentialsFile) {
408
+ args.push('--credentials-file', this.config.cloudflareCredentialsFile);
409
+ }
410
+
411
+ if (this.config.cloudflareTunnelName) {
412
+ args.push('run', this.config.cloudflareTunnelName);
413
+ } else {
414
+ // Quick tunnel (no account required)
415
+ args.push('--url', `http://${this.config.host}:${this.config.port}`);
416
+ }
417
+
418
+ this.process = spawn('cloudflared', args, {
419
+ stdio: ['ignore', 'pipe', 'pipe'],
420
+ });
421
+
422
+ this.setupProcessHandlers();
423
+
424
+ // Parse URL from output
425
+ return this.waitForCloudflareUrl();
426
+ }
427
+
428
+ /**
429
+ * Wait for Cloudflare tunnel URL from output
430
+ */
431
+ private async waitForCloudflareUrl(): Promise<string> {
432
+ return new Promise((resolve, reject) => {
433
+ const timeout = setTimeout(() => {
434
+ reject(new Error('Timeout waiting for Cloudflare tunnel URL'));
435
+ }, 30000);
436
+
437
+ const urlPattern = /https:\/\/[a-z0-9-]+\.trycloudflare\.com/;
438
+
439
+ const handleData = (data: Buffer) => {
440
+ const output = data.toString();
441
+ const match = output.match(urlPattern);
442
+ if (match) {
443
+ clearTimeout(timeout);
444
+ this.process?.stdout?.off('data', handleData);
445
+ this.process?.stderr?.off('data', handleData);
446
+ resolve(match[0]);
447
+ }
448
+ };
449
+
450
+ this.process?.stdout?.on('data', handleData);
451
+ this.process?.stderr?.on('data', handleData);
452
+ });
453
+ }
454
+
455
+ /**
456
+ * Start localtunnel
457
+ */
458
+ private async startLocaltunnel(): Promise<string> {
459
+ const args = ['--port', this.config.port.toString()];
460
+
461
+ if (this.config.host !== 'localhost') {
462
+ args.push('--local-host', this.config.host);
463
+ }
464
+
465
+ this.process = spawn('lt', args, {
466
+ stdio: ['ignore', 'pipe', 'pipe'],
467
+ });
468
+
469
+ this.setupProcessHandlers();
470
+
471
+ // Parse URL from output
472
+ return this.waitForLocaltunnelUrl();
473
+ }
474
+
475
+ /**
476
+ * Wait for localtunnel URL from output
477
+ */
478
+ private async waitForLocaltunnelUrl(): Promise<string> {
479
+ return new Promise((resolve, reject) => {
480
+ const timeout = setTimeout(() => {
481
+ reject(new Error('Timeout waiting for localtunnel URL'));
482
+ }, 30000);
483
+
484
+ const urlPattern = /https:\/\/[a-z0-9-]+\.loca\.lt/;
485
+
486
+ const handleData = (data: Buffer) => {
487
+ const output = data.toString();
488
+ const match = output.match(urlPattern);
489
+ if (match) {
490
+ clearTimeout(timeout);
491
+ this.process?.stdout?.off('data', handleData);
492
+ resolve(match[0]);
493
+ }
494
+ };
495
+
496
+ this.process?.stdout?.on('data', handleData);
497
+ });
498
+ }
499
+
500
+ /**
501
+ * Set up process event handlers
502
+ */
503
+ private setupProcessHandlers(): void {
504
+ if (!this.process) return;
505
+
506
+ this.process.on('exit', (code, signal) => {
507
+ if (this._status === 'running' && this.config.autoRestart) {
508
+ console.log(`Tunnel process exited (code: ${code}, signal: ${signal}), restarting...`);
509
+ this._status = 'stopped';
510
+ this.scheduleRestart();
511
+ }
512
+ });
513
+
514
+ this.process.on('error', (error) => {
515
+ console.error('Tunnel process error:', error);
516
+ this._status = 'error';
517
+ this._error = error.message;
518
+ this.emit('error', error);
519
+
520
+ if (this.config.autoRestart) {
521
+ this.scheduleRestart();
522
+ }
523
+ });
524
+
525
+ if (this.config.verbose && this.process.stderr) {
526
+ this.process.stderr.on('data', (data) => {
527
+ console.log(`[${this.config.provider}]`, data.toString().trim());
528
+ });
529
+ }
530
+ }
531
+
532
+ /**
533
+ * Schedule a restart
534
+ */
535
+ private scheduleRestart(): void {
536
+ if (this.restartTimer) {
537
+ return;
538
+ }
539
+
540
+ this.restartTimer = setTimeout(async () => {
541
+ this.restartTimer = undefined;
542
+ try {
543
+ await this.start();
544
+ } catch (error) {
545
+ console.error('Failed to restart tunnel:', error);
546
+ this.scheduleRestart();
547
+ }
548
+ }, this.config.restartDelay);
549
+ }
550
+
551
+ /**
552
+ * Simple HTTP GET request
553
+ */
554
+ private httpGet(url: string): Promise<string> {
555
+ return new Promise((resolve, reject) => {
556
+ const client = url.startsWith('https') ? https : http;
557
+
558
+ const request = client.get(url, (response) => {
559
+ let data = '';
560
+ response.on('data', (chunk) => {
561
+ data += chunk;
562
+ });
563
+ response.on('end', () => {
564
+ resolve(data);
565
+ });
566
+ });
567
+
568
+ request.on('error', reject);
569
+ request.setTimeout(5000, () => {
570
+ request.destroy();
571
+ reject(new Error('Request timeout'));
572
+ });
573
+ });
574
+ }
575
+
576
+ /**
577
+ * Sleep helper
578
+ */
579
+ private sleep(ms: number): Promise<void> {
580
+ return new Promise((resolve) => setTimeout(resolve, ms));
581
+ }
582
+ }
583
+
584
+ /**
585
+ * Check which tunnel providers are available
586
+ */
587
+ export async function getAvailableTunnelProviders(): Promise<TunnelProvider[]> {
588
+ const providers: TunnelProvider[] = [];
589
+ const commands: Record<TunnelProvider, string> = {
590
+ ngrok: 'ngrok version',
591
+ tailscale: 'tailscale version',
592
+ cloudflare: 'cloudflared version',
593
+ localtunnel: 'lt --version',
594
+ };
595
+
596
+ for (const [provider, command] of Object.entries(commands) as [TunnelProvider, string][]) {
597
+ try {
598
+ execSync(command, { encoding: 'utf-8', stdio: 'pipe' });
599
+ providers.push(provider);
600
+ } catch {
601
+ // Provider not installed
602
+ }
603
+ }
604
+
605
+ return providers;
606
+ }
607
+
608
+ /**
609
+ * Create a tunnel with auto-detection of available provider
610
+ */
611
+ export async function createAutoTunnel(port: number, preferredProvider?: TunnelProvider): Promise<TunnelManager> {
612
+ const available = await getAvailableTunnelProviders();
613
+
614
+ if (available.length === 0) {
615
+ throw new Error('No tunnel providers installed. Install ngrok, Tailscale, cloudflared, or localtunnel.');
616
+ }
617
+
618
+ let provider = preferredProvider;
619
+ if (!provider || !available.includes(provider)) {
620
+ // Priority: ngrok > tailscale > cloudflare > localtunnel
621
+ const priority: TunnelProvider[] = ['ngrok', 'tailscale', 'cloudflare', 'localtunnel'];
622
+ provider = priority.find((p) => available.includes(p))!;
623
+ }
624
+
625
+ return new TunnelManager({ provider, port });
626
+ }