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,313 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * multimodal.mjs — Shared image/audio processing for crewswarm
4
+ *
5
+ * Supports:
6
+ * - Image analysis via Groq Vision (Llama 4 Scout) or Gemini 2.0 Flash
7
+ * - Audio transcription via Groq Whisper or Gemini
8
+ * - Used by Telegram, WhatsApp, dashboard, and CrewChat
9
+ */
10
+
11
+ import { readFileSync } from "node:fs";
12
+ import { homedir } from "node:os";
13
+ import { join } from "node:path";
14
+ import { loadSwarmConfig } from "../runtime/config.mjs";
15
+
16
+ // ── Config ────────────────────────────────────────────────────────────────────
17
+
18
+ const cfg = loadSwarmConfig();
19
+ const providers = cfg.providers || {};
20
+
21
+ // Provider selection priority: Groq (fast/cheap) → Gemini → OpenAI → fail
22
+ const GROQ_KEY = providers.groq?.apiKey || "";
23
+ const GEMINI_KEY = providers.google?.apiKey || providers.gemini?.apiKey || "";
24
+ const OPENAI_KEY = providers.openai?.apiKey || "";
25
+
26
+ const GROQ_VISION_MODEL = "meta-llama/llama-4-scout-17b-16e-instruct";
27
+ const GROQ_WHISPER_MODEL = "whisper-large-v3-turbo"; // 216x realtime, $0.04/hr
28
+ const GEMINI_MODEL = "gemini-2.0-flash-exp";
29
+
30
+ // ── Image Analysis ────────────────────────────────────────────────────────────
31
+
32
+ /**
33
+ * Analyze an image via URL or base64
34
+ * @param {string} imageUrlOrBase64 - Public URL or base64 data URI
35
+ * @param {string} prompt - Question/instruction for the model
36
+ * @param {object} options - { provider: 'groq'|'gemini'|'auto' }
37
+ * @returns {Promise<string>} - Model's response
38
+ */
39
+ export async function analyzeImage(imageUrlOrBase64, prompt = "Describe this image in detail.", options = {}) {
40
+ const provider = options.provider || "auto";
41
+
42
+ // Auto-select: prefer Groq (cheaper), fallback to Gemini
43
+ if (provider === "auto") {
44
+ if (GROQ_KEY) return analyzeImageGroq(imageUrlOrBase64, prompt);
45
+ if (GEMINI_KEY) return analyzeImageGemini(imageUrlOrBase64, prompt);
46
+ throw new Error("No vision provider configured (need Groq or Gemini API key)");
47
+ }
48
+
49
+ if (provider === "groq") return analyzeImageGroq(imageUrlOrBase64, prompt);
50
+ if (provider === "gemini") return analyzeImageGemini(imageUrlOrBase64, prompt);
51
+ throw new Error(`Unknown vision provider: ${provider}`);
52
+ }
53
+
54
+ async function analyzeImageGroq(imageUrlOrBase64, prompt) {
55
+ if (!GROQ_KEY) throw new Error("Groq API key missing (providers.groq.apiKey)");
56
+
57
+ // Convert to message format Groq expects
58
+ const isUrl = imageUrlOrBase64.startsWith("http://") || imageUrlOrBase64.startsWith("https://");
59
+ const imageContent = isUrl
60
+ ? { type: "image_url", image_url: { url: imageUrlOrBase64 } }
61
+ : { type: "image_url", image_url: { url: imageUrlOrBase64 } }; // base64 also uses image_url
62
+
63
+ const res = await fetch("https://api.groq.com/openai/v1/chat/completions", {
64
+ method: "POST",
65
+ headers: {
66
+ "Authorization": `Bearer ${GROQ_KEY}`,
67
+ "Content-Type": "application/json"
68
+ },
69
+ body: JSON.stringify({
70
+ model: GROQ_VISION_MODEL,
71
+ messages: [
72
+ {
73
+ role: "user",
74
+ content: [
75
+ { type: "text", text: prompt },
76
+ imageContent
77
+ ]
78
+ }
79
+ ],
80
+ temperature: 0.7,
81
+ max_tokens: 1024
82
+ })
83
+ });
84
+
85
+ if (!res.ok) {
86
+ const error = await res.text();
87
+ throw new Error(`Groq vision API error: ${res.status} ${error}`);
88
+ }
89
+
90
+ const data = await res.json();
91
+ return data.choices?.[0]?.message?.content || "No response from vision model";
92
+ }
93
+
94
+ async function analyzeImageGemini(imageUrlOrBase64, prompt) {
95
+ if (!GEMINI_KEY) throw new Error("Gemini API key missing (providers.google.apiKey)");
96
+
97
+ // Gemini expects base64 inline parts
98
+ let imagePart;
99
+ if (imageUrlOrBase64.startsWith("data:image/")) {
100
+ // Extract mime and base64 from data URI
101
+ const [mime, base64] = imageUrlOrBase64.replace(/^data:/, "").split(";base64,");
102
+ imagePart = {
103
+ inline_data: {
104
+ mime_type: mime,
105
+ data: base64
106
+ }
107
+ };
108
+ } else if (imageUrlOrBase64.startsWith("http")) {
109
+ // Download and convert to base64
110
+ const imgRes = await fetch(imageUrlOrBase64);
111
+ const buffer = Buffer.from(await imgRes.arrayBuffer());
112
+ const base64 = buffer.toString("base64");
113
+ const mime = imgRes.headers.get("content-type") || "image/jpeg";
114
+ imagePart = {
115
+ inline_data: {
116
+ mime_type: mime,
117
+ data: base64
118
+ }
119
+ };
120
+ } else {
121
+ // Already base64
122
+ imagePart = {
123
+ inline_data: {
124
+ mime_type: "image/jpeg",
125
+ data: imageUrlOrBase64
126
+ }
127
+ };
128
+ }
129
+
130
+ const res = await fetch(
131
+ `https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent?key=${GEMINI_KEY}`,
132
+ {
133
+ method: "POST",
134
+ headers: { "Content-Type": "application/json" },
135
+ body: JSON.stringify({
136
+ contents: [
137
+ {
138
+ parts: [
139
+ { text: prompt },
140
+ imagePart
141
+ ]
142
+ }
143
+ ]
144
+ })
145
+ }
146
+ );
147
+
148
+ if (!res.ok) {
149
+ const error = await res.text();
150
+ throw new Error(`Gemini API error: ${res.status} ${error}`);
151
+ }
152
+
153
+ const data = await res.json();
154
+ return data.candidates?.[0]?.content?.parts?.[0]?.text || "No response from Gemini";
155
+ }
156
+
157
+ // ── Audio Transcription ───────────────────────────────────────────────────────
158
+
159
+ /**
160
+ * Transcribe audio file to text
161
+ * @param {Buffer} audioBuffer - Raw audio file data
162
+ * @param {object} options - { provider, language, mimeType: 'audio/m4a'|'audio/webm'|... }
163
+ * @returns {Promise<string>} - Transcribed text
164
+ */
165
+ export async function transcribeAudio(audioBuffer, options = {}) {
166
+ const provider = options.provider || "auto";
167
+
168
+ // Auto-select: Groq → Gemini → OpenAI (Whisper handles m4a well)
169
+ if (provider === "auto") {
170
+ if (GROQ_KEY) return transcribeAudioGroq(audioBuffer, options);
171
+ if (GEMINI_KEY) return transcribeAudioGemini(audioBuffer, options);
172
+ if (OPENAI_KEY) return transcribeAudioOpenAI(audioBuffer, options);
173
+ throw new Error("No audio provider configured (need Groq, Gemini, or OpenAI API key)");
174
+ }
175
+ if (provider === "groq") return transcribeAudioGroq(audioBuffer, options);
176
+ if (provider === "gemini") return transcribeAudioGemini(audioBuffer, options);
177
+ if (provider === "openai") return transcribeAudioOpenAI(audioBuffer, options);
178
+ throw new Error(`Unknown audio provider: ${provider}`);
179
+ }
180
+
181
+ async function transcribeAudioGroq(audioBuffer, options) {
182
+ if (!GROQ_KEY) throw new Error("Groq API key missing (providers.groq.apiKey)");
183
+ const mime = options.mimeType || "audio/m4a";
184
+ const filename = mime.includes("m4a") || mime === "audio/mp4" ? "audio.m4a" : mime.includes("webm") ? "audio.webm" : "audio.m4a";
185
+ const formData = new FormData();
186
+ formData.append("file", new Blob([audioBuffer], { type: mime }), filename);
187
+ formData.append("model", GROQ_WHISPER_MODEL);
188
+ formData.append("response_format", "json"); // Explicit per Groq docs
189
+ if (options.language && options.language !== "auto") {
190
+ formData.append("language", options.language);
191
+ }
192
+
193
+ const res = await fetch("https://api.groq.com/openai/v1/audio/transcriptions", {
194
+ method: "POST",
195
+ headers: {
196
+ "Authorization": `Bearer ${GROQ_KEY}`
197
+ },
198
+ body: formData
199
+ });
200
+
201
+ if (!res.ok) {
202
+ const error = await res.text();
203
+ throw new Error(`Groq Whisper API error: ${res.status} ${error}`);
204
+ }
205
+
206
+ const data = await res.json();
207
+ const text = (data.text || "").trim();
208
+ if (!text) throw new Error("Groq returned empty transcription (check audio format and length)");
209
+ return text;
210
+ }
211
+
212
+ async function transcribeAudioGemini(audioBuffer, options) {
213
+ if (!GEMINI_KEY) throw new Error("Gemini API key missing (providers.google.apiKey)");
214
+ // Gemini expects audio/mp4 for m4a, not audio/m4a
215
+ const raw = options.mimeType || "audio/m4a";
216
+ const mimeType = raw === "audio/m4a" || raw.includes("m4a") ? "audio/mp4" : raw;
217
+ const base64 = audioBuffer.toString("base64");
218
+ const res = await fetch(
219
+ `https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent?key=${GEMINI_KEY}`,
220
+ {
221
+ method: "POST",
222
+ headers: { "Content-Type": "application/json" },
223
+ body: JSON.stringify({
224
+ contents: [
225
+ {
226
+ parts: [
227
+ { text: "Transcribe this audio to text. Only return the transcription, no other commentary." },
228
+ {
229
+ inline_data: {
230
+ mime_type: mimeType,
231
+ data: base64
232
+ }
233
+ }
234
+ ]
235
+ }
236
+ ]
237
+ })
238
+ }
239
+ );
240
+
241
+ if (!res.ok) {
242
+ const error = await res.text();
243
+ throw new Error(`Gemini audio API error: ${res.status} ${error}`);
244
+ }
245
+
246
+ const data = await res.json();
247
+ const text = (data.candidates?.[0]?.content?.parts?.[0]?.text || "").trim();
248
+ if (!text) throw new Error("Gemini returned empty transcription (check audio format and length)");
249
+ return text;
250
+ }
251
+
252
+ async function transcribeAudioOpenAI(audioBuffer, options) {
253
+ if (!OPENAI_KEY) throw new Error("OpenAI API key missing (providers.openai.apiKey)");
254
+ const mime = options.mimeType || "audio/m4a";
255
+ const filename = mime.includes("m4a") || mime === "audio/mp4" ? "audio.m4a" : mime.includes("webm") ? "audio.webm" : "audio.m4a";
256
+ const formData = new FormData();
257
+ formData.append("file", new Blob([audioBuffer], { type: mime }), filename);
258
+ formData.append("model", "whisper-1");
259
+ const res = await fetch("https://api.openai.com/v1/audio/transcriptions", {
260
+ method: "POST",
261
+ headers: { "Authorization": `Bearer ${OPENAI_KEY}` },
262
+ body: formData
263
+ });
264
+ if (!res.ok) {
265
+ const err = await res.text();
266
+ throw new Error(`OpenAI Whisper API error: ${res.status} ${err}`);
267
+ }
268
+ const data = await res.json();
269
+ const text = (data.text || "").trim();
270
+ if (!text) throw new Error("OpenAI returned empty transcription (check audio format and length)");
271
+ return text;
272
+ }
273
+
274
+ // ── Helpers ───────────────────────────────────────────────────────────────────
275
+
276
+ /**
277
+ * Download file from URL to Buffer
278
+ */
279
+ export async function downloadToBuffer(url) {
280
+ const res = await fetch(url);
281
+ if (!res.ok) throw new Error(`Download failed: ${res.status}`);
282
+ return Buffer.from(await res.arrayBuffer());
283
+ }
284
+
285
+ /**
286
+ * Convert file path to base64 data URI
287
+ */
288
+ export function fileToBase64DataUri(filePath, mimeType = "image/jpeg") {
289
+ const buffer = readFileSync(filePath);
290
+ const base64 = buffer.toString("base64");
291
+ return `data:${mimeType};base64,${base64}`;
292
+ }
293
+
294
+ /**
295
+ * Check if provider is configured
296
+ */
297
+ export function hasVisionProvider() {
298
+ return !!(GROQ_KEY || GEMINI_KEY);
299
+ }
300
+
301
+ export function hasAudioProvider() {
302
+ return !!(GROQ_KEY || GEMINI_KEY || OPENAI_KEY);
303
+ }
304
+
305
+ /**
306
+ * Get active provider names
307
+ */
308
+ export function getActiveProviders() {
309
+ const providers = [];
310
+ if (GROQ_KEY) providers.push("groq");
311
+ if (GEMINI_KEY) providers.push("gemini");
312
+ return providers;
313
+ }
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Telegram Native Streaming Handler
3
+ * Uses sendMessageDraft (Bot API 9.5) for progressive text display
4
+ */
5
+
6
+ /**
7
+ * Stream LLM response progressively to Telegram using sendMessageDraft
8
+ * @param {number} chatId - Telegram chat ID
9
+ * @param {number|null} threadId - Topic ID (if in forum group)
10
+ * @param {string} targetAgent - Agent identifier (for logging)
11
+ * @param {Object} provider - Provider config { baseUrl, apiKey }
12
+ * @param {string} modelId - Model identifier
13
+ * @param {Array} messages - Message array for LLM
14
+ * @param {Function} tgRequest - Telegram API request function
15
+ * @param {Function} log - Logger function
16
+ * @returns {Promise<string>} Final response text
17
+ */
18
+ export async function streamToTelegram({
19
+ chatId,
20
+ threadId = null,
21
+ targetAgent,
22
+ provider,
23
+ modelId,
24
+ messages,
25
+ tgRequest,
26
+ log
27
+ }) {
28
+ const draftId = Date.now(); // Unique draft ID for this stream
29
+ let fullText = "";
30
+ let lastUpdate = 0;
31
+ const UPDATE_INTERVAL_MS = 100; // Update every 100ms (smooth but not spammy)
32
+
33
+ try {
34
+ // Call LLM with streaming enabled
35
+ const response = await fetch(provider.baseUrl + "/chat/completions", {
36
+ method: "POST",
37
+ headers: {
38
+ "Content-Type": "application/json",
39
+ "Authorization": `Bearer ${provider.apiKey}`
40
+ },
41
+ body: JSON.stringify({
42
+ model: modelId,
43
+ messages,
44
+ temperature: 0.7,
45
+ stream: true // Enable streaming
46
+ })
47
+ });
48
+
49
+ if (!response.ok) {
50
+ throw new Error(`LLM API returned ${response.status}`);
51
+ }
52
+
53
+ const reader = response.body.getReader();
54
+ const decoder = new TextDecoder();
55
+ let buffer = "";
56
+
57
+ while (true) {
58
+ const { done, value } = await reader.read();
59
+ if (done) break;
60
+
61
+ buffer += decoder.decode(value, { stream: true });
62
+ const lines = buffer.split("\n");
63
+ buffer = lines.pop() || "";
64
+
65
+ for (const line of lines) {
66
+ if (!line.trim() || !line.startsWith("data: ")) continue;
67
+
68
+ const data = line.slice(6);
69
+ if (data === "[DONE]") continue;
70
+
71
+ try {
72
+ const parsed = JSON.parse(data);
73
+ const content = parsed.choices?.[0]?.delta?.content;
74
+
75
+ if (content) {
76
+ fullText += content;
77
+
78
+ // Throttle updates - only send every 100ms
79
+ const now = Date.now();
80
+ if (now - lastUpdate >= UPDATE_INTERVAL_MS) {
81
+ await tgRequest("sendMessageDraft", {
82
+ chat_id: chatId,
83
+ ...(threadId && { message_thread_id: threadId }),
84
+ draft_id: draftId,
85
+ text: fullText,
86
+ parse_mode: "Markdown"
87
+ }).catch(err => {
88
+ // Fallback: if Markdown fails, try without parse_mode
89
+ return tgRequest("sendMessageDraft", {
90
+ chat_id: chatId,
91
+ ...(threadId && { message_thread_id: threadId }),
92
+ draft_id: draftId,
93
+ text: fullText
94
+ });
95
+ });
96
+
97
+ lastUpdate = now;
98
+ }
99
+ }
100
+ } catch (parseErr) {
101
+ log("warn", "Failed to parse SSE chunk", { error: parseErr.message });
102
+ }
103
+ }
104
+ }
105
+
106
+ // Send final update (in case last chunk didn't trigger threshold)
107
+ if (fullText && Date.now() - lastUpdate >= 50) {
108
+ await tgRequest("sendMessageDraft", {
109
+ chat_id: chatId,
110
+ ...(threadId && { message_thread_id: threadId }),
111
+ draft_id: draftId,
112
+ text: fullText,
113
+ parse_mode: "Markdown"
114
+ }).catch(err => {
115
+ return tgRequest("sendMessageDraft", {
116
+ chat_id: chatId,
117
+ ...(threadId && { message_thread_id: threadId }),
118
+ draft_id: draftId,
119
+ text: fullText
120
+ });
121
+ });
122
+ }
123
+
124
+ log("info", "Streaming complete", {
125
+ targetAgent,
126
+ chatId,
127
+ threadId,
128
+ length: fullText.length
129
+ });
130
+
131
+ return fullText;
132
+
133
+ } catch (err) {
134
+ log("error", "Streaming failed", {
135
+ targetAgent,
136
+ error: err.message
137
+ });
138
+ throw err;
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Check if native streaming is supported for this chat
144
+ * sendMessageDraft only works in private chats (DMs and private topics)
145
+ * @param {number} chatId - Telegram chat ID
146
+ * @returns {boolean}
147
+ */
148
+ export function supportsNativeStreaming(chatId) {
149
+ // Private chats have positive IDs
150
+ // Groups/supergroups have negative IDs
151
+ // BUT: Private chats with topics ARE supported
152
+ return chatId > 0;
153
+ }