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,127 @@
1
+ /**
2
+ * Orchestration Status Panel
3
+ * Live dashboard for crewswarm swarm coordination
4
+ */
5
+
6
+ let orchestrationInterval = null;
7
+
8
+ export async function updateOrchestrationStatus() {
9
+ try {
10
+ // Get health check
11
+ const healthRes = await fetch('/api/health');
12
+ const health = healthRes.ok ? await healthRes.json() : { ok: false };
13
+
14
+ // Get agents status
15
+ const agentsRes = await fetch('/api/agents');
16
+ const agents = agentsRes.ok ? await agentsRes.json() : { count: 0 };
17
+
18
+ // Get project queue status
19
+ const queueRes = await fetch('/api/projects');
20
+ const projects = queueRes.ok ? await queueRes.json() : { projects: [] };
21
+ const allProjects = projects.projects || [];
22
+ const totalPending = allProjects.reduce((sum, p) => sum + (p.roadmap?.pending || 0), 0);
23
+ const totalRunning = allProjects.filter(p => p.running).length;
24
+
25
+ // Get configured models
26
+ const providersRes = await fetch('/api/providers');
27
+ const providers = providersRes.ok ? await providersRes.json() : { providers: [] };
28
+ const configuredProviders = (providers.providers || []).filter(p => p.configured);
29
+ const modelNames = configuredProviders.map(p => {
30
+ if (p.id === 'openai') return 'GPT';
31
+ if (p.id === 'anthropic') return 'Claude';
32
+ if (p.id === 'google') return 'Gemini';
33
+ if (p.id === 'groq') return 'Groq';
34
+ if (p.id === 'xai') return 'Grok';
35
+ if (p.id === 'ollama') return 'Local';
36
+ return p.label?.split(' ')[0];
37
+ });
38
+
39
+ // Update UI
40
+ const systemStatus = document.getElementById('orchSystemStatus');
41
+ const modelStack = document.getElementById('orchModelStack');
42
+ const swarmFill = document.getElementById('orchSwarmFill');
43
+ const swarmPercent = document.getElementById('orchSwarmPercent');
44
+ const activeAgents = document.getElementById('orchActiveAgents');
45
+ const taskQueue = document.getElementById('orchTaskQueue');
46
+
47
+ if (systemStatus) {
48
+ if (health.ok) {
49
+ systemStatus.textContent = '● ONLINE';
50
+ systemStatus.style.color = '#10b981'; // green
51
+ } else {
52
+ systemStatus.textContent = '● OFFLINE';
53
+ systemStatus.style.color = '#ef4444'; // red
54
+ }
55
+ }
56
+
57
+ if (modelStack) {
58
+ modelStack.textContent = modelNames.length > 0
59
+ ? modelNames.slice(0, 3).join(' / ')
60
+ : 'Not configured';
61
+ }
62
+
63
+ const agentCount = agents.count || 0;
64
+ const maxAgents = 30;
65
+ const percent = Math.min(100, Math.floor((agentCount / maxAgents) * 100));
66
+
67
+ if (swarmFill) {
68
+ swarmFill.style.width = `${percent}%`;
69
+ }
70
+ if (swarmPercent) {
71
+ swarmPercent.textContent = `${percent}%`;
72
+ }
73
+ if (activeAgents) {
74
+ activeAgents.textContent = agentCount.toString();
75
+ }
76
+ if (taskQueue) {
77
+ const parts = [];
78
+ if (totalPending > 0) parts.push(`${totalPending} pending`);
79
+ if (totalRunning > 0) parts.push(`${totalRunning} running`);
80
+ taskQueue.textContent = parts.length > 0 ? parts.join(', ') : '0 pending';
81
+ }
82
+
83
+ } catch (err) {
84
+ console.error('[OrchestrationStatus] Update failed:', err);
85
+
86
+ // Show error state
87
+ const systemStatus = document.getElementById('orchSystemStatus');
88
+ if (systemStatus) {
89
+ systemStatus.textContent = '● ERROR';
90
+ systemStatus.style.color = '#ef4444';
91
+ }
92
+ }
93
+ }
94
+
95
+ export function startOrchestrationStatusUpdates() {
96
+ // Initial update
97
+ updateOrchestrationStatus();
98
+
99
+ // Update every 5 seconds
100
+ if (orchestrationInterval) {
101
+ clearInterval(orchestrationInterval);
102
+ }
103
+ orchestrationInterval = setInterval(updateOrchestrationStatus, 5000);
104
+ }
105
+
106
+ export function stopOrchestrationStatusUpdates() {
107
+ if (orchestrationInterval) {
108
+ clearInterval(orchestrationInterval);
109
+ orchestrationInterval = null;
110
+ }
111
+ }
112
+
113
+ // Auto-start when chat view is active
114
+ document.addEventListener('DOMContentLoaded', () => {
115
+ const chatView = document.getElementById('chatView');
116
+ if (chatView && chatView.classList.contains('active')) {
117
+ startOrchestrationStatusUpdates();
118
+ }
119
+ });
120
+
121
+ // Restart when switching to chat view
122
+ const navChat = document.getElementById('navChat');
123
+ if (navChat) {
124
+ navChat.addEventListener('click', () => {
125
+ setTimeout(startOrchestrationStatusUpdates, 100);
126
+ });
127
+ }
@@ -0,0 +1,555 @@
1
+ /**
2
+ * Setup Wizard — first-run onboarding overlay for CrewSwarm dashboard.
3
+ * Shows when no API keys are configured (firstRun === true).
4
+ * Step 1: Welcome → Step 2: API Keys → Step 3: CLI Engines
5
+ * Vanilla JS, no frameworks. Matches the existing dark dashboard theme.
6
+ */
7
+
8
+ import { getJSON, postJSON } from "./core/api.js";
9
+
10
+ // ── All supported providers (synced with models-tab.js BUILTIN_PROVIDERS) ────
11
+ const ALL_PROVIDERS = [
12
+ { id: "anthropic", label: "Anthropic", icon: "\uD83D\uDFE3", placeholder: "sk-ant-...", url: "https://console.anthropic.com/" },
13
+ { id: "openai", label: "OpenAI", icon: "\uD83D\uDFE2", placeholder: "sk-...", url: "https://platform.openai.com/api-keys" },
14
+ { id: "google", label: "Google (Gemini)", icon: "\uD83D\uDD35", placeholder: "AIza...", url: "https://aistudio.google.com/apikey" },
15
+ { id: "groq", label: "Groq", icon: "\u26A1", placeholder: "gsk_...", url: "https://console.groq.com/keys" },
16
+ { id: "fireworks", label: "Fireworks AI", icon: "\uD83C\uDF86", placeholder: "fw_...", url: "https://fireworks.ai/" },
17
+ { id: "openrouter", label: "OpenRouter", icon: "\uD83D\uDD00", placeholder: "sk-or-...", url: "https://openrouter.ai/keys" },
18
+ { id: "xai", label: "xAI (Grok)", icon: "\uD835\uDD4F", placeholder: "xai-...", url: "https://console.x.ai/" },
19
+ { id: "deepseek", label: "DeepSeek", icon: "\uD83C\uDF0A", placeholder: "sk-...", url: "https://platform.deepseek.com/" },
20
+ { id: "mistral", label: "Mistral", icon: "\uD83C\uDF00", placeholder: "...", url: "https://console.mistral.ai/api-keys" },
21
+ { id: "cerebras", label: "Cerebras", icon: "\uD83E\uDDE0", placeholder: "csk-...", url: "https://cloud.cerebras.ai/" },
22
+ { id: "nvidia", label: "NVIDIA NIM", icon: "\uD83C\uDFAE", placeholder: "nvapi-...", url: "https://build.nvidia.com/" },
23
+ { id: "perplexity", label: "Perplexity", icon: "\uD83D\uDD0D", placeholder: "pplx-...", url: "https://www.perplexity.ai/settings/api" },
24
+ { id: "ollama", label: "Ollama (local)", icon: "\uD83C\uDFE0", placeholder: "no key needed", url: "https://ollama.com/download" },
25
+ ];
26
+
27
+ // ── CLI engines we can detect ────────────────────────────────────────────────
28
+ const CLI_ENGINES = [
29
+ { id: "claude-code", cmd: "claude", label: "Claude Code", desc: "Anthropic's CLI agent. Best for complex reasoning and multi-file refactors.", installUrl: "https://docs.anthropic.com/en/docs/claude-code/overview", authCmd: "claude auth", keyProvider: "anthropic" },
30
+ { id: "codex", cmd: "codex", label: "Codex CLI", desc: "OpenAI's CLI agent. Sandboxed execution with full file write access.", installUrl: "https://github.com/openai/codex", authCmd: "codex auth", keyProvider: "openai" },
31
+ { id: "crew-cli", cmd: "crew", label: "crew-cli", desc: "CrewSwarm's own 3-tier pipeline. Supports Anthropic, OpenAI, Gemini, Groq, DeepSeek, and more.", installUrl: null, authCmd: null, keyProvider: null },
32
+ { id: "opencode", cmd: "opencode", label: "OpenCode", desc: "Multi-provider CLI agent. Supports OpenAI, Anthropic, Google, and more.", installUrl: "https://github.com/opencode-ai/opencode", authCmd: null, keyProvider: null },
33
+ { id: "gemini-cli", cmd: "gemini", label: "Gemini CLI", desc: "Google's CLI agent. Fast inference with Gemini models.", installUrl: "https://github.com/google-gemini/gemini-cli", authCmd: "gemini auth", keyProvider: "google" },
34
+ { id: "cursor", cmd: "cursor", label: "Cursor CLI", desc: "Cursor's agent mode via CLI. Requires Cursor IDE installed.", installUrl: "https://www.cursor.com/", authCmd: null, keyProvider: null },
35
+ ];
36
+
37
+ let _currentStep = 1;
38
+ let _overlayEl = null;
39
+ let _providerKeys = {}; // only keys the user actually typed
40
+ let _configuredProviders = []; // already-configured provider IDs from backend
41
+ let _detectedEngines = {}; // { engineId: true/false }
42
+
43
+ // ── Public API ──────────────────────────────────────────────────────────────
44
+
45
+ /**
46
+ * Check first-run status and show wizard if needed.
47
+ * Returns true if wizard was shown, false if skipped.
48
+ */
49
+ export async function checkFirstRun() {
50
+ try {
51
+ const data = await getJSON("/api/first-run-status");
52
+ const forceWizard = new URLSearchParams(window.location.search).has("wizard");
53
+ if (!data.firstRun && !forceWizard) return false;
54
+ _configuredProviders = data.configuredProviders || [];
55
+ _showWizard();
56
+ return true;
57
+ } catch (e) {
58
+ console.warn("[setup-wizard] Could not check first-run status:", e);
59
+ return false;
60
+ }
61
+ }
62
+
63
+ // ── Wizard rendering ────────────────────────────────────────────────────────
64
+
65
+ function _showWizard() {
66
+ _currentStep = 1;
67
+ _providerKeys = {};
68
+
69
+ _overlayEl = document.createElement("div");
70
+ _overlayEl.id = "setupWizardOverlay";
71
+ _overlayEl.className = "setup-wizard-overlay";
72
+ _overlayEl.setAttribute("role", "dialog");
73
+ _overlayEl.setAttribute("aria-modal", "true");
74
+ _overlayEl.setAttribute("aria-label", "CrewSwarm setup wizard");
75
+
76
+ _renderStep();
77
+ document.body.appendChild(_overlayEl);
78
+
79
+ // Force reflow then animate in
80
+ _overlayEl.offsetHeight;
81
+ _overlayEl.classList.add("visible");
82
+ }
83
+
84
+ function _renderStep() {
85
+ if (!_overlayEl) return;
86
+
87
+ const card = _buildStepContent();
88
+ _overlayEl.innerHTML = "";
89
+
90
+ const wrapper = document.createElement("div");
91
+ wrapper.className = "setup-wizard-card";
92
+ wrapper.appendChild(_buildStepIndicator());
93
+ wrapper.appendChild(card);
94
+ _overlayEl.appendChild(wrapper);
95
+
96
+ requestAnimationFrame(() => {
97
+ wrapper.classList.add("visible");
98
+ });
99
+ }
100
+
101
+ function _buildStepIndicator() {
102
+ const labels = ["Welcome", "API Keys", "Engines"];
103
+ const indicator = document.createElement("div");
104
+ indicator.className = "setup-wizard-steps";
105
+ indicator.setAttribute("aria-label", `Step ${_currentStep} of 3`);
106
+
107
+ for (let i = 1; i <= 3; i++) {
108
+ const dot = document.createElement("button");
109
+ dot.className = "setup-wizard-step-dot";
110
+ dot.setAttribute("aria-label", `Step ${i}`);
111
+ dot.tabIndex = -1;
112
+ if (i === _currentStep) dot.classList.add("active");
113
+ if (i < _currentStep) dot.classList.add("completed");
114
+
115
+ const label = document.createElement("span");
116
+ label.className = "setup-wizard-step-label";
117
+ label.textContent = labels[i - 1];
118
+
119
+ const step = document.createElement("div");
120
+ step.className = "setup-wizard-step";
121
+ step.appendChild(dot);
122
+ step.appendChild(label);
123
+ indicator.appendChild(step);
124
+
125
+ if (i < 3) {
126
+ const line = document.createElement("div");
127
+ line.className = "setup-wizard-step-line";
128
+ if (i < _currentStep) line.classList.add("completed");
129
+ indicator.appendChild(line);
130
+ }
131
+ }
132
+
133
+ return indicator;
134
+ }
135
+
136
+ function _buildStepContent() {
137
+ switch (_currentStep) {
138
+ case 1: return _buildWelcomeStep();
139
+ case 2: return _buildProvidersStep();
140
+ case 3: return _buildEnginesStep();
141
+ default: return _buildWelcomeStep();
142
+ }
143
+ }
144
+
145
+ // ── Step 1: Welcome ─────────────────────────────────────────────────────────
146
+
147
+ function _buildWelcomeStep() {
148
+ const frag = document.createElement("div");
149
+ frag.className = "setup-wizard-content";
150
+
151
+ frag.innerHTML = `
152
+ <div class="setup-wizard-hero">
153
+ <div class="setup-wizard-logo-ring">
154
+ <img src="/favicon.png" alt="CrewSwarm" class="setup-wizard-logo" />
155
+ </div>
156
+ <h1 class="setup-wizard-title">Welcome to CrewSwarm</h1>
157
+ <p class="setup-wizard-subtitle">
158
+ Multi-agent orchestration for AI coding tools.<br>
159
+ Let's get you set up in 2 minutes.
160
+ </p>
161
+ </div>
162
+ <div class="setup-wizard-checklist">
163
+ <div class="setup-wizard-check-item">
164
+ <span class="setup-wizard-check-icon done">&check;</span>
165
+ <span>Dashboard installed</span>
166
+ </div>
167
+ <div class="setup-wizard-check-item">
168
+ <span class="setup-wizard-check-icon pending">&bull;</span>
169
+ <span>Add API provider keys</span>
170
+ </div>
171
+ <div class="setup-wizard-check-item">
172
+ <span class="setup-wizard-check-icon pending">&bull;</span>
173
+ <span>Detect & configure CLI engines</span>
174
+ </div>
175
+ </div>
176
+ `;
177
+
178
+ const actions = document.createElement("div");
179
+ actions.className = "setup-wizard-actions";
180
+
181
+ const nextBtn = document.createElement("button");
182
+ nextBtn.className = "setup-wizard-btn-primary";
183
+ nextBtn.textContent = "Get Started";
184
+ nextBtn.addEventListener("click", () => {
185
+ _currentStep = 2;
186
+ _renderStep();
187
+ });
188
+
189
+ const skipBtn = document.createElement("button");
190
+ skipBtn.className = "setup-wizard-btn-ghost";
191
+ skipBtn.textContent = "Skip setup";
192
+ skipBtn.addEventListener("click", _dismiss);
193
+
194
+ actions.appendChild(nextBtn);
195
+ actions.appendChild(skipBtn);
196
+ frag.appendChild(actions);
197
+
198
+ return frag;
199
+ }
200
+
201
+ // ── Step 2: API Keys ────────────────────────────────────────────────────────
202
+
203
+ function _buildProvidersStep() {
204
+ const frag = document.createElement("div");
205
+ frag.className = "setup-wizard-content";
206
+
207
+ const header = document.createElement("div");
208
+ header.className = "setup-wizard-section-header";
209
+ header.innerHTML = `
210
+ <h2 class="setup-wizard-section-title">API Keys</h2>
211
+ <p class="setup-wizard-section-desc">
212
+ Add keys for the providers you want to use. Already-configured keys are shown with a checkmark.
213
+ Only new keys you enter will be saved &mdash; existing keys won't be touched.
214
+ </p>
215
+ `;
216
+ frag.appendChild(header);
217
+
218
+ const list = document.createElement("div");
219
+ list.className = "setup-wizard-provider-list";
220
+
221
+ for (const prov of ALL_PROVIDERS) {
222
+ const alreadyConfigured = _configuredProviders.includes(prov.id);
223
+
224
+ const row = document.createElement("div");
225
+ row.className = "setup-wizard-provider-row";
226
+ if (alreadyConfigured) row.classList.add("already-configured");
227
+
228
+ const labelWrap = document.createElement("div");
229
+ labelWrap.className = "setup-wizard-provider-label";
230
+
231
+ const provIcon = document.createElement("span");
232
+ provIcon.className = "setup-wizard-provider-icon";
233
+ provIcon.textContent = prov.icon || "";
234
+
235
+ const statusIcon = document.createElement("span");
236
+ statusIcon.className = "setup-wizard-provider-status";
237
+ statusIcon.textContent = alreadyConfigured ? "\u2713" : "";
238
+ statusIcon.title = alreadyConfigured ? "Already configured" : "Not configured";
239
+
240
+ const name = document.createElement("span");
241
+ name.className = "setup-wizard-provider-name";
242
+ name.textContent = prov.label;
243
+
244
+ const link = document.createElement("a");
245
+ link.href = prov.url;
246
+ link.target = "_blank";
247
+ link.rel = "noopener";
248
+ link.className = "setup-wizard-provider-link";
249
+ link.textContent = "Get key";
250
+ link.setAttribute("aria-label", `Get API key for ${prov.label}`);
251
+
252
+ labelWrap.appendChild(provIcon);
253
+ labelWrap.appendChild(name);
254
+ labelWrap.appendChild(statusIcon);
255
+ labelWrap.appendChild(link);
256
+
257
+ const inputWrap = document.createElement("div");
258
+ inputWrap.className = "setup-wizard-provider-input-wrap";
259
+
260
+ const input = document.createElement("input");
261
+ input.type = "password";
262
+ input.className = "setup-wizard-provider-input";
263
+ input.placeholder = alreadyConfigured ? "configured \u2713" : prov.placeholder;
264
+ input.autocomplete = "off";
265
+ input.spellcheck = false;
266
+ input.dataset.providerId = prov.id;
267
+ input.setAttribute("aria-label", `API key for ${prov.label}`);
268
+
269
+ if (_providerKeys[prov.id]) {
270
+ input.value = _providerKeys[prov.id];
271
+ }
272
+
273
+ input.addEventListener("input", () => {
274
+ const val = input.value.trim();
275
+ if (val) {
276
+ _providerKeys[prov.id] = val;
277
+ row.classList.add("has-key");
278
+ } else {
279
+ delete _providerKeys[prov.id];
280
+ row.classList.remove("has-key");
281
+ }
282
+ _updateSaveBtn();
283
+ });
284
+
285
+ const toggleVis = document.createElement("button");
286
+ toggleVis.type = "button";
287
+ toggleVis.className = "setup-wizard-toggle-vis";
288
+ toggleVis.textContent = "\uD83D\uDC41";
289
+ toggleVis.setAttribute("aria-label", "Toggle key visibility");
290
+ toggleVis.addEventListener("click", () => {
291
+ input.type = input.type === "password" ? "text" : "password";
292
+ });
293
+
294
+ inputWrap.appendChild(input);
295
+ inputWrap.appendChild(toggleVis);
296
+
297
+ row.appendChild(labelWrap);
298
+ row.appendChild(inputWrap);
299
+
300
+ if (_providerKeys[prov.id]) {
301
+ row.classList.add("has-key");
302
+ }
303
+
304
+ list.appendChild(row);
305
+ }
306
+
307
+ frag.appendChild(list);
308
+
309
+ const errorEl = document.createElement("div");
310
+ errorEl.className = "setup-wizard-error hidden";
311
+ errorEl.id = "wizardProviderError";
312
+ frag.appendChild(errorEl);
313
+
314
+ const actions = document.createElement("div");
315
+ actions.className = "setup-wizard-actions";
316
+
317
+ const backBtn = document.createElement("button");
318
+ backBtn.className = "setup-wizard-btn-ghost";
319
+ backBtn.textContent = "Back";
320
+ backBtn.addEventListener("click", () => {
321
+ _currentStep = 1;
322
+ _renderStep();
323
+ });
324
+
325
+ const saveBtn = document.createElement("button");
326
+ saveBtn.className = "setup-wizard-btn-primary";
327
+ saveBtn.id = "wizardSaveBtn";
328
+ // Allow continuing even without new keys (they may all be pre-configured)
329
+ const hasNewKeys = Object.keys(_providerKeys).length > 0;
330
+ const hasExistingKeys = _configuredProviders.length > 0;
331
+ saveBtn.textContent = hasNewKeys ? "Save & Continue" : "Continue";
332
+ saveBtn.disabled = !hasNewKeys && !hasExistingKeys;
333
+ saveBtn.addEventListener("click", _saveProviders);
334
+
335
+ actions.appendChild(backBtn);
336
+ actions.appendChild(saveBtn);
337
+ frag.appendChild(actions);
338
+
339
+ return frag;
340
+ }
341
+
342
+ function _updateSaveBtn() {
343
+ const btn = document.getElementById("wizardSaveBtn");
344
+ if (!btn) return;
345
+ const hasNewKeys = Object.keys(_providerKeys).length > 0;
346
+ const hasExistingKeys = _configuredProviders.length > 0;
347
+ btn.textContent = hasNewKeys ? "Save & Continue" : "Continue";
348
+ btn.disabled = !hasNewKeys && !hasExistingKeys;
349
+ }
350
+
351
+ async function _saveProviders() {
352
+ const btn = document.getElementById("wizardSaveBtn");
353
+ const errorEl = document.getElementById("wizardProviderError");
354
+
355
+ const newKeys = Object.entries(_providerKeys).filter(([, v]) => v && v.length > 0);
356
+
357
+ if (newKeys.length > 0) {
358
+ if (btn) {
359
+ btn.disabled = true;
360
+ btn.textContent = "Saving...";
361
+ }
362
+ if (errorEl) errorEl.classList.add("hidden");
363
+
364
+ try {
365
+ for (const [providerId, apiKey] of newKeys) {
366
+ await postJSON("/api/providers/builtin/save", { providerId, apiKey });
367
+ }
368
+ } catch (e) {
369
+ if (errorEl) {
370
+ errorEl.textContent = "Failed to save: " + (e.message || "Unknown error");
371
+ errorEl.classList.remove("hidden");
372
+ }
373
+ if (btn) {
374
+ btn.disabled = false;
375
+ btn.textContent = "Save & Continue";
376
+ }
377
+ return;
378
+ }
379
+ }
380
+
381
+ // Detect engines before showing step 3
382
+ await _detectEngines();
383
+ _currentStep = 3;
384
+ _renderStep();
385
+ }
386
+
387
+ // ── Step 3: CLI Engines ─────────────────────────────────────────────────────
388
+
389
+ async function _detectEngines() {
390
+ try {
391
+ const data = await getJSON("/api/first-run-engines");
392
+ _detectedEngines = data.engines || {};
393
+ } catch {
394
+ // If endpoint doesn't exist yet, fall back to empty
395
+ _detectedEngines = {};
396
+ }
397
+ }
398
+
399
+ function _buildEnginesStep() {
400
+ const frag = document.createElement("div");
401
+ frag.className = "setup-wizard-content";
402
+
403
+ const header = document.createElement("div");
404
+ header.className = "setup-wizard-section-header";
405
+ header.innerHTML = `
406
+ <h2 class="setup-wizard-section-title">CLI Engines</h2>
407
+ <p class="setup-wizard-section-desc">
408
+ CrewSwarm dispatches tasks to these CLI coding agents.
409
+ You need at least one installed. Use the API keys from Step 2 to authenticate.
410
+ </p>
411
+ `;
412
+ frag.appendChild(header);
413
+
414
+ const grid = document.createElement("div");
415
+ grid.className = "setup-wizard-engine-grid";
416
+
417
+ const detectedCount = Object.values(_detectedEngines).filter(Boolean).length;
418
+
419
+ for (const engine of CLI_ENGINES) {
420
+ const detected = _detectedEngines[engine.id] === true;
421
+ // crew-cli is always available (it's part of this repo)
422
+ const available = engine.id === "crew-cli" || detected;
423
+
424
+ const card = document.createElement("div");
425
+ card.className = "setup-wizard-engine-card";
426
+ if (available) card.classList.add("available");
427
+
428
+ // Status badge
429
+ const badge = document.createElement("div");
430
+ badge.className = "setup-wizard-engine-badge";
431
+ if (available) {
432
+ badge.textContent = "\u2713 Installed";
433
+ badge.classList.add("installed");
434
+ } else {
435
+ badge.textContent = "Not found";
436
+ badge.classList.add("missing");
437
+ }
438
+ card.appendChild(badge);
439
+
440
+ // Engine name + command
441
+ const title = document.createElement("div");
442
+ title.className = "setup-wizard-engine-title";
443
+ title.textContent = engine.label;
444
+ card.appendChild(title);
445
+
446
+ const cmd = document.createElement("code");
447
+ cmd.className = "setup-wizard-engine-cmd";
448
+ cmd.textContent = engine.cmd;
449
+ card.appendChild(cmd);
450
+
451
+ // Description
452
+ const desc = document.createElement("p");
453
+ desc.className = "setup-wizard-engine-desc";
454
+ desc.textContent = engine.desc;
455
+ card.appendChild(desc);
456
+
457
+ // Action area
458
+ const actionArea = document.createElement("div");
459
+ actionArea.className = "setup-wizard-engine-action";
460
+
461
+ if (available && engine.authCmd) {
462
+ const authLabel = document.createElement("span");
463
+ authLabel.className = "setup-wizard-engine-auth-label";
464
+ authLabel.textContent = "Auth:";
465
+ const authCode = document.createElement("code");
466
+ authCode.className = "setup-wizard-engine-auth-cmd";
467
+ authCode.textContent = engine.authCmd;
468
+ actionArea.appendChild(authLabel);
469
+ actionArea.appendChild(authCode);
470
+ } else if (available && engine.keyProvider) {
471
+ const keyNote = document.createElement("span");
472
+ keyNote.className = "setup-wizard-engine-key-note";
473
+ const provLabel = ALL_PROVIDERS.find(p => p.id === engine.keyProvider)?.label || engine.keyProvider;
474
+ const hasKey = _configuredProviders.includes(engine.keyProvider);
475
+ keyNote.textContent = hasKey ? `Uses ${provLabel} key \u2713` : `Needs ${provLabel} key`;
476
+ keyNote.classList.add(hasKey ? "key-ok" : "key-missing");
477
+ actionArea.appendChild(keyNote);
478
+ } else if (!available && engine.installUrl) {
479
+ const installLink = document.createElement("a");
480
+ installLink.href = engine.installUrl;
481
+ installLink.target = "_blank";
482
+ installLink.rel = "noopener";
483
+ installLink.className = "setup-wizard-engine-install-btn";
484
+ installLink.textContent = "Install \u2192";
485
+ actionArea.appendChild(installLink);
486
+ }
487
+
488
+ card.appendChild(actionArea);
489
+ grid.appendChild(card);
490
+ }
491
+
492
+ frag.appendChild(grid);
493
+
494
+ if (detectedCount === 0 && Object.keys(_detectedEngines).length > 0) {
495
+ const hint = document.createElement("p");
496
+ hint.className = "setup-wizard-engine-hint";
497
+ hint.innerHTML = "No external CLI engines detected. <strong>crew-cli</strong> is built in and always available.";
498
+ frag.appendChild(hint);
499
+ }
500
+
501
+ const actions = document.createElement("div");
502
+ actions.className = "setup-wizard-actions";
503
+
504
+ const backBtn = document.createElement("button");
505
+ backBtn.className = "setup-wizard-btn-ghost";
506
+ backBtn.textContent = "Back";
507
+ backBtn.addEventListener("click", () => {
508
+ _currentStep = 2;
509
+ _renderStep();
510
+ });
511
+
512
+ const startBtn = document.createElement("button");
513
+ startBtn.className = "setup-wizard-btn-primary setup-wizard-btn-start";
514
+ startBtn.textContent = "Launch Dashboard";
515
+ startBtn.addEventListener("click", _finishSetup);
516
+
517
+ actions.appendChild(backBtn);
518
+ actions.appendChild(startBtn);
519
+ frag.appendChild(actions);
520
+
521
+ return frag;
522
+ }
523
+
524
+ // ── Finish / dismiss ────────────────────────────────────────────────────────
525
+
526
+ async function _finishSetup() {
527
+ const btn = _overlayEl?.querySelector(".setup-wizard-btn-start");
528
+ if (btn) {
529
+ btn.disabled = true;
530
+ btn.textContent = "Loading...";
531
+ }
532
+
533
+ _dismiss();
534
+ window.location.href = window.location.pathname; // strip ?wizard param
535
+ }
536
+
537
+ function _dismiss() {
538
+ if (!_overlayEl) return;
539
+ _overlayEl.classList.remove("visible");
540
+ _overlayEl.classList.add("dismissing");
541
+ _overlayEl.addEventListener(
542
+ "transitionend",
543
+ () => {
544
+ _overlayEl.remove();
545
+ _overlayEl = null;
546
+ },
547
+ { once: true },
548
+ );
549
+ setTimeout(() => {
550
+ if (_overlayEl) {
551
+ _overlayEl.remove();
552
+ _overlayEl = null;
553
+ }
554
+ }, 400);
555
+ }