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,895 @@
1
+ "use strict";
2
+ /**
3
+ * TrayManager - macOS Menu Bar App Integration
4
+ *
5
+ * Provides a native menu bar icon with:
6
+ * - Status indicator (connected/disconnected channels)
7
+ * - Quick actions menu (new task, workspaces, settings)
8
+ * - Show/hide main window on click
9
+ * - Gateway status monitoring
10
+ *
11
+ * Settings are stored encrypted in the database using SecureSettingsRepository.
12
+ */
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || (function () {
30
+ var ownKeys = function(o) {
31
+ ownKeys = Object.getOwnPropertyNames || function (o) {
32
+ var ar = [];
33
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34
+ return ar;
35
+ };
36
+ return ownKeys(o);
37
+ };
38
+ return function (mod) {
39
+ if (mod && mod.__esModule) return mod;
40
+ var result = {};
41
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
42
+ __setModuleDefault(result, mod);
43
+ return result;
44
+ };
45
+ })();
46
+ Object.defineProperty(exports, "__esModule", { value: true });
47
+ exports.trayManager = exports.TrayManager = void 0;
48
+ const electron_1 = require("electron");
49
+ const path = __importStar(require("path"));
50
+ const os = __importStar(require("os"));
51
+ const fs = __importStar(require("fs"));
52
+ const repositories_1 = require("../database/repositories");
53
+ const QuickInputWindow_1 = require("./QuickInputWindow");
54
+ const types_1 = require("../../shared/types");
55
+ const SecureSettingsRepository_1 = require("../database/SecureSettingsRepository");
56
+ const LEGACY_SETTINGS_FILE = 'tray-settings.json';
57
+ const DEFAULT_SETTINGS = {
58
+ enabled: true,
59
+ showDockIcon: true,
60
+ startMinimized: false,
61
+ closeToTray: true,
62
+ showNotifications: true,
63
+ };
64
+ class TrayManager {
65
+ static getInstance() {
66
+ if (!TrayManager.instance) {
67
+ TrayManager.instance = new TrayManager();
68
+ }
69
+ return TrayManager.instance;
70
+ }
71
+ constructor() {
72
+ this.tray = null;
73
+ this.mainWindow = null;
74
+ this.gateway = null;
75
+ this.dbManager = null;
76
+ this.agentDaemon = null;
77
+ this.taskRepo = null;
78
+ this.workspaceRepo = null;
79
+ this.settings = DEFAULT_SETTINGS;
80
+ this.connectedChannels = 0;
81
+ this.activeTaskCount = 0;
82
+ this.quickInputWindow = null;
83
+ this.currentQuickTaskId = null;
84
+ this.quickTaskAccumulatedResponse = '';
85
+ this.currentStepInfo = '';
86
+ const userDataPath = electron_1.app.getPath('userData');
87
+ this.legacySettingsPath = path.join(userDataPath, LEGACY_SETTINGS_FILE);
88
+ }
89
+ /**
90
+ * Initialize the tray manager
91
+ */
92
+ async initialize(mainWindow, gateway, dbManager, agentDaemon, options = {}) {
93
+ this.mainWindow = mainWindow;
94
+ this.gateway = gateway;
95
+ this.dbManager = dbManager;
96
+ this.agentDaemon = agentDaemon || null;
97
+ // Initialize repositories
98
+ const db = dbManager.getDatabase();
99
+ this.taskRepo = new repositories_1.TaskRepository(db);
100
+ this.workspaceRepo = new repositories_1.WorkspaceRepository(db);
101
+ // Load settings
102
+ this.loadSettings();
103
+ // Apply options overrides
104
+ if (options.showDockIcon !== undefined) {
105
+ this.settings.showDockIcon = options.showDockIcon;
106
+ }
107
+ if (options.startMinimized !== undefined) {
108
+ this.settings.startMinimized = options.startMinimized;
109
+ }
110
+ if (options.closeToTray !== undefined) {
111
+ this.settings.closeToTray = options.closeToTray;
112
+ }
113
+ // Create tray if enabled
114
+ if (this.settings.enabled) {
115
+ this.createTray();
116
+ }
117
+ // Apply dock icon setting (macOS only)
118
+ this.applyDockIconSetting();
119
+ // Handle start minimized
120
+ if (this.settings.startMinimized && this.mainWindow) {
121
+ this.mainWindow.hide();
122
+ }
123
+ // Set up window close behavior
124
+ this.setupCloseToTray();
125
+ // Update status periodically
126
+ this.startStatusUpdates();
127
+ // Set up task event listening for quick input responses
128
+ this.setupTaskEventListener();
129
+ // Initialize quick input window
130
+ this.quickInputWindow = new QuickInputWindow_1.QuickInputWindow();
131
+ this.quickInputWindow.setOnSubmit((task, workspaceId) => {
132
+ this.handleQuickTaskSubmit(task, workspaceId);
133
+ });
134
+ this.quickInputWindow.setOnOpenMain(() => {
135
+ this.showMainWindow();
136
+ this.quickInputWindow?.hide();
137
+ });
138
+ // Register global shortcut for quick input (Cmd+Shift+Space)
139
+ this.registerGlobalShortcut();
140
+ console.log('[TrayManager] Initialized');
141
+ }
142
+ /**
143
+ * Set up listener for task events to stream to quick input
144
+ */
145
+ setupTaskEventListener() {
146
+ if (!this.agentDaemon)
147
+ return;
148
+ // Listen for assistant messages (the main text response)
149
+ this.agentDaemon.on('assistant_message', (event) => {
150
+ if (event.taskId !== this.currentQuickTaskId)
151
+ return;
152
+ const message = event.message || '';
153
+ if (message) {
154
+ // Append to accumulated response (assistant may send multiple messages)
155
+ if (this.quickTaskAccumulatedResponse) {
156
+ this.quickTaskAccumulatedResponse += '\n\n' + message;
157
+ }
158
+ else {
159
+ this.quickTaskAccumulatedResponse = message;
160
+ }
161
+ this.quickInputWindow?.updateResponse(this.formatResponseWithQuestion(this.quickTaskAccumulatedResponse), false);
162
+ }
163
+ });
164
+ // Listen for progress updates
165
+ this.agentDaemon.on('progress_update', (event) => {
166
+ if (event.taskId !== this.currentQuickTaskId)
167
+ return;
168
+ // Only show progress if we don't have response content yet
169
+ if (!this.quickTaskAccumulatedResponse && event.message) {
170
+ this.quickInputWindow?.updateResponse(`<p style="color: rgba(255,255,255,0.6);">${event.message}</p>`, false);
171
+ }
172
+ });
173
+ // Listen for task completion
174
+ this.agentDaemon.on('task_completed', (event) => {
175
+ if (event.taskId !== this.currentQuickTaskId)
176
+ return;
177
+ // Show the accumulated response as complete (without step prefix)
178
+ const finalContent = this.quickTaskAccumulatedResponse || event.result || event.message || 'Task completed successfully';
179
+ this.quickInputWindow?.updateResponse(this.formatResponseWithQuestion(finalContent), true);
180
+ this.currentQuickTaskId = null;
181
+ this.quickTaskAccumulatedResponse = '';
182
+ this.currentStepInfo = '';
183
+ });
184
+ // Listen for errors
185
+ this.agentDaemon.on('error', (event) => {
186
+ if (event.taskId !== this.currentQuickTaskId)
187
+ return;
188
+ const question = this.quickInputWindow?.getCurrentQuestion() || '';
189
+ const questionHtml = question ? `<div class="user-question"><strong>You:</strong> ${question.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')}</div>` : '';
190
+ this.quickInputWindow?.updateResponse(`${questionHtml}<div class="error-message">Error: ${event.message || 'An error occurred'}</div>`, true);
191
+ this.currentQuickTaskId = null;
192
+ this.quickTaskAccumulatedResponse = '';
193
+ this.currentStepInfo = '';
194
+ });
195
+ // Listen for step started (show what step is being executed)
196
+ this.agentDaemon.on('step_started', (event) => {
197
+ if (event.taskId !== this.currentQuickTaskId)
198
+ return;
199
+ // Show step info above the response
200
+ if (event.step?.description) {
201
+ const stepInfo = `**Step ${event.step.id}:** ${event.step.description}\n\n`;
202
+ // Prepend step info (it will be replaced by next step)
203
+ this.currentStepInfo = stepInfo;
204
+ this.quickInputWindow?.updateResponse(this.formatResponseWithQuestion(this.currentStepInfo + this.quickTaskAccumulatedResponse), false);
205
+ }
206
+ });
207
+ // Listen for plan created (show what the agent is going to do)
208
+ this.agentDaemon.on('plan_created', (event) => {
209
+ if (event.taskId !== this.currentQuickTaskId)
210
+ return;
211
+ if (event.plan?.steps && event.plan.steps.length > 0) {
212
+ const planSummary = event.plan.steps.map((s, i) => `${i + 1}. ${s.description}`).join('\n');
213
+ this.quickTaskAccumulatedResponse = `**Plan:**\n${planSummary}\n\n`;
214
+ this.quickInputWindow?.updateResponse(this.formatResponseWithQuestion(this.quickTaskAccumulatedResponse), false);
215
+ }
216
+ });
217
+ }
218
+ /**
219
+ * Format response text for HTML display
220
+ */
221
+ formatResponseForDisplay(text) {
222
+ // Basic markdown-like formatting
223
+ return text
224
+ // Escape HTML
225
+ .replace(/&/g, '&amp;')
226
+ .replace(/</g, '&lt;')
227
+ .replace(/>/g, '&gt;')
228
+ // Bold
229
+ .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
230
+ // Code blocks
231
+ .replace(/```(\w*)\n?([\s\S]*?)```/g, '<pre><code>$2</code></pre>')
232
+ // Inline code
233
+ .replace(/`([^`]+)`/g, '<code>$1</code>')
234
+ // Line breaks
235
+ .replace(/\n/g, '<br>');
236
+ }
237
+ /**
238
+ * Format response with user's question prepended
239
+ */
240
+ formatResponseWithQuestion(text) {
241
+ const question = this.quickInputWindow?.getCurrentQuestion() || '';
242
+ const formattedResponse = this.formatResponseForDisplay(text);
243
+ if (question) {
244
+ const escapedQuestion = question
245
+ .replace(/&/g, '&amp;')
246
+ .replace(/</g, '&lt;')
247
+ .replace(/>/g, '&gt;');
248
+ return `<div class="user-question"><strong>You:</strong> ${escapedQuestion}</div>${formattedResponse}`;
249
+ }
250
+ return formattedResponse;
251
+ }
252
+ /**
253
+ * Get or create the temp workspace
254
+ */
255
+ async getOrCreateTempWorkspace() {
256
+ if (!this.dbManager)
257
+ throw new Error('Database not available');
258
+ const db = this.dbManager.getDatabase();
259
+ // Check if temp workspace exists
260
+ const existing = this.workspaceRepo?.findById(types_1.TEMP_WORKSPACE_ID);
261
+ if (existing) {
262
+ const updatedPermissions = {
263
+ ...existing.permissions,
264
+ read: true,
265
+ write: true,
266
+ delete: true,
267
+ network: true,
268
+ shell: existing.permissions.shell ?? false,
269
+ unrestrictedFileAccess: true,
270
+ };
271
+ if (!existing.permissions.unrestrictedFileAccess) {
272
+ this.workspaceRepo?.updatePermissions(existing.id, updatedPermissions);
273
+ }
274
+ // Verify directory exists
275
+ if (fs.existsSync(existing.path)) {
276
+ return { ...existing, permissions: updatedPermissions, isTemp: true };
277
+ }
278
+ // Directory deleted, remove and recreate
279
+ this.workspaceRepo?.delete(types_1.TEMP_WORKSPACE_ID);
280
+ }
281
+ // Create temp directory
282
+ const tempDir = path.join(os.tmpdir(), 'cowork-os-temp');
283
+ if (!fs.existsSync(tempDir)) {
284
+ fs.mkdirSync(tempDir, { recursive: true });
285
+ }
286
+ // Create workspace record
287
+ const tempWorkspace = {
288
+ id: types_1.TEMP_WORKSPACE_ID,
289
+ name: types_1.TEMP_WORKSPACE_NAME,
290
+ path: tempDir,
291
+ createdAt: Date.now(),
292
+ permissions: {
293
+ read: true,
294
+ write: true,
295
+ delete: true,
296
+ network: true,
297
+ shell: false,
298
+ unrestrictedFileAccess: true,
299
+ },
300
+ isTemp: true,
301
+ };
302
+ const stmt = db.prepare(`
303
+ INSERT OR REPLACE INTO workspaces (id, name, path, created_at, permissions)
304
+ VALUES (?, ?, ?, ?, ?)
305
+ `);
306
+ stmt.run(tempWorkspace.id, tempWorkspace.name, tempWorkspace.path, tempWorkspace.createdAt, JSON.stringify(tempWorkspace.permissions));
307
+ return tempWorkspace;
308
+ }
309
+ /**
310
+ * Handle quick task submission - create and run task
311
+ */
312
+ async handleQuickTaskSubmit(prompt, workspaceId) {
313
+ if (!this.taskRepo || !this.workspaceRepo || !this.agentDaemon) {
314
+ // Fall back to sending to main window
315
+ console.log('[TrayManager] Agent daemon not available, falling back to main window');
316
+ this.showMainWindow();
317
+ this.mainWindow?.webContents.send('tray:quick-task', { task: prompt, workspaceId });
318
+ return;
319
+ }
320
+ // Show loading state and reset accumulated response
321
+ this.quickInputWindow?.showLoading();
322
+ this.quickTaskAccumulatedResponse = '';
323
+ this.currentStepInfo = '';
324
+ try {
325
+ // Get or select workspace
326
+ let wsId = workspaceId;
327
+ if (!wsId) {
328
+ // Get the first non-temp workspace, or use temp workspace as fallback
329
+ const workspaces = this.workspaceRepo.findAll().filter(w => w.id !== types_1.TEMP_WORKSPACE_ID);
330
+ if (workspaces.length > 0) {
331
+ wsId = workspaces[0].id;
332
+ }
333
+ else {
334
+ // No user workspaces, use temp workspace
335
+ const tempWorkspace = await this.getOrCreateTempWorkspace();
336
+ wsId = tempWorkspace.id;
337
+ }
338
+ }
339
+ // Create task
340
+ const task = this.taskRepo.create({
341
+ title: prompt.slice(0, 50) + (prompt.length > 50 ? '...' : ''),
342
+ prompt,
343
+ workspaceId: wsId,
344
+ status: 'queued',
345
+ });
346
+ this.currentQuickTaskId = task.id;
347
+ // Start task execution
348
+ await this.agentDaemon.startTask(task);
349
+ // Also notify main window so it updates the task list
350
+ this.mainWindow?.webContents.send('tray:task-created', { taskId: task.id });
351
+ }
352
+ catch (error) {
353
+ console.error('[TrayManager] Failed to create quick task:', error);
354
+ const question = this.quickInputWindow?.getCurrentQuestion() || '';
355
+ const questionHtml = question ? `<div class="user-question"><strong>You:</strong> ${question.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')}</div>` : '';
356
+ this.quickInputWindow?.updateResponse(`${questionHtml}<div class="error-message">Failed to create task: ${error instanceof Error ? error.message : 'Unknown error'}</div>`, true);
357
+ this.currentQuickTaskId = null;
358
+ }
359
+ }
360
+ /**
361
+ * Show the quick input window
362
+ */
363
+ showQuickInput() {
364
+ this.quickInputWindow?.show();
365
+ }
366
+ /**
367
+ * Toggle the quick input window
368
+ */
369
+ toggleQuickInput() {
370
+ this.quickInputWindow?.toggle();
371
+ }
372
+ /**
373
+ * Register global keyboard shortcut for quick input
374
+ */
375
+ registerGlobalShortcut() {
376
+ try {
377
+ // Unregister first in case it's already registered
378
+ electron_1.globalShortcut.unregister('CommandOrControl+Shift+Space');
379
+ const registered = electron_1.globalShortcut.register('CommandOrControl+Shift+Space', () => {
380
+ this.showQuickInput();
381
+ });
382
+ if (registered) {
383
+ console.log('[TrayManager] Global shortcut registered: Cmd+Shift+Space');
384
+ }
385
+ else {
386
+ console.warn('[TrayManager] Failed to register global shortcut - may be in use by another app');
387
+ }
388
+ }
389
+ catch (error) {
390
+ console.error('[TrayManager] Error registering global shortcut:', error);
391
+ }
392
+ }
393
+ /**
394
+ * Unregister global keyboard shortcut
395
+ */
396
+ unregisterGlobalShortcut() {
397
+ try {
398
+ electron_1.globalShortcut.unregister('CommandOrControl+Shift+Space');
399
+ console.log('[TrayManager] Global shortcut unregistered');
400
+ }
401
+ catch (error) {
402
+ console.error('[TrayManager] Error unregistering global shortcut:', error);
403
+ }
404
+ }
405
+ /**
406
+ * Create the system tray icon
407
+ */
408
+ createTray() {
409
+ if (this.tray) {
410
+ return;
411
+ }
412
+ try {
413
+ // Create tray icon (use template image for macOS)
414
+ const icon = this.getTrayIcon('idle');
415
+ this.tray = new electron_1.Tray(icon);
416
+ this.tray.setToolTip('CoWork OS');
417
+ // Build and set context menu
418
+ this.updateContextMenu();
419
+ // Handle click events - always show context menu on click
420
+ this.tray.on('click', () => {
421
+ this.tray?.popUpContextMenu();
422
+ });
423
+ }
424
+ catch (error) {
425
+ console.error('[TrayManager] Failed to create tray:', error);
426
+ }
427
+ }
428
+ /**
429
+ * Get or create tray icon
430
+ */
431
+ getTrayIcon(state) {
432
+ // Try to load from file first
433
+ const iconPath = this.getIconPath(state === 'active' ? 'trayActiveTemplate' : 'trayTemplate');
434
+ const fs = require('fs');
435
+ if (fs.existsSync(iconPath)) {
436
+ const icon = electron_1.nativeImage.createFromPath(iconPath);
437
+ if (process.platform === 'darwin') {
438
+ icon.setTemplateImage(true);
439
+ }
440
+ return icon;
441
+ }
442
+ // Create programmatic icon if file doesn't exist
443
+ return this.createProgrammaticIcon(state);
444
+ }
445
+ /**
446
+ * Create a programmatic tray icon using raw RGBA bitmap
447
+ * More reliable than SVG data URLs for Electron tray icons
448
+ */
449
+ createProgrammaticIcon(state) {
450
+ // Standard macOS menu bar icon size (16x16 for 1x, 32x32 for 2x retina)
451
+ const size = 16;
452
+ const scale = 2; // Create at 2x for retina
453
+ const actualSize = size * scale;
454
+ // Create RGBA buffer (4 bytes per pixel)
455
+ const buffer = Buffer.alloc(actualSize * actualSize * 4);
456
+ // Get color based on state
457
+ const [r, g, b] = state === 'error' ? [255, 59, 48] : // Red
458
+ state === 'active' ? [0, 122, 255] : // Blue
459
+ [255, 255, 255]; // White
460
+ // Draw a simple filled circle
461
+ const centerX = actualSize / 2;
462
+ const centerY = actualSize / 2;
463
+ const outerRadius = actualSize / 2 - 2;
464
+ const innerRadius = outerRadius - 4;
465
+ for (let y = 0; y < actualSize; y++) {
466
+ for (let x = 0; x < actualSize; x++) {
467
+ const dx = x - centerX;
468
+ const dy = y - centerY;
469
+ const distance = Math.sqrt(dx * dx + dy * dy);
470
+ const idx = (y * actualSize + x) * 4;
471
+ // Draw ring (between inner and outer radius)
472
+ if (distance <= outerRadius && distance >= innerRadius) {
473
+ // Anti-aliasing at edges
474
+ let alpha = 255;
475
+ if (distance > outerRadius - 1) {
476
+ alpha = Math.round(255 * (outerRadius - distance));
477
+ }
478
+ else if (distance < innerRadius + 1) {
479
+ alpha = Math.round(255 * (distance - innerRadius));
480
+ }
481
+ alpha = Math.max(0, Math.min(255, alpha));
482
+ buffer[idx] = r;
483
+ buffer[idx + 1] = g;
484
+ buffer[idx + 2] = b;
485
+ buffer[idx + 3] = alpha;
486
+ }
487
+ else {
488
+ // Transparent
489
+ buffer[idx] = 0;
490
+ buffer[idx + 1] = 0;
491
+ buffer[idx + 2] = 0;
492
+ buffer[idx + 3] = 0;
493
+ }
494
+ }
495
+ }
496
+ return electron_1.nativeImage.createFromBuffer(buffer, {
497
+ width: actualSize,
498
+ height: actualSize,
499
+ scaleFactor: scale,
500
+ });
501
+ }
502
+ /**
503
+ * Get the path to a tray icon
504
+ */
505
+ getIconPath(name) {
506
+ const isDev = process.env.NODE_ENV === 'development';
507
+ const basePath = isDev
508
+ ? path.join(__dirname, '../../../assets/tray')
509
+ : path.join(process.resourcesPath, 'assets/tray');
510
+ // Use PNG for cross-platform compatibility
511
+ const extension = process.platform === 'darwin' ? 'png' : 'png';
512
+ return path.join(basePath, `${name}.${extension}`);
513
+ }
514
+ /**
515
+ * Update the tray context menu
516
+ */
517
+ updateContextMenu() {
518
+ if (!this.tray)
519
+ return;
520
+ const statusText = this.getStatusText();
521
+ const workspaces = this.getWorkspaces();
522
+ const menuTemplate = [
523
+ // Status section
524
+ {
525
+ label: statusText,
526
+ enabled: false,
527
+ icon: this.getStatusIcon(),
528
+ },
529
+ { type: 'separator' },
530
+ // Quick actions
531
+ {
532
+ label: 'Quick Task...',
533
+ accelerator: 'CmdOrCtrl+Shift+Space',
534
+ click: () => {
535
+ this.showQuickInput();
536
+ },
537
+ },
538
+ {
539
+ label: 'New Task...',
540
+ accelerator: 'CmdOrCtrl+N',
541
+ click: () => {
542
+ this.showMainWindow();
543
+ this.mainWindow?.webContents.send('tray:new-task');
544
+ },
545
+ },
546
+ { type: 'separator' },
547
+ // Workspaces submenu
548
+ {
549
+ label: 'Workspaces',
550
+ submenu: workspaces.length > 0
551
+ ? workspaces.map((ws) => ({
552
+ label: ws.name,
553
+ click: () => {
554
+ this.showMainWindow();
555
+ this.mainWindow?.webContents.send('tray:select-workspace', ws.id);
556
+ },
557
+ }))
558
+ : [{ label: 'No workspaces', enabled: false }],
559
+ },
560
+ // Channels submenu
561
+ {
562
+ label: 'Channels',
563
+ submenu: this.buildChannelsSubmenu(),
564
+ },
565
+ { type: 'separator' },
566
+ // Window controls
567
+ {
568
+ label: this.mainWindow?.isVisible() ? 'Hide Window' : 'Show Window',
569
+ accelerator: 'CmdOrCtrl+H',
570
+ click: () => this.toggleMainWindow(),
571
+ },
572
+ {
573
+ label: 'Settings...',
574
+ accelerator: 'CmdOrCtrl+,',
575
+ click: () => {
576
+ this.showMainWindow();
577
+ this.mainWindow?.webContents.send('tray:open-settings');
578
+ },
579
+ },
580
+ { type: 'separator' },
581
+ // App controls
582
+ {
583
+ label: 'About CoWork OS',
584
+ click: () => {
585
+ this.showMainWindow();
586
+ this.mainWindow?.webContents.send('tray:open-about');
587
+ },
588
+ },
589
+ {
590
+ label: 'Check for Updates...',
591
+ click: () => {
592
+ this.showMainWindow();
593
+ this.mainWindow?.webContents.send('tray:check-updates');
594
+ },
595
+ },
596
+ { type: 'separator' },
597
+ {
598
+ label: 'Quit CoWork OS',
599
+ accelerator: 'CmdOrCtrl+Q',
600
+ click: () => {
601
+ // Force quit (bypass close-to-tray)
602
+ this.settings.closeToTray = false;
603
+ electron_1.app.quit();
604
+ },
605
+ },
606
+ ];
607
+ const contextMenu = electron_1.Menu.buildFromTemplate(menuTemplate);
608
+ this.tray.setContextMenu(contextMenu);
609
+ }
610
+ /**
611
+ * Build the channels submenu
612
+ */
613
+ buildChannelsSubmenu() {
614
+ const channels = this.gateway?.getChannels() || [];
615
+ if (channels.length === 0) {
616
+ return [{ label: 'No channels configured', enabled: false }];
617
+ }
618
+ return channels.map((channel) => {
619
+ const statusIcon = channel.status === 'connected' ? '🟢' :
620
+ channel.status === 'connecting' ? '🟡' :
621
+ channel.status === 'error' ? '🔴' : '⚪';
622
+ return {
623
+ label: `${statusIcon} ${channel.name} (${channel.type})`,
624
+ enabled: false,
625
+ };
626
+ });
627
+ }
628
+ /**
629
+ * Get status text for the menu
630
+ */
631
+ getStatusText() {
632
+ const channels = this.gateway?.getChannels() || [];
633
+ this.connectedChannels = channels.filter((c) => c.status === 'connected').length;
634
+ if (this.activeTaskCount > 0) {
635
+ return `Working on ${this.activeTaskCount} task${this.activeTaskCount > 1 ? 's' : ''}`;
636
+ }
637
+ if (this.connectedChannels > 0) {
638
+ return `${this.connectedChannels} channel${this.connectedChannels > 1 ? 's' : ''} connected`;
639
+ }
640
+ return 'Ready';
641
+ }
642
+ /**
643
+ * Get status icon for the menu
644
+ */
645
+ getStatusIcon() {
646
+ // Return undefined for now - icons in menu items can be complex
647
+ return undefined;
648
+ }
649
+ /**
650
+ * Get workspaces from database (excluding temp workspace)
651
+ */
652
+ getWorkspaces() {
653
+ if (!this.dbManager)
654
+ return [];
655
+ try {
656
+ const db = this.dbManager.getDatabase();
657
+ const stmt = db.prepare('SELECT id, name, path FROM workspaces WHERE id != ? ORDER BY name');
658
+ return stmt.all(types_1.TEMP_WORKSPACE_ID);
659
+ }
660
+ catch (error) {
661
+ console.error('[TrayManager] Failed to get workspaces:', error);
662
+ return [];
663
+ }
664
+ }
665
+ /**
666
+ * Toggle main window visibility
667
+ */
668
+ toggleMainWindow() {
669
+ if (!this.mainWindow)
670
+ return;
671
+ if (this.mainWindow.isVisible()) {
672
+ this.mainWindow.hide();
673
+ }
674
+ else {
675
+ this.showMainWindow();
676
+ }
677
+ // Update menu to reflect new state
678
+ this.updateContextMenu();
679
+ }
680
+ /**
681
+ * Show and focus the main window
682
+ */
683
+ showMainWindow() {
684
+ if (!this.mainWindow)
685
+ return;
686
+ this.mainWindow.show();
687
+ this.mainWindow.focus();
688
+ // On macOS, also bring app to foreground
689
+ if (process.platform === 'darwin') {
690
+ electron_1.app.dock?.show();
691
+ }
692
+ }
693
+ /**
694
+ * Set up close-to-tray behavior
695
+ */
696
+ setupCloseToTray() {
697
+ if (!this.mainWindow)
698
+ return;
699
+ this.mainWindow.on('close', (event) => {
700
+ if (this.settings.closeToTray && this.tray) {
701
+ event.preventDefault();
702
+ this.mainWindow?.hide();
703
+ // On macOS, hide from dock when minimized to tray
704
+ if (process.platform === 'darwin' && !this.settings.showDockIcon) {
705
+ electron_1.app.dock?.hide();
706
+ }
707
+ }
708
+ });
709
+ }
710
+ /**
711
+ * Apply dock icon visibility setting (macOS only)
712
+ */
713
+ applyDockIconSetting() {
714
+ if (process.platform !== 'darwin')
715
+ return;
716
+ if (this.settings.showDockIcon) {
717
+ electron_1.app.dock?.show();
718
+ }
719
+ else {
720
+ electron_1.app.dock?.hide();
721
+ }
722
+ }
723
+ /**
724
+ * Start periodic status updates
725
+ */
726
+ startStatusUpdates() {
727
+ // Update every 5 seconds
728
+ setInterval(() => {
729
+ this.updateContextMenu();
730
+ this.updateTrayIcon();
731
+ }, 5000);
732
+ }
733
+ /**
734
+ * Update tray icon based on status
735
+ */
736
+ updateTrayIcon() {
737
+ if (!this.tray)
738
+ return;
739
+ // Determine icon state based on app status
740
+ const state = this.activeTaskCount > 0 ? 'active' : 'idle';
741
+ const icon = this.getTrayIcon(state);
742
+ this.tray.setImage(icon);
743
+ }
744
+ /**
745
+ * Update active task count
746
+ */
747
+ setActiveTaskCount(count) {
748
+ this.activeTaskCount = count;
749
+ this.updateContextMenu();
750
+ this.updateTrayIcon();
751
+ }
752
+ /**
753
+ * Migrate settings from legacy JSON file to encrypted database
754
+ */
755
+ migrateFromLegacyFile() {
756
+ if (TrayManager.migrationCompleted)
757
+ return;
758
+ try {
759
+ if (!SecureSettingsRepository_1.SecureSettingsRepository.isInitialized()) {
760
+ return;
761
+ }
762
+ const repository = SecureSettingsRepository_1.SecureSettingsRepository.getInstance();
763
+ // Check if already migrated
764
+ if (repository.exists('tray')) {
765
+ TrayManager.migrationCompleted = true;
766
+ return;
767
+ }
768
+ // Check if legacy file exists
769
+ if (!fs.existsSync(this.legacySettingsPath)) {
770
+ TrayManager.migrationCompleted = true;
771
+ return;
772
+ }
773
+ console.log('[TrayManager] Migrating settings from legacy JSON file to encrypted database...');
774
+ // Create backup before migration
775
+ const backupPath = this.legacySettingsPath + '.migration-backup';
776
+ fs.copyFileSync(this.legacySettingsPath, backupPath);
777
+ try {
778
+ const data = fs.readFileSync(this.legacySettingsPath, 'utf-8');
779
+ const parsed = JSON.parse(data);
780
+ const merged = { ...DEFAULT_SETTINGS, ...parsed };
781
+ repository.save('tray', merged);
782
+ console.log('[TrayManager] Settings migrated to encrypted database');
783
+ // Migration successful - delete backup and original
784
+ fs.unlinkSync(backupPath);
785
+ fs.unlinkSync(this.legacySettingsPath);
786
+ console.log('[TrayManager] Migration complete, cleaned up legacy files');
787
+ TrayManager.migrationCompleted = true;
788
+ }
789
+ catch (migrationError) {
790
+ console.error('[TrayManager] Migration failed, backup preserved at:', backupPath);
791
+ throw migrationError;
792
+ }
793
+ }
794
+ catch (error) {
795
+ console.error('[TrayManager] Migration failed:', error);
796
+ }
797
+ }
798
+ /**
799
+ * Load settings from encrypted database
800
+ */
801
+ loadSettings() {
802
+ // Migrate from legacy file if needed
803
+ this.migrateFromLegacyFile();
804
+ try {
805
+ if (SecureSettingsRepository_1.SecureSettingsRepository.isInitialized()) {
806
+ const repository = SecureSettingsRepository_1.SecureSettingsRepository.getInstance();
807
+ const stored = repository.load('tray');
808
+ if (stored) {
809
+ this.settings = { ...DEFAULT_SETTINGS, ...stored };
810
+ console.log('[TrayManager] Loaded settings from encrypted database');
811
+ return;
812
+ }
813
+ }
814
+ }
815
+ catch (error) {
816
+ console.error('[TrayManager] Failed to load settings:', error);
817
+ }
818
+ // Fall back to defaults
819
+ this.settings = { ...DEFAULT_SETTINGS };
820
+ }
821
+ /**
822
+ * Save settings to encrypted database
823
+ */
824
+ saveSettings(settings) {
825
+ this.settings = { ...this.settings, ...settings };
826
+ try {
827
+ if (SecureSettingsRepository_1.SecureSettingsRepository.isInitialized()) {
828
+ const repository = SecureSettingsRepository_1.SecureSettingsRepository.getInstance();
829
+ repository.save('tray', this.settings);
830
+ console.log('[TrayManager] Settings saved to encrypted database');
831
+ }
832
+ else {
833
+ console.warn('[TrayManager] SecureSettingsRepository not initialized, settings not persisted');
834
+ }
835
+ // Apply settings immediately
836
+ this.applyDockIconSetting();
837
+ // Recreate tray if enabled status changed
838
+ if (settings.enabled !== undefined) {
839
+ if (settings.enabled && !this.tray) {
840
+ this.createTray();
841
+ }
842
+ else if (!settings.enabled && this.tray) {
843
+ this.destroy();
844
+ }
845
+ }
846
+ }
847
+ catch (error) {
848
+ console.error('[TrayManager] Failed to save settings:', error);
849
+ }
850
+ }
851
+ /**
852
+ * Get current settings
853
+ */
854
+ getSettings() {
855
+ return { ...this.settings };
856
+ }
857
+ /**
858
+ * Show a notification from the tray
859
+ */
860
+ showNotification(title, body) {
861
+ if (!this.settings.showNotifications)
862
+ return;
863
+ const { Notification } = require('electron');
864
+ if (Notification.isSupported()) {
865
+ const notification = new Notification({
866
+ title,
867
+ body,
868
+ silent: false,
869
+ });
870
+ notification.on('click', () => {
871
+ this.showMainWindow();
872
+ });
873
+ notification.show();
874
+ }
875
+ }
876
+ /**
877
+ * Destroy the tray
878
+ */
879
+ destroy() {
880
+ // Unregister global shortcut
881
+ this.unregisterGlobalShortcut();
882
+ if (this.quickInputWindow) {
883
+ this.quickInputWindow.destroy();
884
+ this.quickInputWindow = null;
885
+ }
886
+ if (this.tray) {
887
+ this.tray.destroy();
888
+ this.tray = null;
889
+ }
890
+ }
891
+ }
892
+ exports.TrayManager = TrayManager;
893
+ TrayManager.instance = null;
894
+ TrayManager.migrationCompleted = false;
895
+ exports.trayManager = TrayManager.getInstance();