crewswarm 0.8.1-beta

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 (362) hide show
  1. package/.env.example +155 -0
  2. package/LICENSE +21 -0
  3. package/README.md +316 -0
  4. package/apps/dashboard/dist/assets/chat-core-BwSoInmZ.js +1 -0
  5. package/apps/dashboard/dist/assets/chat-core-BwSoInmZ.js.br +0 -0
  6. package/apps/dashboard/dist/assets/cli-process-COMRNPqr.js +1 -0
  7. package/apps/dashboard/dist/assets/cli-process-COMRNPqr.js.br +0 -0
  8. package/apps/dashboard/dist/assets/components-CSUb80ze.js +1 -0
  9. package/apps/dashboard/dist/assets/components-CSUb80ze.js.br +0 -0
  10. package/apps/dashboard/dist/assets/core-utils-CAVnDoe1.js +1 -0
  11. package/apps/dashboard/dist/assets/core-utils-CAVnDoe1.js.br +0 -0
  12. package/apps/dashboard/dist/assets/index-CF0aJRtC.css +1 -0
  13. package/apps/dashboard/dist/assets/index-CF0aJRtC.css.br +0 -0
  14. package/apps/dashboard/dist/assets/index-Px49zu76.js +2 -0
  15. package/apps/dashboard/dist/assets/index-Px49zu76.js.br +0 -0
  16. package/apps/dashboard/dist/assets/orchestration-Ca2DLWN-.js +1 -0
  17. package/apps/dashboard/dist/assets/orchestration-Ca2DLWN-.js.br +0 -0
  18. package/apps/dashboard/dist/assets/setup-wizard-i3eEixlo.js +1 -0
  19. package/apps/dashboard/dist/assets/setup-wizard-i3eEixlo.js.br +0 -0
  20. package/apps/dashboard/dist/assets/tab-agents-tab-BThdsdJY.js +1 -0
  21. package/apps/dashboard/dist/assets/tab-agents-tab-BThdsdJY.js.br +0 -0
  22. package/apps/dashboard/dist/assets/tab-benchmarks-tab-DfCuAClu.js +1 -0
  23. package/apps/dashboard/dist/assets/tab-comms-tab-eHpOSBhG.js +1 -0
  24. package/apps/dashboard/dist/assets/tab-comms-tab-eHpOSBhG.js.br +0 -0
  25. package/apps/dashboard/dist/assets/tab-contacts-tab-yEegNyO4.js +1 -0
  26. package/apps/dashboard/dist/assets/tab-contacts-tab-yEegNyO4.js.br +0 -0
  27. package/apps/dashboard/dist/assets/tab-engines-tab-C3DYxTwy.js +1 -0
  28. package/apps/dashboard/dist/assets/tab-engines-tab-C3DYxTwy.js.br +0 -0
  29. package/apps/dashboard/dist/assets/tab-memory-tab-C59BYFQD.js +1 -0
  30. package/apps/dashboard/dist/assets/tab-memory-tab-C59BYFQD.js.br +0 -0
  31. package/apps/dashboard/dist/assets/tab-models-tab-9Ur7pXWA.js +1 -0
  32. package/apps/dashboard/dist/assets/tab-models-tab-9Ur7pXWA.js.br +0 -0
  33. package/apps/dashboard/dist/assets/tab-pm-loop-tab-D7mnDelU.js +1 -0
  34. package/apps/dashboard/dist/assets/tab-pm-loop-tab-D7mnDelU.js.br +0 -0
  35. package/apps/dashboard/dist/assets/tab-projects-tab-C6h2Mv1K.js +1 -0
  36. package/apps/dashboard/dist/assets/tab-projects-tab-C6h2Mv1K.js.br +0 -0
  37. package/apps/dashboard/dist/assets/tab-prompts-tab-C0wZvWK3.js +1 -0
  38. package/apps/dashboard/dist/assets/tab-prompts-tab-C0wZvWK3.js.br +0 -0
  39. package/apps/dashboard/dist/assets/tab-services-tab-DBj_w3bc.js +1 -0
  40. package/apps/dashboard/dist/assets/tab-services-tab-DBj_w3bc.js.br +0 -0
  41. package/apps/dashboard/dist/assets/tab-settings-tab-ezeqAjZk.js +1 -0
  42. package/apps/dashboard/dist/assets/tab-settings-tab-ezeqAjZk.js.br +0 -0
  43. package/apps/dashboard/dist/assets/tab-skills-tab-BYdU2whk.js +1 -0
  44. package/apps/dashboard/dist/assets/tab-skills-tab-BYdU2whk.js.br +0 -0
  45. package/apps/dashboard/dist/assets/tab-spending-tab-Bg6w9t_p.js +1 -0
  46. package/apps/dashboard/dist/assets/tab-spending-tab-Bg6w9t_p.js.br +0 -0
  47. package/apps/dashboard/dist/assets/tab-swarm-chat-tab-BBV9HB2X.js +1 -0
  48. package/apps/dashboard/dist/assets/tab-swarm-chat-tab-BBV9HB2X.js.br +0 -0
  49. package/apps/dashboard/dist/assets/tab-swarm-tab-ChqLlEVs.js +1 -0
  50. package/apps/dashboard/dist/assets/tab-swarm-tab-ChqLlEVs.js.br +0 -0
  51. package/apps/dashboard/dist/assets/tab-usage-tab-B2UWXenJ.js +1 -0
  52. package/apps/dashboard/dist/assets/tab-usage-tab-B2UWXenJ.js.br +0 -0
  53. package/apps/dashboard/dist/assets/tab-waves-tab-SaJDkb4x.js +1 -0
  54. package/apps/dashboard/dist/assets/tab-waves-tab-SaJDkb4x.js.br +0 -0
  55. package/apps/dashboard/dist/assets/tab-workflows-tab-6QSXLJ0i.js +1 -0
  56. package/apps/dashboard/dist/assets/tab-workflows-tab-6QSXLJ0i.js.br +0 -0
  57. package/apps/dashboard/dist/favicon.png +0 -0
  58. package/apps/dashboard/dist/index.html +6466 -0
  59. package/apps/dashboard/dist/index.html.br +0 -0
  60. package/apps/dashboard/dist/index.html.gz +0 -0
  61. package/apps/dashboard/dist/signup.html +446 -0
  62. package/apps/dashboard/index.html +6442 -0
  63. package/apps/dashboard/package.json +15 -0
  64. package/apps/dashboard/src/app.js +2823 -0
  65. package/apps/dashboard/src/app.js.br +0 -0
  66. package/apps/dashboard/src/app.js.gz +0 -0
  67. package/apps/dashboard/src/chat/chat-actions.js +1847 -0
  68. package/apps/dashboard/src/chat/chat-actions.js.br +0 -0
  69. package/apps/dashboard/src/chat/unified-messages.js +327 -0
  70. package/apps/dashboard/src/chat/unified-messages.js.br +0 -0
  71. package/apps/dashboard/src/cli-process.js +208 -0
  72. package/apps/dashboard/src/cli-process.js.br +0 -0
  73. package/apps/dashboard/src/cli-process.js.gz +0 -0
  74. package/apps/dashboard/src/components/active-tasks-panel.js +175 -0
  75. package/apps/dashboard/src/components/active-tasks-panel.js.br +0 -0
  76. package/apps/dashboard/src/core/api.js +18 -0
  77. package/apps/dashboard/src/core/api.js.br +0 -0
  78. package/apps/dashboard/src/core/dom.js +220 -0
  79. package/apps/dashboard/src/core/dom.js.br +0 -0
  80. package/apps/dashboard/src/core/state.js +91 -0
  81. package/apps/dashboard/src/core/state.js.br +0 -0
  82. package/apps/dashboard/src/core/task-manager.js +134 -0
  83. package/apps/dashboard/src/core/task-manager.js.br +0 -0
  84. package/apps/dashboard/src/orchestration-status.js +127 -0
  85. package/apps/dashboard/src/orchestration-status.js.br +0 -0
  86. package/apps/dashboard/src/setup-wizard.js +555 -0
  87. package/apps/dashboard/src/setup-wizard.js.br +0 -0
  88. package/apps/dashboard/src/styles.css +2085 -0
  89. package/apps/dashboard/src/styles.css.br +0 -0
  90. package/apps/dashboard/src/styles.css.gz +0 -0
  91. package/apps/dashboard/src/tabs/agents-tab.js +2237 -0
  92. package/apps/dashboard/src/tabs/agents-tab.js.br +0 -0
  93. package/apps/dashboard/src/tabs/benchmarks-tab.js +229 -0
  94. package/apps/dashboard/src/tabs/benchmarks-tab.js.br +0 -0
  95. package/apps/dashboard/src/tabs/comms-tab.js +955 -0
  96. package/apps/dashboard/src/tabs/comms-tab.js.br +0 -0
  97. package/apps/dashboard/src/tabs/contacts-tab.js +654 -0
  98. package/apps/dashboard/src/tabs/contacts-tab.js.br +0 -0
  99. package/apps/dashboard/src/tabs/engines-tab.js +175 -0
  100. package/apps/dashboard/src/tabs/engines-tab.js.br +0 -0
  101. package/apps/dashboard/src/tabs/memory-tab.js +182 -0
  102. package/apps/dashboard/src/tabs/memory-tab.js.br +0 -0
  103. package/apps/dashboard/src/tabs/models-tab.js +441 -0
  104. package/apps/dashboard/src/tabs/models-tab.js.br +0 -0
  105. package/apps/dashboard/src/tabs/pm-loop-tab.js +185 -0
  106. package/apps/dashboard/src/tabs/pm-loop-tab.js.br +0 -0
  107. package/apps/dashboard/src/tabs/projects-tab.js +663 -0
  108. package/apps/dashboard/src/tabs/projects-tab.js.br +0 -0
  109. package/apps/dashboard/src/tabs/projects-tab.js.gz +0 -0
  110. package/apps/dashboard/src/tabs/prompts-tab.js +160 -0
  111. package/apps/dashboard/src/tabs/prompts-tab.js.br +0 -0
  112. package/apps/dashboard/src/tabs/services-tab.js +202 -0
  113. package/apps/dashboard/src/tabs/services-tab.js.br +0 -0
  114. package/apps/dashboard/src/tabs/settings-tab.js +803 -0
  115. package/apps/dashboard/src/tabs/settings-tab.js.br +0 -0
  116. package/apps/dashboard/src/tabs/skills-tab.js +284 -0
  117. package/apps/dashboard/src/tabs/skills-tab.js.br +0 -0
  118. package/apps/dashboard/src/tabs/spending-tab.js +173 -0
  119. package/apps/dashboard/src/tabs/spending-tab.js.br +0 -0
  120. package/apps/dashboard/src/tabs/swarm-chat-tab.js +660 -0
  121. package/apps/dashboard/src/tabs/swarm-chat-tab.js.br +0 -0
  122. package/apps/dashboard/src/tabs/swarm-tab.js +538 -0
  123. package/apps/dashboard/src/tabs/swarm-tab.js.br +0 -0
  124. package/apps/dashboard/src/tabs/usage-tab.js +390 -0
  125. package/apps/dashboard/src/tabs/usage-tab.js.br +0 -0
  126. package/apps/dashboard/src/tabs/waves-tab.js +238 -0
  127. package/apps/dashboard/src/tabs/waves-tab.js.br +0 -0
  128. package/apps/dashboard/src/tabs/workflows-tab.js +747 -0
  129. package/apps/dashboard/src/tabs/workflows-tab.js.br +0 -0
  130. package/apps/vibe/.crew/agent-memory/pipeline.json +249 -0
  131. package/apps/vibe/.crew/cost.json +17 -0
  132. package/apps/vibe/.crew/json-parse-metrics.jsonl +22 -0
  133. package/apps/vibe/.crew/pipeline-metrics.jsonl +22 -0
  134. package/apps/vibe/.crew/pipeline-runs/pipeline-0f90c392-2425-4ae5-850c-bd9d17b1d690.jsonl +5 -0
  135. package/apps/vibe/.crew/pipeline-runs/pipeline-1c269dd9-a63f-4fba-af81-5cf08048ef06.jsonl +5 -0
  136. package/apps/vibe/.crew/pipeline-runs/pipeline-288a7765-da24-4a22-89bc-1f3cc9b0562c.jsonl +1 -0
  137. package/apps/vibe/.crew/pipeline-runs/pipeline-2c78fd22-a657-4bd1-bc49-0679fb384409.jsonl +5 -0
  138. package/apps/vibe/.crew/pipeline-runs/pipeline-3e6fe08d-3264-404a-8df3-aab7efef10e7.jsonl +5 -0
  139. package/apps/vibe/.crew/pipeline-runs/pipeline-42eec610-57fe-4e09-9e7e-b315038495c2.jsonl +5 -0
  140. package/apps/vibe/.crew/pipeline-runs/pipeline-4438eb4c-ae13-42b1-90e2-b043d8983be8.jsonl +5 -0
  141. package/apps/vibe/.crew/pipeline-runs/pipeline-4740a9f5-86e7-44b6-a394-de433e291727.jsonl +5 -0
  142. package/apps/vibe/.crew/pipeline-runs/pipeline-49e1da6a-957e-48fd-9220-415019e4f8e2.jsonl +5 -0
  143. package/apps/vibe/.crew/pipeline-runs/pipeline-4c9251db-be68-427b-a3fc-a264f2b5778d.jsonl +5 -0
  144. package/apps/vibe/.crew/pipeline-runs/pipeline-65e29a57-664d-4196-8109-017e364f182e.jsonl +5 -0
  145. package/apps/vibe/.crew/pipeline-runs/pipeline-6aa04bc5-9593-4b1f-b58d-3bf2978cb602.jsonl +5 -0
  146. package/apps/vibe/.crew/pipeline-runs/pipeline-6e1cba53-9b70-457e-99e0-59199149dd21.jsonl +5 -0
  147. package/apps/vibe/.crew/pipeline-runs/pipeline-749f41cc-4dac-4204-be64-873a6080a0d2.jsonl +5 -0
  148. package/apps/vibe/.crew/pipeline-runs/pipeline-74d68121-e181-4864-bd9a-c3211341dfaf.jsonl +5 -0
  149. package/apps/vibe/.crew/pipeline-runs/pipeline-8509bc24-142d-4e07-b44a-a50bf99d1103.jsonl +5 -0
  150. package/apps/vibe/.crew/pipeline-runs/pipeline-960339c6-07ca-43ce-9900-f6e1702b39b9.jsonl +5 -0
  151. package/apps/vibe/.crew/pipeline-runs/pipeline-9c6480a9-7031-4146-b241-825b9a2d1de1.jsonl +5 -0
  152. package/apps/vibe/.crew/pipeline-runs/pipeline-9fd42426-8492-4157-9d5f-e1537c060489.jsonl +2 -0
  153. package/apps/vibe/.crew/pipeline-runs/pipeline-ad6d40a3-2f5e-46a9-a345-47caaccc51aa.jsonl +5 -0
  154. package/apps/vibe/.crew/pipeline-runs/pipeline-bc606133-8d5b-4535-8d85-f1a29cdaa981.jsonl +5 -0
  155. package/apps/vibe/.crew/pipeline-runs/pipeline-c1a13ccd-634a-4d01-a4a7-1177b8a752ff.jsonl +5 -0
  156. package/apps/vibe/.crew/pipeline-runs/pipeline-c7d27b42-249e-4bd4-8f26-6aa998110b8a.jsonl +5 -0
  157. package/apps/vibe/.crew/pipeline-runs/pipeline-cca2e9b9-4a34-4d25-a311-5c793fa7e91e.jsonl +5 -0
  158. package/apps/vibe/.crew/sandbox.json +7 -0
  159. package/apps/vibe/.crew/session.json +285 -0
  160. package/apps/vibe/.crew/training-data.jsonl +0 -0
  161. package/apps/vibe/.github/workflows/studio-quality.yml +37 -0
  162. package/apps/vibe/.studio-data/project-messages/chuck-norris.jsonl +12 -0
  163. package/apps/vibe/.studio-data/project-messages/general.jsonl +54 -0
  164. package/apps/vibe/.studio-data/project-messages/studio-local.jsonl +10 -0
  165. package/apps/vibe/ARCHITECTURE.md +3393 -0
  166. package/apps/vibe/QUICK-REFERENCE.md +211 -0
  167. package/apps/vibe/README.md +76 -0
  168. package/apps/vibe/ROADMAP.md +41 -0
  169. package/apps/vibe/STUDIO-SETUP-COMPLETE.md +35 -0
  170. package/apps/vibe/VISUAL-GUIDE.md +378 -0
  171. package/apps/vibe/capture-demo.mjs +160 -0
  172. package/apps/vibe/capture-vibe-assets.mjs +71 -0
  173. package/apps/vibe/capture-vibe-video.mjs +260 -0
  174. package/apps/vibe/check-buttons.js +41 -0
  175. package/apps/vibe/diagnose.html +106 -0
  176. package/apps/vibe/fix-buttons.js +103 -0
  177. package/apps/vibe/index.html +3401 -0
  178. package/apps/vibe/package-lock.json +920 -0
  179. package/apps/vibe/package.json +31 -0
  180. package/apps/vibe/public/favicon.png +0 -0
  181. package/apps/vibe/scripts/studio-pty-host.py +117 -0
  182. package/apps/vibe/server.mjs +1835 -0
  183. package/apps/vibe/src/main.js +2846 -0
  184. package/apps/vibe/src/register-all-languages.js +98 -0
  185. package/apps/vibe/start-studio.sh +11 -0
  186. package/apps/vibe/test/accessibility-tests.js +77 -0
  187. package/apps/vibe/test/browser-performance-audit.mjs +205 -0
  188. package/apps/vibe/test/performance-tests.js +120 -0
  189. package/apps/vibe/test/security-tests.js +213 -0
  190. package/apps/vibe/tests/e2e.local.mjs +54 -0
  191. package/apps/vibe/tests/server.smoke.mjs +106 -0
  192. package/apps/vibe/update_website.mjs +74 -0
  193. package/apps/vibe/vite.config.js +19 -0
  194. package/apps/vibe/watch-server.mjs +108 -0
  195. package/contrib/openclaw-plugin/README.md +199 -0
  196. package/contrib/openclaw-plugin/index.ts +306 -0
  197. package/contrib/openclaw-plugin/openclaw.plugin.json +41 -0
  198. package/contrib/openclaw-plugin/package.json +27 -0
  199. package/contrib/openclaw-plugin/skills/crewswarm/SKILL.md +88 -0
  200. package/crew-lead.mjs +649 -0
  201. package/engines/claude-code.json +36 -0
  202. package/engines/codex.json +37 -0
  203. package/engines/crew-cli.json +42 -0
  204. package/engines/cursor.json +40 -0
  205. package/engines/docker-sandbox.json +38 -0
  206. package/engines/gemini-cli.json +75 -0
  207. package/engines/opencode.json +31 -0
  208. package/gateway-bridge.mjs +1575 -0
  209. package/install.sh +738 -0
  210. package/lib/agent-registry.mjs +232 -0
  211. package/lib/agents/daemon.mjs +121 -0
  212. package/lib/agents/dispatch.mjs +225 -0
  213. package/lib/agents/permissions.mjs +90 -0
  214. package/lib/agents/platform-formatting.mjs +102 -0
  215. package/lib/agents/registry.mjs +81 -0
  216. package/lib/agents/tool-instructions.mjs +257 -0
  217. package/lib/agents/validation.mjs +75 -0
  218. package/lib/approval/policy-manager.mjs +221 -0
  219. package/lib/autoharness/index.mjs +391 -0
  220. package/lib/bridges/cli-executor.mjs +332 -0
  221. package/lib/bridges/gateway-ws.mjs +345 -0
  222. package/lib/bridges/integration.mjs +229 -0
  223. package/lib/bridges/rag-helper.mjs +90 -0
  224. package/lib/browser/opencode-passthrough-filter.js +44 -0
  225. package/lib/browser/passthrough-stderr.js +109 -0
  226. package/lib/chat/autonomous-mentions.mjs +373 -0
  227. package/lib/chat/history.mjs +82 -0
  228. package/lib/chat/mention-routing-intent.mjs +136 -0
  229. package/lib/chat/participants.mjs +95 -0
  230. package/lib/chat/project-messages-rag.mjs +265 -0
  231. package/lib/chat/project-messages.mjs +479 -0
  232. package/lib/chat/shared-chat-prompt-overlay.mjs +52 -0
  233. package/lib/chat/thread-binding.mjs +34 -0
  234. package/lib/chat/unified-history.mjs +223 -0
  235. package/lib/chat/unified-wrapper.mjs +41 -0
  236. package/lib/cli-process-tracker.mjs +228 -0
  237. package/lib/collections/index.mjs +433 -0
  238. package/lib/contacts/identity-linker.mjs +248 -0
  239. package/lib/contacts/index.mjs +341 -0
  240. package/lib/crew-judge/PROMPT.md +93 -0
  241. package/lib/crew-judge/judge.mjs +260 -0
  242. package/lib/crew-lead/agent-manager.mjs +125 -0
  243. package/lib/crew-lead/background.mjs +270 -0
  244. package/lib/crew-lead/brain.mjs +110 -0
  245. package/lib/crew-lead/chat-handler.mjs +2603 -0
  246. package/lib/crew-lead/chat-handler.mjs.bak +1274 -0
  247. package/lib/crew-lead/classifier.mjs +83 -0
  248. package/lib/crew-lead/http-server.mjs +4824 -0
  249. package/lib/crew-lead/intent.mjs +102 -0
  250. package/lib/crew-lead/interval-manager.mjs +41 -0
  251. package/lib/crew-lead/llm-caller.mjs +544 -0
  252. package/lib/crew-lead/prompts.mjs +392 -0
  253. package/lib/crew-lead/retry-manager.mjs +118 -0
  254. package/lib/crew-lead/tools.mjs +318 -0
  255. package/lib/crew-lead/wave-dispatcher.mjs +798 -0
  256. package/lib/crew-lead/waves-config.json +73 -0
  257. package/lib/crew-lead/waves-loader.mjs +110 -0
  258. package/lib/crew-lead/ws-router.mjs +428 -0
  259. package/lib/dispatch/parsers.mjs +299 -0
  260. package/lib/domain-planning/detector.mjs +196 -0
  261. package/lib/domain-planning/prompts/crew-pm-cli.md +96 -0
  262. package/lib/domain-planning/prompts/crew-pm-core.md +122 -0
  263. package/lib/domain-planning/prompts/crew-pm-frontend.md +111 -0
  264. package/lib/engines/crew-cli-sandbox.mjs +422 -0
  265. package/lib/engines/crew-cli.mjs +155 -0
  266. package/lib/engines/cursor-launcher.mjs +110 -0
  267. package/lib/engines/engine-registry.mjs +253 -0
  268. package/lib/engines/llm-direct.mjs +184 -0
  269. package/lib/engines/opencode.mjs +256 -0
  270. package/lib/engines/ouroboros.mjs +114 -0
  271. package/lib/engines/rt-envelope.mjs +1643 -0
  272. package/lib/engines/rt-envelope.mjs.backup-current +870 -0
  273. package/lib/engines/runners.mjs +1367 -0
  274. package/lib/gemini-cli-passthrough-noise.mjs +37 -0
  275. package/lib/integrations/code-search.mjs +259 -0
  276. package/lib/integrations/greptile.mjs +148 -0
  277. package/lib/integrations/multimodal.mjs +313 -0
  278. package/lib/integrations/telegram-streaming.mjs +153 -0
  279. package/lib/integrations/tts.mjs +312 -0
  280. package/lib/integrations/twitter-links.mjs +294 -0
  281. package/lib/memory/shared-adapter.mjs +296 -0
  282. package/lib/pipeline/manager.mjs +539 -0
  283. package/lib/preferences/extractor.mjs +347 -0
  284. package/lib/project-dir.mjs +20 -0
  285. package/lib/runtime/config.mjs +388 -0
  286. package/lib/runtime/dlq.mjs +170 -0
  287. package/lib/runtime/log-rotation.mjs +82 -0
  288. package/lib/runtime/logger.mjs +58 -0
  289. package/lib/runtime/memory.mjs +421 -0
  290. package/lib/runtime/paths.mjs +76 -0
  291. package/lib/runtime/project-dir.mjs +127 -0
  292. package/lib/runtime/spending.mjs +204 -0
  293. package/lib/runtime/startup-guard.mjs +291 -0
  294. package/lib/runtime/task-lease.mjs +234 -0
  295. package/lib/runtime/telemetry-schema.mjs +208 -0
  296. package/lib/runtime/telemetry.mjs +101 -0
  297. package/lib/runtime/utils.mjs +64 -0
  298. package/lib/skills/index.mjs +265 -0
  299. package/lib/tools/browser.mjs +135 -0
  300. package/lib/tools/executor.mjs +913 -0
  301. package/lib/types.d.ts +57 -0
  302. package/package.json +106 -0
  303. package/pm-loop.mjs +1626 -0
  304. package/prompts/coder-back.md +27 -0
  305. package/prompts/coder-front.md +27 -0
  306. package/prompts/coder.md +28 -0
  307. package/prompts/copywriter.md +17 -0
  308. package/prompts/fixer.md +39 -0
  309. package/prompts/frontend.md +23 -0
  310. package/prompts/github.md +24 -0
  311. package/prompts/main.md +39 -0
  312. package/prompts/pm-cli.md +95 -0
  313. package/prompts/pm-core.md +121 -0
  314. package/prompts/pm-frontend.md +110 -0
  315. package/prompts/pm.md +234 -0
  316. package/prompts/qa.md +44 -0
  317. package/prompts/security.md +19 -0
  318. package/scripts/build-crew-chat.sh +28 -0
  319. package/scripts/build-llms-full.mjs +52 -0
  320. package/scripts/chatmock-login.sh +16 -0
  321. package/scripts/chatmock-serve.sh +16 -0
  322. package/scripts/check-dashboard.mjs +88 -0
  323. package/scripts/crew-scribe.mjs +326 -0
  324. package/scripts/dashboard-helpers.mjs +391 -0
  325. package/scripts/dashboard-validation.mjs +198 -0
  326. package/scripts/dashboard.mjs +9717 -0
  327. package/scripts/dlq-replay.mjs +61 -0
  328. package/scripts/doctor.mjs +196 -0
  329. package/scripts/file-lock.mjs +186 -0
  330. package/scripts/fresh-machine-smoke.sh +323 -0
  331. package/scripts/generate-changelog.mjs +227 -0
  332. package/scripts/generate-openapi.mjs +334 -0
  333. package/scripts/health-check.mjs +229 -0
  334. package/scripts/install-docker.sh +213 -0
  335. package/scripts/mcp-server.mjs +1625 -0
  336. package/scripts/opencrew-rt-daemon.mjs +568 -0
  337. package/scripts/openswitchctl +646 -0
  338. package/scripts/refactor-configs.mjs +39 -0
  339. package/scripts/release-check.sh +46 -0
  340. package/scripts/resolve-node-bin.sh +25 -0
  341. package/scripts/restart-all-from-repo.sh +329 -0
  342. package/scripts/restart-crew-lead.sh +98 -0
  343. package/scripts/restart-dashboard.sh +104 -0
  344. package/scripts/restart-service.sh +274 -0
  345. package/scripts/run-accessibility-audit.mjs +356 -0
  346. package/scripts/run-integration-bounded.mjs +188 -0
  347. package/scripts/run-scheduled-pipeline.mjs +230 -0
  348. package/scripts/run.mjs +41 -0
  349. package/scripts/scan-skills.mjs +79 -0
  350. package/scripts/setup-firewall.sh +128 -0
  351. package/scripts/smoke-dispatch.mjs +149 -0
  352. package/scripts/smoke.sh +163 -0
  353. package/scripts/start-crew.mjs +328 -0
  354. package/scripts/start.mjs +146 -0
  355. package/scripts/swiftbar-restart-service.sh +19 -0
  356. package/scripts/sync-agents.mjs +152 -0
  357. package/scripts/sync-prompts.mjs +79 -0
  358. package/scripts/validate-config.mjs +337 -0
  359. package/scripts/wow.mjs +89 -0
  360. package/telegram-bridge.mjs +2421 -0
  361. package/unified-orchestrator.mjs +519 -0
  362. package/whatsapp-bridge.mjs +1481 -0
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Active Tasks Panel - Shows running tasks with individual controls
3
+ */
4
+
5
+ import { taskManager } from '../core/task-manager.js';
6
+
7
+ let _container = null;
8
+ let _completedTasks = []; // Track recently completed tasks
9
+ const COMPLETED_TASK_RETENTION_MS = 5 * 60 * 1000; // Keep for 5 minutes
10
+
11
+ function getRecentCompletedTasks() {
12
+ const now = Date.now();
13
+ // Filter out tasks older than 5 minutes
14
+ _completedTasks = _completedTasks.filter(t => now - t.completedAt < COMPLETED_TASK_RETENTION_MS);
15
+ return _completedTasks;
16
+ }
17
+
18
+ export function initActiveTasksPanel(containerId = 'activeTasksPanel') {
19
+ _container = document.getElementById(containerId);
20
+ if (!_container) {
21
+ console.warn('Active tasks panel container not found:', containerId);
22
+ return;
23
+ }
24
+
25
+ // Subscribe to task changes
26
+ taskManager.subscribe((tasks) => {
27
+ // Track completed tasks before they're removed
28
+ const activeTasks = taskManager.getActiveTasks();
29
+ const taskIds = new Set(activeTasks.map(t => t.id));
30
+
31
+ // Find tasks that just completed (were in list before, not anymore)
32
+ if (_container._lastTaskIds) {
33
+ _container._lastTaskIds.forEach(oldId => {
34
+ if (!taskIds.has(oldId)) {
35
+ // Task completed or failed - add to completed list
36
+ const existingCompleted = _completedTasks.find(t => t.id === oldId);
37
+ if (!existingCompleted) {
38
+ _completedTasks.push({
39
+ id: oldId,
40
+ agent: 'Task',
41
+ type: 'completed',
42
+ status: 'completed',
43
+ completedAt: Date.now(),
44
+ startTime: Date.now() - 30000, // Estimate it took 30s
45
+ duration: '30s'
46
+ });
47
+ }
48
+ }
49
+ });
50
+ }
51
+
52
+ _container._lastTaskIds = taskIds;
53
+ renderTasksPanel(tasks);
54
+ });
55
+
56
+ // Initial render
57
+ renderTasksPanel(taskManager.getActiveTasks());
58
+ }
59
+
60
+ function renderTasksPanel(tasks) {
61
+ if (!_container) return;
62
+
63
+ // Get recent completed tasks
64
+ const recentCompletions = getRecentCompletedTasks();
65
+ const allTasks = [...tasks, ...recentCompletions];
66
+
67
+ if (allTasks.length === 0) {
68
+ _container.style.display = 'none';
69
+ return;
70
+ }
71
+
72
+ _container.style.display = 'block';
73
+
74
+ const header = document.createElement('div');
75
+ header.style.cssText = 'display:flex;align-items:center;justify-content:space-between;padding:8px 12px;border-bottom:1px solid var(--border);background:var(--surface-2);';
76
+
77
+ const title = document.createElement('div');
78
+ title.style.cssText = 'font-size:12px;font-weight:600;color:var(--text-1);';
79
+ const activeCount = tasks.length;
80
+ const completedCount = recentCompletions.length;
81
+ title.textContent = `⚡ Tasks: ${activeCount} active${completedCount > 0 ? `, ${completedCount} completed` : ''}`;
82
+
83
+ const stopAllBtn = document.createElement('button');
84
+ stopAllBtn.textContent = '⏹ Stop All';
85
+ stopAllBtn.style.cssText = 'font-size:11px;padding:3px 8px;border-radius:4px;border:1px solid var(--red-hi);background:transparent;color:var(--red-hi);cursor:pointer;';
86
+ stopAllBtn.onclick = () => {
87
+ if (confirm('Stop all active tasks?')) {
88
+ taskManager.stopAll();
89
+ }
90
+ };
91
+
92
+ header.appendChild(title);
93
+ if (activeCount > 0) header.appendChild(stopAllBtn);
94
+
95
+ const tasksList = document.createElement('div');
96
+ tasksList.style.cssText = 'max-height:200px;overflow-y:auto;';
97
+
98
+ allTasks.forEach((task) => {
99
+ const isCompleted = task.status === 'completed' || task.status === 'failed';
100
+ const taskRow = document.createElement('div');
101
+ taskRow.style.cssText = `display:flex;align-items:center;gap:8px;padding:8px 12px;border-bottom:1px solid var(--border);background:var(--bg-card);${isCompleted ? 'opacity:0.6;' : ''}`;
102
+
103
+ // Status icon
104
+ const statusIcon = document.createElement('span');
105
+ statusIcon.style.cssText = 'font-size:14px;flex-shrink:0;';
106
+ if (task.status === 'completed') {
107
+ statusIcon.textContent = '✅';
108
+ } else if (task.status === 'failed') {
109
+ statusIcon.textContent = '❌';
110
+ } else {
111
+ statusIcon.textContent = '⚡';
112
+ }
113
+
114
+ // Agent badge
115
+ const agentBadge = document.createElement('span');
116
+ agentBadge.style.cssText = 'font-size:10px;font-weight:600;padding:2px 6px;border-radius:12px;background:var(--purple);color:#fff;white-space:nowrap;';
117
+ agentBadge.textContent = task.agent || task.type || 'task';
118
+
119
+ // Task description
120
+ const desc = document.createElement('div');
121
+ desc.style.cssText = 'flex:1;font-size:12px;color:var(--text-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;';
122
+ desc.textContent = task.description || (isCompleted ? 'Completed' : 'Working...');
123
+ desc.title = task.description || '';
124
+
125
+ // Duration
126
+ const duration = document.createElement('span');
127
+ duration.style.cssText = 'font-size:10px;color:var(--text-3);white-space:nowrap;';
128
+ const elapsed = task.duration || (Math.floor((Date.now() - task.startTime) / 1000) + 's');
129
+ duration.textContent = elapsed;
130
+
131
+ taskRow.appendChild(statusIcon);
132
+ taskRow.appendChild(agentBadge);
133
+ taskRow.appendChild(desc);
134
+ taskRow.appendChild(duration);
135
+
136
+ // Stop button only for active tasks
137
+ if (!isCompleted) {
138
+ const stopBtn = document.createElement('button');
139
+ stopBtn.textContent = '⏹';
140
+ stopBtn.title = 'Stop this task';
141
+ stopBtn.style.cssText = 'font-size:14px;padding:2px 6px;border-radius:4px;border:1px solid var(--border);background:var(--surface-2);color:var(--red-hi);cursor:pointer;';
142
+ stopBtn.onclick = () => {
143
+ taskManager.stopTask(task.id);
144
+ };
145
+ taskRow.appendChild(stopBtn);
146
+ }
147
+
148
+ tasksList.appendChild(taskRow);
149
+ });
150
+
151
+ _container.replaceChildren(header, tasksList);
152
+
153
+ // Update durations every second
154
+ if (!_container._intervalSet) {
155
+ _container._intervalSet = true;
156
+ setInterval(() => {
157
+ const activeTasks = taskManager.getActiveTasks();
158
+ if (activeTasks.length > 0 || getRecentCompletedTasks().length > 0) {
159
+ renderTasksPanel(activeTasks);
160
+ }
161
+ }, 1000);
162
+ }
163
+ }
164
+
165
+ export function showActiveTasksPanel() {
166
+ if (_container) {
167
+ _container.style.display = 'block';
168
+ }
169
+ }
170
+
171
+ export function hideActiveTasksPanel() {
172
+ if (_container) {
173
+ _container.style.display = 'none';
174
+ }
175
+ }
@@ -0,0 +1,18 @@
1
+ // Simple fetch wrapper - no cache for dev tools
2
+ export async function getJSON(p, { ttl = 0, bust = false } = {}) {
3
+ const r = await fetch(p);
4
+ if (!r.ok) throw new Error(await r.text());
5
+ return await r.json();
6
+ }
7
+
8
+ /** No-op - cache removed for dev tool responsiveness */
9
+ export function bustCache(p) {
10
+ // No cache to bust
11
+ }
12
+
13
+ export async function postJSON(p, body, signal) {
14
+ const r = await fetch(p, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(body), signal });
15
+ const txt = await r.text();
16
+ if (!r.ok) throw new Error(txt.slice(0, 120));
17
+ try { return JSON.parse(txt); } catch { throw new Error('Bad response: ' + txt.slice(0, 80)); }
18
+ }
@@ -0,0 +1,220 @@
1
+ export function renderStatusBadge(liveness, ageSec) {
2
+ if (liveness === "online")
3
+ return '<span title="● online — heartbeat <90s" style="display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--green);box-shadow:0 0 5px var(--green);margin-right:4px;flex-shrink:0;"></span>';
4
+ if (liveness === "stale")
5
+ return (
6
+ '<span title="● stale — last seen >' +
7
+ (ageSec || "?") +
8
+ 's ago" style="display:inline-block;width:7px;height:7px;border-radius:50%;background:#f59e0b;margin-right:4px;flex-shrink:0;"></span>'
9
+ );
10
+ if (liveness === "offline")
11
+ return '<span title="● offline — no heartbeat in 5min" style="display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--red-hi);margin-right:4px;flex-shrink:0;"></span>';
12
+ return '<span title="● unknown — never seen" style="display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--text-3);margin-right:4px;flex-shrink:0;"></span>';
13
+ }
14
+
15
+ export function showLoading(el, msg) {
16
+ if (el)
17
+ el.innerHTML =
18
+ '<div class="meta" style="padding:20px;">' +
19
+ (msg || "Loading\u2026") +
20
+ "</div>";
21
+ }
22
+
23
+ export function showEmpty(el, msg) {
24
+ if (el)
25
+ el.innerHTML =
26
+ '<div class="meta" style="padding:20px;">' +
27
+ (msg || "No items found.") +
28
+ "</div>";
29
+ }
30
+
31
+ export function showError(el, msg) {
32
+ if (el)
33
+ el.innerHTML =
34
+ '<div class="meta" style="padding:20px;color:var(--red-hi);">' +
35
+ (msg || "An error occurred.") +
36
+ "</div>";
37
+ }
38
+
39
+ export function escHtml(s) {
40
+ return String(s ?? "")
41
+ .replace(/&/g, "&amp;")
42
+ .replace(/</g, "&lt;")
43
+ .replace(/>/g, "&gt;")
44
+ .replace(/"/g, "&quot;")
45
+ .replace(/'/g, "&#39;");
46
+ }
47
+
48
+ export function showNotification(msg, type) {
49
+ const d = document.createElement("div");
50
+ d.className =
51
+ "notification" +
52
+ (type === "error" || type === true
53
+ ? " error"
54
+ : type === "warning"
55
+ ? " warning"
56
+ : "");
57
+ d.setAttribute("role", "alert");
58
+ d.setAttribute("aria-live", "polite");
59
+ d.textContent = msg;
60
+ document.body.appendChild(d);
61
+ setTimeout(() => d.remove(), 4500);
62
+ }
63
+
64
+ export function fmt(ts) {
65
+ try {
66
+ return new Date(ts).toLocaleTimeString();
67
+ } catch {
68
+ return String(ts);
69
+ }
70
+ }
71
+
72
+ export function createdAt(info) {
73
+ return (info && info.time && info.time.created) || "";
74
+ }
75
+
76
+ export function appendChatBubble(
77
+ role,
78
+ text,
79
+ fallbackModel,
80
+ fallbackReason,
81
+ primaryModel,
82
+ engineUsed,
83
+ sourceInfo,
84
+ bubbleOptions,
85
+ ) {
86
+ const box = document.getElementById("chatMessages");
87
+ if (!box) return;
88
+ const isUser = role === "user";
89
+ const isHistoryRender = Boolean(sourceInfo);
90
+ const forceAppend =
91
+ bubbleOptions &&
92
+ typeof bubbleOptions === "object" &&
93
+ bubbleOptions.force === true;
94
+ if (!isUser && !forceAppend) {
95
+ const last = box.lastElementChild;
96
+ if (last && last.children.length >= 2) {
97
+ const lastBubbleText = last.children[1].textContent;
98
+ if (lastBubbleText.trim() === String(text).trim()) return;
99
+ }
100
+ }
101
+ const div = document.createElement("div");
102
+ div.style.cssText =
103
+ "display:flex;flex-direction:column;align-items:" +
104
+ (isUser ? "flex-end" : "flex-start") +
105
+ ";gap:4px;";
106
+ const labelEl = document.createElement("div");
107
+ labelEl.style.cssText =
108
+ "font-size:11px;color:var(--text-3);padding:0 6px;display:flex;align-items:center;gap:6px;";
109
+ const cl = window._crewLeadInfo || { emoji: "🧠", name: "crew-lead" };
110
+
111
+ // If sourceInfo provided (from history), show source indicator instead of default
112
+ if (sourceInfo) {
113
+ let agentName = "crew-lead";
114
+ if (isUser) {
115
+ agentName = "You";
116
+ } else if (sourceInfo.agentName) {
117
+ agentName = sourceInfo.agentName;
118
+ } else if (sourceInfo.agent) {
119
+ agentName = sourceInfo.agent;
120
+ } else if (sourceInfo.source === "cli") {
121
+ agentName = sourceInfo.engine || "cli";
122
+ } else if (sourceInfo.source === "sub-agent") {
123
+ agentName = "sub-agent";
124
+ } else if (sourceInfo.source === "agent") {
125
+ agentName = sourceInfo.targetAgent || "agent";
126
+ } else if (sourceInfo.source === "dashboard") {
127
+ agentName = "crew-lead";
128
+ }
129
+ const engineLabel =
130
+ !isUser && sourceInfo.engine && sourceInfo.engine !== agentName
131
+ ? ` · ${sourceInfo.engine}`
132
+ : "";
133
+ labelEl.textContent = `${sourceInfo.emoji || "🤖"} ${agentName}${engineLabel}`;
134
+
135
+ // Add timestamp as a separate subdued span
136
+ const ts = document.createElement("span");
137
+ ts.style.cssText = "opacity:0.6;";
138
+ ts.textContent = sourceInfo.timestamp ? " · " + sourceInfo.timestamp : "";
139
+ labelEl.appendChild(ts);
140
+ } else {
141
+ const displayName = isUser
142
+ ? "You"
143
+ : role === "assistant"
144
+ ? cl.emoji + " " + cl.name
145
+ : role;
146
+ labelEl.textContent = displayName;
147
+ }
148
+
149
+ // Show model badge - always for non-user messages
150
+ if (!isUser) {
151
+ const modelToShow = fallbackModel || primaryModel;
152
+ if (modelToShow) {
153
+ const badge = document.createElement("span");
154
+ if (fallbackModel) {
155
+ badge.title =
156
+ "Primary failed (" +
157
+ (fallbackReason || "error") +
158
+ ") — running on fallback";
159
+ badge.style.cssText =
160
+ "font-size:10px;padding:1px 6px;border-radius:999px;background:rgba(245,158,11,0.15);color:#f59e0b;border:1px solid rgba(245,158,11,0.3);cursor:default;";
161
+ badge.textContent = "⚡ fallback: " + fallbackModel;
162
+ } else {
163
+ badge.title = "Primary model";
164
+ badge.style.cssText =
165
+ "font-size:10px;padding:1px 6px;border-radius:999px;background:rgba(52,211,153,0.1);color:#34d399;border:1px solid rgba(52,211,153,0.2);cursor:default;";
166
+ badge.textContent = modelToShow;
167
+ }
168
+ labelEl.appendChild(badge);
169
+ }
170
+
171
+ // Show engine badge if available (for coding agents using CLIs)
172
+ if (engineUsed) {
173
+ const engineColors = {
174
+ claude: "#e07a5f",
175
+ codex: "#8338ec",
176
+ cursor: "#3d405b",
177
+ opencode: "#06d6a0",
178
+ gemini: "#4285f4",
179
+ "docker-sandbox": "#0db7ed",
180
+ };
181
+ const engineLabels = {
182
+ claude: "🤖 Claude Code",
183
+ codex: "🟣 Codex",
184
+ cursor: "🖱 Cursor",
185
+ opencode: "⚡ OpenCode",
186
+ gemini: "✨ Gemini",
187
+ "docker-sandbox": "🐳 Docker",
188
+ };
189
+ const engineBadge = document.createElement("span");
190
+ engineBadge.title =
191
+ "Executed by " + (engineLabels[engineUsed] || engineUsed);
192
+ engineBadge.style.cssText =
193
+ "font-size:10px;padding:1px 6px;border-radius:999px;color:#fff;background:" +
194
+ (engineColors[engineUsed] || "var(--text-3)") +
195
+ ";cursor:default;";
196
+ engineBadge.textContent = engineLabels[engineUsed] || engineUsed;
197
+ labelEl.appendChild(engineBadge);
198
+ }
199
+ }
200
+
201
+ const bubble = document.createElement("div");
202
+ const assistantBg = "var(--surface-2)";
203
+ const assistantText = "var(--text-2)";
204
+ const assistantBorder = "var(--border)";
205
+ bubble.style.cssText =
206
+ "max-width:80%;padding:10px 14px;border-radius:" +
207
+ (isUser ? "14px 14px 4px 14px" : "14px 14px 14px 4px") +
208
+ ";background:" +
209
+ (isUser ? "var(--purple)" : assistantBg) +
210
+ ";color:" +
211
+ (isUser ? "#fff" : assistantText) +
212
+ ";font-size:14px;line-height:1.5;white-space:pre-wrap;word-break:break-word;border:1px solid " +
213
+ (isUser ? "var(--border)" : assistantBorder) +
214
+ ";";
215
+ bubble.textContent = text;
216
+ div.appendChild(labelEl);
217
+ div.appendChild(bubble);
218
+ box.appendChild(div);
219
+ box.scrollTop = box.scrollHeight;
220
+ }
@@ -0,0 +1,91 @@
1
+ // Shared in-memory state — mutate via the exported object properties
2
+ // Restored from sessionStorage on page load to survive refresh
3
+
4
+ const STORAGE_KEY = 'crewswarm_ui_state';
5
+
6
+ function loadSaved() {
7
+ try {
8
+ const raw = sessionStorage.getItem(STORAGE_KEY);
9
+ return raw ? JSON.parse(raw) : {};
10
+ } catch { return {}; }
11
+ }
12
+
13
+ const saved = loadSaved();
14
+
15
+ export const state = {
16
+ // OpenCode session selection (Sessions tab)
17
+ selected: saved.selected || null,
18
+
19
+ // Selected CLI engine for Sessions tab (opencode, claude, codex, gemini, crew-cli)
20
+ selectedEngine: saved.selectedEngine || 'opencode',
21
+
22
+ // Agent list (loaded from /api/agents)
23
+ agents: saved.agents || [],
24
+
25
+ // Active chat project
26
+ chatActiveProjectId: saved.chatActiveProjectId || '',
27
+
28
+ // Active shared channel/project for the Swarm tab
29
+ swarmChatProjectId: saved.swarmChatProjectId || '',
30
+
31
+ // Project registry cache (populated by loadProjects)
32
+ projectsData: saved.projectsData || {},
33
+
34
+ // Active tab (for scroll restoration)
35
+ activeTab: saved.activeTab || 'chat',
36
+
37
+ // Per-tab scroll positions { tabName: scrollTop }
38
+ scrollPositions: saved.scrollPositions || {},
39
+ };
40
+
41
+ /** Persist current state to sessionStorage (call after meaningful state changes). */
42
+ export function persistState() {
43
+ try {
44
+ sessionStorage.setItem(STORAGE_KEY, JSON.stringify({
45
+ selected: state.selected,
46
+ selectedEngine: state.selectedEngine,
47
+ chatActiveProjectId: state.chatActiveProjectId,
48
+ swarmChatProjectId: state.swarmChatProjectId,
49
+ projectsData: state.projectsData,
50
+ activeTab: state.activeTab,
51
+ scrollPositions: state.scrollPositions,
52
+ // Don't persist agents list — it's large and gets stale
53
+ }));
54
+ } catch { /* quota exceeded or private mode — ignore */ }
55
+ }
56
+
57
+ /** Save scroll position for the current active tab. */
58
+ export function saveScrollPosition(tabName) {
59
+ const main = document.querySelector('.view.active');
60
+ if (main) {
61
+ state.scrollPositions[tabName || state.activeTab] = main.scrollTop;
62
+ persistState();
63
+ }
64
+ }
65
+
66
+ /** Restore scroll position for a tab after re-render. */
67
+ export function restoreScrollPosition(tabName) {
68
+ const pos = state.scrollPositions[tabName];
69
+ if (pos != null) {
70
+ requestAnimationFrame(() => {
71
+ const main = document.querySelector('.view.active');
72
+ if (main) main.scrollTop = pos;
73
+ });
74
+ }
75
+ }
76
+
77
+ export const AGENT_RANK = {
78
+ 'crew-lead': 0,
79
+ 'crew-orchestrator': 1, 'orchestrator': 1, 'crew-main': 2,
80
+ 'crew-pm': 3, 'crew-architect': 4,
81
+ 'crew-coder': 5, 'crew-coder-back': 6, 'crew-coder-front': 7, 'crew-frontend': 8,
82
+ 'crew-ml': 9, 'crew-fixer': 10,
83
+ 'crew-qa': 11, 'crew-security': 12,
84
+ 'crew-researcher': 13, 'crew-copywriter': 14, 'crew-seo': 15,
85
+ 'crew-github': 16, 'crew-db-migrator': 17,
86
+ 'crew-telegram': 18, 'crew-mega': 19,
87
+ };
88
+
89
+ export function sortAgents(arr) {
90
+ return (arr || []).sort((a, b) => (AGENT_RANK[a.id] ?? 50) - (AGENT_RANK[b.id] ?? 50));
91
+ }
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Task Manager - Tracks and controls active tasks/agents
3
+ * Allows individual stop controls and concurrent operations
4
+ */
5
+
6
+ export class TaskManager {
7
+ constructor() {
8
+ this.activeTasks = new Map(); // taskId -> { agent, controller, startTime, status, type }
9
+ this.listeners = new Set();
10
+ }
11
+
12
+ /**
13
+ * Register a new task with abort controller
14
+ * @param {string} taskId - Unique task identifier
15
+ * @param {object} details - { agent, type, description, controller }
16
+ */
17
+ registerTask(taskId, details) {
18
+ this.activeTasks.set(taskId, {
19
+ ...details,
20
+ startTime: Date.now(),
21
+ status: 'running',
22
+ });
23
+ this.notifyListeners();
24
+ }
25
+
26
+ /**
27
+ * Stop a specific task by ID
28
+ * @param {string} taskId
29
+ */
30
+ stopTask(taskId) {
31
+ const task = this.activeTasks.get(taskId);
32
+ if (!task) return false;
33
+
34
+ if (task.controller) {
35
+ task.controller.abort();
36
+ }
37
+
38
+ task.status = 'stopped';
39
+ this.activeTasks.delete(taskId);
40
+ this.notifyListeners();
41
+ return true;
42
+ }
43
+
44
+ /**
45
+ * Mark task as completed
46
+ * @param {string} taskId
47
+ */
48
+ completeTask(taskId) {
49
+ const task = this.activeTasks.get(taskId);
50
+ if (!task) return;
51
+
52
+ task.status = 'completed';
53
+ this.activeTasks.delete(taskId);
54
+ this.notifyListeners();
55
+ }
56
+
57
+ /**
58
+ * Mark task as failed
59
+ * @param {string} taskId
60
+ * @param {string} error
61
+ */
62
+ failTask(taskId, error) {
63
+ const task = this.activeTasks.get(taskId);
64
+ if (!task) return;
65
+
66
+ task.status = 'failed';
67
+ task.error = error;
68
+ this.activeTasks.delete(taskId);
69
+ this.notifyListeners();
70
+ }
71
+
72
+ /**
73
+ * Get all active tasks
74
+ */
75
+ getActiveTasks() {
76
+ return Array.from(this.activeTasks.entries()).map(([id, task]) => ({
77
+ id,
78
+ ...task,
79
+ }));
80
+ }
81
+
82
+ /**
83
+ * Check if a specific agent is currently busy
84
+ * @param {string} agent
85
+ */
86
+ isAgentBusy(agent) {
87
+ return Array.from(this.activeTasks.values()).some(
88
+ (task) => task.agent === agent && task.status === 'running'
89
+ );
90
+ }
91
+
92
+ /**
93
+ * Stop all tasks
94
+ */
95
+ stopAll() {
96
+ for (const [taskId] of this.activeTasks) {
97
+ this.stopTask(taskId);
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Stop all tasks for a specific agent
103
+ * @param {string} agent
104
+ */
105
+ stopAgent(agent) {
106
+ for (const [taskId, task] of this.activeTasks) {
107
+ if (task.agent === agent) {
108
+ this.stopTask(taskId);
109
+ }
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Subscribe to task changes
115
+ * @param {function} callback
116
+ */
117
+ subscribe(callback) {
118
+ this.listeners.add(callback);
119
+ return () => this.listeners.delete(callback);
120
+ }
121
+
122
+ notifyListeners() {
123
+ for (const listener of this.listeners) {
124
+ try {
125
+ listener(this.getActiveTasks());
126
+ } catch (err) {
127
+ console.error('TaskManager listener error:', err);
128
+ }
129
+ }
130
+ }
131
+ }
132
+
133
+ // Singleton instance
134
+ export const taskManager = new TaskManager();