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,975 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.AgentDaemon = void 0;
37
+ const events_1 = require("events");
38
+ const electron_1 = require("electron");
39
+ const fs = __importStar(require("fs"));
40
+ const crypto = __importStar(require("crypto"));
41
+ const repositories_1 = require("../database/repositories");
42
+ const ActivityRepository_1 = require("../activity/ActivityRepository");
43
+ const types_1 = require("../../shared/types");
44
+ const executor_1 = require("./executor");
45
+ const queue_manager_1 = require("./queue-manager");
46
+ const concurrency_1 = require("../security/concurrency");
47
+ const MemoryService_1 = require("../memory/MemoryService");
48
+ // Memory management constants
49
+ const MAX_CACHED_EXECUTORS = 10; // Maximum number of completed task executors to keep in memory
50
+ const EXECUTOR_CACHE_TTL_MS = 30 * 60 * 1000; // 30 minutes - time before completed executors are cleaned up
51
+ /**
52
+ * AgentDaemon is the core orchestrator that manages task execution
53
+ * It coordinates between the database, task executors, and UI
54
+ */
55
+ class AgentDaemon extends events_1.EventEmitter {
56
+ constructor(dbManager) {
57
+ super();
58
+ this.dbManager = dbManager;
59
+ this.activeTasks = new Map();
60
+ this.pendingApprovals = new Map();
61
+ const db = dbManager.getDatabase();
62
+ this.taskRepo = new repositories_1.TaskRepository(db);
63
+ this.eventRepo = new repositories_1.TaskEventRepository(db);
64
+ this.workspaceRepo = new repositories_1.WorkspaceRepository(db);
65
+ this.approvalRepo = new repositories_1.ApprovalRepository(db);
66
+ this.artifactRepo = new repositories_1.ArtifactRepository(db);
67
+ this.activityRepo = new ActivityRepository_1.ActivityRepository(db);
68
+ // Initialize queue manager with callbacks
69
+ this.queueManager = new queue_manager_1.TaskQueueManager({
70
+ startTaskImmediate: (task) => this.startTaskImmediate(task),
71
+ emitQueueUpdate: (status) => this.emitQueueUpdate(status),
72
+ getTaskById: (taskId) => this.taskRepo.findById(taskId),
73
+ updateTaskStatus: (taskId, status) => this.taskRepo.update(taskId, { status }),
74
+ onTaskTimeout: (taskId) => this.handleTaskTimeout(taskId),
75
+ });
76
+ // Start periodic cleanup of old executors
77
+ this.cleanupIntervalHandle = setInterval(() => this.cleanupOldExecutors(), 5 * 60 * 1000); // Run every 5 minutes
78
+ }
79
+ /**
80
+ * Initialize the daemon - call after construction to set up queue
81
+ */
82
+ async initialize() {
83
+ // Find queued tasks from database for queue recovery
84
+ const queuedTasks = this.taskRepo.findByStatus('queued');
85
+ // Find "running" tasks from previous session - these are orphaned since we lost their executors
86
+ const orphanedTasks = this.taskRepo.findByStatus(['planning', 'executing']);
87
+ // Mark orphaned tasks as failed - they can't be resumed since we lost their state
88
+ if (orphanedTasks.length > 0) {
89
+ console.log(`[AgentDaemon] Found ${orphanedTasks.length} orphaned tasks from previous session, marking as failed`);
90
+ for (const task of orphanedTasks) {
91
+ this.taskRepo.update(task.id, {
92
+ status: 'failed',
93
+ error: 'Task interrupted - application was restarted while task was running',
94
+ });
95
+ }
96
+ }
97
+ // Only initialize queue with queued tasks (not orphaned "running" tasks)
98
+ await this.queueManager.initialize(queuedTasks, []);
99
+ }
100
+ /**
101
+ * Clean up old completed task executors to prevent memory leaks
102
+ */
103
+ cleanupOldExecutors() {
104
+ const now = Date.now();
105
+ const toDelete = [];
106
+ let completedCount = 0;
107
+ // Find executors to clean up
108
+ this.activeTasks.forEach((cached, taskId) => {
109
+ if (cached.status === 'completed') {
110
+ completedCount++;
111
+ // Remove if older than TTL
112
+ if (now - cached.lastAccessed > EXECUTOR_CACHE_TTL_MS) {
113
+ toDelete.push(taskId);
114
+ }
115
+ }
116
+ });
117
+ // Also remove oldest completed executors if we have too many
118
+ if (completedCount > MAX_CACHED_EXECUTORS) {
119
+ const completedTasks = Array.from(this.activeTasks.entries())
120
+ .filter(([_, cached]) => cached.status === 'completed')
121
+ .sort((a, b) => a[1].lastAccessed - b[1].lastAccessed);
122
+ const excessCount = completedCount - MAX_CACHED_EXECUTORS;
123
+ for (let i = 0; i < excessCount; i++) {
124
+ const [taskId] = completedTasks[i];
125
+ if (!toDelete.includes(taskId)) {
126
+ toDelete.push(taskId);
127
+ }
128
+ }
129
+ }
130
+ // Delete the marked executors
131
+ for (const taskId of toDelete) {
132
+ console.log(`[AgentDaemon] Cleaning up cached executor for task ${taskId}`);
133
+ this.activeTasks.delete(taskId);
134
+ }
135
+ if (toDelete.length > 0) {
136
+ console.log(`[AgentDaemon] Cleaned up ${toDelete.length} old executor(s). Active: ${this.activeTasks.size}`);
137
+ }
138
+ }
139
+ /**
140
+ * Queue a task for execution
141
+ * The task will either start immediately or be queued based on concurrency limits
142
+ */
143
+ async startTask(task) {
144
+ await this.queueManager.enqueue(task);
145
+ }
146
+ /**
147
+ * Start executing a task immediately (internal - called by queue manager)
148
+ */
149
+ async startTaskImmediate(task) {
150
+ console.log(`[AgentDaemon] Starting task ${task.id}: ${task.title}`);
151
+ // Get workspace details
152
+ const workspace = this.workspaceRepo.findById(task.workspaceId);
153
+ if (!workspace) {
154
+ throw new Error(`Workspace ${task.workspaceId} not found`);
155
+ }
156
+ console.log(`[AgentDaemon] Workspace found: ${workspace.name}`);
157
+ // Create task executor - wrapped in try-catch to handle provider initialization errors
158
+ let executor;
159
+ try {
160
+ console.log(`[AgentDaemon] Creating TaskExecutor...`);
161
+ executor = new executor_1.TaskExecutor(task, workspace, this);
162
+ console.log(`[AgentDaemon] TaskExecutor created successfully`);
163
+ }
164
+ catch (error) {
165
+ console.error(`[AgentDaemon] Task ${task.id} failed to initialize:`, error);
166
+ this.taskRepo.update(task.id, {
167
+ status: 'failed',
168
+ error: error.message || 'Failed to initialize task executor',
169
+ completedAt: Date.now(),
170
+ });
171
+ this.logEvent(task.id, 'error', { error: error.message });
172
+ // Notify queue manager so it can start next task
173
+ this.queueManager.onTaskFinished(task.id);
174
+ return;
175
+ }
176
+ this.activeTasks.set(task.id, {
177
+ executor,
178
+ lastAccessed: Date.now(),
179
+ status: 'active',
180
+ });
181
+ // Update task status
182
+ this.taskRepo.update(task.id, { status: 'planning' });
183
+ this.logEvent(task.id, 'task_created', { task });
184
+ console.log(`[AgentDaemon] Task status updated to 'planning', starting execution...`);
185
+ // Start execution (non-blocking)
186
+ executor.execute().catch(error => {
187
+ console.error(`[AgentDaemon] Task ${task.id} execution failed:`, error);
188
+ this.taskRepo.update(task.id, {
189
+ status: 'failed',
190
+ error: error.message,
191
+ completedAt: Date.now(),
192
+ });
193
+ this.logEvent(task.id, 'error', { error: error.message });
194
+ this.activeTasks.delete(task.id);
195
+ // Notify queue manager so it can start next task
196
+ this.queueManager.onTaskFinished(task.id);
197
+ });
198
+ }
199
+ /**
200
+ * Create a new task in the database and start it
201
+ * This is a convenience method used by the cron service
202
+ */
203
+ async createTask(params) {
204
+ const task = this.taskRepo.create({
205
+ title: params.title,
206
+ prompt: params.prompt,
207
+ status: 'pending',
208
+ workspaceId: params.workspaceId,
209
+ budgetTokens: params.budgetTokens,
210
+ budgetCost: params.budgetCost,
211
+ });
212
+ // Start the task (will be queued if necessary)
213
+ await this.startTask(task);
214
+ return task;
215
+ }
216
+ /**
217
+ * Get a task by its ID
218
+ */
219
+ async getTaskById(taskId) {
220
+ return this.taskRepo.findById(taskId);
221
+ }
222
+ /**
223
+ * Get all child tasks for a given parent task
224
+ */
225
+ async getChildTasks(parentTaskId) {
226
+ return this.taskRepo.findByParent(parentTaskId);
227
+ }
228
+ /**
229
+ * Create a child task (sub-agent or parallel agent)
230
+ */
231
+ async createChildTask(params) {
232
+ const task = this.taskRepo.create({
233
+ title: params.title,
234
+ prompt: params.prompt,
235
+ status: 'pending',
236
+ workspaceId: params.workspaceId,
237
+ parentTaskId: params.parentTaskId,
238
+ agentType: params.agentType,
239
+ agentConfig: params.agentConfig,
240
+ depth: params.depth ?? 0,
241
+ budgetTokens: params.budgetTokens,
242
+ budgetCost: params.budgetCost,
243
+ });
244
+ // Start the task (will be queued if necessary)
245
+ await this.startTask(task);
246
+ return task;
247
+ }
248
+ /**
249
+ * Cancel a running or queued task
250
+ */
251
+ async cancelTask(taskId) {
252
+ // Check if task is queued (not yet started)
253
+ if (this.queueManager.cancelQueuedTask(taskId)) {
254
+ this.taskRepo.update(taskId, { status: 'cancelled', completedAt: Date.now() });
255
+ this.logEvent(taskId, 'task_cancelled', {
256
+ message: 'Task removed from queue',
257
+ });
258
+ return;
259
+ }
260
+ // Task is running - cancel it
261
+ const cached = this.activeTasks.get(taskId);
262
+ if (cached) {
263
+ await cached.executor.cancel();
264
+ this.activeTasks.delete(taskId);
265
+ }
266
+ // Always notify queue manager to remove from running set
267
+ // (handles orphaned tasks that are in runningTaskIds but have no executor)
268
+ this.queueManager.onTaskFinished(taskId);
269
+ // Always emit cancelled event so UI updates
270
+ this.logEvent(taskId, 'task_cancelled', {
271
+ message: 'Task was stopped by user',
272
+ });
273
+ }
274
+ /**
275
+ * Pause a running task
276
+ */
277
+ async pauseTask(taskId) {
278
+ const cached = this.activeTasks.get(taskId);
279
+ if (cached) {
280
+ cached.lastAccessed = Date.now();
281
+ await cached.executor.pause();
282
+ }
283
+ }
284
+ /**
285
+ * Resume a paused task
286
+ */
287
+ async resumeTask(taskId) {
288
+ const cached = this.activeTasks.get(taskId);
289
+ if (cached) {
290
+ cached.lastAccessed = Date.now();
291
+ cached.status = 'active';
292
+ this.updateTaskStatus(taskId, 'executing');
293
+ this.logEvent(taskId, 'task_resumed', { message: 'Task resumed' });
294
+ await cached.executor.resume();
295
+ }
296
+ }
297
+ /**
298
+ * Send stdin input to a running command in a task
299
+ */
300
+ sendStdinToTask(taskId, input) {
301
+ const cached = this.activeTasks.get(taskId);
302
+ if (!cached) {
303
+ return false;
304
+ }
305
+ return cached.executor.sendStdin(input);
306
+ }
307
+ /**
308
+ * Kill the running command in a task (send SIGINT like Ctrl+C)
309
+ * @param taskId - The task ID
310
+ * @param force - If true, send SIGKILL immediately instead of graceful escalation
311
+ */
312
+ killCommandInTask(taskId, force) {
313
+ const cached = this.activeTasks.get(taskId);
314
+ if (!cached) {
315
+ return false;
316
+ }
317
+ return cached.executor.killShellProcess(force);
318
+ }
319
+ /**
320
+ * Request approval from user for an action
321
+ */
322
+ async requestApproval(taskId, type, description, details) {
323
+ const approval = this.approvalRepo.create({
324
+ taskId,
325
+ type: type,
326
+ description,
327
+ details,
328
+ status: 'pending',
329
+ requestedAt: Date.now(),
330
+ });
331
+ // Emit event to UI
332
+ this.logEvent(taskId, 'approval_requested', { approval });
333
+ // Wait for user response
334
+ return new Promise((resolve, reject) => {
335
+ // Timeout after 5 minutes
336
+ const timeoutHandle = setTimeout(() => {
337
+ const pending = this.pendingApprovals.get(approval.id);
338
+ if (pending && !pending.resolved) {
339
+ pending.resolved = true;
340
+ this.pendingApprovals.delete(approval.id);
341
+ this.approvalRepo.update(approval.id, 'denied');
342
+ this.logEvent(taskId, 'approval_denied', { approvalId: approval.id, reason: 'timeout' });
343
+ reject(new Error('Approval request timed out'));
344
+ }
345
+ }, 5 * 60 * 1000);
346
+ this.pendingApprovals.set(approval.id, { taskId, resolve, reject, resolved: false, timeoutHandle });
347
+ });
348
+ }
349
+ /**
350
+ * Respond to an approval request
351
+ * Uses idempotency to prevent double-approval race conditions
352
+ * Implements C6: Approval Gate Enforcement
353
+ */
354
+ async respondToApproval(approvalId, approved) {
355
+ // Generate idempotency key for this approval response
356
+ const idempotencyKey = concurrency_1.IdempotencyManager.generateKey('approval:respond', approvalId, approved ? 'approve' : 'deny');
357
+ // Check if this exact response was already processed
358
+ const existing = concurrency_1.approvalIdempotency.check(idempotencyKey);
359
+ if (existing.exists) {
360
+ console.log(`[AgentDaemon] Duplicate approval response ignored: ${approvalId}`);
361
+ return; // Silently ignore duplicate
362
+ }
363
+ // Start tracking this operation
364
+ if (!concurrency_1.approvalIdempotency.start(idempotencyKey)) {
365
+ console.log(`[AgentDaemon] Concurrent approval response in progress: ${approvalId}`);
366
+ return; // Another response is being processed
367
+ }
368
+ try {
369
+ const pending = this.pendingApprovals.get(approvalId);
370
+ if (pending && !pending.resolved) {
371
+ // Mark as resolved first to prevent race condition with timeout
372
+ pending.resolved = true;
373
+ // Clear the timeout
374
+ clearTimeout(pending.timeoutHandle);
375
+ this.pendingApprovals.delete(approvalId);
376
+ this.approvalRepo.update(approvalId, approved ? 'approved' : 'denied');
377
+ // Emit event so UI knows the approval has been handled
378
+ const eventType = approved ? 'approval_granted' : 'approval_denied';
379
+ this.logEvent(pending.taskId, eventType, { approvalId });
380
+ if (approved) {
381
+ pending.resolve(true);
382
+ }
383
+ else {
384
+ pending.reject(new Error('User denied approval'));
385
+ }
386
+ }
387
+ concurrency_1.approvalIdempotency.complete(idempotencyKey, { success: true });
388
+ }
389
+ catch (error) {
390
+ concurrency_1.approvalIdempotency.fail(idempotencyKey, error);
391
+ throw error;
392
+ }
393
+ }
394
+ /**
395
+ * Log an event for a task
396
+ */
397
+ logEvent(taskId, type, payload) {
398
+ this.eventRepo.create({
399
+ taskId,
400
+ timestamp: Date.now(),
401
+ type: type,
402
+ payload,
403
+ });
404
+ this.logActivityForEvent(taskId, type, payload);
405
+ this.emitTaskEvent(taskId, type, payload);
406
+ // Capture to memory system (async, don't block)
407
+ this.captureToMemory(taskId, type, payload).catch((error) => {
408
+ // Silently log - memory capture is optional enhancement
409
+ console.debug('[AgentDaemon] Memory capture failed:', error);
410
+ });
411
+ }
412
+ /**
413
+ * Capture task event to memory system for cross-session context
414
+ */
415
+ async captureToMemory(taskId, type, payload) {
416
+ // Map event types to memory types
417
+ const memoryTypeMap = {
418
+ tool_call: 'observation',
419
+ tool_result: 'observation',
420
+ tool_error: 'error',
421
+ step_started: 'observation',
422
+ step_completed: 'observation',
423
+ step_failed: 'error',
424
+ assistant_message: 'observation',
425
+ plan_created: 'decision',
426
+ plan_revised: 'decision',
427
+ error: 'error',
428
+ verification_passed: 'insight',
429
+ verification_failed: 'error',
430
+ file_created: 'observation',
431
+ file_modified: 'observation',
432
+ };
433
+ const memoryType = memoryTypeMap[type];
434
+ if (!memoryType)
435
+ return;
436
+ const task = this.taskRepo.findById(taskId);
437
+ if (!task)
438
+ return;
439
+ // Build content string based on event type
440
+ let content = '';
441
+ if (type === 'tool_call') {
442
+ content = `Tool called: ${payload.tool || payload.name}\nInput: ${JSON.stringify(payload.input, null, 2)}`;
443
+ }
444
+ else if (type === 'tool_result') {
445
+ const result = typeof payload.result === 'string' ? payload.result : JSON.stringify(payload.result);
446
+ content = `Tool result for ${payload.tool || payload.name}:\n${result}`;
447
+ }
448
+ else if (type === 'tool_error') {
449
+ content = `Tool error for ${payload.tool || payload.name}: ${payload.error}`;
450
+ }
451
+ else if (type === 'assistant_message') {
452
+ content = payload.content || payload.message || JSON.stringify(payload);
453
+ }
454
+ else if (type === 'plan_created' || type === 'plan_revised') {
455
+ content = `Plan ${type === 'plan_revised' ? 'revised' : 'created'}:\n${JSON.stringify(payload.plan || payload, null, 2)}`;
456
+ }
457
+ else if (type === 'step_completed') {
458
+ content = `Step completed: ${payload.step?.description || JSON.stringify(payload)}`;
459
+ }
460
+ else if (type === 'step_failed') {
461
+ content = `Step failed: ${payload.step?.description || ''}\nError: ${payload.error || 'Unknown error'}`;
462
+ }
463
+ else if (type === 'file_created' || type === 'file_modified') {
464
+ content = `File ${type === 'file_created' ? 'created' : 'modified'}: ${payload.path}`;
465
+ }
466
+ else if (type === 'verification_passed') {
467
+ content = `Verification passed: ${payload.message || 'Task completed successfully'}`;
468
+ }
469
+ else if (type === 'verification_failed') {
470
+ content = `Verification failed: ${payload.message || payload.error || 'Unknown failure'}`;
471
+ }
472
+ else {
473
+ content = JSON.stringify(payload);
474
+ }
475
+ // Truncate very long content
476
+ if (content.length > 5000) {
477
+ content = content.slice(0, 5000) + '\n[... truncated]';
478
+ }
479
+ await MemoryService_1.MemoryService.capture(task.workspaceId, taskId, memoryType, content);
480
+ }
481
+ /**
482
+ * Log notable task events to the Activity feed
483
+ */
484
+ logActivityForEvent(taskId, type, payload) {
485
+ const task = this.taskRepo.findById(taskId);
486
+ if (!task)
487
+ return;
488
+ const activity = this.buildActivityFromEvent(task, type, payload);
489
+ if (!activity)
490
+ return;
491
+ const created = this.activityRepo.create(activity);
492
+ this.emitActivityEvent(created);
493
+ }
494
+ buildActivityFromEvent(task, type, payload) {
495
+ const actorType = task.assignedAgentRoleId ? 'agent' : 'system';
496
+ const agentRoleId = task.assignedAgentRoleId;
497
+ const activityType = type;
498
+ switch (type) {
499
+ case 'task_created':
500
+ return {
501
+ workspaceId: task.workspaceId,
502
+ taskId: task.id,
503
+ agentRoleId,
504
+ actorType,
505
+ activityType,
506
+ title: 'Task created',
507
+ description: task.title,
508
+ };
509
+ case 'task_completed':
510
+ return {
511
+ workspaceId: task.workspaceId,
512
+ taskId: task.id,
513
+ agentRoleId,
514
+ actorType,
515
+ activityType,
516
+ title: 'Task completed',
517
+ description: task.title,
518
+ };
519
+ case 'executing':
520
+ return {
521
+ workspaceId: task.workspaceId,
522
+ taskId: task.id,
523
+ agentRoleId,
524
+ actorType,
525
+ activityType: 'task_started',
526
+ title: 'Task started',
527
+ description: task.title,
528
+ };
529
+ case 'task_cancelled':
530
+ return {
531
+ workspaceId: task.workspaceId,
532
+ taskId: task.id,
533
+ agentRoleId,
534
+ actorType,
535
+ activityType: 'info',
536
+ title: 'Task cancelled',
537
+ description: task.title,
538
+ };
539
+ case 'task_paused':
540
+ return {
541
+ workspaceId: task.workspaceId,
542
+ taskId: task.id,
543
+ agentRoleId,
544
+ actorType,
545
+ activityType,
546
+ title: 'Task paused',
547
+ description: task.title,
548
+ };
549
+ case 'task_resumed':
550
+ return {
551
+ workspaceId: task.workspaceId,
552
+ taskId: task.id,
553
+ agentRoleId,
554
+ actorType,
555
+ activityType,
556
+ title: 'Task resumed',
557
+ description: task.title,
558
+ };
559
+ case 'approval_requested':
560
+ return {
561
+ workspaceId: task.workspaceId,
562
+ taskId: task.id,
563
+ agentRoleId,
564
+ actorType,
565
+ activityType: 'info',
566
+ title: 'Approval requested',
567
+ description: payload?.approval?.description || task.title,
568
+ };
569
+ case 'approval_granted':
570
+ return {
571
+ workspaceId: task.workspaceId,
572
+ taskId: task.id,
573
+ agentRoleId,
574
+ actorType,
575
+ activityType: 'info',
576
+ title: 'Approval granted',
577
+ description: task.title,
578
+ };
579
+ case 'approval_denied':
580
+ return {
581
+ workspaceId: task.workspaceId,
582
+ taskId: task.id,
583
+ agentRoleId,
584
+ actorType,
585
+ activityType: 'info',
586
+ title: 'Approval denied',
587
+ description: payload?.reason || task.title,
588
+ };
589
+ case 'error':
590
+ case 'step_failed':
591
+ case 'verification_failed':
592
+ return {
593
+ workspaceId: task.workspaceId,
594
+ taskId: task.id,
595
+ agentRoleId,
596
+ actorType,
597
+ activityType: 'error',
598
+ title: type === 'error' ? 'Task error' : 'Execution issue',
599
+ description: payload?.error || payload?.message || payload?.step?.description || task.title,
600
+ };
601
+ case 'verification_passed':
602
+ return {
603
+ workspaceId: task.workspaceId,
604
+ taskId: task.id,
605
+ agentRoleId,
606
+ actorType,
607
+ activityType: 'info',
608
+ title: 'Verification passed',
609
+ description: payload?.message || task.title,
610
+ };
611
+ case 'file_created':
612
+ return {
613
+ workspaceId: task.workspaceId,
614
+ taskId: task.id,
615
+ agentRoleId,
616
+ actorType,
617
+ activityType,
618
+ title: 'File created',
619
+ description: payload?.path || task.title,
620
+ };
621
+ case 'file_modified':
622
+ return {
623
+ workspaceId: task.workspaceId,
624
+ taskId: task.id,
625
+ agentRoleId,
626
+ actorType,
627
+ activityType,
628
+ title: 'File modified',
629
+ description: payload?.path || task.title,
630
+ };
631
+ case 'file_deleted':
632
+ return {
633
+ workspaceId: task.workspaceId,
634
+ taskId: task.id,
635
+ agentRoleId,
636
+ actorType,
637
+ activityType,
638
+ title: 'File deleted',
639
+ description: payload?.path || task.title,
640
+ };
641
+ case 'tool_call':
642
+ return {
643
+ workspaceId: task.workspaceId,
644
+ taskId: task.id,
645
+ agentRoleId,
646
+ actorType,
647
+ activityType: 'tool_used',
648
+ title: 'Tool used',
649
+ description: payload?.tool || payload?.name || task.title,
650
+ };
651
+ default:
652
+ return undefined;
653
+ }
654
+ }
655
+ emitActivityEvent(activity) {
656
+ const windows = electron_1.BrowserWindow.getAllWindows();
657
+ windows.forEach(window => {
658
+ try {
659
+ if (!window.isDestroyed() && window.webContents && !window.webContents.isDestroyed()) {
660
+ window.webContents.send(types_1.IPC_CHANNELS.ACTIVITY_EVENT, { type: 'created', activity });
661
+ }
662
+ }
663
+ catch (error) {
664
+ console.error('[AgentDaemon] Error sending activity IPC:', error);
665
+ }
666
+ });
667
+ }
668
+ /**
669
+ * Register an artifact (file created during task execution)
670
+ * This allows files like screenshots to be sent back to the user
671
+ */
672
+ registerArtifact(taskId, filePath, mimeType) {
673
+ try {
674
+ if (!fs.existsSync(filePath)) {
675
+ console.error(`[AgentDaemon] Artifact file not found: ${filePath}`);
676
+ return;
677
+ }
678
+ const stats = fs.statSync(filePath);
679
+ const fileBuffer = fs.readFileSync(filePath);
680
+ const sha256 = crypto.createHash('sha256').update(fileBuffer).digest('hex');
681
+ this.artifactRepo.create({
682
+ taskId,
683
+ path: filePath,
684
+ mimeType,
685
+ sha256,
686
+ size: stats.size,
687
+ createdAt: Date.now(),
688
+ });
689
+ console.log(`[AgentDaemon] Registered artifact: ${filePath}`);
690
+ }
691
+ catch (error) {
692
+ console.error(`[AgentDaemon] Failed to register artifact:`, error);
693
+ }
694
+ }
695
+ /**
696
+ * Emit event to renderer process and local listeners
697
+ */
698
+ emitTaskEvent(taskId, type, payload) {
699
+ // Emit to local EventEmitter listeners (for gateway integration)
700
+ try {
701
+ this.emit(type, { taskId, ...payload });
702
+ }
703
+ catch (error) {
704
+ console.error(`[AgentDaemon] Error emitting event ${type}:`, error);
705
+ }
706
+ // Emit to renderer process via IPC
707
+ const windows = electron_1.BrowserWindow.getAllWindows();
708
+ windows.forEach(window => {
709
+ // Check if window is still valid before sending
710
+ try {
711
+ if (!window.isDestroyed() && window.webContents && !window.webContents.isDestroyed()) {
712
+ window.webContents.send(types_1.IPC_CHANNELS.TASK_EVENT, {
713
+ taskId,
714
+ type,
715
+ payload,
716
+ timestamp: Date.now(),
717
+ });
718
+ }
719
+ }
720
+ catch (error) {
721
+ // Window might have been destroyed between check and send
722
+ console.error(`[AgentDaemon] Error sending IPC to window:`, error);
723
+ }
724
+ });
725
+ }
726
+ /**
727
+ * Update task status
728
+ */
729
+ updateTaskStatus(taskId, status) {
730
+ this.taskRepo.update(taskId, { status });
731
+ }
732
+ /**
733
+ * Get task by ID
734
+ */
735
+ getTask(taskId) {
736
+ return this.taskRepo.findById(taskId);
737
+ }
738
+ /**
739
+ * Update task workspace ID in database
740
+ */
741
+ updateTaskWorkspace(taskId, workspaceId) {
742
+ this.taskRepo.update(taskId, { workspaceId });
743
+ }
744
+ /**
745
+ * Get workspace by ID
746
+ */
747
+ getWorkspaceById(id) {
748
+ return this.workspaceRepo.findById(id);
749
+ }
750
+ /**
751
+ * Get workspace by path
752
+ */
753
+ getWorkspaceByPath(path) {
754
+ return this.workspaceRepo.findByPath(path);
755
+ }
756
+ /**
757
+ * Create a new workspace with default permissions
758
+ */
759
+ createWorkspace(name, path) {
760
+ const defaultPermissions = {
761
+ read: true,
762
+ write: true,
763
+ delete: false,
764
+ network: true,
765
+ shell: false,
766
+ };
767
+ return this.workspaceRepo.create(name, path, defaultPermissions);
768
+ }
769
+ /**
770
+ * Update task fields (for Goal Mode attempt tracking, etc.)
771
+ */
772
+ updateTask(taskId, updates) {
773
+ this.taskRepo.update(taskId, updates);
774
+ }
775
+ /**
776
+ * Mark task as completed
777
+ * Note: We keep the executor in memory for follow-up messages (with TTL-based cleanup)
778
+ */
779
+ completeTask(taskId) {
780
+ this.taskRepo.update(taskId, {
781
+ status: 'completed',
782
+ completedAt: Date.now(),
783
+ });
784
+ // Mark executor as completed for TTL-based cleanup
785
+ const cached = this.activeTasks.get(taskId);
786
+ if (cached) {
787
+ cached.status = 'completed';
788
+ cached.lastAccessed = Date.now();
789
+ }
790
+ this.logEvent(taskId, 'task_completed', { message: 'Task completed successfully' });
791
+ // Notify queue manager so it can start next task
792
+ this.queueManager.onTaskFinished(taskId);
793
+ }
794
+ /**
795
+ * Send a follow-up message to a task
796
+ */
797
+ async sendMessage(taskId, message) {
798
+ let cached = this.activeTasks.get(taskId);
799
+ let executor;
800
+ // Always get fresh task and workspace from DB to pick up permission changes
801
+ const task = this.taskRepo.findById(taskId);
802
+ if (!task) {
803
+ throw new Error(`Task ${taskId} not found`);
804
+ }
805
+ const workspace = this.workspaceRepo.findById(task.workspaceId);
806
+ if (!workspace) {
807
+ throw new Error(`Workspace ${task.workspaceId} not found`);
808
+ }
809
+ if (!cached) {
810
+ // Task executor not in memory - need to recreate it
811
+ // Create new executor
812
+ executor = new executor_1.TaskExecutor(task, workspace, this);
813
+ // Rebuild conversation history from saved events
814
+ const events = this.eventRepo.findByTaskId(taskId);
815
+ if (events.length > 0) {
816
+ executor.rebuildConversationFromEvents(events);
817
+ }
818
+ this.activeTasks.set(taskId, {
819
+ executor,
820
+ lastAccessed: Date.now(),
821
+ status: 'active',
822
+ });
823
+ }
824
+ else {
825
+ executor = cached.executor;
826
+ // Update workspace to pick up permission changes (e.g., shell enabled)
827
+ executor.updateWorkspace(workspace);
828
+ cached.lastAccessed = Date.now();
829
+ cached.status = 'active';
830
+ }
831
+ // Send the message
832
+ await executor.sendMessage(message);
833
+ }
834
+ // ===== Queue Management Methods =====
835
+ /**
836
+ * Get current queue status
837
+ */
838
+ getQueueStatus() {
839
+ return this.queueManager.getStatus();
840
+ }
841
+ /**
842
+ * Get queue settings
843
+ */
844
+ getQueueSettings() {
845
+ return this.queueManager.getSettings();
846
+ }
847
+ /**
848
+ * Save queue settings
849
+ */
850
+ saveQueueSettings(settings) {
851
+ this.queueManager.saveSettings(settings);
852
+ }
853
+ /**
854
+ * Clear stuck tasks from the queue
855
+ * Used to recover from stuck state when tasks fail to clean up
856
+ * Also properly cancels running tasks to clean up resources (browser sessions, etc.)
857
+ */
858
+ async clearStuckTasks() {
859
+ // Get running task IDs before clearing
860
+ const status = this.queueManager.getStatus();
861
+ const runningTaskIds = [...status.runningTaskIds];
862
+ const queuedTaskIds = [...status.queuedTaskIds];
863
+ console.log(`[AgentDaemon] Clearing ${runningTaskIds.length} running tasks and ${queuedTaskIds.length} queued tasks`);
864
+ // Cancel all running tasks properly (this cleans up browser sessions, etc.)
865
+ for (const taskId of runningTaskIds) {
866
+ const cached = this.activeTasks.get(taskId);
867
+ if (cached) {
868
+ try {
869
+ console.log(`[AgentDaemon] Cancelling running task: ${taskId}`);
870
+ await cached.executor.cancel();
871
+ this.activeTasks.delete(taskId);
872
+ }
873
+ catch (error) {
874
+ console.error(`[AgentDaemon] Error cancelling task ${taskId}:`, error);
875
+ }
876
+ }
877
+ }
878
+ // Now clear the queue state
879
+ return this.queueManager.clearStuckTasks();
880
+ }
881
+ /**
882
+ * Handle a task that has timed out
883
+ * Called by queue manager when a task exceeds the configured timeout
884
+ */
885
+ async handleTaskTimeout(taskId) {
886
+ console.log(`[AgentDaemon] Task ${taskId} has timed out, cancelling...`);
887
+ const cached = this.activeTasks.get(taskId);
888
+ if (cached) {
889
+ try {
890
+ // Cancel the task (this cleans up browser sessions, etc.)
891
+ await cached.executor.cancel();
892
+ this.activeTasks.delete(taskId);
893
+ }
894
+ catch (error) {
895
+ console.error(`[AgentDaemon] Error cancelling timed out task ${taskId}:`, error);
896
+ }
897
+ }
898
+ // Update task status to failed with timeout message
899
+ this.taskRepo.update(taskId, {
900
+ status: 'failed',
901
+ error: 'Task timed out - exceeded maximum allowed execution time',
902
+ });
903
+ // Emit timeout event
904
+ this.logEvent(taskId, 'step_timeout', {
905
+ message: 'Task exceeded maximum execution time and was automatically cancelled',
906
+ });
907
+ }
908
+ /**
909
+ * Emit queue update event to all windows
910
+ */
911
+ emitQueueUpdate(status) {
912
+ const windows = electron_1.BrowserWindow.getAllWindows();
913
+ windows.forEach(window => {
914
+ try {
915
+ if (!window.isDestroyed() && window.webContents && !window.webContents.isDestroyed()) {
916
+ window.webContents.send(types_1.IPC_CHANNELS.QUEUE_UPDATE, status);
917
+ }
918
+ }
919
+ catch (error) {
920
+ console.error(`[AgentDaemon] Error sending queue update to window:`, error);
921
+ }
922
+ });
923
+ }
924
+ /**
925
+ * Shutdown daemon
926
+ * Properly awaits all task cancellations and clears intervals
927
+ */
928
+ async shutdown() {
929
+ console.log('Shutting down agent daemon...');
930
+ // Clear the cleanup interval
931
+ if (this.cleanupIntervalHandle) {
932
+ clearInterval(this.cleanupIntervalHandle);
933
+ this.cleanupIntervalHandle = undefined;
934
+ }
935
+ // Clear all pending approval timeouts and reject pending promises
936
+ this.pendingApprovals.forEach((pending, approvalId) => {
937
+ clearTimeout(pending.timeoutHandle);
938
+ if (!pending.resolved) {
939
+ pending.resolved = true;
940
+ pending.reject(new Error('Daemon shutting down'));
941
+ }
942
+ });
943
+ this.pendingApprovals.clear();
944
+ // Cancel all active tasks and wait for them to complete
945
+ const cancelPromises = [];
946
+ this.activeTasks.forEach((cached, taskId) => {
947
+ const promise = cached.executor.cancel().catch(err => {
948
+ console.error(`Error cancelling task ${taskId}:`, err);
949
+ });
950
+ cancelPromises.push(promise);
951
+ });
952
+ // Wait for all cancellations to complete (with timeout)
953
+ await Promise.race([
954
+ Promise.all(cancelPromises),
955
+ new Promise(resolve => setTimeout(resolve, 5000)), // 5 second timeout
956
+ ]);
957
+ this.activeTasks.clear();
958
+ // Remove all EventEmitter listeners to prevent memory leaks
959
+ this.removeAllListeners();
960
+ console.log('Agent daemon shutdown complete');
961
+ }
962
+ /**
963
+ * Prune old conversation snapshots for a task, keeping only the most recent one.
964
+ * This prevents database bloat from accumulating snapshots.
965
+ */
966
+ pruneOldSnapshots(taskId) {
967
+ try {
968
+ this.eventRepo.pruneOldSnapshots(taskId);
969
+ }
970
+ catch (error) {
971
+ console.debug('[AgentDaemon] Failed to prune old snapshots:', error);
972
+ }
973
+ }
974
+ }
975
+ exports.AgentDaemon = AgentDaemon;