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,714 @@
1
+ "use strict";
2
+ /**
3
+ * Canvas Manager
4
+ *
5
+ * Manages Live Canvas sessions - agent-driven visual workspaces that render
6
+ * HTML/CSS/JS content in dedicated Electron BrowserWindows.
7
+ *
8
+ * Features:
9
+ * - Session lifecycle management (create, show, hide, close)
10
+ * - Content pushing with auto-reload via file watching
11
+ * - JavaScript execution in canvas context
12
+ * - Screenshot capture
13
+ * - A2UI (Agent-to-UI) action handling
14
+ */
15
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ var desc = Object.getOwnPropertyDescriptor(m, k);
18
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
19
+ desc = { enumerable: true, get: function() { return m[k]; } };
20
+ }
21
+ Object.defineProperty(o, k2, desc);
22
+ }) : (function(o, m, k, k2) {
23
+ if (k2 === undefined) k2 = k;
24
+ o[k2] = m[k];
25
+ }));
26
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
27
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
28
+ }) : function(o, v) {
29
+ o["default"] = v;
30
+ });
31
+ var __importStar = (this && this.__importStar) || (function () {
32
+ var ownKeys = function(o) {
33
+ ownKeys = Object.getOwnPropertyNames || function (o) {
34
+ var ar = [];
35
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
36
+ return ar;
37
+ };
38
+ return ownKeys(o);
39
+ };
40
+ return function (mod) {
41
+ if (mod && mod.__esModule) return mod;
42
+ var result = {};
43
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
44
+ __setModuleDefault(result, mod);
45
+ return result;
46
+ };
47
+ })();
48
+ var __importDefault = (this && this.__importDefault) || function (mod) {
49
+ return (mod && mod.__esModule) ? mod : { "default": mod };
50
+ };
51
+ Object.defineProperty(exports, "__esModule", { value: true });
52
+ exports.CanvasManager = void 0;
53
+ const electron_1 = require("electron");
54
+ const path = __importStar(require("path"));
55
+ const fs = __importStar(require("fs/promises"));
56
+ const fs_1 = require("fs");
57
+ const crypto_1 = require("crypto");
58
+ const chokidar_1 = __importDefault(require("chokidar"));
59
+ const canvas_store_1 = require("./canvas-store");
60
+ // Default HTML scaffold for new canvas sessions
61
+ const DEFAULT_HTML = `<!DOCTYPE html>
62
+ <html>
63
+ <head>
64
+ <meta charset="UTF-8">
65
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
66
+ <title>Live Canvas</title>
67
+ <style>
68
+ body {
69
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
70
+ margin: 0;
71
+ padding: 20px;
72
+ background: #0f1220;
73
+ color: #e7e9f2;
74
+ min-height: 100vh;
75
+ display: grid;
76
+ place-items: center;
77
+ }
78
+ .loading {
79
+ display: flex;
80
+ flex-direction: column;
81
+ align-items: center;
82
+ justify-content: center;
83
+ gap: 16px;
84
+ text-align: center;
85
+ }
86
+ .spinner {
87
+ width: 44px;
88
+ height: 44px;
89
+ border-radius: 50%;
90
+ border: 4px solid rgba(255, 255, 255, 0.15);
91
+ border-top-color: #52d1dc;
92
+ animation: spin 0.9s linear infinite;
93
+ box-shadow: 0 0 18px rgba(82, 209, 220, 0.35);
94
+ }
95
+ .message {
96
+ font-size: 1.05em;
97
+ color: #a3acc4;
98
+ letter-spacing: 0.2px;
99
+ }
100
+ @keyframes spin {
101
+ to { transform: rotate(360deg); }
102
+ }
103
+ </style>
104
+ </head>
105
+ <body>
106
+ <div class="loading">
107
+ <div class="spinner"></div>
108
+ <div class="message">Waiting for content...</div>
109
+ </div>
110
+ </body>
111
+ </html>`;
112
+ /**
113
+ * Canvas Manager Singleton
114
+ */
115
+ class CanvasManager {
116
+ constructor() {
117
+ this.sessions = new Map();
118
+ this.windows = new Map();
119
+ this.watchers = new Map();
120
+ this.windowToSession = new Map();
121
+ this.mainWindow = null;
122
+ this.eventCallback = null;
123
+ this.a2uiCallback = null;
124
+ }
125
+ getSessionMode(session) {
126
+ return session.mode || 'html';
127
+ }
128
+ getCanvasUrl(sessionId) {
129
+ return `canvas://${sessionId}/index.html`;
130
+ }
131
+ normalizeUrl(rawUrl) {
132
+ const trimmed = rawUrl.trim();
133
+ if (!trimmed) {
134
+ throw new Error('URL cannot be empty');
135
+ }
136
+ const withScheme = /^https?:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
137
+ const parsed = new URL(withScheme);
138
+ if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
139
+ throw new Error('Only http and https URLs are supported for canvas browsing');
140
+ }
141
+ return parsed.toString();
142
+ }
143
+ /**
144
+ * Get the singleton instance
145
+ */
146
+ static getInstance() {
147
+ if (!CanvasManager.instance) {
148
+ CanvasManager.instance = new CanvasManager();
149
+ }
150
+ return CanvasManager.instance;
151
+ }
152
+ /**
153
+ * Set the main window reference for event broadcasting
154
+ */
155
+ setMainWindow(window) {
156
+ this.mainWindow = window;
157
+ }
158
+ /**
159
+ * Set callback for canvas events (used for IPC broadcasting)
160
+ */
161
+ setEventCallback(callback) {
162
+ this.eventCallback = callback;
163
+ }
164
+ /**
165
+ * Set callback for A2UI actions
166
+ */
167
+ setA2UICallback(callback) {
168
+ this.a2uiCallback = callback;
169
+ }
170
+ /**
171
+ * Restore sessions from disk storage
172
+ * Called on app startup to reload persisted sessions
173
+ */
174
+ async restoreSessions() {
175
+ try {
176
+ const store = await (0, canvas_store_1.loadCanvasStore)();
177
+ for (const session of store.sessions) {
178
+ // Only restore active sessions with valid directories
179
+ if (session.status === 'active' && (0, fs_1.existsSync)(session.sessionDir)) {
180
+ this.sessions.set(session.id, session);
181
+ console.log(`[CanvasManager] Restored session ${session.id} for task ${session.taskId}`);
182
+ }
183
+ }
184
+ console.log(`[CanvasManager] Restored ${this.sessions.size} sessions from disk`);
185
+ }
186
+ catch (error) {
187
+ console.error('[CanvasManager] Failed to restore sessions:', error);
188
+ }
189
+ }
190
+ /**
191
+ * Persist all sessions to disk
192
+ */
193
+ async persistSessions() {
194
+ try {
195
+ const sessions = Array.from(this.sessions.values());
196
+ await (0, canvas_store_1.saveCanvasStore)({ version: 1, sessions });
197
+ console.log(`[CanvasManager] Persisted ${sessions.length} sessions to disk`);
198
+ }
199
+ catch (error) {
200
+ console.error('[CanvasManager] Failed to persist sessions:', error);
201
+ }
202
+ }
203
+ /**
204
+ * Create a new canvas session
205
+ */
206
+ async createSession(taskId, workspaceId, title, options) {
207
+ const sessionId = (0, crypto_1.randomUUID)();
208
+ const sessionDir = path.join(electron_1.app.getPath('userData'), 'canvas', sessionId);
209
+ // Create session directory
210
+ await fs.mkdir(sessionDir, { recursive: true });
211
+ // Write default HTML scaffold
212
+ await fs.writeFile(path.join(sessionDir, 'index.html'), DEFAULT_HTML, 'utf-8');
213
+ const normalizedUrl = options?.url ? this.normalizeUrl(options.url) : undefined;
214
+ const normalizedMode = options?.mode === 'browser' && normalizedUrl ? 'browser' : 'html';
215
+ const session = {
216
+ id: sessionId,
217
+ taskId,
218
+ workspaceId,
219
+ sessionDir,
220
+ mode: normalizedMode,
221
+ url: normalizedMode === 'browser' ? normalizedUrl : undefined,
222
+ status: 'active',
223
+ title: title || `Canvas ${new Date().toLocaleTimeString()}`,
224
+ createdAt: Date.now(),
225
+ lastUpdatedAt: Date.now(),
226
+ };
227
+ this.sessions.set(sessionId, session);
228
+ // Persist sessions to disk
229
+ await this.persistSessions();
230
+ // Emit event
231
+ this.emitEvent({
232
+ type: 'session_created',
233
+ sessionId,
234
+ taskId,
235
+ timestamp: Date.now(),
236
+ session,
237
+ });
238
+ console.log(`[CanvasManager] Created session ${sessionId} for task ${taskId}`);
239
+ return session;
240
+ }
241
+ /**
242
+ * Get a session by ID
243
+ */
244
+ getSession(sessionId) {
245
+ return this.sessions.get(sessionId);
246
+ }
247
+ /**
248
+ * Get session ID from a BrowserWindow
249
+ */
250
+ getSessionFromWindow(window) {
251
+ return this.windowToSession.get(window.id);
252
+ }
253
+ /**
254
+ * List all sessions for a task
255
+ */
256
+ listSessionsForTask(taskId) {
257
+ return Array.from(this.sessions.values()).filter((s) => s.taskId === taskId);
258
+ }
259
+ /**
260
+ * List all active sessions
261
+ */
262
+ listAllSessions() {
263
+ return Array.from(this.sessions.values());
264
+ }
265
+ /**
266
+ * Push content to a canvas session
267
+ */
268
+ async pushContent(sessionId, content, filename = 'index.html') {
269
+ const session = this.sessions.get(sessionId);
270
+ if (!session) {
271
+ const existingSessions = Array.from(this.sessions.keys());
272
+ console.error(`[CanvasManager] Session not found: "${sessionId}"`);
273
+ console.error(`[CanvasManager] Existing sessions: ${existingSessions.length > 0 ? existingSessions.join(', ') : 'none'}`);
274
+ throw new Error(`Canvas session not found: "${sessionId}". Available sessions: ${existingSessions.join(', ') || 'none'}`);
275
+ }
276
+ const wasBrowser = this.getSessionMode(session) === 'browser';
277
+ // Sanitize filename to prevent path traversal
278
+ const safeFilename = path.basename(filename);
279
+ const filePath = path.join(session.sessionDir, safeFilename);
280
+ await fs.writeFile(filePath, content, 'utf-8');
281
+ // Switch back to HTML mode when content is pushed
282
+ session.mode = 'html';
283
+ session.url = undefined;
284
+ // Update session timestamp
285
+ session.lastUpdatedAt = Date.now();
286
+ // Persist sessions to disk (in background, don't await to avoid blocking)
287
+ this.persistSessions().catch(err => console.error('[CanvasManager] Failed to persist after push:', err));
288
+ // Ensure a hidden window exists for snapshots (NOT shown to user)
289
+ // The window will only be shown when user explicitly requests via showCanvas()
290
+ const window = await this.ensureWindowForSnapshots(sessionId);
291
+ // If the session previously loaded a remote URL, navigate back to canvas content
292
+ if (wasBrowser && window && !window.isDestroyed()) {
293
+ await window.loadURL(this.getCanvasUrl(sessionId));
294
+ }
295
+ // Ensure watcher is running for HTML mode
296
+ this.startWatcher(sessionId, session.sessionDir, window);
297
+ // Emit event
298
+ this.emitEvent({
299
+ type: 'content_pushed',
300
+ sessionId,
301
+ taskId: session.taskId,
302
+ timestamp: Date.now(),
303
+ });
304
+ this.emitEvent({
305
+ type: 'session_updated',
306
+ sessionId,
307
+ taskId: session.taskId,
308
+ timestamp: Date.now(),
309
+ session,
310
+ });
311
+ console.log(`[CanvasManager] Pushed ${safeFilename} to session ${sessionId}`);
312
+ }
313
+ /**
314
+ * Open a remote URL inside the canvas window (browser mode)
315
+ */
316
+ async openUrl(sessionId, rawUrl, options) {
317
+ const session = this.sessions.get(sessionId);
318
+ if (!session) {
319
+ const existingSessions = Array.from(this.sessions.keys());
320
+ console.error(`[CanvasManager] Session not found: "${sessionId}"`);
321
+ console.error(`[CanvasManager] Existing sessions: ${existingSessions.length > 0 ? existingSessions.join(', ') : 'none'}`);
322
+ throw new Error(`Canvas session not found: "${sessionId}". Available sessions: ${existingSessions.join(', ') || 'none'}`);
323
+ }
324
+ const normalizedUrl = this.normalizeUrl(rawUrl);
325
+ session.mode = 'browser';
326
+ session.url = normalizedUrl;
327
+ session.lastUpdatedAt = Date.now();
328
+ this.persistSessions().catch(err => console.error('[CanvasManager] Failed to persist after openUrl:', err));
329
+ const window = await this.ensureWindowForSnapshots(sessionId);
330
+ if (window && !window.isDestroyed()) {
331
+ this.stopWatcher(sessionId);
332
+ if (window.webContents.getURL() !== normalizedUrl) {
333
+ await window.loadURL(normalizedUrl);
334
+ }
335
+ }
336
+ this.emitEvent({
337
+ type: 'session_updated',
338
+ sessionId,
339
+ taskId: session.taskId,
340
+ timestamp: Date.now(),
341
+ session,
342
+ });
343
+ if (options?.show) {
344
+ await this.showCanvas(sessionId);
345
+ }
346
+ console.log(`[CanvasManager] Opened URL in session ${sessionId}: ${normalizedUrl}`);
347
+ return normalizedUrl;
348
+ }
349
+ /**
350
+ * Ensure a window exists for taking snapshots (hidden by default)
351
+ * This creates a hidden window that can be used for previews without
352
+ * showing a separate window to the user
353
+ */
354
+ async ensureWindowForSnapshots(sessionId) {
355
+ const session = this.sessions.get(sessionId);
356
+ if (!session) {
357
+ throw new Error('Canvas session not found');
358
+ }
359
+ let window = this.windows.get(sessionId);
360
+ if (!window || window.isDestroyed()) {
361
+ // Calculate initial position - to the right of main window or right side of screen
362
+ let initialX;
363
+ let initialY;
364
+ let initialHeight = 700;
365
+ if (this.mainWindow && !this.mainWindow.isDestroyed()) {
366
+ const mainBounds = this.mainWindow.getBounds();
367
+ initialX = mainBounds.x + mainBounds.width + 20;
368
+ initialY = mainBounds.y;
369
+ initialHeight = mainBounds.height;
370
+ }
371
+ else {
372
+ // Fallback: position on right side of primary display
373
+ const primaryDisplay = electron_1.screen.getPrimaryDisplay();
374
+ const { width: screenWidth, height: screenHeight } = primaryDisplay.workAreaSize;
375
+ initialX = screenWidth - 920; // 900 width + 20 margin
376
+ initialY = 50;
377
+ initialHeight = screenHeight - 100;
378
+ }
379
+ // Create new HIDDEN window for snapshots
380
+ // NOT a child window - will be positioned to the side when shown
381
+ window = new electron_1.BrowserWindow({
382
+ x: initialX,
383
+ y: initialY,
384
+ width: 900,
385
+ height: initialHeight,
386
+ title: session.title || 'Live Canvas',
387
+ show: false, // Start hidden - only show when user explicitly requests
388
+ // No parent - independent window that won't overlap main app
389
+ webPreferences: {
390
+ preload: path.join(__dirname, 'canvas-preload.js'),
391
+ contextIsolation: true,
392
+ nodeIntegration: false,
393
+ sandbox: false,
394
+ },
395
+ backgroundColor: '#1a1a2e',
396
+ });
397
+ this.windows.set(sessionId, window);
398
+ this.windowToSession.set(window.id, sessionId);
399
+ // Handle window close
400
+ window.on('closed', () => {
401
+ this.windows.delete(sessionId);
402
+ this.windowToSession.delete(window.id);
403
+ this.stopWatcher(sessionId);
404
+ });
405
+ const mode = this.getSessionMode(session);
406
+ let targetUrl = this.getCanvasUrl(sessionId);
407
+ if (mode === 'browser' && session.url) {
408
+ try {
409
+ targetUrl = this.normalizeUrl(session.url);
410
+ }
411
+ catch (error) {
412
+ console.warn('[CanvasManager] Invalid stored URL, falling back to canvas content:', error);
413
+ session.mode = 'html';
414
+ session.url = undefined;
415
+ }
416
+ }
417
+ // Load the canvas URL (or remote URL for browser mode)
418
+ await window.loadURL(targetUrl);
419
+ // Start file watcher for auto-reload only in HTML mode
420
+ if (mode === 'html') {
421
+ this.startWatcher(sessionId, session.sessionDir, window);
422
+ }
423
+ }
424
+ // Ensure watcher state is correct for existing windows
425
+ if (window && !window.isDestroyed()) {
426
+ const mode = this.getSessionMode(session);
427
+ if (mode === 'html') {
428
+ this.startWatcher(sessionId, session.sessionDir, window);
429
+ }
430
+ else {
431
+ this.stopWatcher(sessionId);
432
+ }
433
+ }
434
+ return window;
435
+ }
436
+ /**
437
+ * Show the canvas window (opens it visibly to the user)
438
+ */
439
+ async showCanvas(sessionId) {
440
+ // Ensure window exists (may be hidden)
441
+ const window = await this.ensureWindowForSnapshots(sessionId);
442
+ let bounds;
443
+ if (this.mainWindow && !this.mainWindow.isDestroyed()) {
444
+ const mainBounds = this.mainWindow.getBounds();
445
+ console.log(`[CanvasManager] Main window bounds:`, mainBounds);
446
+ // Position canvas window completely to the RIGHT of the main window
447
+ // This ensures it never overlaps with the main app
448
+ bounds = {
449
+ x: mainBounds.x + mainBounds.width + 20, // 20px gap to the right
450
+ y: mainBounds.y,
451
+ width: 900,
452
+ height: mainBounds.height,
453
+ };
454
+ }
455
+ else {
456
+ console.log(`[CanvasManager] WARNING: mainWindow not available, using fallback position`);
457
+ // Fallback: position on right side of primary display
458
+ const primaryDisplay = electron_1.screen.getPrimaryDisplay();
459
+ const { width: screenWidth, height: screenHeight } = primaryDisplay.workAreaSize;
460
+ bounds = {
461
+ x: screenWidth - 920, // 900 width + 20 margin
462
+ y: 50,
463
+ width: 900,
464
+ height: screenHeight - 100,
465
+ };
466
+ }
467
+ console.log(`[CanvasManager] Setting canvas window bounds:`, bounds);
468
+ // Always set position first to ensure correct placement
469
+ window.setPosition(bounds.x, bounds.y);
470
+ window.setSize(bounds.width, bounds.height);
471
+ // Show and focus the window so keyboard input works for interactive browsing
472
+ if (!window.isVisible()) {
473
+ window.show();
474
+ }
475
+ window.focus();
476
+ // Ensure bounds are applied after show (some systems need this)
477
+ window.setBounds(bounds);
478
+ this.emitEvent({
479
+ type: 'window_opened',
480
+ sessionId,
481
+ taskId: this.sessions.get(sessionId).taskId,
482
+ timestamp: Date.now(),
483
+ });
484
+ }
485
+ /**
486
+ * Hide the canvas window
487
+ */
488
+ hideCanvas(sessionId) {
489
+ const window = this.windows.get(sessionId);
490
+ if (window && !window.isDestroyed()) {
491
+ window.hide();
492
+ }
493
+ }
494
+ /**
495
+ * Close a canvas session
496
+ */
497
+ async closeSession(sessionId) {
498
+ const session = this.sessions.get(sessionId);
499
+ if (!session) {
500
+ return;
501
+ }
502
+ // Close window if open
503
+ const window = this.windows.get(sessionId);
504
+ if (window && !window.isDestroyed()) {
505
+ window.close();
506
+ }
507
+ // Stop watcher
508
+ this.stopWatcher(sessionId);
509
+ // Update session status
510
+ session.status = 'closed';
511
+ // Persist sessions to disk (removes closed sessions)
512
+ await this.persistSessions();
513
+ // Emit event
514
+ this.emitEvent({
515
+ type: 'session_closed',
516
+ sessionId,
517
+ taskId: session.taskId,
518
+ timestamp: Date.now(),
519
+ });
520
+ console.log(`[CanvasManager] Closed session ${sessionId}`);
521
+ }
522
+ /**
523
+ * Execute JavaScript in the canvas context
524
+ */
525
+ async evalScript(sessionId, script) {
526
+ // Ensure window exists (create hidden one if needed)
527
+ const window = await this.ensureWindowForSnapshots(sessionId);
528
+ if (!window || window.isDestroyed()) {
529
+ throw new Error('Canvas window could not be created');
530
+ }
531
+ return window.webContents.executeJavaScript(script);
532
+ }
533
+ /**
534
+ * Take a screenshot of the canvas
535
+ */
536
+ async takeSnapshot(sessionId) {
537
+ // Ensure window exists (create hidden one if needed)
538
+ const window = await this.ensureWindowForSnapshots(sessionId);
539
+ if (!window || window.isDestroyed()) {
540
+ throw new Error('Canvas window could not be created');
541
+ }
542
+ const image = await window.webContents.capturePage();
543
+ const size = image.getSize();
544
+ return {
545
+ sessionId,
546
+ imageBase64: image.toPNG().toString('base64'),
547
+ width: size.width,
548
+ height: size.height,
549
+ };
550
+ }
551
+ /**
552
+ * Export canvas content as a standalone HTML file
553
+ * Returns the HTML content with all assets inlined if possible
554
+ */
555
+ async exportAsHTML(sessionId) {
556
+ const session = this.sessions.get(sessionId);
557
+ if (!session) {
558
+ throw new Error(`Canvas session not found: ${sessionId}`);
559
+ }
560
+ const htmlPath = path.join(session.sessionDir, 'index.html');
561
+ if (!(0, fs_1.existsSync)(htmlPath)) {
562
+ throw new Error('Canvas index.html not found');
563
+ }
564
+ const content = await fs.readFile(htmlPath, 'utf-8');
565
+ const filename = `canvas-${session.title?.replace(/[^a-z0-9]/gi, '-') || sessionId.slice(0, 8)}.html`;
566
+ console.log(`[CanvasManager] Exported HTML for session ${sessionId}`);
567
+ return { content, filename };
568
+ }
569
+ /**
570
+ * Export all canvas files to a target directory
571
+ */
572
+ async exportToFolder(sessionId, targetDir) {
573
+ const session = this.sessions.get(sessionId);
574
+ if (!session) {
575
+ throw new Error(`Canvas session not found: ${sessionId}`);
576
+ }
577
+ if (!(0, fs_1.existsSync)(session.sessionDir)) {
578
+ throw new Error('Canvas session directory not found');
579
+ }
580
+ // Create target directory if it doesn't exist
581
+ await fs.mkdir(targetDir, { recursive: true });
582
+ // Get all files in the session directory
583
+ const files = (0, fs_1.readdirSync)(session.sessionDir);
584
+ const copiedFiles = [];
585
+ for (const file of files) {
586
+ const srcPath = path.join(session.sessionDir, file);
587
+ const destPath = path.join(targetDir, file);
588
+ await fs.copyFile(srcPath, destPath);
589
+ copiedFiles.push(file);
590
+ }
591
+ console.log(`[CanvasManager] Exported ${copiedFiles.length} files for session ${sessionId} to ${targetDir}`);
592
+ return { files: copiedFiles, targetDir };
593
+ }
594
+ /**
595
+ * Open canvas content in the default system browser
596
+ */
597
+ async openInBrowser(sessionId) {
598
+ const session = this.sessions.get(sessionId);
599
+ if (!session) {
600
+ throw new Error(`Canvas session not found: ${sessionId}`);
601
+ }
602
+ if (this.getSessionMode(session) === 'browser' && session.url) {
603
+ await electron_1.shell.openExternal(session.url);
604
+ console.log(`[CanvasManager] Opened session ${sessionId} in browser: ${session.url}`);
605
+ return { success: true, path: session.url };
606
+ }
607
+ const htmlPath = path.join(session.sessionDir, 'index.html');
608
+ if (!(0, fs_1.existsSync)(htmlPath)) {
609
+ throw new Error('Canvas index.html not found');
610
+ }
611
+ // Open in default browser
612
+ await electron_1.shell.openPath(htmlPath);
613
+ console.log(`[CanvasManager] Opened session ${sessionId} in browser: ${htmlPath}`);
614
+ return { success: true, path: htmlPath };
615
+ }
616
+ /**
617
+ * Get the session directory path for external access
618
+ */
619
+ getSessionDir(sessionId) {
620
+ const session = this.sessions.get(sessionId);
621
+ return session?.sessionDir || null;
622
+ }
623
+ /**
624
+ * Handle A2UI action from canvas window
625
+ */
626
+ handleA2UIAction(windowId, action) {
627
+ const sessionId = this.windowToSession.get(windowId);
628
+ if (!sessionId)
629
+ return;
630
+ const session = this.sessions.get(sessionId);
631
+ if (!session)
632
+ return;
633
+ const a2uiAction = {
634
+ actionName: action.actionName,
635
+ sessionId,
636
+ componentId: action.componentId,
637
+ context: action.context,
638
+ timestamp: Date.now(),
639
+ };
640
+ // Emit event for UI
641
+ this.emitEvent({
642
+ type: 'a2ui_action',
643
+ sessionId,
644
+ taskId: session.taskId,
645
+ timestamp: Date.now(),
646
+ action: a2uiAction,
647
+ });
648
+ // Call A2UI callback if set
649
+ if (this.a2uiCallback) {
650
+ this.a2uiCallback(a2uiAction);
651
+ }
652
+ }
653
+ /**
654
+ * Start file watcher for a session
655
+ */
656
+ startWatcher(sessionId, sessionDir, window) {
657
+ if (this.watchers.has(sessionId)) {
658
+ return;
659
+ }
660
+ const watcher = chokidar_1.default.watch(sessionDir, {
661
+ ignoreInitial: true,
662
+ awaitWriteFinish: {
663
+ stabilityThreshold: 100,
664
+ pollInterval: 50,
665
+ },
666
+ });
667
+ watcher.on('change', () => {
668
+ if (!window.isDestroyed()) {
669
+ window.webContents.reload();
670
+ }
671
+ });
672
+ this.watchers.set(sessionId, watcher);
673
+ }
674
+ /**
675
+ * Stop file watcher for a session
676
+ */
677
+ stopWatcher(sessionId) {
678
+ const watcher = this.watchers.get(sessionId);
679
+ if (watcher) {
680
+ watcher.close();
681
+ this.watchers.delete(sessionId);
682
+ }
683
+ }
684
+ /**
685
+ * Emit a canvas event
686
+ */
687
+ emitEvent(event) {
688
+ // Call event callback
689
+ if (this.eventCallback) {
690
+ this.eventCallback(event);
691
+ }
692
+ // Broadcast to main window
693
+ if (this.mainWindow && !this.mainWindow.isDestroyed()) {
694
+ this.mainWindow.webContents.send('canvas:event', event);
695
+ }
696
+ }
697
+ /**
698
+ * Cleanup all sessions and resources
699
+ */
700
+ async cleanup() {
701
+ // Close all windows
702
+ for (const [sessionId, window] of this.windows) {
703
+ if (!window.isDestroyed()) {
704
+ window.close();
705
+ }
706
+ this.stopWatcher(sessionId);
707
+ }
708
+ this.sessions.clear();
709
+ this.windows.clear();
710
+ this.windowToSession.clear();
711
+ console.log('[CanvasManager] Cleanup complete');
712
+ }
713
+ }
714
+ exports.CanvasManager = CanvasManager;