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,6 @@
1
+ /**
2
+ * Tray Module - macOS Menu Bar Integration
3
+ */
4
+
5
+ export { TrayManager, trayManager } from './TrayManager';
6
+ export type { TraySettings, TrayManagerOptions } from './TrayManager';
@@ -0,0 +1 @@
1
+ export { UpdateManager, updateManager } from './update-manager';
@@ -0,0 +1,447 @@
1
+ import { app, BrowserWindow } from 'electron';
2
+ import { exec, spawn } from 'child_process';
3
+ import { promisify } from 'util';
4
+ import * as path from 'path';
5
+ import * as fs from 'fs';
6
+ import { UpdateInfo, UpdateProgress, AppVersionInfo, IPC_CHANNELS } from '../../shared/types';
7
+
8
+ const execAsync = promisify(exec);
9
+
10
+ interface GitHubRelease {
11
+ tag_name: string;
12
+ name: string;
13
+ body: string;
14
+ html_url: string;
15
+ published_at: string;
16
+ assets: Array<{
17
+ name: string;
18
+ browser_download_url: string;
19
+ size: number;
20
+ }>;
21
+ }
22
+
23
+ export class UpdateManager {
24
+ private mainWindow: BrowserWindow | null = null;
25
+ private repoOwner = 'CoWork-OS';
26
+ private repoName = 'cowork-os';
27
+ private isUpdating = false;
28
+
29
+ setMainWindow(window: BrowserWindow): void {
30
+ this.mainWindow = window;
31
+ }
32
+
33
+ private sendProgress(progress: UpdateProgress): void {
34
+ if (this.mainWindow && !this.mainWindow.isDestroyed()) {
35
+ this.mainWindow.webContents.send(IPC_CHANNELS.APP_UPDATE_PROGRESS, progress);
36
+ }
37
+ }
38
+
39
+ private sendError(error: string): void {
40
+ if (this.mainWindow && !this.mainWindow.isDestroyed()) {
41
+ this.mainWindow.webContents.send(IPC_CHANNELS.APP_UPDATE_ERROR, { error });
42
+ }
43
+ }
44
+
45
+ async getVersionInfo(): Promise<AppVersionInfo> {
46
+ const version = app.getVersion();
47
+ const isDev = !app.isPackaged;
48
+ let isGitRepo = false;
49
+ let isNpmGlobal = false;
50
+ let gitBranch: string | undefined;
51
+ let gitCommit: string | undefined;
52
+
53
+ const appPath = app.getAppPath();
54
+
55
+ // Check if installed via npm global
56
+ isNpmGlobal = this.detectNpmGlobalInstall(appPath);
57
+
58
+ if (isDev && !isNpmGlobal) {
59
+ try {
60
+ const { stdout: branchOut } = await execAsync('git rev-parse --abbrev-ref HEAD', { cwd: appPath });
61
+ gitBranch = branchOut.trim();
62
+
63
+ const { stdout: commitOut } = await execAsync('git rev-parse --short HEAD', { cwd: appPath });
64
+ gitCommit = commitOut.trim();
65
+
66
+ isGitRepo = true;
67
+ } catch {
68
+ isGitRepo = false;
69
+ }
70
+ }
71
+
72
+ return {
73
+ version,
74
+ isDev,
75
+ isGitRepo,
76
+ isNpmGlobal,
77
+ gitBranch,
78
+ gitCommit,
79
+ };
80
+ }
81
+
82
+ private detectNpmGlobalInstall(appPath: string): boolean {
83
+ // Check common npm global installation paths
84
+ const npmGlobalPatterns = [
85
+ '/usr/local/lib/node_modules',
86
+ '/usr/lib/node_modules',
87
+ '/opt/homebrew/lib/node_modules',
88
+ 'node_modules/cowork-os',
89
+ '.nvm/versions/node',
90
+ '.npm-global',
91
+ 'AppData/Roaming/npm/node_modules', // Windows
92
+ ];
93
+
94
+ const normalizedPath = appPath.replace(/\\/g, '/');
95
+ return npmGlobalPatterns.some(pattern => normalizedPath.includes(pattern));
96
+ }
97
+
98
+ async checkForUpdates(): Promise<UpdateInfo> {
99
+ const versionInfo = await this.getVersionInfo();
100
+ const currentVersion = versionInfo.version;
101
+
102
+ this.sendProgress({ phase: 'checking', message: 'Checking for updates...' });
103
+
104
+ try {
105
+ // Fetch latest release from GitHub
106
+ const response = await fetch(
107
+ `https://api.github.com/repos/${this.repoOwner}/${this.repoName}/releases/latest`,
108
+ {
109
+ headers: {
110
+ 'Accept': 'application/vnd.github.v3+json',
111
+ 'User-Agent': 'CoWork-OS-Updater',
112
+ },
113
+ }
114
+ );
115
+
116
+ if (!response.ok) {
117
+ if (response.status === 404) {
118
+ return {
119
+ available: false,
120
+ currentVersion,
121
+ latestVersion: currentVersion,
122
+ updateMode: this.getUpdateMode(versionInfo),
123
+ };
124
+ }
125
+ throw new Error(`GitHub API error: ${response.status}`);
126
+ }
127
+
128
+ const release = await response.json() as GitHubRelease;
129
+ const latestVersion = release.tag_name.replace(/^v/, '');
130
+ const available = this.isNewerVersion(latestVersion, currentVersion);
131
+
132
+ // Determine update mode based on installation type
133
+ const updateMode = this.getUpdateMode(versionInfo);
134
+
135
+ if (versionInfo.isGitRepo && !available) {
136
+ // Only check for new commits if versions are equal (not if local version is newer)
137
+ const localIsNewer = this.isNewerVersion(currentVersion, latestVersion);
138
+ if (!localIsNewer) {
139
+ // Check for new commits even if version tag is same
140
+ const hasNewCommits = await this.checkForNewCommits();
141
+ if (hasNewCommits) {
142
+ return {
143
+ available: true,
144
+ currentVersion: `${currentVersion} (${versionInfo.gitCommit})`,
145
+ latestVersion: `${latestVersion} (new commits)`,
146
+ releaseNotes: 'New commits available on the main branch.',
147
+ releaseUrl: `https://github.com/${this.repoOwner}/${this.repoName}`,
148
+ updateMode: 'git',
149
+ };
150
+ }
151
+ }
152
+ }
153
+
154
+ return {
155
+ available,
156
+ currentVersion,
157
+ latestVersion,
158
+ releaseNotes: release.body,
159
+ releaseUrl: release.html_url,
160
+ publishedAt: release.published_at,
161
+ updateMode,
162
+ };
163
+ } catch (error: any) {
164
+ this.sendError(error.message);
165
+ throw error;
166
+ }
167
+ }
168
+
169
+ private async checkForNewCommits(): Promise<boolean> {
170
+ try {
171
+ const appPath = app.getAppPath();
172
+
173
+ // Fetch latest from remote
174
+ await execAsync('git fetch origin', { cwd: appPath });
175
+
176
+ // Check if there are commits ahead on remote
177
+ const { stdout } = await execAsync('git rev-list HEAD..origin/main --count', { cwd: appPath });
178
+ const commitsAhead = parseInt(stdout.trim(), 10);
179
+
180
+ return commitsAhead > 0;
181
+ } catch {
182
+ return false;
183
+ }
184
+ }
185
+
186
+ private isNewerVersion(latest: string, current: string): boolean {
187
+ // Normalize versions: convert "0.3.9-1" to "0.3.9.1" for comparison
188
+ const normalizeVersion = (v: string): number[] => {
189
+ // Replace hyphens with dots for consistent parsing
190
+ const normalized = v.replace(/-/g, '.');
191
+ return normalized.split('.').map(n => parseInt(n, 10) || 0);
192
+ };
193
+
194
+ const latestParts = normalizeVersion(latest);
195
+ const currentParts = normalizeVersion(current);
196
+
197
+ for (let i = 0; i < Math.max(latestParts.length, currentParts.length); i++) {
198
+ const l = latestParts[i] || 0;
199
+ const c = currentParts[i] || 0;
200
+ if (l > c) return true;
201
+ if (l < c) return false;
202
+ }
203
+ return false;
204
+ }
205
+
206
+ private getUpdateMode(versionInfo: AppVersionInfo): 'git' | 'npm' | 'electron-updater' {
207
+ if (versionInfo.isNpmGlobal) {
208
+ return 'npm';
209
+ }
210
+ if (versionInfo.isGitRepo) {
211
+ return 'git';
212
+ }
213
+ return 'electron-updater';
214
+ }
215
+
216
+ async downloadAndInstallUpdate(updateInfo: UpdateInfo): Promise<void> {
217
+ if (this.isUpdating) {
218
+ throw new Error('Update already in progress');
219
+ }
220
+
221
+ this.isUpdating = true;
222
+
223
+ try {
224
+ if (updateInfo.updateMode === 'npm') {
225
+ await this.npmUpdate();
226
+ } else if (updateInfo.updateMode === 'git') {
227
+ await this.gitUpdate();
228
+ } else {
229
+ await this.electronUpdaterUpdate();
230
+ }
231
+ } finally {
232
+ this.isUpdating = false;
233
+ }
234
+ }
235
+
236
+ private async gitUpdate(): Promise<void> {
237
+ const appPath = app.getAppPath();
238
+
239
+ try {
240
+ // Step 1: Stash any local changes
241
+ this.sendProgress({ phase: 'downloading', percent: 10, message: 'Stashing local changes...' });
242
+ try {
243
+ await execAsync('git stash', { cwd: appPath });
244
+ } catch {
245
+ // Ignore if nothing to stash
246
+ }
247
+
248
+ // Step 2: Fetch and pull latest
249
+ this.sendProgress({ phase: 'downloading', percent: 30, message: 'Pulling latest changes from GitHub...' });
250
+ await execAsync('git fetch origin', { cwd: appPath });
251
+ await execAsync('git pull origin main', { cwd: appPath });
252
+
253
+ // Step 3: Install dependencies
254
+ this.sendProgress({ phase: 'installing', percent: 50, message: 'Installing dependencies (npm install)...' });
255
+ await this.runNpmInstall(appPath);
256
+
257
+ // Step 4: Rebuild
258
+ this.sendProgress({ phase: 'installing', percent: 80, message: 'Building application (npm run build)...' });
259
+ await this.runNpmBuild(appPath);
260
+
261
+ // Step 5: Complete
262
+ this.sendProgress({ phase: 'complete', percent: 100, message: 'Update complete! Please restart the application.' });
263
+
264
+ if (this.mainWindow && !this.mainWindow.isDestroyed()) {
265
+ this.mainWindow.webContents.send(IPC_CHANNELS.APP_UPDATE_DOWNLOADED, {
266
+ requiresRestart: true,
267
+ message: 'Update complete! Please restart the application to apply changes.',
268
+ });
269
+ }
270
+ } catch (error: any) {
271
+ this.sendProgress({ phase: 'error', message: `Update failed: ${error.message}` });
272
+ this.sendError(error.message);
273
+ throw error;
274
+ }
275
+ }
276
+
277
+ private async npmUpdate(): Promise<void> {
278
+ try {
279
+ // Step 1: Run npm update
280
+ this.sendProgress({ phase: 'downloading', percent: 20, message: 'Updating via npm...' });
281
+ await this.runNpmGlobalUpdate();
282
+
283
+ // Step 2: Complete
284
+ this.sendProgress({ phase: 'complete', percent: 100, message: 'Update complete! Please restart the application.' });
285
+
286
+ if (this.mainWindow && !this.mainWindow.isDestroyed()) {
287
+ this.mainWindow.webContents.send(IPC_CHANNELS.APP_UPDATE_DOWNLOADED, {
288
+ requiresRestart: true,
289
+ message: 'Update complete! Please restart the application to apply changes.',
290
+ });
291
+ }
292
+ } catch (error: any) {
293
+ this.sendProgress({ phase: 'error', message: `Update failed: ${error.message}` });
294
+ this.sendError(error.message);
295
+ throw error;
296
+ }
297
+ }
298
+
299
+ private runNpmGlobalUpdate(): Promise<void> {
300
+ return new Promise((resolve, reject) => {
301
+ const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm';
302
+ const child = spawn(npm, ['install', '-g', 'cowork-os@latest'], { shell: true });
303
+
304
+ let stderr = '';
305
+
306
+ child.stderr.on('data', (data) => {
307
+ stderr += data.toString();
308
+ });
309
+
310
+ child.on('close', (code) => {
311
+ if (code === 0) {
312
+ resolve();
313
+ } else {
314
+ reject(new Error(`npm update failed with code ${code}: ${stderr}`));
315
+ }
316
+ });
317
+
318
+ child.on('error', reject);
319
+ });
320
+ }
321
+
322
+ private runNpmInstall(cwd: string): Promise<void> {
323
+ return new Promise((resolve, reject) => {
324
+ const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm';
325
+ const child = spawn(npm, ['install'], { cwd, shell: true });
326
+
327
+ let stderr = '';
328
+
329
+ child.stderr.on('data', (data) => {
330
+ stderr += data.toString();
331
+ });
332
+
333
+ child.on('close', (code) => {
334
+ if (code === 0) {
335
+ resolve();
336
+ } else {
337
+ reject(new Error(`npm install failed with code ${code}: ${stderr}`));
338
+ }
339
+ });
340
+
341
+ child.on('error', reject);
342
+ });
343
+ }
344
+
345
+ private runNpmBuild(cwd: string): Promise<void> {
346
+ return new Promise((resolve, reject) => {
347
+ const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm';
348
+ const child = spawn(npm, ['run', 'build'], { cwd, shell: true });
349
+
350
+ let stderr = '';
351
+
352
+ child.stderr.on('data', (data) => {
353
+ stderr += data.toString();
354
+ });
355
+
356
+ child.on('close', (code) => {
357
+ if (code === 0) {
358
+ resolve();
359
+ } else {
360
+ reject(new Error(`npm run build failed with code ${code}: ${stderr}`));
361
+ }
362
+ });
363
+
364
+ child.on('error', reject);
365
+ });
366
+ }
367
+
368
+ private async electronUpdaterUpdate(): Promise<void> {
369
+ // For packaged apps, we'll use electron-updater
370
+ // This requires electron-updater to be installed and configured
371
+ try {
372
+ // Dynamic import to avoid issues when running in dev mode
373
+ const electronUpdater = await import('electron-updater').catch(() => null);
374
+ if (!electronUpdater) {
375
+ throw new Error('electron-updater not available');
376
+ }
377
+ const { autoUpdater } = electronUpdater;
378
+
379
+ autoUpdater.on('checking-for-update', () => {
380
+ this.sendProgress({ phase: 'checking', message: 'Checking for updates...' });
381
+ });
382
+
383
+ autoUpdater.on('update-available', () => {
384
+ this.sendProgress({ phase: 'downloading', percent: 0, message: 'Update available, starting download...' });
385
+ });
386
+
387
+ autoUpdater.on('download-progress', (progress: { percent: number; transferred: number; total: number }) => {
388
+ this.sendProgress({
389
+ phase: 'downloading',
390
+ percent: Math.round(progress.percent),
391
+ message: `Downloading update... ${Math.round(progress.percent)}%`,
392
+ bytesDownloaded: progress.transferred,
393
+ bytesTotal: progress.total,
394
+ });
395
+ });
396
+
397
+ autoUpdater.on('update-downloaded', () => {
398
+ this.sendProgress({ phase: 'complete', percent: 100, message: 'Update downloaded. Ready to install.' });
399
+ if (this.mainWindow && !this.mainWindow.isDestroyed()) {
400
+ this.mainWindow.webContents.send(IPC_CHANNELS.APP_UPDATE_DOWNLOADED, {
401
+ requiresRestart: true,
402
+ message: 'Update downloaded. Click "Install & Restart" to apply.',
403
+ });
404
+ }
405
+ });
406
+
407
+ autoUpdater.on('error', (error: Error) => {
408
+ this.sendProgress({ phase: 'error', message: `Update error: ${error.message}` });
409
+ this.sendError(error.message);
410
+ });
411
+
412
+ await autoUpdater.downloadUpdate();
413
+ } catch (error: any) {
414
+ // If electron-updater is not available, fall back to manual download
415
+ this.sendProgress({ phase: 'error', message: 'electron-updater not available. Please download manually from GitHub.' });
416
+ throw new Error('Auto-update not available for packaged builds. Please download the latest release from GitHub.');
417
+ }
418
+ }
419
+
420
+ async installUpdateAndRestart(): Promise<void> {
421
+ const versionInfo = await this.getVersionInfo();
422
+
423
+ if (versionInfo.isGitRepo) {
424
+ // For git-based updates, just restart the app
425
+ app.relaunch();
426
+ app.exit(0);
427
+ } else {
428
+ // For electron-updater, quit and install
429
+ try {
430
+ const electronUpdater = await import('electron-updater').catch(() => null);
431
+ if (electronUpdater) {
432
+ electronUpdater.autoUpdater.quitAndInstall();
433
+ } else {
434
+ // Fallback: just restart
435
+ app.relaunch();
436
+ app.exit(0);
437
+ }
438
+ } catch {
439
+ // Fallback: just restart
440
+ app.relaunch();
441
+ app.exit(0);
442
+ }
443
+ }
444
+ }
445
+ }
446
+
447
+ export const updateManager = new UpdateManager();
@@ -0,0 +1,203 @@
1
+ /**
2
+ * Migration utility for users upgrading from .env-based configuration
3
+ * to GUI Settings with secure storage.
4
+ *
5
+ * This runs once on app startup and:
6
+ * 1. Detects if a .env file exists in the app directory
7
+ * 2. Reads any configured credentials
8
+ * 3. Migrates them to the new Settings system (with safeStorage encryption)
9
+ * 4. Renames the .env file to .env.migrated to prevent re-migration
10
+ * 5. Returns a summary for the user notification
11
+ */
12
+
13
+ import * as fs from 'fs';
14
+ import * as path from 'path';
15
+ import { app } from 'electron';
16
+ import { LLMProviderFactory } from '../agent/llm';
17
+ import { SearchProviderFactory } from '../agent/search';
18
+
19
+ interface MigrationResult {
20
+ migrated: boolean;
21
+ migratedKeys: string[];
22
+ error?: string;
23
+ }
24
+
25
+ /**
26
+ * Parse a .env file into key-value pairs
27
+ */
28
+ function parseEnvFile(content: string): Record<string, string> {
29
+ const result: Record<string, string> = {};
30
+ const lines = content.split('\n');
31
+
32
+ for (const line of lines) {
33
+ // Skip empty lines and comments
34
+ const trimmed = line.trim();
35
+ if (!trimmed || trimmed.startsWith('#')) continue;
36
+
37
+ // Parse KEY=VALUE (handle quoted values)
38
+ const eqIndex = trimmed.indexOf('=');
39
+ if (eqIndex === -1) continue;
40
+
41
+ const key = trimmed.slice(0, eqIndex).trim();
42
+ let value = trimmed.slice(eqIndex + 1).trim();
43
+
44
+ // Remove surrounding quotes if present
45
+ if ((value.startsWith('"') && value.endsWith('"')) ||
46
+ (value.startsWith("'") && value.endsWith("'"))) {
47
+ value = value.slice(1, -1);
48
+ }
49
+
50
+ if (key && value) {
51
+ result[key] = value;
52
+ }
53
+ }
54
+
55
+ return result;
56
+ }
57
+
58
+ /**
59
+ * Check for and migrate .env configuration to Settings
60
+ */
61
+ export async function migrateEnvToSettings(): Promise<MigrationResult> {
62
+ const migratedKeys: string[] = [];
63
+
64
+ // Check multiple possible locations for .env
65
+ const possiblePaths = [
66
+ path.join(app.getAppPath(), '.env'),
67
+ path.join(process.cwd(), '.env'),
68
+ path.join(app.getPath('userData'), '.env'),
69
+ ];
70
+
71
+ let envPath: string | null = null;
72
+ let envContent: string | null = null;
73
+
74
+ for (const p of possiblePaths) {
75
+ try {
76
+ if (fs.existsSync(p)) {
77
+ envContent = fs.readFileSync(p, 'utf-8');
78
+ envPath = p;
79
+ break;
80
+ }
81
+ } catch {
82
+ // Ignore read errors, try next path
83
+ }
84
+ }
85
+
86
+ if (!envPath || !envContent) {
87
+ return { migrated: false, migratedKeys: [] };
88
+ }
89
+
90
+ // Check if already migrated
91
+ const migratedPath = envPath + '.migrated';
92
+ if (fs.existsSync(migratedPath)) {
93
+ return { migrated: false, migratedKeys: [] };
94
+ }
95
+
96
+ try {
97
+ const env = parseEnvFile(envContent);
98
+
99
+ // Load current settings
100
+ const llmSettings = LLMProviderFactory.loadSettings();
101
+ const searchSettings = SearchProviderFactory.loadSettings();
102
+ let llmChanged = false;
103
+ let searchChanged = false;
104
+
105
+ // Migrate Anthropic API key
106
+ if (env.ANTHROPIC_API_KEY && !llmSettings.anthropic?.apiKey) {
107
+ llmSettings.anthropic = { ...llmSettings.anthropic, apiKey: env.ANTHROPIC_API_KEY };
108
+ migratedKeys.push('Anthropic API Key');
109
+ llmChanged = true;
110
+ }
111
+
112
+ // Migrate AWS Bedrock credentials
113
+ if (env.AWS_ACCESS_KEY_ID && !llmSettings.bedrock?.accessKeyId) {
114
+ llmSettings.bedrock = {
115
+ ...llmSettings.bedrock,
116
+ accessKeyId: env.AWS_ACCESS_KEY_ID,
117
+ secretAccessKey: env.AWS_SECRET_ACCESS_KEY,
118
+ sessionToken: env.AWS_SESSION_TOKEN,
119
+ region: env.AWS_REGION || env.AWS_DEFAULT_REGION,
120
+ profile: env.AWS_PROFILE,
121
+ };
122
+ migratedKeys.push('AWS Bedrock Credentials');
123
+ llmChanged = true;
124
+ }
125
+
126
+ // Migrate Gemini API key
127
+ if (env.GEMINI_API_KEY && !llmSettings.gemini?.apiKey) {
128
+ llmSettings.gemini = { ...llmSettings.gemini, apiKey: env.GEMINI_API_KEY };
129
+ migratedKeys.push('Gemini API Key');
130
+ llmChanged = true;
131
+ }
132
+
133
+ // Migrate OpenRouter API key
134
+ if (env.OPENROUTER_API_KEY && !llmSettings.openrouter?.apiKey) {
135
+ llmSettings.openrouter = { ...llmSettings.openrouter, apiKey: env.OPENROUTER_API_KEY };
136
+ migratedKeys.push('OpenRouter API Key');
137
+ llmChanged = true;
138
+ }
139
+
140
+ // Migrate Ollama settings
141
+ if (env.OLLAMA_BASE_URL && !llmSettings.ollama?.baseUrl) {
142
+ llmSettings.ollama = {
143
+ ...llmSettings.ollama,
144
+ baseUrl: env.OLLAMA_BASE_URL,
145
+ apiKey: env.OLLAMA_API_KEY,
146
+ };
147
+ migratedKeys.push('Ollama Configuration');
148
+ llmChanged = true;
149
+ }
150
+
151
+ // Migrate Search API keys
152
+ if (env.TAVILY_API_KEY && !searchSettings.tavily?.apiKey) {
153
+ searchSettings.tavily = { apiKey: env.TAVILY_API_KEY };
154
+ migratedKeys.push('Tavily API Key');
155
+ searchChanged = true;
156
+ }
157
+
158
+ if (env.BRAVE_API_KEY && !searchSettings.brave?.apiKey) {
159
+ searchSettings.brave = { apiKey: env.BRAVE_API_KEY };
160
+ migratedKeys.push('Brave Search API Key');
161
+ searchChanged = true;
162
+ }
163
+
164
+ if (env.SERPAPI_API_KEY && !searchSettings.serpapi?.apiKey) {
165
+ searchSettings.serpapi = { apiKey: env.SERPAPI_API_KEY };
166
+ migratedKeys.push('SerpAPI Key');
167
+ searchChanged = true;
168
+ }
169
+
170
+ if (env.GOOGLE_API_KEY && !searchSettings.google?.apiKey) {
171
+ searchSettings.google = {
172
+ apiKey: env.GOOGLE_API_KEY,
173
+ searchEngineId: env.GOOGLE_SEARCH_ENGINE_ID,
174
+ };
175
+ migratedKeys.push('Google Search API Key');
176
+ searchChanged = true;
177
+ }
178
+
179
+ // Save migrated settings
180
+ if (llmChanged) {
181
+ LLMProviderFactory.saveSettings(llmSettings);
182
+ }
183
+ if (searchChanged) {
184
+ SearchProviderFactory.saveSettings(searchSettings);
185
+ }
186
+
187
+ // Rename .env to .env.migrated to prevent re-migration
188
+ if (migratedKeys.length > 0) {
189
+ fs.renameSync(envPath, migratedPath);
190
+ }
191
+
192
+ return {
193
+ migrated: migratedKeys.length > 0,
194
+ migratedKeys,
195
+ };
196
+ } catch (error: any) {
197
+ return {
198
+ migrated: false,
199
+ migratedKeys: [],
200
+ error: error.message,
201
+ };
202
+ }
203
+ }