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,281 @@
1
+ "use strict";
2
+ /**
3
+ * Skill Eligibility Checker
4
+ *
5
+ * Determines if a skill is eligible to run based on its requirements:
6
+ * - Required binaries (bins)
7
+ * - Any-of binaries (anyBins)
8
+ * - Environment variables (env)
9
+ * - Config paths (config)
10
+ * - Operating system (os)
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.SkillEligibilityChecker = void 0;
14
+ exports.getSkillEligibilityChecker = getSkillEligibilityChecker;
15
+ const child_process_1 = require("child_process");
16
+ const util_1 = require("util");
17
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
18
+ // Regex for valid binary names: alphanumeric, hyphens, underscores, dots
19
+ // This prevents command injection via malicious binary names
20
+ const VALID_BINARY_NAME = /^[a-zA-Z0-9._-]+$/;
21
+ /**
22
+ * Validate and sanitize a binary name to prevent command injection
23
+ * Returns null if the binary name is invalid/unsafe
24
+ */
25
+ function sanitizeBinaryName(bin) {
26
+ if (!bin || typeof bin !== 'string') {
27
+ return null;
28
+ }
29
+ // Trim whitespace
30
+ const trimmed = bin.trim();
31
+ // Check length limits (reasonable binary name length)
32
+ if (trimmed.length === 0 || trimmed.length > 256) {
33
+ return null;
34
+ }
35
+ // Validate against allowed pattern
36
+ if (!VALID_BINARY_NAME.test(trimmed)) {
37
+ console.warn(`[SkillEligibilityChecker] Invalid binary name rejected: ${bin}`);
38
+ return null;
39
+ }
40
+ return trimmed;
41
+ }
42
+ class SkillEligibilityChecker {
43
+ constructor(config) {
44
+ this.binCache = new Map();
45
+ this.config = config;
46
+ }
47
+ /**
48
+ * Check if a binary exists in PATH
49
+ */
50
+ async checkBinary(bin) {
51
+ // Sanitize binary name to prevent command injection
52
+ const safeBin = sanitizeBinaryName(bin);
53
+ if (!safeBin) {
54
+ // Invalid binary name - treat as not found
55
+ return false;
56
+ }
57
+ // Check cache first
58
+ if (this.binCache.has(safeBin)) {
59
+ return this.binCache.get(safeBin);
60
+ }
61
+ try {
62
+ // Use 'which' on Unix-like systems, 'where' on Windows
63
+ const command = process.platform === 'win32' ? `where ${safeBin}` : `which ${safeBin}`;
64
+ await execAsync(command);
65
+ this.binCache.set(safeBin, true);
66
+ return true;
67
+ }
68
+ catch {
69
+ this.binCache.set(safeBin, false);
70
+ return false;
71
+ }
72
+ }
73
+ /**
74
+ * Check if all specified binaries exist
75
+ */
76
+ async checkAllBinaries(bins) {
77
+ const results = await Promise.all(bins.map(async (bin) => ({
78
+ bin,
79
+ exists: await this.checkBinary(bin),
80
+ })));
81
+ return {
82
+ found: results.filter((r) => r.exists).map((r) => r.bin),
83
+ missing: results.filter((r) => !r.exists).map((r) => r.bin),
84
+ };
85
+ }
86
+ /**
87
+ * Check if at least one of the specified binaries exists
88
+ */
89
+ async checkAnyBinary(bins) {
90
+ const results = await Promise.all(bins.map(async (bin) => ({
91
+ bin,
92
+ exists: await this.checkBinary(bin),
93
+ })));
94
+ const found = results.filter((r) => r.exists).map((r) => r.bin);
95
+ // If any binary is found, none are "missing" for anyBins requirement
96
+ // If none are found, all are missing
97
+ const missing = found.length > 0 ? [] : bins;
98
+ return { found, missing };
99
+ }
100
+ /**
101
+ * Check if an environment variable is set
102
+ */
103
+ checkEnvVar(envVar) {
104
+ const value = process.env[envVar];
105
+ return value !== undefined && value !== '';
106
+ }
107
+ /**
108
+ * Check if all specified environment variables are set
109
+ */
110
+ checkAllEnvVars(envVars) {
111
+ const found = [];
112
+ const missing = [];
113
+ for (const envVar of envVars) {
114
+ if (this.checkEnvVar(envVar)) {
115
+ found.push(envVar);
116
+ }
117
+ else {
118
+ missing.push(envVar);
119
+ }
120
+ }
121
+ return { found, missing };
122
+ }
123
+ /**
124
+ * Check if config path is truthy (placeholder for future config system)
125
+ */
126
+ checkConfigPath(configPath) {
127
+ // TODO: Implement config path checking when config system is available
128
+ // For now, always return false (missing)
129
+ return false;
130
+ }
131
+ /**
132
+ * Check if all specified config paths are truthy
133
+ */
134
+ checkAllConfigPaths(configPaths) {
135
+ const found = [];
136
+ const missing = [];
137
+ for (const configPath of configPaths) {
138
+ if (this.checkConfigPath(configPath)) {
139
+ found.push(configPath);
140
+ }
141
+ else {
142
+ missing.push(configPath);
143
+ }
144
+ }
145
+ return { found, missing };
146
+ }
147
+ /**
148
+ * Check if current OS matches required OS
149
+ */
150
+ checkOS(requiredOS) {
151
+ const current = process.platform;
152
+ const matches = requiredOS.length === 0 || requiredOS.includes(current);
153
+ return {
154
+ matches,
155
+ current,
156
+ missing: matches ? [] : requiredOS,
157
+ };
158
+ }
159
+ /**
160
+ * Check if a skill is blocked by allowlist/denylist
161
+ */
162
+ isBlockedByList(skillId) {
163
+ if (!this.config)
164
+ return false;
165
+ // Check denylist first
166
+ if (this.config.denylist?.includes(skillId)) {
167
+ return true;
168
+ }
169
+ // Check allowlist (if set, skill must be in it)
170
+ if (this.config.allowlist && this.config.allowlist.length > 0) {
171
+ return !this.config.allowlist.includes(skillId);
172
+ }
173
+ return false;
174
+ }
175
+ /**
176
+ * Check all requirements for a skill and return eligibility status
177
+ */
178
+ async checkEligibility(skill) {
179
+ const missing = {
180
+ bins: [],
181
+ anyBins: [],
182
+ env: [],
183
+ config: [],
184
+ os: [],
185
+ };
186
+ const requires = skill.requires;
187
+ // Check required binaries
188
+ if (requires?.bins && requires.bins.length > 0) {
189
+ const binCheck = await this.checkAllBinaries(requires.bins);
190
+ missing.bins = binCheck.missing;
191
+ }
192
+ // Check any-of binaries
193
+ if (requires?.anyBins && requires.anyBins.length > 0) {
194
+ const anyBinCheck = await this.checkAnyBinary(requires.anyBins);
195
+ missing.anyBins = anyBinCheck.missing;
196
+ }
197
+ // Check environment variables
198
+ if (requires?.env && requires.env.length > 0) {
199
+ const envCheck = this.checkAllEnvVars(requires.env);
200
+ missing.env = envCheck.missing;
201
+ }
202
+ // Check config paths
203
+ if (requires?.config && requires.config.length > 0) {
204
+ const configCheck = this.checkAllConfigPaths(requires.config);
205
+ missing.config = configCheck.missing;
206
+ }
207
+ // Check OS
208
+ if (requires?.os && requires.os.length > 0) {
209
+ const osCheck = this.checkOS(requires.os);
210
+ missing.os = osCheck.missing;
211
+ }
212
+ // Check if skill is disabled
213
+ const disabled = skill.enabled === false;
214
+ // Check if blocked by allowlist/denylist
215
+ const blockedByAllowlist = this.isBlockedByList(skill.id);
216
+ // Skill is eligible if not disabled, not blocked, and no missing requirements
217
+ const hasMissingRequirements = missing.bins.length > 0 ||
218
+ missing.anyBins.length > 0 ||
219
+ missing.env.length > 0 ||
220
+ missing.config.length > 0 ||
221
+ missing.os.length > 0;
222
+ const eligible = !disabled && !blockedByAllowlist && !hasMissingRequirements;
223
+ return {
224
+ eligible,
225
+ disabled,
226
+ blockedByAllowlist,
227
+ missing,
228
+ };
229
+ }
230
+ /**
231
+ * Build a full status entry for a skill
232
+ */
233
+ async buildStatusEntry(skill) {
234
+ const eligibility = await this.checkEligibility(skill);
235
+ const requires = skill.requires || {};
236
+ return {
237
+ ...skill,
238
+ eligible: eligibility.eligible,
239
+ disabled: eligibility.disabled,
240
+ blockedByAllowlist: eligibility.blockedByAllowlist,
241
+ requirements: {
242
+ bins: requires.bins || [],
243
+ anyBins: requires.anyBins || [],
244
+ env: requires.env || [],
245
+ config: requires.config || [],
246
+ os: requires.os || [],
247
+ },
248
+ missing: eligibility.missing,
249
+ };
250
+ }
251
+ /**
252
+ * Build status entries for multiple skills
253
+ */
254
+ async buildStatusEntries(skills) {
255
+ return Promise.all(skills.map((skill) => this.buildStatusEntry(skill)));
256
+ }
257
+ /**
258
+ * Clear the binary cache (useful after installations)
259
+ */
260
+ clearCache() {
261
+ this.binCache.clear();
262
+ }
263
+ /**
264
+ * Update config (for allowlist/denylist changes)
265
+ */
266
+ updateConfig(config) {
267
+ this.config = config;
268
+ }
269
+ }
270
+ exports.SkillEligibilityChecker = SkillEligibilityChecker;
271
+ // Singleton instance
272
+ let instance = null;
273
+ function getSkillEligibilityChecker(config) {
274
+ if (!instance) {
275
+ instance = new SkillEligibilityChecker(config);
276
+ }
277
+ else if (config) {
278
+ instance.updateConfig(config);
279
+ }
280
+ return instance;
281
+ }
@@ -0,0 +1,396 @@
1
+ "use strict";
2
+ /**
3
+ * Skill Registry Service
4
+ *
5
+ * Handles communication with the remote skill registry for:
6
+ * - Searching skills
7
+ * - Installing skills
8
+ * - Updating skills
9
+ * - Publishing skills (future)
10
+ */
11
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ var desc = Object.getOwnPropertyDescriptor(m, k);
14
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
+ desc = { enumerable: true, get: function() { return m[k]; } };
16
+ }
17
+ Object.defineProperty(o, k2, desc);
18
+ }) : (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ o[k2] = m[k];
21
+ }));
22
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
23
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
24
+ }) : function(o, v) {
25
+ o["default"] = v;
26
+ });
27
+ var __importStar = (this && this.__importStar) || (function () {
28
+ var ownKeys = function(o) {
29
+ ownKeys = Object.getOwnPropertyNames || function (o) {
30
+ var ar = [];
31
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
32
+ return ar;
33
+ };
34
+ return ownKeys(o);
35
+ };
36
+ return function (mod) {
37
+ if (mod && mod.__esModule) return mod;
38
+ var result = {};
39
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
40
+ __setModuleDefault(result, mod);
41
+ return result;
42
+ };
43
+ })();
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.SkillRegistry = void 0;
46
+ exports.getSkillRegistry = getSkillRegistry;
47
+ exports.resetSkillRegistry = resetSkillRegistry;
48
+ const fs = __importStar(require("fs"));
49
+ const path = __importStar(require("path"));
50
+ const electron_1 = require("electron");
51
+ // Default registry URL - can be overridden via SKILLHUB_REGISTRY env var
52
+ const DEFAULT_REGISTRY_URL = process.env.SKILLHUB_REGISTRY || 'https://skill-hub.com/api';
53
+ const SKILLS_FOLDER_NAME = 'skills';
54
+ // Regex for valid skill IDs: lowercase alphanumeric, hyphens, underscores
55
+ // This prevents path traversal attacks via malicious skill IDs
56
+ const VALID_SKILL_ID = /^[a-z0-9_-]+$/;
57
+ /**
58
+ * Validate and sanitize a skill ID to prevent path traversal
59
+ * Returns null if the skill ID is invalid/unsafe
60
+ */
61
+ function sanitizeSkillId(skillId) {
62
+ if (!skillId || typeof skillId !== 'string') {
63
+ return null;
64
+ }
65
+ // Trim whitespace and convert to lowercase
66
+ const normalized = skillId.trim().toLowerCase();
67
+ // Check length limits
68
+ if (normalized.length === 0 || normalized.length > 128) {
69
+ return null;
70
+ }
71
+ // Reject path traversal attempts
72
+ if (normalized.includes('..') || normalized.includes('/') || normalized.includes('\\')) {
73
+ console.warn(`[SkillRegistry] Path traversal attempt rejected: ${skillId}`);
74
+ return null;
75
+ }
76
+ // Validate against allowed pattern
77
+ if (!VALID_SKILL_ID.test(normalized)) {
78
+ console.warn(`[SkillRegistry] Invalid skill ID rejected: ${skillId}`);
79
+ return null;
80
+ }
81
+ return normalized;
82
+ }
83
+ class SkillRegistry {
84
+ constructor(config) {
85
+ this.registryUrl = config?.registryUrl || DEFAULT_REGISTRY_URL;
86
+ this.managedSkillsDir =
87
+ config?.managedSkillsDir ||
88
+ path.join(electron_1.app.getPath('userData'), SKILLS_FOLDER_NAME);
89
+ // Ensure managed skills directory exists
90
+ this.ensureSkillsDirectory();
91
+ }
92
+ /**
93
+ * Ensure the managed skills directory exists
94
+ */
95
+ ensureSkillsDirectory() {
96
+ if (!fs.existsSync(this.managedSkillsDir)) {
97
+ fs.mkdirSync(this.managedSkillsDir, { recursive: true });
98
+ console.log(`[SkillRegistry] Created managed skills directory: ${this.managedSkillsDir}`);
99
+ }
100
+ }
101
+ /**
102
+ * Get the managed skills directory path
103
+ */
104
+ getManagedSkillsDir() {
105
+ return this.managedSkillsDir;
106
+ }
107
+ /**
108
+ * Search the registry for skills
109
+ */
110
+ async search(query, options) {
111
+ const page = options?.page ?? 1;
112
+ const pageSize = options?.pageSize ?? 20;
113
+ try {
114
+ const url = new URL(`${this.registryUrl}/skills/search`);
115
+ url.searchParams.set('q', query);
116
+ url.searchParams.set('page', String(page));
117
+ url.searchParams.set('pageSize', String(pageSize));
118
+ const response = await fetch(url.toString());
119
+ if (!response.ok) {
120
+ throw new Error(`Registry search failed: ${response.status} ${response.statusText}`);
121
+ }
122
+ const data = await response.json();
123
+ return data;
124
+ }
125
+ catch (error) {
126
+ console.error('[SkillRegistry] Search failed:', error);
127
+ // Return empty result on error
128
+ return {
129
+ query,
130
+ total: 0,
131
+ page,
132
+ pageSize,
133
+ results: [],
134
+ };
135
+ }
136
+ }
137
+ /**
138
+ * Get skill details from registry
139
+ */
140
+ async getSkillDetails(skillId) {
141
+ // Validate skill ID
142
+ const safeId = sanitizeSkillId(skillId);
143
+ if (!safeId) {
144
+ console.error(`[SkillRegistry] Invalid skill ID: ${skillId}`);
145
+ return null;
146
+ }
147
+ try {
148
+ const response = await fetch(`${this.registryUrl}/skills/${safeId}`);
149
+ if (!response.ok) {
150
+ if (response.status === 404) {
151
+ return null;
152
+ }
153
+ throw new Error(`Failed to get skill details: ${response.status}`);
154
+ }
155
+ return (await response.json());
156
+ }
157
+ catch (error) {
158
+ console.error(`[SkillRegistry] Failed to get skill ${skillId}:`, error);
159
+ return null;
160
+ }
161
+ }
162
+ /**
163
+ * Install a skill from the registry
164
+ */
165
+ async install(skillId, version, onProgress) {
166
+ // Validate skill ID before any operations
167
+ const safeId = sanitizeSkillId(skillId);
168
+ if (!safeId) {
169
+ return { success: false, error: `Invalid skill ID: ${skillId}` };
170
+ }
171
+ const notify = (progress) => {
172
+ onProgress?.({
173
+ skillId: safeId,
174
+ status: 'downloading',
175
+ ...progress,
176
+ });
177
+ };
178
+ try {
179
+ notify({ status: 'downloading', progress: 0, message: 'Fetching skill from registry...' });
180
+ // Fetch skill data from registry
181
+ const url = version
182
+ ? `${this.registryUrl}/skills/${safeId}/download?version=${version}`
183
+ : `${this.registryUrl}/skills/${safeId}/download`;
184
+ const response = await fetch(url);
185
+ if (!response.ok) {
186
+ throw new Error(`Failed to download skill: ${response.status} ${response.statusText}`);
187
+ }
188
+ notify({ status: 'downloading', progress: 50, message: 'Downloading skill data...' });
189
+ const skillData = await response.json();
190
+ notify({ status: 'extracting', progress: 70, message: 'Processing skill...' });
191
+ // Validate skill data
192
+ if (!this.validateSkillData(skillData)) {
193
+ throw new Error('Invalid skill data received from registry');
194
+ }
195
+ notify({ status: 'installing', progress: 80, message: 'Installing skill...' });
196
+ // Save skill to managed skills directory (using validated safeId)
197
+ const skillPath = path.join(this.managedSkillsDir, `${safeId}.json`);
198
+ const skill = {
199
+ ...skillData,
200
+ source: 'managed',
201
+ filePath: skillPath,
202
+ };
203
+ fs.writeFileSync(skillPath, JSON.stringify(skill, null, 2), 'utf-8');
204
+ notify({ status: 'completed', progress: 100, message: 'Skill installed successfully' });
205
+ console.log(`[SkillRegistry] Installed skill: ${safeId} at ${skillPath}`);
206
+ return { success: true, skill };
207
+ }
208
+ catch (error) {
209
+ const errorMessage = error instanceof Error ? error.message : String(error);
210
+ console.error(`[SkillRegistry] Install failed for ${safeId}:`, errorMessage);
211
+ notify({ status: 'failed', progress: 0, message: errorMessage, error: errorMessage });
212
+ return { success: false, error: errorMessage };
213
+ }
214
+ }
215
+ /**
216
+ * Update a managed skill to the latest version
217
+ */
218
+ async update(skillId, version, onProgress) {
219
+ // Validate skill ID
220
+ const safeId = sanitizeSkillId(skillId);
221
+ if (!safeId) {
222
+ return { success: false, error: `Invalid skill ID: ${skillId}` };
223
+ }
224
+ // Check if skill is installed
225
+ const skillPath = path.join(this.managedSkillsDir, `${safeId}.json`);
226
+ if (!fs.existsSync(skillPath)) {
227
+ return { success: false, error: `Skill ${safeId} is not installed` };
228
+ }
229
+ // Re-install with latest version
230
+ return this.install(safeId, version, onProgress);
231
+ }
232
+ /**
233
+ * Update all managed skills
234
+ */
235
+ async updateAll(onProgress) {
236
+ const updated = [];
237
+ const failed = [];
238
+ const managedSkills = this.listManagedSkills();
239
+ for (const skill of managedSkills) {
240
+ const result = await this.update(skill.id, undefined, (progress) => {
241
+ onProgress?.(skill.id, progress);
242
+ });
243
+ if (result.success) {
244
+ updated.push(skill.id);
245
+ }
246
+ else {
247
+ failed.push(skill.id);
248
+ }
249
+ }
250
+ return { updated, failed };
251
+ }
252
+ /**
253
+ * Uninstall a managed skill
254
+ */
255
+ uninstall(skillId) {
256
+ // Validate skill ID
257
+ const safeId = sanitizeSkillId(skillId);
258
+ if (!safeId) {
259
+ return { success: false, error: `Invalid skill ID: ${skillId}` };
260
+ }
261
+ const skillPath = path.join(this.managedSkillsDir, `${safeId}.json`);
262
+ if (!fs.existsSync(skillPath)) {
263
+ return { success: false, error: `Skill ${safeId} is not installed` };
264
+ }
265
+ try {
266
+ fs.unlinkSync(skillPath);
267
+ console.log(`[SkillRegistry] Uninstalled skill: ${safeId}`);
268
+ return { success: true };
269
+ }
270
+ catch (error) {
271
+ const errorMessage = error instanceof Error ? error.message : String(error);
272
+ console.error(`[SkillRegistry] Uninstall failed for ${safeId}:`, errorMessage);
273
+ return { success: false, error: errorMessage };
274
+ }
275
+ }
276
+ /**
277
+ * List all managed (installed from registry) skills
278
+ */
279
+ listManagedSkills() {
280
+ const skills = [];
281
+ if (!fs.existsSync(this.managedSkillsDir)) {
282
+ return skills;
283
+ }
284
+ const files = fs.readdirSync(this.managedSkillsDir);
285
+ for (const file of files) {
286
+ if (!file.endsWith('.json'))
287
+ continue;
288
+ try {
289
+ const filePath = path.join(this.managedSkillsDir, file);
290
+ const content = fs.readFileSync(filePath, 'utf-8');
291
+ const skill = JSON.parse(content);
292
+ skill.filePath = filePath;
293
+ skill.source = 'managed';
294
+ skills.push(skill);
295
+ }
296
+ catch (error) {
297
+ console.error(`[SkillRegistry] Failed to load managed skill ${file}:`, error);
298
+ }
299
+ }
300
+ return skills;
301
+ }
302
+ /**
303
+ * Check if a skill is installed
304
+ */
305
+ isInstalled(skillId) {
306
+ // Validate skill ID
307
+ const safeId = sanitizeSkillId(skillId);
308
+ if (!safeId) {
309
+ return false;
310
+ }
311
+ const skillPath = path.join(this.managedSkillsDir, `${safeId}.json`);
312
+ return fs.existsSync(skillPath);
313
+ }
314
+ /**
315
+ * Get installed skill version
316
+ */
317
+ getInstalledVersion(skillId) {
318
+ // Validate skill ID
319
+ const safeId = sanitizeSkillId(skillId);
320
+ if (!safeId) {
321
+ return null;
322
+ }
323
+ const skillPath = path.join(this.managedSkillsDir, `${safeId}.json`);
324
+ if (!fs.existsSync(skillPath)) {
325
+ return null;
326
+ }
327
+ try {
328
+ const content = fs.readFileSync(skillPath, 'utf-8');
329
+ const skill = JSON.parse(content);
330
+ return skill.metadata?.version || null;
331
+ }
332
+ catch {
333
+ return null;
334
+ }
335
+ }
336
+ /**
337
+ * Check for available updates
338
+ */
339
+ async checkForUpdates(skillId) {
340
+ // Validate skill ID (getInstalledVersion and getSkillDetails also validate, but check early)
341
+ const safeId = sanitizeSkillId(skillId);
342
+ if (!safeId) {
343
+ return { hasUpdate: false, currentVersion: null, latestVersion: null };
344
+ }
345
+ const currentVersion = this.getInstalledVersion(safeId);
346
+ const details = await this.getSkillDetails(safeId);
347
+ if (!details) {
348
+ return { hasUpdate: false, currentVersion, latestVersion: null };
349
+ }
350
+ const hasUpdate = currentVersion !== details.version;
351
+ return {
352
+ hasUpdate,
353
+ currentVersion,
354
+ latestVersion: details.version,
355
+ };
356
+ }
357
+ /**
358
+ * Validate skill data from registry
359
+ */
360
+ validateSkillData(data) {
361
+ if (!data || typeof data !== 'object')
362
+ return false;
363
+ const skill = data;
364
+ return (typeof skill.id === 'string' &&
365
+ typeof skill.name === 'string' &&
366
+ typeof skill.description === 'string' &&
367
+ typeof skill.prompt === 'string');
368
+ }
369
+ /**
370
+ * Update registry URL
371
+ */
372
+ setRegistryUrl(url) {
373
+ this.registryUrl = url;
374
+ }
375
+ /**
376
+ * Get current registry URL
377
+ */
378
+ getRegistryUrl() {
379
+ return this.registryUrl;
380
+ }
381
+ }
382
+ exports.SkillRegistry = SkillRegistry;
383
+ // Singleton instance
384
+ let instance = null;
385
+ function getSkillRegistry(config) {
386
+ if (!instance) {
387
+ instance = new SkillRegistry(config);
388
+ }
389
+ return instance;
390
+ }
391
+ /**
392
+ * Reset the singleton instance (useful for testing)
393
+ */
394
+ function resetSkillRegistry() {
395
+ instance = null;
396
+ }