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,291 @@
1
+ /**
2
+ * LLM Provider abstraction types
3
+ * Allows switching between Anthropic API and AWS Bedrock
4
+ */
5
+
6
+ export type LLMProviderType = 'anthropic' | 'bedrock' | 'ollama' | 'gemini' | 'openrouter' | 'openai';
7
+
8
+ export interface LLMProviderConfig {
9
+ type: LLMProviderType;
10
+ model: string;
11
+ // Anthropic-specific
12
+ anthropicApiKey?: string;
13
+ // Bedrock-specific
14
+ awsRegion?: string;
15
+ awsAccessKeyId?: string;
16
+ awsSecretAccessKey?: string;
17
+ awsSessionToken?: string;
18
+ // Use AWS profile instead of explicit credentials
19
+ awsProfile?: string;
20
+ // Ollama-specific
21
+ ollamaBaseUrl?: string;
22
+ ollamaApiKey?: string; // Optional API key for remote Ollama servers
23
+ // Gemini-specific
24
+ geminiApiKey?: string;
25
+ // OpenRouter-specific
26
+ openrouterApiKey?: string;
27
+ // OpenAI-specific
28
+ openaiApiKey?: string;
29
+ openaiAccessToken?: string; // OAuth access token
30
+ openaiRefreshToken?: string; // OAuth refresh token
31
+ openaiTokenExpiresAt?: number; // OAuth token expiry timestamp
32
+ }
33
+
34
+ export interface LLMTool {
35
+ name: string;
36
+ description: string;
37
+ input_schema: {
38
+ type: 'object';
39
+ properties: Record<string, any>;
40
+ required?: string[];
41
+ };
42
+ }
43
+
44
+ export interface LLMToolUse {
45
+ type: 'tool_use';
46
+ id: string;
47
+ name: string;
48
+ input: Record<string, any>;
49
+ }
50
+
51
+ export interface LLMTextContent {
52
+ type: 'text';
53
+ text: string;
54
+ }
55
+
56
+ export type LLMContent = LLMToolUse | LLMTextContent;
57
+
58
+ export interface LLMToolResult {
59
+ type: 'tool_result';
60
+ tool_use_id: string;
61
+ content: string;
62
+ is_error?: boolean;
63
+ }
64
+
65
+ export interface LLMMessage {
66
+ role: 'user' | 'assistant';
67
+ content: string | LLMContent[] | LLMToolResult[];
68
+ }
69
+
70
+ export interface LLMRequest {
71
+ model: string;
72
+ maxTokens: number;
73
+ system: string;
74
+ messages: LLMMessage[];
75
+ tools?: LLMTool[];
76
+ /** Optional abort signal to cancel the request */
77
+ signal?: AbortSignal;
78
+ }
79
+
80
+ export interface LLMResponse {
81
+ content: LLMContent[];
82
+ stopReason: 'end_turn' | 'tool_use' | 'max_tokens' | 'stop_sequence';
83
+ usage?: {
84
+ inputTokens: number;
85
+ outputTokens: number;
86
+ };
87
+ }
88
+
89
+ /**
90
+ * Abstract LLM Provider interface
91
+ */
92
+ export interface LLMProvider {
93
+ readonly type: LLMProviderType;
94
+
95
+ /**
96
+ * Send a message to the LLM and get a response
97
+ */
98
+ createMessage(request: LLMRequest): Promise<LLMResponse>;
99
+
100
+ /**
101
+ * Test the provider connection
102
+ */
103
+ testConnection(): Promise<{ success: boolean; error?: string }>;
104
+ }
105
+
106
+ /**
107
+ * Available AI models with their IDs for each provider
108
+ * Note: Bedrock uses inference profile IDs (us. prefix) for newer models
109
+ * Note: Ollama models are dynamic and fetched from the server
110
+ */
111
+ export const MODELS = {
112
+ 'opus-4-5': {
113
+ anthropic: 'claude-opus-4-5-20251101',
114
+ bedrock: 'us.anthropic.claude-opus-4-5-20251101-v1:0',
115
+ displayName: 'Opus 4.5',
116
+ },
117
+ 'sonnet-4-5': {
118
+ anthropic: 'claude-sonnet-4-5-20250514',
119
+ bedrock: 'us.anthropic.claude-sonnet-4-5-20250514-v1:0',
120
+ displayName: 'Sonnet 4.5',
121
+ },
122
+ 'haiku-4-5': {
123
+ anthropic: 'claude-haiku-4-5-20250514',
124
+ bedrock: 'us.anthropic.claude-haiku-4-5-20250514-v1:0',
125
+ displayName: 'Haiku 4.5',
126
+ },
127
+ 'sonnet-4': {
128
+ anthropic: 'claude-sonnet-4-20250514',
129
+ bedrock: 'us.anthropic.claude-sonnet-4-20250514-v1:0',
130
+ displayName: 'Sonnet 4',
131
+ },
132
+ 'sonnet-3-5': {
133
+ anthropic: 'claude-3-5-sonnet-20241022',
134
+ bedrock: 'us.anthropic.claude-3-5-sonnet-20241022-v2:0',
135
+ displayName: 'Sonnet 3.5',
136
+ },
137
+ 'haiku-3-5': {
138
+ anthropic: 'claude-3-5-haiku-20241022',
139
+ bedrock: 'us.anthropic.claude-3-5-haiku-20241022-v1:0',
140
+ displayName: 'Haiku 3.5',
141
+ },
142
+ } as const;
143
+
144
+ /**
145
+ * Available Gemini models from Google AI Studio
146
+ */
147
+ export const GEMINI_MODELS = {
148
+ 'gemini-2.5-pro': {
149
+ id: 'gemini-2.5-pro-preview-05-06',
150
+ displayName: 'Gemini 2.5 Pro',
151
+ description: 'Most capable model for complex tasks',
152
+ },
153
+ 'gemini-2.5-flash': {
154
+ id: 'gemini-2.5-flash-preview-05-20',
155
+ displayName: 'Gemini 2.5 Flash',
156
+ description: 'Fast and efficient for most tasks',
157
+ },
158
+ 'gemini-2.0-flash': {
159
+ id: 'gemini-2.0-flash',
160
+ displayName: 'Gemini 2.0 Flash',
161
+ description: 'Balanced speed and capability',
162
+ },
163
+ 'gemini-2.0-flash-lite': {
164
+ id: 'gemini-2.0-flash-lite',
165
+ displayName: 'Gemini 2.0 Flash Lite',
166
+ description: 'Fastest and most cost-effective',
167
+ },
168
+ 'gemini-1.5-pro': {
169
+ id: 'gemini-1.5-pro',
170
+ displayName: 'Gemini 1.5 Pro',
171
+ description: 'Previous generation pro model',
172
+ },
173
+ 'gemini-1.5-flash': {
174
+ id: 'gemini-1.5-flash',
175
+ displayName: 'Gemini 1.5 Flash',
176
+ description: 'Previous generation flash model',
177
+ },
178
+ } as const;
179
+
180
+ export type GeminiModelKey = keyof typeof GEMINI_MODELS;
181
+
182
+ /**
183
+ * Popular OpenRouter models
184
+ * OpenRouter provides access to many models from different providers
185
+ */
186
+ export const OPENROUTER_MODELS = {
187
+ 'anthropic/claude-3.5-sonnet': {
188
+ id: 'anthropic/claude-3.5-sonnet',
189
+ displayName: 'Claude 3.5 Sonnet',
190
+ description: 'Anthropic\'s balanced model',
191
+ },
192
+ 'anthropic/claude-3-opus': {
193
+ id: 'anthropic/claude-3-opus',
194
+ displayName: 'Claude 3 Opus',
195
+ description: 'Anthropic\'s most capable model',
196
+ },
197
+ 'openai/gpt-4o': {
198
+ id: 'openai/gpt-4o',
199
+ displayName: 'GPT-4o',
200
+ description: 'OpenAI\'s flagship model',
201
+ },
202
+ 'openai/gpt-4o-mini': {
203
+ id: 'openai/gpt-4o-mini',
204
+ displayName: 'GPT-4o Mini',
205
+ description: 'OpenAI\'s fast and affordable model',
206
+ },
207
+ 'google/gemini-pro-1.5': {
208
+ id: 'google/gemini-pro-1.5',
209
+ displayName: 'Gemini Pro 1.5',
210
+ description: 'Google\'s advanced model',
211
+ },
212
+ 'meta-llama/llama-3.1-405b-instruct': {
213
+ id: 'meta-llama/llama-3.1-405b-instruct',
214
+ displayName: 'Llama 3.1 405B',
215
+ description: 'Meta\'s largest open model',
216
+ },
217
+ 'mistralai/mistral-large': {
218
+ id: 'mistralai/mistral-large',
219
+ displayName: 'Mistral Large',
220
+ description: 'Mistral\'s flagship model',
221
+ },
222
+ 'deepseek/deepseek-chat': {
223
+ id: 'deepseek/deepseek-chat',
224
+ displayName: 'DeepSeek Chat',
225
+ description: 'DeepSeek\'s conversational model',
226
+ },
227
+ } as const;
228
+
229
+ export type OpenRouterModelKey = keyof typeof OPENROUTER_MODELS;
230
+
231
+ /**
232
+ * Available OpenAI models
233
+ * Users with ChatGPT Plus/Team/Enterprise subscriptions can use these models
234
+ */
235
+ export const OPENAI_MODELS = {
236
+ 'gpt-4o': {
237
+ id: 'gpt-4o',
238
+ displayName: 'GPT-4o',
239
+ description: 'Most capable model for complex tasks',
240
+ },
241
+ 'gpt-4o-mini': {
242
+ id: 'gpt-4o-mini',
243
+ displayName: 'GPT-4o Mini',
244
+ description: 'Fast and affordable for most tasks',
245
+ },
246
+ 'gpt-4-turbo': {
247
+ id: 'gpt-4-turbo',
248
+ displayName: 'GPT-4 Turbo',
249
+ description: 'Previous generation flagship',
250
+ },
251
+ 'gpt-3.5-turbo': {
252
+ id: 'gpt-3.5-turbo',
253
+ displayName: 'GPT-3.5 Turbo',
254
+ description: 'Fast and cost-effective',
255
+ },
256
+ 'o1': {
257
+ id: 'o1',
258
+ displayName: 'o1',
259
+ description: 'Advanced reasoning model',
260
+ },
261
+ 'o1-mini': {
262
+ id: 'o1-mini',
263
+ displayName: 'o1 Mini',
264
+ description: 'Fast reasoning model',
265
+ },
266
+ } as const;
267
+
268
+ export type OpenAIModelKey = keyof typeof OPENAI_MODELS;
269
+
270
+ /**
271
+ * Popular Ollama models with their details
272
+ * Users can use any model available on their Ollama server
273
+ */
274
+ export const OLLAMA_MODELS = {
275
+ 'llama3.2': { displayName: 'Llama 3.2', size: '3B' },
276
+ 'llama3.1': { displayName: 'Llama 3.1', size: '8B' },
277
+ 'llama3.1:70b': { displayName: 'Llama 3.1 70B', size: '70B' },
278
+ 'mistral': { displayName: 'Mistral', size: '7B' },
279
+ 'mixtral': { displayName: 'Mixtral', size: '47B' },
280
+ 'codellama': { displayName: 'Code Llama', size: '7B' },
281
+ 'deepseek-coder': { displayName: 'DeepSeek Coder', size: '6.7B' },
282
+ 'qwen2.5': { displayName: 'Qwen 2.5', size: '7B' },
283
+ 'phi3': { displayName: 'Phi-3', size: '3.8B' },
284
+ 'gemma2': { displayName: 'Gemma 2', size: '9B' },
285
+ } as const;
286
+
287
+ export type OllamaModelKey = keyof typeof OLLAMA_MODELS;
288
+
289
+ export type ModelKey = keyof typeof MODELS;
290
+
291
+ export const DEFAULT_MODEL: ModelKey = 'opus-4-5';
@@ -0,0 +1,408 @@
1
+ /**
2
+ * Task Queue Manager
3
+ *
4
+ * Manages parallel task execution with configurable concurrency limits.
5
+ * Provides queue management, status tracking, and settings persistence.
6
+ * Settings are stored encrypted in the database using SecureSettingsRepository.
7
+ */
8
+
9
+ import { app } from 'electron';
10
+ import * as fs from 'fs';
11
+ import * as path from 'path';
12
+ import { Task, TaskStatus, QueueSettings, QueueStatus, DEFAULT_QUEUE_SETTINGS } from '../../shared/types';
13
+ import { SecureSettingsRepository } from '../database/SecureSettingsRepository';
14
+
15
+ const LEGACY_SETTINGS_FILE = 'queue-settings.json';
16
+
17
+ // Forward declaration - will be set by daemon
18
+ type DaemonCallbacks = {
19
+ startTaskImmediate: (task: Task) => Promise<void>;
20
+ emitQueueUpdate: (status: QueueStatus) => void;
21
+ getTaskById: (taskId: string) => Task | undefined;
22
+ updateTaskStatus: (taskId: string, status: TaskStatus) => void;
23
+ onTaskTimeout: (taskId: string) => Promise<void>; // Called when a task times out
24
+ };
25
+
26
+ export class TaskQueueManager {
27
+ private queuedTaskIds: string[] = []; // FIFO queue of task IDs
28
+ private runningTaskIds: Set<string> = new Set(); // Currently executing task IDs
29
+ private taskStartTimes: Map<string, number> = new Map(); // Track when each task started
30
+ private settings: QueueSettings;
31
+ private legacySettingsPath: string;
32
+ private callbacks: DaemonCallbacks;
33
+ private initialized: boolean = false;
34
+ private timeoutCheckInterval?: ReturnType<typeof setInterval>;
35
+ private static migrationCompleted = false;
36
+
37
+ constructor(callbacks: DaemonCallbacks) {
38
+ this.callbacks = callbacks;
39
+ const userDataPath = app.getPath('userData');
40
+ this.legacySettingsPath = path.join(userDataPath, LEGACY_SETTINGS_FILE);
41
+
42
+ // Migrate from legacy file if needed
43
+ this.migrateFromLegacyFile();
44
+
45
+ this.settings = this.loadSettings();
46
+
47
+ // Start periodic timeout check (every minute)
48
+ this.timeoutCheckInterval = setInterval(() => this.checkForTimedOutTasks(), 60 * 1000);
49
+ }
50
+
51
+ /**
52
+ * Migrate settings from legacy JSON file to encrypted database
53
+ */
54
+ private migrateFromLegacyFile(): void {
55
+ if (TaskQueueManager.migrationCompleted) return;
56
+
57
+ try {
58
+ if (!SecureSettingsRepository.isInitialized()) {
59
+ return;
60
+ }
61
+
62
+ const repository = SecureSettingsRepository.getInstance();
63
+
64
+ if (repository.exists('queue')) {
65
+ TaskQueueManager.migrationCompleted = true;
66
+ return;
67
+ }
68
+
69
+ if (!fs.existsSync(this.legacySettingsPath)) {
70
+ TaskQueueManager.migrationCompleted = true;
71
+ return;
72
+ }
73
+
74
+ console.log('[TaskQueueManager] Migrating settings from legacy JSON file to encrypted database...');
75
+
76
+ // Create backup before migration
77
+ const backupPath = this.legacySettingsPath + '.migration-backup';
78
+ fs.copyFileSync(this.legacySettingsPath, backupPath);
79
+
80
+ try {
81
+ const data = fs.readFileSync(this.legacySettingsPath, 'utf-8');
82
+ const parsed = JSON.parse(data);
83
+ const merged = { ...DEFAULT_QUEUE_SETTINGS, ...parsed };
84
+
85
+ repository.save('queue', merged);
86
+ console.log('[TaskQueueManager] Settings migrated to encrypted database');
87
+
88
+ // Migration successful - delete backup and original
89
+ fs.unlinkSync(backupPath);
90
+ fs.unlinkSync(this.legacySettingsPath);
91
+ console.log('[TaskQueueManager] Migration complete, cleaned up legacy files');
92
+
93
+ TaskQueueManager.migrationCompleted = true;
94
+ } catch (migrationError) {
95
+ console.error('[TaskQueueManager] Migration failed, backup preserved at:', backupPath);
96
+ throw migrationError;
97
+ }
98
+ } catch (error) {
99
+ console.error('[TaskQueueManager] Migration failed:', error);
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Cleanup resources (call on shutdown)
105
+ */
106
+ destroy(): void {
107
+ if (this.timeoutCheckInterval) {
108
+ clearInterval(this.timeoutCheckInterval);
109
+ this.timeoutCheckInterval = undefined;
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Initialize the queue manager - recover queue from database on startup
115
+ * Should be called after database is ready
116
+ */
117
+ async initialize(
118
+ queuedTasks: Task[],
119
+ runningTasks: Task[]
120
+ ): Promise<void> {
121
+ if (this.initialized) {
122
+ console.log('[TaskQueueManager] Already initialized, skipping');
123
+ return;
124
+ }
125
+
126
+ console.log('[TaskQueueManager] Initializing queue manager');
127
+ console.log(`[TaskQueueManager] Found ${queuedTasks.length} queued tasks, ${runningTasks.length} running tasks`);
128
+
129
+ // Restore queued tasks in FIFO order by creation time
130
+ this.queuedTaskIds = queuedTasks
131
+ .sort((a, b) => a.createdAt - b.createdAt)
132
+ .map(t => t.id);
133
+
134
+ // Track currently running tasks
135
+ runningTasks.forEach(t => this.runningTaskIds.add(t.id));
136
+
137
+ this.initialized = true;
138
+
139
+ // Start processing queue if there are slots available
140
+ await this.processQueue();
141
+
142
+ // Emit initial queue status
143
+ this.emitQueueUpdate();
144
+ }
145
+
146
+ /**
147
+ * Enqueue a new task - either start immediately or add to queue
148
+ *
149
+ * Sub-agents (tasks with parentTaskId) bypass the concurrency limit to prevent
150
+ * deadlocks where a parent task waits for sub-agents that are stuck in the queue.
151
+ */
152
+ async enqueue(task: Task): Promise<void> {
153
+ console.log(`[TaskQueueManager] Enqueueing task ${task.id}: ${task.title}`);
154
+
155
+ // Sub-agents bypass concurrency limits to prevent deadlock
156
+ // (parent would wait forever for sub-agents stuck in queue)
157
+ const isSubAgent = !!task.parentTaskId;
158
+
159
+ if (isSubAgent) {
160
+ console.log(`[TaskQueueManager] Starting sub-agent immediately (bypasses concurrency limit)`);
161
+ await this.startTask(task);
162
+ } else if (this.canStartImmediately()) {
163
+ console.log(`[TaskQueueManager] Starting task immediately (${this.runningTaskIds.size}/${this.settings.maxConcurrentTasks} slots used)`);
164
+ await this.startTask(task);
165
+ } else {
166
+ console.log(`[TaskQueueManager] Queue full, adding task to queue (position: ${this.queuedTaskIds.length + 1})`);
167
+ this.queuedTaskIds.push(task.id);
168
+ this.callbacks.updateTaskStatus(task.id, 'queued');
169
+ this.emitQueueUpdate();
170
+ }
171
+ }
172
+
173
+ /**
174
+ * Called when a task finishes (completed, failed, or cancelled)
175
+ */
176
+ async onTaskFinished(taskId: string): Promise<void> {
177
+ console.log(`[TaskQueueManager] Task ${taskId} finished`);
178
+
179
+ // Remove from running set and clear start time
180
+ this.runningTaskIds.delete(taskId);
181
+ this.taskStartTimes.delete(taskId);
182
+
183
+ // Process next task in queue
184
+ await this.processQueue();
185
+
186
+ // Emit updated status
187
+ this.emitQueueUpdate();
188
+ }
189
+
190
+ /**
191
+ * Cancel a queued task (remove from queue without starting)
192
+ * Returns true if task was in queue and removed
193
+ */
194
+ cancelQueuedTask(taskId: string): boolean {
195
+ const index = this.queuedTaskIds.indexOf(taskId);
196
+ if (index !== -1) {
197
+ console.log(`[TaskQueueManager] Removing task ${taskId} from queue`);
198
+ this.queuedTaskIds.splice(index, 1);
199
+ this.emitQueueUpdate();
200
+ return true;
201
+ }
202
+ return false;
203
+ }
204
+
205
+ /**
206
+ * Check if a task is currently in the queue
207
+ */
208
+ isQueued(taskId: string): boolean {
209
+ return this.queuedTaskIds.includes(taskId);
210
+ }
211
+
212
+ /**
213
+ * Check if a task is currently running
214
+ */
215
+ isRunning(taskId: string): boolean {
216
+ return this.runningTaskIds.has(taskId);
217
+ }
218
+
219
+ /**
220
+ * Clear all stuck tasks from the running set
221
+ * This should be used to recover from stuck state when tasks fail to clean up
222
+ * Returns the number of tasks cleared
223
+ */
224
+ clearStuckTasks(): { clearedRunning: number; clearedQueued: number } {
225
+ const clearedRunning = this.runningTaskIds.size;
226
+ const clearedQueued = this.queuedTaskIds.length;
227
+
228
+ console.log(`[TaskQueueManager] Clearing ${clearedRunning} running tasks and ${clearedQueued} queued tasks`);
229
+
230
+ // Clear running tasks and their start times
231
+ this.runningTaskIds.clear();
232
+ this.taskStartTimes.clear();
233
+
234
+ // Clear queued tasks
235
+ this.queuedTaskIds = [];
236
+
237
+ // Emit update
238
+ this.emitQueueUpdate();
239
+
240
+ return { clearedRunning, clearedQueued };
241
+ }
242
+
243
+ /**
244
+ * Get current queue status for UI
245
+ */
246
+ getStatus(): QueueStatus {
247
+ return {
248
+ runningCount: this.runningTaskIds.size,
249
+ queuedCount: this.queuedTaskIds.length,
250
+ runningTaskIds: Array.from(this.runningTaskIds),
251
+ queuedTaskIds: [...this.queuedTaskIds],
252
+ maxConcurrent: this.settings.maxConcurrentTasks,
253
+ };
254
+ }
255
+
256
+ /**
257
+ * Get current settings
258
+ */
259
+ getSettings(): QueueSettings {
260
+ return { ...this.settings };
261
+ }
262
+
263
+ /**
264
+ * Update settings
265
+ */
266
+ saveSettings(newSettings: Partial<QueueSettings>): void {
267
+ // Validate maxConcurrentTasks
268
+ if (newSettings.maxConcurrentTasks !== undefined) {
269
+ newSettings.maxConcurrentTasks = Math.max(1, Math.min(10, newSettings.maxConcurrentTasks));
270
+ }
271
+
272
+ // Validate taskTimeoutMinutes (5 min to 4 hours)
273
+ if (newSettings.taskTimeoutMinutes !== undefined) {
274
+ newSettings.taskTimeoutMinutes = Math.max(5, Math.min(240, newSettings.taskTimeoutMinutes));
275
+ }
276
+
277
+ this.settings = { ...this.settings, ...newSettings };
278
+
279
+ try {
280
+ if (SecureSettingsRepository.isInitialized()) {
281
+ const repository = SecureSettingsRepository.getInstance();
282
+ repository.save('queue', this.settings);
283
+ console.log('[TaskQueueManager] Settings saved to encrypted database');
284
+ } else {
285
+ console.warn('[TaskQueueManager] SecureSettingsRepository not initialized, settings not persisted');
286
+ }
287
+ } catch (error) {
288
+ console.error('[TaskQueueManager] Failed to save settings:', error);
289
+ }
290
+
291
+ // Process queue in case we increased concurrency
292
+ this.processQueue();
293
+ this.emitQueueUpdate();
294
+ }
295
+
296
+ // ===== Private Methods =====
297
+
298
+ /**
299
+ * Process the queue - start tasks if slots are available
300
+ */
301
+ private async processQueue(): Promise<void> {
302
+ while (this.canStartImmediately() && this.queuedTaskIds.length > 0) {
303
+ const nextTaskId = this.queuedTaskIds.shift()!;
304
+ const task = this.callbacks.getTaskById(nextTaskId);
305
+
306
+ if (task && task.status === 'queued') {
307
+ console.log(`[TaskQueueManager] Dequeuing task ${nextTaskId}`);
308
+ await this.startTask(task);
309
+ } else {
310
+ console.log(`[TaskQueueManager] Skipping task ${nextTaskId} (not found or status changed)`);
311
+ }
312
+ }
313
+ }
314
+
315
+ /**
316
+ * Check if we can start a task immediately
317
+ */
318
+ private canStartImmediately(): boolean {
319
+ return this.runningTaskIds.size < this.settings.maxConcurrentTasks;
320
+ }
321
+
322
+ /**
323
+ * Start a task
324
+ */
325
+ private async startTask(task: Task): Promise<void> {
326
+ this.runningTaskIds.add(task.id);
327
+ this.taskStartTimes.set(task.id, Date.now());
328
+ this.emitQueueUpdate();
329
+
330
+ try {
331
+ await this.callbacks.startTaskImmediate(task);
332
+ } catch (error) {
333
+ console.error(`[TaskQueueManager] Failed to start task ${task.id}:`, error);
334
+ this.runningTaskIds.delete(task.id);
335
+ this.taskStartTimes.delete(task.id);
336
+ this.emitQueueUpdate();
337
+ }
338
+ }
339
+
340
+ /**
341
+ * Emit queue status update
342
+ */
343
+ private emitQueueUpdate(): void {
344
+ this.callbacks.emitQueueUpdate(this.getStatus());
345
+ }
346
+
347
+ /**
348
+ * Check for tasks that have exceeded the timeout and clear them
349
+ */
350
+ private async checkForTimedOutTasks(): Promise<void> {
351
+ const now = Date.now();
352
+ const timeoutMs = this.settings.taskTimeoutMinutes * 60 * 1000;
353
+ const timedOutTasks: string[] = [];
354
+
355
+ // Find tasks that have exceeded the timeout
356
+ for (const [taskId, startTime] of this.taskStartTimes) {
357
+ const elapsed = now - startTime;
358
+ if (elapsed > timeoutMs) {
359
+ const elapsedMinutes = Math.round(elapsed / 60000);
360
+ console.log(`[TaskQueueManager] Task ${taskId} has timed out (running for ${elapsedMinutes} minutes, timeout: ${this.settings.taskTimeoutMinutes} minutes)`);
361
+ timedOutTasks.push(taskId);
362
+ }
363
+ }
364
+
365
+ // Process timed out tasks
366
+ for (const taskId of timedOutTasks) {
367
+ try {
368
+ // Notify daemon to handle the timeout (cancel task, cleanup resources)
369
+ await this.callbacks.onTaskTimeout(taskId);
370
+
371
+ // Remove from tracking (daemon will call onTaskFinished which also removes, but do it here just in case)
372
+ this.runningTaskIds.delete(taskId);
373
+ this.taskStartTimes.delete(taskId);
374
+ } catch (error) {
375
+ console.error(`[TaskQueueManager] Error handling timeout for task ${taskId}:`, error);
376
+ // Force remove from tracking even if daemon callback fails
377
+ this.runningTaskIds.delete(taskId);
378
+ this.taskStartTimes.delete(taskId);
379
+ }
380
+ }
381
+
382
+ // If any tasks were cleared, process the queue and emit update
383
+ if (timedOutTasks.length > 0) {
384
+ await this.processQueue();
385
+ this.emitQueueUpdate();
386
+ }
387
+ }
388
+
389
+ /**
390
+ * Load settings from encrypted database
391
+ */
392
+ private loadSettings(): QueueSettings {
393
+ try {
394
+ if (SecureSettingsRepository.isInitialized()) {
395
+ const repository = SecureSettingsRepository.getInstance();
396
+ const stored = repository.load<QueueSettings>('queue');
397
+ if (stored) {
398
+ // Merge with defaults to handle missing fields
399
+ console.log('[TaskQueueManager] Loaded settings from encrypted database');
400
+ return { ...DEFAULT_QUEUE_SETTINGS, ...stored };
401
+ }
402
+ }
403
+ } catch (error) {
404
+ console.error('[TaskQueueManager] Failed to load settings:', error);
405
+ }
406
+ return { ...DEFAULT_QUEUE_SETTINGS };
407
+ }
408
+ }