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,466 @@
1
+ /**
2
+ * Hooks Settings Manager
3
+ *
4
+ * Manages webhook configuration with encrypted storage.
5
+ * Settings are stored encrypted in the database using SecureSettingsRepository.
6
+ */
7
+
8
+ import { app, safeStorage } from 'electron';
9
+ import * as fs from 'fs';
10
+ import * as path from 'path';
11
+ import crypto from 'crypto';
12
+ import {
13
+ HooksConfig,
14
+ GmailHooksConfig,
15
+ HookMappingConfig,
16
+ DEFAULT_HOOKS_CONFIG,
17
+ DEFAULT_HOOKS_PATH,
18
+ DEFAULT_HOOKS_MAX_BODY_BYTES,
19
+ DEFAULT_GMAIL_LABEL,
20
+ DEFAULT_GMAIL_SERVE_BIND,
21
+ DEFAULT_GMAIL_SERVE_PORT,
22
+ DEFAULT_GMAIL_SERVE_PATH,
23
+ DEFAULT_GMAIL_MAX_BYTES,
24
+ DEFAULT_GMAIL_RENEW_MINUTES,
25
+ DEFAULT_GMAIL_SUBSCRIPTION,
26
+ DEFAULT_GMAIL_TOPIC,
27
+ } from './types';
28
+ import { SecureSettingsRepository } from '../database/SecureSettingsRepository';
29
+
30
+ const LEGACY_SETTINGS_FILE = 'hooks-settings.json';
31
+ const MASKED_VALUE = '***configured***';
32
+ const ENCRYPTED_PREFIX = 'encrypted:';
33
+
34
+ /**
35
+ * Generate a secure random token
36
+ */
37
+ export function generateHookToken(bytes = 24): string {
38
+ return crypto.randomBytes(bytes).toString('hex');
39
+ }
40
+
41
+ /**
42
+ * Encrypt a secret using OS keychain via safeStorage
43
+ */
44
+ function encryptSecret(value?: string): string | undefined {
45
+ if (!value || !value.trim()) return undefined;
46
+ const trimmed = value.trim();
47
+ if (trimmed === MASKED_VALUE) return undefined;
48
+
49
+ try {
50
+ if (safeStorage.isEncryptionAvailable()) {
51
+ const encrypted = safeStorage.encryptString(trimmed);
52
+ return ENCRYPTED_PREFIX + encrypted.toString('base64');
53
+ }
54
+ } catch (error) {
55
+ console.warn('[Hooks Settings] Failed to encrypt secret, storing masked:', error);
56
+ }
57
+ // Fallback to masked value if encryption fails
58
+ return MASKED_VALUE;
59
+ }
60
+
61
+ /**
62
+ * Decrypt a secret that was encrypted with safeStorage
63
+ */
64
+ function decryptSecret(value?: string): string | undefined {
65
+ if (!value) return undefined;
66
+ if (value === MASKED_VALUE) return undefined;
67
+
68
+ if (value.startsWith(ENCRYPTED_PREFIX)) {
69
+ try {
70
+ if (safeStorage.isEncryptionAvailable()) {
71
+ const encrypted = Buffer.from(value.slice(ENCRYPTED_PREFIX.length), 'base64');
72
+ const decrypted = safeStorage.decryptString(encrypted);
73
+ return decrypted;
74
+ } else {
75
+ console.error('[Hooks Settings] safeStorage encryption not available - cannot decrypt secrets');
76
+ }
77
+ } catch (error: any) {
78
+ console.error('[Hooks Settings] Failed to decrypt secret:', error.message || error);
79
+ }
80
+ }
81
+
82
+ // If not encrypted and not masked, return as-is (for backwards compatibility)
83
+ if (value !== MASKED_VALUE && !value.startsWith(ENCRYPTED_PREFIX)) {
84
+ return value.trim() || undefined;
85
+ }
86
+
87
+ return undefined;
88
+ }
89
+
90
+ /**
91
+ * Encrypt all credentials in settings before saving to disk
92
+ */
93
+ function encryptSettings(settings: HooksConfig): HooksConfig {
94
+ return {
95
+ ...settings,
96
+ token: encryptSecret(settings.token) || '',
97
+ gmail: settings.gmail ? {
98
+ ...settings.gmail,
99
+ pushToken: encryptSecret(settings.gmail.pushToken),
100
+ } : undefined,
101
+ };
102
+ }
103
+
104
+ /**
105
+ * Decrypt all credentials in settings after loading from disk
106
+ */
107
+ function decryptSettings(settings: HooksConfig): HooksConfig {
108
+ return {
109
+ ...settings,
110
+ token: decryptSecret(settings.token) || '',
111
+ gmail: settings.gmail ? {
112
+ ...settings.gmail,
113
+ pushToken: decryptSecret(settings.gmail.pushToken),
114
+ } : undefined,
115
+ };
116
+ }
117
+
118
+ /**
119
+ * Hooks Settings Manager
120
+ */
121
+ export class HooksSettingsManager {
122
+ private static legacySettingsPath: string;
123
+ private static cachedSettings: HooksConfig | null = null;
124
+ private static initialized = false;
125
+ private static migrationCompleted = false;
126
+
127
+ /**
128
+ * Initialize the settings manager (must be called after app is ready)
129
+ */
130
+ static initialize(): void {
131
+ if (this.initialized) return;
132
+
133
+ const userDataPath = app.getPath('userData');
134
+ this.legacySettingsPath = path.join(userDataPath, LEGACY_SETTINGS_FILE);
135
+ this.initialized = true;
136
+
137
+ console.log('[Hooks Settings] Initialized');
138
+
139
+ // Migrate from legacy JSON file to encrypted database
140
+ this.migrateFromLegacyFile();
141
+ }
142
+
143
+ /**
144
+ * Migrate settings from legacy JSON file to encrypted database
145
+ */
146
+ private static migrateFromLegacyFile(): void {
147
+ if (this.migrationCompleted) return;
148
+
149
+ try {
150
+ if (!SecureSettingsRepository.isInitialized()) {
151
+ console.log('[Hooks Settings] SecureSettingsRepository not yet initialized, skipping migration');
152
+ return;
153
+ }
154
+
155
+ const repository = SecureSettingsRepository.getInstance();
156
+
157
+ if (repository.exists('hooks')) {
158
+ this.migrationCompleted = true;
159
+ return;
160
+ }
161
+
162
+ if (!fs.existsSync(this.legacySettingsPath)) {
163
+ console.log('[Hooks Settings] No legacy settings file found');
164
+ this.migrationCompleted = true;
165
+ return;
166
+ }
167
+
168
+ console.log('[Hooks Settings] Migrating settings from legacy JSON file to encrypted database...');
169
+
170
+ // Create backup before migration
171
+ const backupPath = this.legacySettingsPath + '.migration-backup';
172
+ fs.copyFileSync(this.legacySettingsPath, backupPath);
173
+
174
+ try {
175
+ const data = fs.readFileSync(this.legacySettingsPath, 'utf-8');
176
+ const parsed = JSON.parse(data);
177
+
178
+ const merged: HooksConfig = {
179
+ ...DEFAULT_HOOKS_CONFIG,
180
+ ...parsed,
181
+ mappings: parsed.mappings || [],
182
+ presets: parsed.presets || [],
183
+ };
184
+
185
+ // Decrypt any existing encrypted values before saving to the new encrypted database
186
+ const decrypted = decryptSettings(merged);
187
+
188
+ repository.save('hooks', decrypted);
189
+ console.log('[Hooks Settings] Settings migrated to encrypted database');
190
+
191
+ // Migration successful - delete backup and original
192
+ fs.unlinkSync(backupPath);
193
+ fs.unlinkSync(this.legacySettingsPath);
194
+ console.log('[Hooks Settings] Migration complete, cleaned up legacy files');
195
+
196
+ this.migrationCompleted = true;
197
+ } catch (migrationError) {
198
+ console.error('[Hooks Settings] Migration failed, backup preserved at:', backupPath);
199
+ throw migrationError;
200
+ }
201
+ } catch (error) {
202
+ console.error('[Hooks Settings] Migration failed:', error);
203
+ }
204
+ }
205
+
206
+ /**
207
+ * Load settings from encrypted database
208
+ */
209
+ static loadSettings(): HooksConfig {
210
+ this.ensureInitialized();
211
+
212
+ if (this.cachedSettings) {
213
+ return this.cachedSettings;
214
+ }
215
+
216
+ try {
217
+ if (SecureSettingsRepository.isInitialized()) {
218
+ const repository = SecureSettingsRepository.getInstance();
219
+ const stored = repository.load<HooksConfig>('hooks');
220
+ if (stored) {
221
+ const merged: HooksConfig = {
222
+ ...DEFAULT_HOOKS_CONFIG,
223
+ ...stored,
224
+ mappings: stored.mappings || [],
225
+ presets: stored.presets || [],
226
+ };
227
+ this.cachedSettings = merged;
228
+ console.log('[Hooks Settings] Loaded settings from encrypted database');
229
+ return this.cachedSettings;
230
+ }
231
+ }
232
+ } catch (error) {
233
+ console.error('[Hooks Settings] Failed to load settings:', error);
234
+ }
235
+
236
+ console.log('[Hooks Settings] No settings found, using defaults');
237
+ this.cachedSettings = { ...DEFAULT_HOOKS_CONFIG };
238
+ return this.cachedSettings;
239
+ }
240
+
241
+ /**
242
+ * Save settings to encrypted database
243
+ */
244
+ static saveSettings(settings: HooksConfig): void {
245
+ this.ensureInitialized();
246
+
247
+ try {
248
+ if (!SecureSettingsRepository.isInitialized()) {
249
+ throw new Error('SecureSettingsRepository not initialized');
250
+ }
251
+
252
+ const repository = SecureSettingsRepository.getInstance();
253
+ repository.save('hooks', settings);
254
+ this.cachedSettings = settings;
255
+ console.log('[Hooks Settings] Saved settings to encrypted database');
256
+ } catch (error) {
257
+ console.error('[Hooks Settings] Failed to save settings:', error);
258
+ throw error;
259
+ }
260
+ }
261
+
262
+ /**
263
+ * Clear the settings cache (forces reload on next access)
264
+ */
265
+ static clearCache(): void {
266
+ this.cachedSettings = null;
267
+ }
268
+
269
+ /**
270
+ * Get default settings
271
+ */
272
+ static getDefaults(): HooksConfig {
273
+ return { ...DEFAULT_HOOKS_CONFIG };
274
+ }
275
+
276
+ /**
277
+ * Update hooks configuration
278
+ */
279
+ static updateConfig(updates: Partial<HooksConfig>): HooksConfig {
280
+ const settings = this.loadSettings();
281
+ const updated = { ...settings, ...updates };
282
+ this.saveSettings(updated);
283
+ return updated;
284
+ }
285
+
286
+ /**
287
+ * Enable hooks with a new token if not already configured
288
+ */
289
+ static enableHooks(): HooksConfig {
290
+ const settings = this.loadSettings();
291
+ if (!settings.token) {
292
+ settings.token = generateHookToken();
293
+ }
294
+ settings.enabled = true;
295
+ this.saveSettings(settings);
296
+ return settings;
297
+ }
298
+
299
+ /**
300
+ * Disable hooks
301
+ */
302
+ static disableHooks(): HooksConfig {
303
+ const settings = this.loadSettings();
304
+ settings.enabled = false;
305
+ this.saveSettings(settings);
306
+ return settings;
307
+ }
308
+
309
+ /**
310
+ * Regenerate the hook token
311
+ */
312
+ static regenerateToken(): string {
313
+ const settings = this.loadSettings();
314
+ settings.token = generateHookToken();
315
+ this.saveSettings(settings);
316
+ return settings.token;
317
+ }
318
+
319
+ /**
320
+ * Add or update a preset
321
+ */
322
+ static addPreset(preset: string): HooksConfig {
323
+ const settings = this.loadSettings();
324
+ const presets = new Set(settings.presets);
325
+ presets.add(preset);
326
+ settings.presets = Array.from(presets);
327
+ this.saveSettings(settings);
328
+ return settings;
329
+ }
330
+
331
+ /**
332
+ * Remove a preset
333
+ */
334
+ static removePreset(preset: string): HooksConfig {
335
+ const settings = this.loadSettings();
336
+ settings.presets = settings.presets.filter((p) => p !== preset);
337
+ this.saveSettings(settings);
338
+ return settings;
339
+ }
340
+
341
+ /**
342
+ * Add a custom mapping
343
+ */
344
+ static addMapping(mapping: HookMappingConfig): HooksConfig {
345
+ const settings = this.loadSettings();
346
+ settings.mappings.push(mapping);
347
+ this.saveSettings(settings);
348
+ return settings;
349
+ }
350
+
351
+ /**
352
+ * Update a mapping by ID
353
+ */
354
+ static updateMapping(id: string, updates: Partial<HookMappingConfig>): HooksConfig | null {
355
+ const settings = this.loadSettings();
356
+ const index = settings.mappings.findIndex((m) => m.id === id);
357
+ if (index === -1) return null;
358
+
359
+ settings.mappings[index] = { ...settings.mappings[index], ...updates };
360
+ this.saveSettings(settings);
361
+ return settings;
362
+ }
363
+
364
+ /**
365
+ * Remove a mapping by ID
366
+ */
367
+ static removeMapping(id: string): HooksConfig {
368
+ const settings = this.loadSettings();
369
+ settings.mappings = settings.mappings.filter((m) => m.id !== id);
370
+ this.saveSettings(settings);
371
+ return settings;
372
+ }
373
+
374
+ /**
375
+ * Configure Gmail hooks
376
+ */
377
+ static configureGmail(gmailConfig: GmailHooksConfig): HooksConfig {
378
+ const settings = this.loadSettings();
379
+ settings.gmail = {
380
+ ...settings.gmail,
381
+ ...gmailConfig,
382
+ };
383
+
384
+ // Auto-add gmail preset if account is configured
385
+ if (gmailConfig.account && !settings.presets.includes('gmail')) {
386
+ settings.presets.push('gmail');
387
+ }
388
+
389
+ this.saveSettings(settings);
390
+ return settings;
391
+ }
392
+
393
+ /**
394
+ * Get Gmail configuration with defaults filled in
395
+ */
396
+ static getGmailConfig(): GmailHooksConfig {
397
+ const settings = this.loadSettings();
398
+ const gmail = settings.gmail || {};
399
+
400
+ return {
401
+ account: gmail.account,
402
+ label: gmail.label || DEFAULT_GMAIL_LABEL,
403
+ topic: gmail.topic || DEFAULT_GMAIL_TOPIC,
404
+ subscription: gmail.subscription || DEFAULT_GMAIL_SUBSCRIPTION,
405
+ pushToken: gmail.pushToken,
406
+ hookUrl: gmail.hookUrl,
407
+ includeBody: gmail.includeBody ?? true,
408
+ maxBytes: gmail.maxBytes || DEFAULT_GMAIL_MAX_BYTES,
409
+ renewEveryMinutes: gmail.renewEveryMinutes || DEFAULT_GMAIL_RENEW_MINUTES,
410
+ model: gmail.model,
411
+ thinking: gmail.thinking,
412
+ allowUnsafeExternalContent: gmail.allowUnsafeExternalContent,
413
+ serve: {
414
+ bind: gmail.serve?.bind || DEFAULT_GMAIL_SERVE_BIND,
415
+ port: gmail.serve?.port || DEFAULT_GMAIL_SERVE_PORT,
416
+ path: gmail.serve?.path || DEFAULT_GMAIL_SERVE_PATH,
417
+ },
418
+ tailscale: {
419
+ mode: gmail.tailscale?.mode || 'off',
420
+ path: gmail.tailscale?.path || DEFAULT_GMAIL_SERVE_PATH,
421
+ target: gmail.tailscale?.target,
422
+ },
423
+ };
424
+ }
425
+
426
+ /**
427
+ * Get settings for UI display (masks sensitive data)
428
+ */
429
+ static getSettingsForDisplay(): HooksConfig {
430
+ const settings = this.loadSettings();
431
+
432
+ return {
433
+ ...settings,
434
+ token: settings.token ? MASKED_VALUE : '',
435
+ gmail: settings.gmail ? {
436
+ ...settings.gmail,
437
+ pushToken: settings.gmail.pushToken ? MASKED_VALUE : undefined,
438
+ } : undefined,
439
+ };
440
+ }
441
+
442
+ /**
443
+ * Check if hooks are properly configured
444
+ */
445
+ static isConfigured(): boolean {
446
+ const settings = this.loadSettings();
447
+ return settings.enabled && !!settings.token;
448
+ }
449
+
450
+ /**
451
+ * Check if Gmail hooks are configured
452
+ */
453
+ static isGmailConfigured(): boolean {
454
+ const settings = this.loadSettings();
455
+ return !!(settings.gmail?.account && settings.gmail?.topic && settings.gmail?.pushToken);
456
+ }
457
+
458
+ /**
459
+ * Ensure the manager is initialized
460
+ */
461
+ private static ensureInitialized(): void {
462
+ if (!this.initialized) {
463
+ this.initialize();
464
+ }
465
+ }
466
+ }
@@ -0,0 +1,245 @@
1
+ /**
2
+ * Hooks Configuration Types
3
+ *
4
+ * Webhook ingress for wake and isolated agent runs.
5
+ */
6
+
7
+ import type { ChannelType } from '../../shared/types';
8
+
9
+ // ============ Hook Configuration ============
10
+
11
+ export interface HooksConfig {
12
+ enabled: boolean;
13
+ token: string;
14
+ path: string;
15
+ maxBodyBytes: number;
16
+ presets: string[];
17
+ mappings: HookMappingConfig[];
18
+ transformsDir?: string;
19
+ gmail?: GmailHooksConfig;
20
+ }
21
+
22
+ export interface GmailHooksConfig {
23
+ account?: string;
24
+ label?: string;
25
+ topic?: string;
26
+ subscription?: string;
27
+ pushToken?: string;
28
+ hookUrl?: string;
29
+ includeBody?: boolean;
30
+ maxBytes?: number;
31
+ renewEveryMinutes?: number;
32
+ model?: string;
33
+ thinking?: string;
34
+ allowUnsafeExternalContent?: boolean;
35
+ serve?: {
36
+ bind?: string;
37
+ port?: number;
38
+ path?: string;
39
+ };
40
+ tailscale?: {
41
+ mode?: 'off' | 'serve' | 'funnel';
42
+ path?: string;
43
+ target?: string;
44
+ };
45
+ }
46
+
47
+ // ============ Hook Mapping Configuration ============
48
+
49
+ export interface HookMappingConfig {
50
+ id?: string;
51
+ match?: {
52
+ path?: string;
53
+ source?: string;
54
+ };
55
+ action?: 'wake' | 'agent';
56
+ wakeMode?: 'now' | 'next-heartbeat';
57
+ name?: string;
58
+ sessionKey?: string;
59
+ messageTemplate?: string;
60
+ textTemplate?: string;
61
+ deliver?: boolean;
62
+ allowUnsafeExternalContent?: boolean;
63
+ channel?: HookMessageChannel;
64
+ to?: string;
65
+ model?: string;
66
+ thinking?: string;
67
+ timeoutSeconds?: number;
68
+ transform?: {
69
+ module: string;
70
+ export?: string;
71
+ };
72
+ }
73
+
74
+ export type HookMessageChannel = ChannelType | 'last';
75
+
76
+ // ============ Resolved Hook Mapping ============
77
+
78
+ export interface HookMappingResolved {
79
+ id: string;
80
+ matchPath?: string;
81
+ matchSource?: string;
82
+ action: 'wake' | 'agent';
83
+ wakeMode?: 'now' | 'next-heartbeat';
84
+ name?: string;
85
+ sessionKey?: string;
86
+ messageTemplate?: string;
87
+ textTemplate?: string;
88
+ deliver?: boolean;
89
+ allowUnsafeExternalContent?: boolean;
90
+ channel?: HookMessageChannel;
91
+ to?: string;
92
+ model?: string;
93
+ thinking?: string;
94
+ timeoutSeconds?: number;
95
+ transform?: HookMappingTransformResolved;
96
+ }
97
+
98
+ export interface HookMappingTransformResolved {
99
+ modulePath: string;
100
+ exportName?: string;
101
+ }
102
+
103
+ // ============ Hook Payloads ============
104
+
105
+ export interface WakeHookPayload {
106
+ text: string;
107
+ mode?: 'now' | 'next-heartbeat';
108
+ }
109
+
110
+ export interface AgentHookPayload {
111
+ message: string;
112
+ name?: string;
113
+ sessionKey?: string;
114
+ wakeMode?: 'now' | 'next-heartbeat';
115
+ deliver?: boolean;
116
+ channel?: HookMessageChannel;
117
+ to?: string;
118
+ model?: string;
119
+ thinking?: string;
120
+ timeoutSeconds?: number;
121
+ workspaceId?: string;
122
+ }
123
+
124
+ // ============ Hook Actions ============
125
+
126
+ export type HookAction =
127
+ | {
128
+ kind: 'wake';
129
+ text: string;
130
+ mode: 'now' | 'next-heartbeat';
131
+ }
132
+ | {
133
+ kind: 'agent';
134
+ message: string;
135
+ name?: string;
136
+ wakeMode: 'now' | 'next-heartbeat';
137
+ sessionKey?: string;
138
+ deliver?: boolean;
139
+ allowUnsafeExternalContent?: boolean;
140
+ channel?: HookMessageChannel;
141
+ to?: string;
142
+ model?: string;
143
+ thinking?: string;
144
+ timeoutSeconds?: number;
145
+ };
146
+
147
+ export type HookMappingResult =
148
+ | { ok: true; action: HookAction }
149
+ | { ok: true; action: null; skipped: true }
150
+ | { ok: false; error: string };
151
+
152
+ // ============ Hook Context ============
153
+
154
+ export interface HookMappingContext {
155
+ payload: Record<string, unknown>;
156
+ headers: Record<string, string>;
157
+ url: URL;
158
+ path: string;
159
+ }
160
+
161
+ // ============ Resolved Hooks Config ============
162
+
163
+ export interface HooksConfigResolved {
164
+ basePath: string;
165
+ token: string;
166
+ maxBodyBytes: number;
167
+ mappings: HookMappingResolved[];
168
+ }
169
+
170
+ // ============ Gmail Runtime Config ============
171
+
172
+ export interface GmailHookRuntimeConfig {
173
+ account: string;
174
+ label: string;
175
+ topic: string;
176
+ subscription: string;
177
+ pushToken: string;
178
+ hookToken: string;
179
+ hookUrl: string;
180
+ includeBody: boolean;
181
+ maxBytes: number;
182
+ renewEveryMinutes: number;
183
+ serve: {
184
+ bind: string;
185
+ port: number;
186
+ path: string;
187
+ };
188
+ tailscale: {
189
+ mode: 'off' | 'serve' | 'funnel';
190
+ path: string;
191
+ target?: string;
192
+ };
193
+ }
194
+
195
+ // ============ Hook Server Events ============
196
+
197
+ export interface HookServerEvent {
198
+ action: 'started' | 'stopped' | 'request' | 'error';
199
+ timestamp: number;
200
+ path?: string;
201
+ method?: string;
202
+ statusCode?: number;
203
+ error?: string;
204
+ }
205
+
206
+ // ============ Default Values ============
207
+
208
+ export const DEFAULT_HOOKS_PATH = '/hooks';
209
+ export const DEFAULT_HOOKS_MAX_BODY_BYTES = 256 * 1024; // 256KB
210
+ export const DEFAULT_HOOKS_PORT = 9877;
211
+
212
+ export const DEFAULT_GMAIL_LABEL = 'INBOX';
213
+ export const DEFAULT_GMAIL_TOPIC = 'cowork-gmail-watch';
214
+ export const DEFAULT_GMAIL_SUBSCRIPTION = 'cowork-gmail-watch-push';
215
+ export const DEFAULT_GMAIL_SERVE_BIND = '127.0.0.1';
216
+ export const DEFAULT_GMAIL_SERVE_PORT = 8788;
217
+ export const DEFAULT_GMAIL_SERVE_PATH = '/gmail-pubsub';
218
+ export const DEFAULT_GMAIL_MAX_BYTES = 20_000;
219
+ export const DEFAULT_GMAIL_RENEW_MINUTES = 12 * 60; // 12 hours
220
+
221
+ export const DEFAULT_HOOKS_CONFIG: HooksConfig = {
222
+ enabled: false,
223
+ token: '',
224
+ path: DEFAULT_HOOKS_PATH,
225
+ maxBodyBytes: DEFAULT_HOOKS_MAX_BODY_BYTES,
226
+ presets: [],
227
+ mappings: [],
228
+ };
229
+
230
+ // ============ Gmail Preset Mapping ============
231
+
232
+ export const GMAIL_PRESET_MAPPING: HookMappingConfig = {
233
+ id: 'gmail',
234
+ match: { path: 'gmail' },
235
+ action: 'agent',
236
+ wakeMode: 'now',
237
+ name: 'Gmail',
238
+ sessionKey: 'hook:gmail:{{messages[0].id}}',
239
+ messageTemplate:
240
+ 'New email from {{messages[0].from}}\nSubject: {{messages[0].subject}}\n{{messages[0].snippet}}\n{{messages[0].body}}',
241
+ };
242
+
243
+ export const HOOK_PRESET_MAPPINGS: Record<string, HookMappingConfig[]> = {
244
+ gmail: [GMAIL_PRESET_MAPPING],
245
+ };