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,62 @@
1
+ /**
2
+ * X/Twitter Settings Manager
3
+ *
4
+ * Stores X integration settings in encrypted database.
5
+ */
6
+
7
+ import { SecureSettingsRepository } from '../database/SecureSettingsRepository';
8
+ import { XSettingsData } from '../../shared/types';
9
+
10
+ const DEFAULT_SETTINGS: XSettingsData = {
11
+ enabled: false,
12
+ authMethod: 'browser',
13
+ cookieSource: ['chrome'],
14
+ timeoutMs: 20000,
15
+ cookieTimeoutMs: 20000,
16
+ quoteDepth: 1,
17
+ };
18
+
19
+ export class XSettingsManager {
20
+ private static cachedSettings: XSettingsData | null = null;
21
+
22
+ static loadSettings(): XSettingsData {
23
+ if (this.cachedSettings) {
24
+ return this.cachedSettings;
25
+ }
26
+
27
+ let settings: XSettingsData = { ...DEFAULT_SETTINGS };
28
+
29
+ try {
30
+ if (SecureSettingsRepository.isInitialized()) {
31
+ const repository = SecureSettingsRepository.getInstance();
32
+ const stored = repository.load<XSettingsData>('x');
33
+ if (stored) {
34
+ settings = { ...DEFAULT_SETTINGS, ...stored };
35
+ }
36
+ }
37
+ } catch (error) {
38
+ console.error('[XSettingsManager] Failed to load settings:', error);
39
+ }
40
+
41
+ this.cachedSettings = settings;
42
+ return settings;
43
+ }
44
+
45
+ static saveSettings(settings: XSettingsData): void {
46
+ try {
47
+ if (!SecureSettingsRepository.isInitialized()) {
48
+ throw new Error('SecureSettingsRepository not initialized');
49
+ }
50
+ const repository = SecureSettingsRepository.getInstance();
51
+ repository.save('x', settings);
52
+ this.cachedSettings = settings;
53
+ console.log('[XSettingsManager] Settings saved');
54
+ } catch (error) {
55
+ console.error('[XSettingsManager] Failed to save settings:', error);
56
+ }
57
+ }
58
+
59
+ static clearCache(): void {
60
+ this.cachedSettings = null;
61
+ }
62
+ }
@@ -0,0 +1,262 @@
1
+ /**
2
+ * Tailscale Exposure Manager
3
+ *
4
+ * High-level API for exposing local services via Tailscale Serve or Funnel.
5
+ * Handles lifecycle management, cleanup, and status tracking.
6
+ */
7
+
8
+ import {
9
+ isTailscaleInstalled,
10
+ getTailnetHostname,
11
+ enableTailscaleServe,
12
+ disableTailscaleServe,
13
+ enableTailscaleFunnel,
14
+ disableTailscaleFunnel,
15
+ checkTailscaleFunnelAvailable,
16
+ } from './tailscale';
17
+ import { TailscaleSettingsManager, type TailscaleMode } from './settings';
18
+
19
+ /**
20
+ * Configuration for starting Tailscale exposure
21
+ */
22
+ export interface TailscaleExposureConfig {
23
+ /** Mode: 'serve' (Tailnet only) or 'funnel' (public internet) */
24
+ mode: TailscaleMode;
25
+ /** Local port to expose */
26
+ port: number;
27
+ /** URL path prefix (default: '/') */
28
+ pathPrefix?: string;
29
+ /** Reset Tailscale config on cleanup */
30
+ resetOnExit?: boolean;
31
+ /** Logger functions */
32
+ log?: (message: string) => void;
33
+ warn?: (message: string) => void;
34
+ }
35
+
36
+ /**
37
+ * Result from starting Tailscale exposure
38
+ */
39
+ export interface TailscaleExposureResult {
40
+ /** Whether exposure was successfully enabled */
41
+ success: boolean;
42
+ /** The public/Tailnet hostname */
43
+ hostname?: string;
44
+ /** Full HTTPS URL to access the service */
45
+ httpsUrl?: string;
46
+ /** Full WebSocket URL */
47
+ wssUrl?: string;
48
+ /** Error message if failed */
49
+ error?: string;
50
+ /** Cleanup function to disable exposure */
51
+ cleanup?: () => Promise<void>;
52
+ }
53
+
54
+ /**
55
+ * Active exposure state tracking
56
+ */
57
+ interface ActiveExposure {
58
+ mode: TailscaleMode;
59
+ port: number;
60
+ hostname: string;
61
+ startedAt: number;
62
+ }
63
+
64
+ let activeExposure: ActiveExposure | null = null;
65
+
66
+ /**
67
+ * Get current exposure status
68
+ */
69
+ export function getExposureStatus(): {
70
+ active: boolean;
71
+ mode?: TailscaleMode;
72
+ hostname?: string;
73
+ httpsUrl?: string;
74
+ wssUrl?: string;
75
+ startedAt?: number;
76
+ } {
77
+ if (!activeExposure) {
78
+ return { active: false };
79
+ }
80
+
81
+ return {
82
+ active: true,
83
+ mode: activeExposure.mode,
84
+ hostname: activeExposure.hostname,
85
+ httpsUrl: `https://${activeExposure.hostname}`,
86
+ wssUrl: `wss://${activeExposure.hostname}`,
87
+ startedAt: activeExposure.startedAt,
88
+ };
89
+ }
90
+
91
+ /**
92
+ * Start Tailscale exposure for a local service
93
+ *
94
+ * @param config - Exposure configuration
95
+ * @returns Result with URLs and cleanup function
96
+ */
97
+ export async function startTailscaleExposure(
98
+ config: TailscaleExposureConfig
99
+ ): Promise<TailscaleExposureResult> {
100
+ const log = config.log || console.log;
101
+ const warn = config.warn || console.warn;
102
+
103
+ // Return early if mode is 'off'
104
+ if (config.mode === 'off') {
105
+ return { success: true };
106
+ }
107
+
108
+ // Check if Tailscale is installed
109
+ const installed = await isTailscaleInstalled();
110
+ if (!installed) {
111
+ const error = 'Tailscale is not installed. Please install Tailscale first.';
112
+ warn(`[Tailscale Exposure] ${error}`);
113
+ return { success: false, error };
114
+ }
115
+
116
+ // If mode is funnel, check availability
117
+ if (config.mode === 'funnel') {
118
+ const funnelAvailable = await checkTailscaleFunnelAvailable();
119
+ if (!funnelAvailable) {
120
+ warn('[Tailscale Exposure] Funnel not available, falling back to Serve mode');
121
+ config.mode = 'serve';
122
+ }
123
+ }
124
+
125
+ // Enable the appropriate mode
126
+ let enabled = false;
127
+ try {
128
+ if (config.mode === 'funnel') {
129
+ enabled = await enableTailscaleFunnel(config.port, config.pathPrefix || '/');
130
+ } else if (config.mode === 'serve') {
131
+ enabled = await enableTailscaleServe(config.port, config.pathPrefix || '/');
132
+ }
133
+ } catch (error: any) {
134
+ const message = error.message || String(error);
135
+ warn(`[Tailscale Exposure] Failed to enable ${config.mode}: ${message}`);
136
+ return { success: false, error: message };
137
+ }
138
+
139
+ if (!enabled) {
140
+ const error = `Failed to enable Tailscale ${config.mode}`;
141
+ return { success: false, error };
142
+ }
143
+
144
+ // Get the hostname
145
+ const hostname = await getTailnetHostname();
146
+ if (!hostname) {
147
+ warn('[Tailscale Exposure] Could not determine Tailnet hostname');
148
+ // Try to clean up
149
+ if (config.mode === 'funnel') {
150
+ await disableTailscaleFunnel();
151
+ } else {
152
+ await disableTailscaleServe();
153
+ }
154
+ return { success: false, error: 'Could not determine Tailnet hostname' };
155
+ }
156
+
157
+ // Build URLs
158
+ const pathPrefix = config.pathPrefix || '';
159
+ const httpsUrl = `https://${hostname}${pathPrefix}`;
160
+ const wssUrl = `wss://${hostname}${pathPrefix}`;
161
+
162
+ // Update settings
163
+ TailscaleSettingsManager.updateSettings({
164
+ mode: config.mode,
165
+ lastHostname: hostname,
166
+ lastStatusCheck: Date.now(),
167
+ resetOnExit: config.resetOnExit ?? true,
168
+ pathPrefix: config.pathPrefix,
169
+ });
170
+
171
+ // Track active exposure
172
+ activeExposure = {
173
+ mode: config.mode,
174
+ port: config.port,
175
+ hostname,
176
+ startedAt: Date.now(),
177
+ };
178
+
179
+ log(`[Tailscale Exposure] ${config.mode === 'funnel' ? 'Funnel' : 'Serve'} enabled`);
180
+ log(`[Tailscale Exposure] HTTPS: ${httpsUrl}`);
181
+ log(`[Tailscale Exposure] WSS: ${wssUrl}`);
182
+
183
+ // Create cleanup function
184
+ const cleanup = async () => {
185
+ try {
186
+ if (config.resetOnExit !== false) {
187
+ if (config.mode === 'funnel') {
188
+ await disableTailscaleFunnel();
189
+ } else if (config.mode === 'serve') {
190
+ await disableTailscaleServe();
191
+ }
192
+ log(`[Tailscale Exposure] ${config.mode} disabled`);
193
+ }
194
+ } catch (error: any) {
195
+ warn(`[Tailscale Exposure] Cleanup error: ${error.message || error}`);
196
+ } finally {
197
+ activeExposure = null;
198
+ TailscaleSettingsManager.updateSettings({ mode: 'off' });
199
+ }
200
+ };
201
+
202
+ return {
203
+ success: true,
204
+ hostname,
205
+ httpsUrl,
206
+ wssUrl,
207
+ cleanup,
208
+ };
209
+ }
210
+
211
+ /**
212
+ * Stop any active Tailscale exposure
213
+ */
214
+ export async function stopTailscaleExposure(): Promise<void> {
215
+ if (!activeExposure) {
216
+ return;
217
+ }
218
+
219
+ try {
220
+ if (activeExposure.mode === 'funnel') {
221
+ await disableTailscaleFunnel();
222
+ } else if (activeExposure.mode === 'serve') {
223
+ await disableTailscaleServe();
224
+ }
225
+ console.log(`[Tailscale Exposure] ${activeExposure.mode} disabled`);
226
+ } catch (error: any) {
227
+ console.error('[Tailscale Exposure] Stop error:', error.message || error);
228
+ } finally {
229
+ activeExposure = null;
230
+ TailscaleSettingsManager.updateSettings({ mode: 'off' });
231
+ }
232
+ }
233
+
234
+ /**
235
+ * Check Tailscale availability and status
236
+ */
237
+ export async function checkTailscaleAvailability(): Promise<{
238
+ installed: boolean;
239
+ funnelAvailable: boolean;
240
+ hostname: string | null;
241
+ }> {
242
+ const installed = await isTailscaleInstalled();
243
+
244
+ if (!installed) {
245
+ return {
246
+ installed: false,
247
+ funnelAvailable: false,
248
+ hostname: null,
249
+ };
250
+ }
251
+
252
+ const [funnelAvailable, hostname] = await Promise.all([
253
+ checkTailscaleFunnelAvailable(),
254
+ getTailnetHostname(),
255
+ ]);
256
+
257
+ return {
258
+ installed: true,
259
+ funnelAvailable,
260
+ hostname,
261
+ };
262
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Tailscale Integration Module
3
+ *
4
+ * Provides utilities for Tailscale Serve and Funnel functionality.
5
+ * - Serve: Share local services to your Tailnet (private network)
6
+ * - Funnel: Expose local services to the public internet via Tailscale
7
+ */
8
+
9
+ export {
10
+ findTailscaleBinary,
11
+ getTailscaleBinary,
12
+ isTailscaleInstalled,
13
+ getTailscaleStatus,
14
+ getTailnetHostname,
15
+ enableTailscaleServe,
16
+ disableTailscaleServe,
17
+ enableTailscaleFunnel,
18
+ disableTailscaleFunnel,
19
+ checkTailscaleFunnelAvailable,
20
+ } from './tailscale';
21
+
22
+ export {
23
+ TailscaleSettingsManager,
24
+ type TailscaleSettings,
25
+ } from './settings';
26
+
27
+ export {
28
+ startTailscaleExposure,
29
+ stopTailscaleExposure,
30
+ getExposureStatus,
31
+ checkTailscaleAvailability,
32
+ type TailscaleExposureConfig,
33
+ type TailscaleExposureResult,
34
+ } from './exposure';
@@ -0,0 +1,218 @@
1
+ /**
2
+ * Tailscale Settings Manager
3
+ *
4
+ * Manages Tailscale configuration persistence.
5
+ * Settings are stored encrypted in the database using SecureSettingsRepository.
6
+ */
7
+
8
+ import { app } from 'electron';
9
+ import * as fs from 'fs';
10
+ import * as path from 'path';
11
+ import { SecureSettingsRepository } from '../database/SecureSettingsRepository';
12
+
13
+ const LEGACY_SETTINGS_FILE = 'tailscale-settings.json';
14
+
15
+ /**
16
+ * Tailscale mode options
17
+ * - off: Tailscale integration disabled
18
+ * - serve: Expose to Tailnet (private network)
19
+ * - funnel: Expose to public internet
20
+ */
21
+ export type TailscaleMode = 'off' | 'serve' | 'funnel';
22
+
23
+ /**
24
+ * Tailscale settings interface
25
+ */
26
+ export interface TailscaleSettings {
27
+ /** Current mode */
28
+ mode: TailscaleMode;
29
+ /** Whether to reset Tailscale config on app exit */
30
+ resetOnExit: boolean;
31
+ /** Custom path prefix for the exposed endpoint */
32
+ pathPrefix?: string;
33
+ /** Last known hostname */
34
+ lastHostname?: string;
35
+ /** Timestamp of last status check */
36
+ lastStatusCheck?: number;
37
+ }
38
+
39
+ /**
40
+ * Default Tailscale settings
41
+ */
42
+ export const DEFAULT_TAILSCALE_SETTINGS: TailscaleSettings = {
43
+ mode: 'off',
44
+ resetOnExit: true,
45
+ };
46
+
47
+ /**
48
+ * Tailscale Settings Manager
49
+ */
50
+ export class TailscaleSettingsManager {
51
+ private static legacySettingsPath: string;
52
+ private static cachedSettings: TailscaleSettings | null = null;
53
+ private static initialized = false;
54
+ private static migrationCompleted = false;
55
+
56
+ /**
57
+ * Initialize the settings manager (must be called after app is ready)
58
+ */
59
+ static initialize(): void {
60
+ if (this.initialized) return;
61
+
62
+ const userDataPath = app.getPath('userData');
63
+ this.legacySettingsPath = path.join(userDataPath, LEGACY_SETTINGS_FILE);
64
+ this.initialized = true;
65
+
66
+ console.log('[Tailscale Settings] Initialized');
67
+
68
+ // Migrate from legacy JSON file to encrypted database
69
+ this.migrateFromLegacyFile();
70
+ }
71
+
72
+ /**
73
+ * Migrate settings from legacy JSON file to encrypted database
74
+ */
75
+ private static migrateFromLegacyFile(): void {
76
+ if (this.migrationCompleted) return;
77
+
78
+ try {
79
+ if (!SecureSettingsRepository.isInitialized()) {
80
+ console.log('[Tailscale Settings] SecureSettingsRepository not yet initialized, skipping migration');
81
+ return;
82
+ }
83
+
84
+ const repository = SecureSettingsRepository.getInstance();
85
+
86
+ if (repository.exists('tailscale')) {
87
+ this.migrationCompleted = true;
88
+ return;
89
+ }
90
+
91
+ if (!fs.existsSync(this.legacySettingsPath)) {
92
+ console.log('[Tailscale Settings] No legacy settings file found');
93
+ this.migrationCompleted = true;
94
+ return;
95
+ }
96
+
97
+ console.log('[Tailscale Settings] Migrating settings from legacy JSON file to encrypted database...');
98
+
99
+ // Create backup before migration
100
+ const backupPath = this.legacySettingsPath + '.migration-backup';
101
+ fs.copyFileSync(this.legacySettingsPath, backupPath);
102
+
103
+ try {
104
+ const data = fs.readFileSync(this.legacySettingsPath, 'utf-8');
105
+ const legacySettings = { ...DEFAULT_TAILSCALE_SETTINGS, ...JSON.parse(data) };
106
+
107
+ repository.save('tailscale', legacySettings);
108
+ console.log('[Tailscale Settings] Settings migrated to encrypted database');
109
+
110
+ // Migration successful - delete backup and original
111
+ fs.unlinkSync(backupPath);
112
+ fs.unlinkSync(this.legacySettingsPath);
113
+ console.log('[Tailscale Settings] Migration complete, cleaned up legacy files');
114
+
115
+ this.migrationCompleted = true;
116
+ } catch (migrationError) {
117
+ console.error('[Tailscale Settings] Migration failed, backup preserved at:', backupPath);
118
+ throw migrationError;
119
+ }
120
+ } catch (error) {
121
+ console.error('[Tailscale Settings] Migration failed:', error);
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Ensure the manager is initialized
127
+ */
128
+ private static ensureInitialized(): void {
129
+ if (!this.initialized) {
130
+ this.initialize();
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Load settings from encrypted database
136
+ */
137
+ static loadSettings(): TailscaleSettings {
138
+ this.ensureInitialized();
139
+
140
+ if (this.cachedSettings) {
141
+ return this.cachedSettings;
142
+ }
143
+
144
+ try {
145
+ if (SecureSettingsRepository.isInitialized()) {
146
+ const repository = SecureSettingsRepository.getInstance();
147
+ const stored = repository.load<TailscaleSettings>('tailscale');
148
+ if (stored) {
149
+ const merged: TailscaleSettings = {
150
+ ...DEFAULT_TAILSCALE_SETTINGS,
151
+ ...stored,
152
+ };
153
+ this.cachedSettings = merged;
154
+ console.log('[Tailscale Settings] Loaded settings from encrypted database');
155
+ return this.cachedSettings;
156
+ }
157
+ }
158
+ } catch (error) {
159
+ console.error('[Tailscale Settings] Failed to load settings:', error);
160
+ }
161
+
162
+ console.log('[Tailscale Settings] No settings found, using defaults');
163
+ this.cachedSettings = { ...DEFAULT_TAILSCALE_SETTINGS };
164
+ return this.cachedSettings;
165
+ }
166
+
167
+ /**
168
+ * Save settings to encrypted database
169
+ */
170
+ static saveSettings(settings: TailscaleSettings): void {
171
+ this.ensureInitialized();
172
+
173
+ try {
174
+ if (!SecureSettingsRepository.isInitialized()) {
175
+ throw new Error('SecureSettingsRepository not initialized');
176
+ }
177
+
178
+ const repository = SecureSettingsRepository.getInstance();
179
+ repository.save('tailscale', settings);
180
+ this.cachedSettings = settings;
181
+ console.log('[Tailscale Settings] Saved settings to encrypted database');
182
+ } catch (error) {
183
+ console.error('[Tailscale Settings] Failed to save settings:', error);
184
+ throw error;
185
+ }
186
+ }
187
+
188
+ /**
189
+ * Update settings partially
190
+ */
191
+ static updateSettings(updates: Partial<TailscaleSettings>): TailscaleSettings {
192
+ const settings = this.loadSettings();
193
+ const updated = { ...settings, ...updates };
194
+ this.saveSettings(updated);
195
+ return updated;
196
+ }
197
+
198
+ /**
199
+ * Set the Tailscale mode
200
+ */
201
+ static setMode(mode: TailscaleMode): TailscaleSettings {
202
+ return this.updateSettings({ mode });
203
+ }
204
+
205
+ /**
206
+ * Clear the settings cache
207
+ */
208
+ static clearCache(): void {
209
+ this.cachedSettings = null;
210
+ }
211
+
212
+ /**
213
+ * Get default settings
214
+ */
215
+ static getDefaults(): TailscaleSettings {
216
+ return { ...DEFAULT_TAILSCALE_SETTINGS };
217
+ }
218
+ }