crewswarm 0.9.2 → 0.9.3

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 (207) hide show
  1. package/README.md +22 -9
  2. package/apps/dashboard/dist/assets/{chat-core-Cx4sTxDd.js → chat-core-3KirthZA.js} +1 -1
  3. package/apps/dashboard/dist/assets/index-GSWxxEPO.js +2 -0
  4. package/apps/dashboard/dist/assets/{tab-pm-loop-tab-Bfd449B4.js → tab-pm-loop-tab-DiAPTJXu.js} +1 -1
  5. package/apps/dashboard/dist/assets/{tab-projects-tab-DhNWnlzt.js → tab-projects-tab-SFH4E--a.js} +1 -1
  6. package/apps/dashboard/dist/assets/tab-settings-tab-BselH1c0.js +1 -0
  7. package/apps/dashboard/dist/index.html +82 -11
  8. package/apps/vibe/README.md +2 -2
  9. package/apps/vibe/package.json +1 -1
  10. package/apps/vibe/server.mjs +3 -3
  11. package/crew-lead.mjs +34 -4
  12. package/lib/bridges/gateway-ws.mjs +4 -0
  13. package/lib/crew-lead/chat-handler.mjs +34 -0
  14. package/lib/crew-lead/http-server.mjs +55 -14
  15. package/lib/crew-lead/llm-caller.mjs +24 -8
  16. package/lib/crew-lead/prompts.mjs +7 -0
  17. package/lib/crew-lead/wave-dispatcher.mjs +15 -3
  18. package/lib/crew-lead/ws-router.mjs +219 -27
  19. package/lib/engines/engine-registry.mjs +9 -0
  20. package/lib/engines/rt-envelope.mjs +1 -0
  21. package/lib/engines/runners.mjs +5 -2
  22. package/lib/runtime/paths.mjs +12 -8
  23. package/package.json +35 -15
  24. package/scripts/capture-build-flow.mjs +118 -0
  25. package/scripts/coverage-report.mjs +209 -0
  26. package/scripts/coverage-summary.mjs +47 -0
  27. package/scripts/dashboard-validation.mjs +74 -0
  28. package/scripts/dashboard.mjs +560 -70
  29. package/scripts/live-bridge-matrix.mjs +79 -0
  30. package/scripts/live-cli-matrix.mjs +166 -0
  31. package/scripts/live-crewchat-check.mjs +42 -0
  32. package/scripts/live-engine-matrix.mjs +50 -0
  33. package/scripts/live-provider-failover-matrix.mjs +107 -0
  34. package/scripts/live-provider-matrix.mjs +228 -0
  35. package/scripts/restart-all-from-repo.sh +4 -4
  36. package/scripts/smoke-dispatch.mjs +4 -1
  37. package/scripts/test-blast-radius.mjs +204 -0
  38. package/scripts/test-report-summary.mjs +88 -0
  39. package/scripts/test-reporter.mjs +651 -0
  40. package/scripts/test-rerun.mjs +136 -0
  41. package/scripts/tmux-bridge +130 -0
  42. package/apps/dashboard/dist/assets/chat-core-Cx4sTxDd.js.br +0 -0
  43. package/apps/dashboard/dist/assets/cli-process-COMRNPqr.js.br +0 -0
  44. package/apps/dashboard/dist/assets/components-BS9fQjE_.js.br +0 -0
  45. package/apps/dashboard/dist/assets/core-utils-CmOkXgzi.js.br +0 -0
  46. package/apps/dashboard/dist/assets/index-CF0aJRtC.css.br +0 -0
  47. package/apps/dashboard/dist/assets/index-DnClJ1ee.js +0 -2
  48. package/apps/dashboard/dist/assets/index-DnClJ1ee.js.br +0 -0
  49. package/apps/dashboard/dist/assets/orchestration-Ca2DLWN-.js.br +0 -0
  50. package/apps/dashboard/dist/assets/setup-wizard-CA0Or47w.js.br +0 -0
  51. package/apps/dashboard/dist/assets/tab-agents-tab-BgpIsjkw.js.br +0 -0
  52. package/apps/dashboard/dist/assets/tab-comms-tab-kguqTIzD.js.br +0 -0
  53. package/apps/dashboard/dist/assets/tab-contacts-tab-DiOyMYth.js.br +0 -0
  54. package/apps/dashboard/dist/assets/tab-engines-tab-BsdZVvU0.js.br +0 -0
  55. package/apps/dashboard/dist/assets/tab-memory-tab-Cu6u13EQ.js.br +0 -0
  56. package/apps/dashboard/dist/assets/tab-models-tab-BLEjmd19.js.br +0 -0
  57. package/apps/dashboard/dist/assets/tab-pm-loop-tab-Bfd449B4.js.br +0 -0
  58. package/apps/dashboard/dist/assets/tab-projects-tab-DhNWnlzt.js.br +0 -0
  59. package/apps/dashboard/dist/assets/tab-prompts-tab-DVkUNaJd.js.br +0 -0
  60. package/apps/dashboard/dist/assets/tab-services-tab-DU_LH3uG.js.br +0 -0
  61. package/apps/dashboard/dist/assets/tab-settings-tab-Bn4nXtDe.js +0 -1
  62. package/apps/dashboard/dist/assets/tab-settings-tab-Bn4nXtDe.js.br +0 -0
  63. package/apps/dashboard/dist/assets/tab-skills-tab-BpY0uZHW.js.br +0 -0
  64. package/apps/dashboard/dist/assets/tab-spending-tab-DEccQHnt.js.br +0 -0
  65. package/apps/dashboard/dist/assets/tab-swarm-chat-tab-BNrd88-r.js.br +0 -0
  66. package/apps/dashboard/dist/assets/tab-swarm-tab-B1AcjL1W.js.br +0 -0
  67. package/apps/dashboard/dist/assets/tab-usage-tab-BIOOnB-Y.js.br +0 -0
  68. package/apps/dashboard/dist/assets/tab-waves-tab-SaJDkb4x.js.br +0 -0
  69. package/apps/dashboard/dist/assets/tab-workflows-tab-B-soSy1k.js.br +0 -0
  70. package/apps/dashboard/dist/index.html.br +0 -0
  71. package/apps/dashboard/dist/index.html.gz +0 -0
  72. package/apps/dashboard/index.html +0 -6529
  73. package/apps/dashboard/package.json +0 -15
  74. package/apps/dashboard/src/app.js +0 -2828
  75. package/apps/dashboard/src/app.js.br +0 -0
  76. package/apps/dashboard/src/app.js.gz +0 -0
  77. package/apps/dashboard/src/chat/chat-actions.js +0 -1847
  78. package/apps/dashboard/src/chat/chat-actions.js.br +0 -0
  79. package/apps/dashboard/src/chat/unified-messages.js +0 -327
  80. package/apps/dashboard/src/chat/unified-messages.js.br +0 -0
  81. package/apps/dashboard/src/cli-process.js +0 -208
  82. package/apps/dashboard/src/cli-process.js.br +0 -0
  83. package/apps/dashboard/src/cli-process.js.gz +0 -0
  84. package/apps/dashboard/src/components/active-tasks-panel.js +0 -175
  85. package/apps/dashboard/src/components/active-tasks-panel.js.br +0 -0
  86. package/apps/dashboard/src/core/api.js +0 -18
  87. package/apps/dashboard/src/core/api.js.br +0 -0
  88. package/apps/dashboard/src/core/dom.js +0 -228
  89. package/apps/dashboard/src/core/dom.js.br +0 -0
  90. package/apps/dashboard/src/core/state.js +0 -91
  91. package/apps/dashboard/src/core/state.js.br +0 -0
  92. package/apps/dashboard/src/core/task-manager.js +0 -134
  93. package/apps/dashboard/src/core/task-manager.js.br +0 -0
  94. package/apps/dashboard/src/orchestration-status.js +0 -127
  95. package/apps/dashboard/src/orchestration-status.js.br +0 -0
  96. package/apps/dashboard/src/setup-wizard.js +0 -562
  97. package/apps/dashboard/src/setup-wizard.js.br +0 -0
  98. package/apps/dashboard/src/styles.css +0 -2085
  99. package/apps/dashboard/src/styles.css.br +0 -0
  100. package/apps/dashboard/src/styles.css.gz +0 -0
  101. package/apps/dashboard/src/tabs/agents-tab.js +0 -2237
  102. package/apps/dashboard/src/tabs/agents-tab.js.br +0 -0
  103. package/apps/dashboard/src/tabs/benchmarks-tab.js +0 -229
  104. package/apps/dashboard/src/tabs/benchmarks-tab.js.br +0 -0
  105. package/apps/dashboard/src/tabs/comms-tab.js +0 -955
  106. package/apps/dashboard/src/tabs/comms-tab.js.br +0 -0
  107. package/apps/dashboard/src/tabs/contacts-tab.js +0 -654
  108. package/apps/dashboard/src/tabs/contacts-tab.js.br +0 -0
  109. package/apps/dashboard/src/tabs/engines-tab.js +0 -175
  110. package/apps/dashboard/src/tabs/engines-tab.js.br +0 -0
  111. package/apps/dashboard/src/tabs/memory-tab.js +0 -182
  112. package/apps/dashboard/src/tabs/memory-tab.js.br +0 -0
  113. package/apps/dashboard/src/tabs/models-tab.js +0 -450
  114. package/apps/dashboard/src/tabs/models-tab.js.br +0 -0
  115. package/apps/dashboard/src/tabs/pm-loop-tab.js +0 -185
  116. package/apps/dashboard/src/tabs/pm-loop-tab.js.br +0 -0
  117. package/apps/dashboard/src/tabs/projects-tab.js +0 -663
  118. package/apps/dashboard/src/tabs/projects-tab.js.br +0 -0
  119. package/apps/dashboard/src/tabs/projects-tab.js.gz +0 -0
  120. package/apps/dashboard/src/tabs/prompts-tab.js +0 -160
  121. package/apps/dashboard/src/tabs/prompts-tab.js.br +0 -0
  122. package/apps/dashboard/src/tabs/services-tab.js +0 -202
  123. package/apps/dashboard/src/tabs/services-tab.js.br +0 -0
  124. package/apps/dashboard/src/tabs/settings-tab.js +0 -861
  125. package/apps/dashboard/src/tabs/settings-tab.js.br +0 -0
  126. package/apps/dashboard/src/tabs/skills-tab.js +0 -284
  127. package/apps/dashboard/src/tabs/skills-tab.js.br +0 -0
  128. package/apps/dashboard/src/tabs/spending-tab.js +0 -173
  129. package/apps/dashboard/src/tabs/spending-tab.js.br +0 -0
  130. package/apps/dashboard/src/tabs/swarm-chat-tab.js +0 -660
  131. package/apps/dashboard/src/tabs/swarm-chat-tab.js.br +0 -0
  132. package/apps/dashboard/src/tabs/swarm-tab.js +0 -538
  133. package/apps/dashboard/src/tabs/swarm-tab.js.br +0 -0
  134. package/apps/dashboard/src/tabs/usage-tab.js +0 -390
  135. package/apps/dashboard/src/tabs/usage-tab.js.br +0 -0
  136. package/apps/dashboard/src/tabs/waves-tab.js +0 -238
  137. package/apps/dashboard/src/tabs/waves-tab.js.br +0 -0
  138. package/apps/dashboard/src/tabs/workflows-tab.js +0 -747
  139. package/apps/dashboard/src/tabs/workflows-tab.js.br +0 -0
  140. package/apps/vibe/.crew/agent-memory/pipeline.json +0 -304
  141. package/apps/vibe/.crew/cost.json +0 -17
  142. package/apps/vibe/.crew/json-parse-metrics.jsonl +0 -27
  143. package/apps/vibe/.crew/pipeline-metrics.jsonl +0 -27
  144. package/apps/vibe/.crew/pipeline-runs/pipeline-0f90c392-2425-4ae5-850c-bd9d17b1d690.jsonl +0 -5
  145. package/apps/vibe/.crew/pipeline-runs/pipeline-1c269dd9-a63f-4fba-af81-5cf08048ef06.jsonl +0 -5
  146. package/apps/vibe/.crew/pipeline-runs/pipeline-288a7765-da24-4a22-89bc-1f3cc9b0562c.jsonl +0 -5
  147. package/apps/vibe/.crew/pipeline-runs/pipeline-2c78fd22-a657-4bd1-bc49-0679fb384409.jsonl +0 -5
  148. package/apps/vibe/.crew/pipeline-runs/pipeline-3da23550-22ed-4904-9a0a-8e79c1f3024c.jsonl +0 -5
  149. package/apps/vibe/.crew/pipeline-runs/pipeline-3e6fe08d-3264-404a-8df3-aab7efef10e7.jsonl +0 -5
  150. package/apps/vibe/.crew/pipeline-runs/pipeline-42eec610-57fe-4e09-9e7e-b315038495c2.jsonl +0 -5
  151. package/apps/vibe/.crew/pipeline-runs/pipeline-4438eb4c-ae13-42b1-90e2-b043d8983be8.jsonl +0 -5
  152. package/apps/vibe/.crew/pipeline-runs/pipeline-4740a9f5-86e7-44b6-a394-de433e291727.jsonl +0 -5
  153. package/apps/vibe/.crew/pipeline-runs/pipeline-49e1da6a-957e-48fd-9220-415019e4f8e2.jsonl +0 -5
  154. package/apps/vibe/.crew/pipeline-runs/pipeline-4c9251db-be68-427b-a3fc-a264f2b5778d.jsonl +0 -5
  155. package/apps/vibe/.crew/pipeline-runs/pipeline-6413fa33-a802-4b57-a8c0-a9056ad67842.jsonl +0 -5
  156. package/apps/vibe/.crew/pipeline-runs/pipeline-65e29a57-664d-4196-8109-017e364f182e.jsonl +0 -5
  157. package/apps/vibe/.crew/pipeline-runs/pipeline-6aa04bc5-9593-4b1f-b58d-3bf2978cb602.jsonl +0 -5
  158. package/apps/vibe/.crew/pipeline-runs/pipeline-6e1cba53-9b70-457e-99e0-59199149dd21.jsonl +0 -5
  159. package/apps/vibe/.crew/pipeline-runs/pipeline-749f41cc-4dac-4204-be64-873a6080a0d2.jsonl +0 -5
  160. package/apps/vibe/.crew/pipeline-runs/pipeline-74d68121-e181-4864-bd9a-c3211341dfaf.jsonl +0 -5
  161. package/apps/vibe/.crew/pipeline-runs/pipeline-8509bc24-142d-4e07-b44a-a50bf99d1103.jsonl +0 -5
  162. package/apps/vibe/.crew/pipeline-runs/pipeline-960339c6-07ca-43ce-9900-f6e1702b39b9.jsonl +0 -5
  163. package/apps/vibe/.crew/pipeline-runs/pipeline-9bef2dd2-6122-42e5-b3d9-19f4d80f9e40.jsonl +0 -5
  164. package/apps/vibe/.crew/pipeline-runs/pipeline-9c6480a9-7031-4146-b241-825b9a2d1de1.jsonl +0 -5
  165. package/apps/vibe/.crew/pipeline-runs/pipeline-9fd42426-8492-4157-9d5f-e1537c060489.jsonl +0 -2
  166. package/apps/vibe/.crew/pipeline-runs/pipeline-ad6d40a3-2f5e-46a9-a345-47caaccc51aa.jsonl +0 -5
  167. package/apps/vibe/.crew/pipeline-runs/pipeline-bc606133-8d5b-4535-8d85-f1a29cdaa981.jsonl +0 -5
  168. package/apps/vibe/.crew/pipeline-runs/pipeline-c1418f4e-b773-4ca1-84a3-216acf36e2f2.jsonl +0 -5
  169. package/apps/vibe/.crew/pipeline-runs/pipeline-c1a13ccd-634a-4d01-a4a7-1177b8a752ff.jsonl +0 -5
  170. package/apps/vibe/.crew/pipeline-runs/pipeline-c7d27b42-249e-4bd4-8f26-6aa998110b8a.jsonl +0 -5
  171. package/apps/vibe/.crew/pipeline-runs/pipeline-cca2e9b9-4a34-4d25-a311-5c793fa7e91e.jsonl +0 -5
  172. package/apps/vibe/.crew/sandbox.json +0 -7
  173. package/apps/vibe/.crew/session.json +0 -330
  174. package/apps/vibe/.crew/training-data.jsonl +0 -0
  175. package/apps/vibe/.github/workflows/studio-quality.yml +0 -37
  176. package/apps/vibe/.studio-data/project-messages/chuck-norris.jsonl +0 -18
  177. package/apps/vibe/.studio-data/project-messages/general.jsonl +0 -81
  178. package/apps/vibe/.studio-data/project-messages/studio-local.jsonl +0 -18
  179. package/apps/vibe/ARCHITECTURE.md +0 -3393
  180. package/apps/vibe/QUICK-REFERENCE.md +0 -211
  181. package/apps/vibe/ROADMAP.md +0 -41
  182. package/apps/vibe/STUDIO-SETUP-COMPLETE.md +0 -35
  183. package/apps/vibe/VISUAL-GUIDE.md +0 -378
  184. package/apps/vibe/capture-demo.mjs +0 -160
  185. package/apps/vibe/capture-full-demo.mjs +0 -255
  186. package/apps/vibe/capture-quickstart.mjs +0 -256
  187. package/apps/vibe/capture-vibe-assets.mjs +0 -71
  188. package/apps/vibe/capture-vibe-video.mjs +0 -260
  189. package/apps/vibe/check-buttons.js +0 -41
  190. package/apps/vibe/diagnose.html +0 -106
  191. package/apps/vibe/fix-buttons.js +0 -103
  192. package/apps/vibe/index.html +0 -3404
  193. package/apps/vibe/package-lock.json +0 -920
  194. package/apps/vibe/scripts/studio-pty-host.py +0 -117
  195. package/apps/vibe/src/main.js +0 -2940
  196. package/apps/vibe/src/register-all-languages.js +0 -98
  197. package/apps/vibe/start-studio.sh +0 -11
  198. package/apps/vibe/test/accessibility-tests.js +0 -77
  199. package/apps/vibe/test/browser-performance-audit.mjs +0 -205
  200. package/apps/vibe/test/performance-tests.js +0 -120
  201. package/apps/vibe/test/security-tests.js +0 -213
  202. package/apps/vibe/tests/e2e.local.mjs +0 -54
  203. package/apps/vibe/tests/server.smoke.mjs +0 -106
  204. package/apps/vibe/update_website.mjs +0 -74
  205. package/apps/vibe/vite.config.js +0 -19
  206. package/lib/crew-lead/chat-handler.mjs.bak +0 -1274
  207. package/lib/engines/rt-envelope.mjs.backup-current +0 -870
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "node:fs";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+
7
+ const jsonMode = process.argv.includes("--json");
8
+ const home = os.homedir();
9
+ const crewDir = path.join(home, ".crewswarm");
10
+ const logsDir = path.join(crewDir, "logs");
11
+
12
+ function exists(file) {
13
+ try {
14
+ return fs.existsSync(file);
15
+ } catch {
16
+ return false;
17
+ }
18
+ }
19
+
20
+ function readJson(file) {
21
+ try {
22
+ return JSON.parse(fs.readFileSync(file, "utf8"));
23
+ } catch {
24
+ return null;
25
+ }
26
+ }
27
+
28
+ const telegramCfg = readJson(path.join(crewDir, "telegram-bridge.json"));
29
+ const whatsappCfg = readJson(path.join(crewDir, "whatsapp-bridge.json"));
30
+
31
+ const payload = {
32
+ telegram: {
33
+ configured: Boolean(telegramCfg?.token),
34
+ allowedChats: Array.isArray(telegramCfg?.allowedChatIds) ? telegramCfg.allowedChatIds.length : 0,
35
+ logFile: path.join(logsDir, "telegram-bridge.jsonl"),
36
+ messagesFile: path.join(logsDir, "telegram-messages.jsonl"),
37
+ logPresent: exists(path.join(logsDir, "telegram-bridge.jsonl")),
38
+ messagesPresent: exists(path.join(logsDir, "telegram-messages.jsonl")),
39
+ },
40
+ whatsapp: {
41
+ configured: exists(path.join(crewDir, "whatsapp-auth", "creds.json")),
42
+ allowedNumbers: Array.isArray(whatsappCfg?.allowedNumbers) ? whatsappCfg.allowedNumbers.length : 0,
43
+ logFile: path.join(logsDir, "whatsapp-bridge.jsonl"),
44
+ messagesFile: path.join(logsDir, "whatsapp-messages.jsonl"),
45
+ logPresent: exists(path.join(logsDir, "whatsapp-bridge.jsonl")),
46
+ messagesPresent: exists(path.join(logsDir, "whatsapp-messages.jsonl")),
47
+ },
48
+ checklist: [
49
+ "1. Start the stack with `npm run restart-all`.",
50
+ "2. Run `node scripts/health-check.mjs` and confirm crew-lead/dashboard are up.",
51
+ "3. For Telegram: run `node --test test/e2e/telegram-roundtrip.test.mjs` with a configured bot token.",
52
+ "4. For WhatsApp: run `node --test test/e2e/whatsapp-roundtrip.test.mjs` after QR auth is established.",
53
+ "5. Send one inbound message and confirm project/history logs update.",
54
+ ],
55
+ };
56
+
57
+ if (jsonMode) {
58
+ console.log(JSON.stringify(payload, null, 2));
59
+ process.exit(0);
60
+ }
61
+
62
+ console.log("CrewSwarm live bridge matrix");
63
+ console.log("");
64
+ console.log("Telegram:");
65
+ console.log(` configured: ${payload.telegram.configured ? "yes" : "no"}`);
66
+ console.log(` allowed chats: ${payload.telegram.allowedChats}`);
67
+ console.log(` log present: ${payload.telegram.logPresent ? "yes" : "no"}`);
68
+ console.log(` messages log present: ${payload.telegram.messagesPresent ? "yes" : "no"}`);
69
+ console.log("");
70
+ console.log("WhatsApp:");
71
+ console.log(` configured: ${payload.whatsapp.configured ? "yes" : "no"}`);
72
+ console.log(` allowed numbers: ${payload.whatsapp.allowedNumbers}`);
73
+ console.log(` log present: ${payload.whatsapp.logPresent ? "yes" : "no"}`);
74
+ console.log(` messages log present: ${payload.whatsapp.messagesPresent ? "yes" : "no"}`);
75
+ console.log("");
76
+ console.log("Checklist:");
77
+ for (const item of payload.checklist) {
78
+ console.log(` ${item}`);
79
+ }
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "node:fs";
4
+ import { execFileSync, spawn } from "node:child_process";
5
+
6
+ const jsonMode = process.argv.includes("--json");
7
+ const smokeMode = process.argv.includes("--smoke");
8
+ const cwd = process.cwd();
9
+ const PROMPT = "Reply with exactly CLI_MATRIX_OK and nothing else.";
10
+ const openCodeModel = process.env.CREWSWARM_OPENCODE_MODEL || "opencode/big-pickle";
11
+
12
+ function hasBin(bin) {
13
+ try {
14
+ if (bin.includes("/") && fs.existsSync(bin)) return true;
15
+ execFileSync("which", [bin], { stdio: "pipe", timeout: 4000 });
16
+ return true;
17
+ } catch {
18
+ return false;
19
+ }
20
+ }
21
+
22
+ function runCli(bin, args, timeoutMs = Number(process.env.CREWSWARM_LIVE_CLI_TIMEOUT_MS || 30000)) {
23
+ return new Promise((resolve) => {
24
+ const child = spawn(bin, args, {
25
+ cwd,
26
+ env: process.env,
27
+ stdio: ["ignore", "pipe", "pipe"],
28
+ });
29
+ let stdout = "";
30
+ let stderr = "";
31
+ let done = false;
32
+ const timer = setTimeout(() => {
33
+ if (!done) {
34
+ done = true;
35
+ child.kill("SIGKILL");
36
+ resolve({ ok: false, error: `timeout after ${timeoutMs}ms`, stdout, stderr });
37
+ }
38
+ }, timeoutMs);
39
+
40
+ child.stdout.on("data", (chunk) => { stdout += chunk.toString(); });
41
+ child.stderr.on("data", (chunk) => { stderr += chunk.toString(); });
42
+ child.on("error", (error) => {
43
+ if (done) return;
44
+ done = true;
45
+ clearTimeout(timer);
46
+ resolve({ ok: false, error: String(error.message || error), stdout, stderr });
47
+ });
48
+ child.on("close", (code) => {
49
+ if (done) return;
50
+ done = true;
51
+ clearTimeout(timer);
52
+ const combined = `${stdout}\n${stderr}`;
53
+ resolve({
54
+ ok: code === 0 && combined.includes("CLI_MATRIX_OK"),
55
+ code,
56
+ stdout,
57
+ stderr,
58
+ });
59
+ });
60
+ });
61
+ }
62
+
63
+ const cursorBin = process.env.CURSOR_CLI_BIN || "agent";
64
+ const clis = [
65
+ {
66
+ id: "claude",
67
+ available: hasBin("claude"),
68
+ command: ["claude", ["-p", "--print", PROMPT]],
69
+ timeoutMs: Number(process.env.CREWSWARM_LIVE_CLAUDE_TIMEOUT_MS || 120000),
70
+ },
71
+ {
72
+ id: "codex",
73
+ available: hasBin("codex"),
74
+ command: ["codex", ["exec", "--sandbox", "read-only", "--json", PROMPT]],
75
+ timeoutMs: Number(process.env.CREWSWARM_LIVE_CODEX_TIMEOUT_MS || 30000),
76
+ },
77
+ {
78
+ id: "cursor",
79
+ available: hasBin(cursorBin),
80
+ command: [
81
+ cursorBin,
82
+ [
83
+ "-p",
84
+ "--force",
85
+ "--trust",
86
+ "--output-format",
87
+ "stream-json",
88
+ PROMPT,
89
+ "--model",
90
+ process.env.CREWSWARM_CURSOR_MODEL || "composer-2-fast",
91
+ "--workspace",
92
+ cwd,
93
+ ],
94
+ ],
95
+ timeoutMs: Number(process.env.CREWSWARM_LIVE_CURSOR_TIMEOUT_MS || 30000),
96
+ },
97
+ {
98
+ id: "gemini",
99
+ available: hasBin("gemini"),
100
+ command: ["gemini", ["-p", PROMPT]],
101
+ timeoutMs: Number(process.env.CREWSWARM_LIVE_GEMINI_TIMEOUT_MS || 120000),
102
+ },
103
+ {
104
+ id: "opencode",
105
+ available: hasBin("opencode"),
106
+ command: ["opencode", ["run", "--model", openCodeModel, PROMPT]],
107
+ timeoutMs: Number(process.env.CREWSWARM_LIVE_OPENCODE_TIMEOUT_MS || 120000),
108
+ },
109
+ {
110
+ id: "crew-cli",
111
+ available: true,
112
+ command: ["node", ["crew-cli/bin/crew.js", "exec", PROMPT]],
113
+ timeoutMs: Number(process.env.CREWSWARM_LIVE_CREWCLI_TIMEOUT_MS || 30000),
114
+ },
115
+ ];
116
+
117
+ const results = [];
118
+ if (smokeMode) {
119
+ for (const cli of clis.filter((item) => item.available)) {
120
+ const [bin, args] = cli.command;
121
+ const started = Date.now();
122
+ const result = await runCli(bin, args, cli.timeoutMs);
123
+ results.push({
124
+ cli: cli.id,
125
+ durationMs: Date.now() - started,
126
+ ...result,
127
+ });
128
+ }
129
+ }
130
+
131
+ const payload = {
132
+ cwd,
133
+ smokeMode,
134
+ clis: clis.map(({ id, available, command }) => ({ id, available, command: [command[0], ...command[1]] })),
135
+ results,
136
+ checklist: [
137
+ "Run `node scripts/live-cli-matrix.mjs --smoke` to execute one tiny one-shot through each installed CLI.",
138
+ "Expect some failures if auth/session state or credits are missing for a given lane.",
139
+ "Use this as a release-time trust check, not an always-on CI gate.",
140
+ ],
141
+ };
142
+
143
+ if (jsonMode) {
144
+ console.log(JSON.stringify(payload, null, 2));
145
+ process.exit(0);
146
+ }
147
+
148
+ console.log("CrewSwarm live CLI matrix");
149
+ console.log("");
150
+ for (const cli of payload.clis) {
151
+ console.log(`${cli.id.padEnd(10)} ${cli.available ? "available" : "missing"}`);
152
+ }
153
+ if (smokeMode) {
154
+ console.log("");
155
+ console.log("Smoke results:");
156
+ for (const result of results) {
157
+ const status = result.ok ? "PASS" : "FAIL";
158
+ const detail = result.ok
159
+ ? (result.stdout || result.stderr).trim().slice(0, 120)
160
+ : (result.error || result.stderr || result.stdout || "").trim().slice(0, 160);
161
+ console.log(`${status.padEnd(5)} ${result.cli.padEnd(10)} ${detail}`);
162
+ }
163
+ } else {
164
+ console.log("");
165
+ console.log("Run with --smoke to execute one tiny real one-shot through each installed CLI.");
166
+ }
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "node:fs";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+
7
+ const jsonMode = process.argv.includes("--json");
8
+ const repoRoot = process.cwd();
9
+ const appPath = path.join(os.homedir(), "Applications", "crewchat.app");
10
+ const buildScript = path.join(repoRoot, "build-crewchat.sh");
11
+ const sourcePath = path.join(repoRoot, "apps", "crewchat", "CrewChat.swift");
12
+
13
+ const payload = {
14
+ buildScriptPresent: fs.existsSync(buildScript),
15
+ sourcePresent: fs.existsSync(sourcePath),
16
+ installedAppPresent: fs.existsSync(appPath),
17
+ appPath,
18
+ checklist: [
19
+ "1. Build: ./build-crewchat.sh",
20
+ "2. Launch: open -a crewchat.app",
21
+ "3. Switch between crew-lead, CLI, and agent modes.",
22
+ "4. Send one text message, one image, and one voice note.",
23
+ "5. Confirm per-project and per-mode history isolation.",
24
+ ],
25
+ };
26
+
27
+ if (jsonMode) {
28
+ console.log(JSON.stringify(payload, null, 2));
29
+ process.exit(0);
30
+ }
31
+
32
+ console.log("crewchat live verification");
33
+ console.log("");
34
+ console.log(`Build script present: ${payload.buildScriptPresent ? "yes" : "no"}`);
35
+ console.log(`Source present: ${payload.sourcePresent ? "yes" : "no"}`);
36
+ console.log(`Installed app present: ${payload.installedAppPresent ? "yes" : "no"}`);
37
+ console.log(`App path: ${payload.appPath}`);
38
+ console.log("");
39
+ console.log("Checklist:");
40
+ for (const item of payload.checklist) {
41
+ console.log(` ${item}`);
42
+ }
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "node:fs";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+
7
+ const configPath = path.join(os.homedir(), ".crewswarm", "crewswarm.json");
8
+ const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
9
+ const agents = Array.isArray(config.agents) ? config.agents : config.agents?.list || [];
10
+
11
+ function detectRoute(agent) {
12
+ if (agent.useCursorCli) return "cursor";
13
+ if (agent.useClaudeCode) return "claude-code";
14
+ if (agent.useCodex) return "codex";
15
+ if (agent.useGeminiCli) return "gemini-cli";
16
+ if (agent.useCrewCLI) return "crew-cli";
17
+ if (agent.useOpenCode) return "opencode";
18
+ if (agent.useDockerSandbox) return "docker-sandbox";
19
+ return "direct";
20
+ }
21
+
22
+ function modelForRoute(agent, route) {
23
+ if (route === "cursor") return agent.cursorCliModel || "(auto)";
24
+ if (route === "claude-code") return agent.claudeCodeModel || "(auto)";
25
+ if (route === "codex") return agent.codexModel || "(auto)";
26
+ if (route === "gemini-cli") return agent.geminiCliModel || "(auto)";
27
+ if (route === "crew-cli") return agent.crewCliModel || "(default)";
28
+ if (route === "opencode") return agent.opencodeModel || "(default)";
29
+ return agent.model || "(none)";
30
+ }
31
+
32
+ const rows = agents.map((agent) => {
33
+ const route = detectRoute(agent);
34
+ return {
35
+ id: agent.id,
36
+ route,
37
+ model: modelForRoute(agent, route),
38
+ fallback: agent.fallbackModel || agent.opencodeFallbackModel || "",
39
+ };
40
+ });
41
+
42
+ console.log("CrewSwarm live engine matrix");
43
+ console.log("");
44
+ for (const row of rows) {
45
+ console.log(`${row.id.padEnd(22)} ${row.route.padEnd(15)} ${row.model}${row.fallback ? ` fallback=${row.fallback}` : ""}`);
46
+ }
47
+
48
+ console.log("");
49
+ console.log("Next step:");
50
+ console.log("Run a real task through each important route and confirm the observed runtime/model in logs or UI.");
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "node:fs";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+
7
+ const jsonMode = process.argv.includes("--json");
8
+ const configPath = path.join(os.homedir(), ".crewswarm", "crewswarm.json");
9
+
10
+ function readConfig() {
11
+ try {
12
+ return JSON.parse(fs.readFileSync(configPath, "utf8"));
13
+ } catch {
14
+ return {};
15
+ }
16
+ }
17
+
18
+ const cfg = readConfig();
19
+ const providers = cfg.providers || {};
20
+ const agents = Array.isArray(cfg.agents) ? cfg.agents : cfg.agents?.list || [];
21
+
22
+ const activeProviders = Object.entries(providers)
23
+ .filter(([, value]) => value?.apiKey && String(value.apiKey).trim())
24
+ .map(([id, value]) => ({
25
+ id,
26
+ hasBaseUrl: Boolean(value.baseUrl),
27
+ }));
28
+
29
+ const interestingAgents = agents
30
+ .filter((agent) => {
31
+ return (
32
+ agent.id === "crew-main" ||
33
+ agent.id === "crew-coder" ||
34
+ agent.id === "crew-qa" ||
35
+ agent.id === "crew-pm" ||
36
+ agent.useClaudeCode ||
37
+ agent.useCodex ||
38
+ agent.useGeminiCli ||
39
+ agent.useCrewCLI ||
40
+ agent.useCursorCli
41
+ );
42
+ })
43
+ .map((agent) => ({
44
+ id: agent.id,
45
+ primary: agent.model || "(none)",
46
+ fallback: agent.fallbackModel || agent.opencodeFallbackModel || "",
47
+ route:
48
+ agent.useClaudeCode ? "claude-code" :
49
+ agent.useCodex ? "codex" :
50
+ agent.useGeminiCli ? "gemini-cli" :
51
+ agent.useCrewCLI ? "crew-cli" :
52
+ agent.useCursorCli ? "cursor" :
53
+ agent.useOpenCode ? "opencode" :
54
+ "direct",
55
+ }));
56
+
57
+ const payload = {
58
+ configPath,
59
+ configuredProviders: activeProviders,
60
+ agents: interestingAgents,
61
+ checklist: [
62
+ "1. Run `npm run restart-all` and confirm `node scripts/health-check.mjs` passes.",
63
+ "2. For each important route, trigger one real task and confirm the observed runtime/model in logs or UI.",
64
+ "3. Intentionally disable or exhaust one primary provider, then confirm fallback activates.",
65
+ "4. Record which routes fail closed vs. fail over successfully.",
66
+ ],
67
+ sampleTasks: [
68
+ 'crew-main: "say: PROVIDER_FAILOVER_OK"',
69
+ 'crew-coder: "Create test-output/provider-fallback.txt with one line: PROVIDER_FALLBACK_OK"',
70
+ 'crew-qa: "Summarize which provider/model you are using in one line"',
71
+ ],
72
+ };
73
+
74
+ if (jsonMode) {
75
+ console.log(JSON.stringify(payload, null, 2));
76
+ process.exit(0);
77
+ }
78
+
79
+ console.log("CrewSwarm live provider/failover matrix");
80
+ console.log("");
81
+ console.log(`Config: ${configPath}`);
82
+ console.log("");
83
+ console.log("Configured providers:");
84
+ if (!activeProviders.length) {
85
+ console.log(" (none)");
86
+ } else {
87
+ for (const provider of activeProviders) {
88
+ console.log(` - ${provider.id}${provider.hasBaseUrl ? " (custom baseUrl)" : ""}`);
89
+ }
90
+ }
91
+ console.log("");
92
+ console.log("Interesting agents/routes:");
93
+ for (const agent of interestingAgents) {
94
+ console.log(
95
+ ` - ${agent.id}: route=${agent.route} primary=${agent.primary}${agent.fallback ? ` fallback=${agent.fallback}` : ""}`,
96
+ );
97
+ }
98
+ console.log("");
99
+ console.log("Checklist:");
100
+ for (const item of payload.checklist) {
101
+ console.log(` ${item}`);
102
+ }
103
+ console.log("");
104
+ console.log("Sample tasks:");
105
+ for (const item of payload.sampleTasks) {
106
+ console.log(` - ${item}`);
107
+ }
@@ -0,0 +1,228 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "node:fs";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+ import { _callLLMOnce } from "../lib/crew-lead/llm-caller.mjs";
7
+
8
+ const jsonMode = process.argv.includes("--json");
9
+ const smokeMode = process.argv.includes("--smoke");
10
+ const configPath = path.join(os.homedir(), ".crewswarm", "crewswarm.json");
11
+ const SMOKE_PROMPT = "Reply with exactly PROVIDER_MATRIX_OK and nothing else.";
12
+
13
+ function readConfig() {
14
+ try {
15
+ return JSON.parse(fs.readFileSync(configPath, "utf8"));
16
+ } catch {
17
+ return {};
18
+ }
19
+ }
20
+
21
+ function modelFromConfig(providerId, providerCfg, agents) {
22
+ const directModel = String(
23
+ providerCfg?.defaultModel || providerCfg?.model || providerCfg?.chatModel || "",
24
+ ).trim();
25
+ if (directModel) return directModel;
26
+
27
+ const listed = Array.isArray(providerCfg?.models)
28
+ ? providerCfg.models.map((entry) => String(entry?.id || "").trim()).filter(Boolean)
29
+ : [];
30
+
31
+ const preferredDefaults = {
32
+ anthropic: "claude-3-haiku-20240307",
33
+ nvidia: "meta/llama-3.1-8b-instruct",
34
+ ollama: "qwen3-coder:480b-cloud",
35
+ "openai-local": "gpt-5.1",
36
+ opencode: "gpt-5.1",
37
+ };
38
+ const preferred = preferredDefaults[providerId];
39
+ if (preferred && listed.includes(preferred)) return preferred;
40
+
41
+ const prefixMap = {
42
+ google: ["google/", "gemini"],
43
+ anthropic: ["anthropic/", "claude"],
44
+ openai: ["openai/", "gpt-"],
45
+ xai: ["xai/", "grok"],
46
+ deepseek: ["deepseek/", "deepseek"],
47
+ groq: ["groq/", "llama", "mixtral", "qwen", "kimi", "compound"],
48
+ mistral: ["mistral/", "mistral"],
49
+ perplexity: ["perplexity/", "sonar"],
50
+ nvidia: ["nvidia/", "meta/", "google/", "deepseek-ai/"],
51
+ cerebras: ["cerebras/"],
52
+ openrouter: ["openrouter/"],
53
+ fireworks: ["fireworks/", "accounts/fireworks/"],
54
+ opencode: [],
55
+ "openai-local": ["openai-local/"],
56
+ };
57
+ const prefixes = prefixMap[providerId] || [];
58
+ const found = agents.find((agent) => {
59
+ const model = String(agent?.model || "").toLowerCase();
60
+ return prefixes.some((prefix) => model.startsWith(prefix) || model.includes(prefix));
61
+ });
62
+ if (found?.model) return String(found.model);
63
+
64
+ const firstListed = listed[0];
65
+ if (firstListed) return String(firstListed);
66
+
67
+ const hardcoded = {
68
+ google: "gemini-2.5-flash",
69
+ anthropic: "claude-3-haiku-20240307",
70
+ openai: "gpt-5.1",
71
+ xai: "grok-4.1-fast",
72
+ deepseek: "deepseek-chat",
73
+ groq: "llama-3.1-8b-instant",
74
+ mistral: "mistral-small-latest",
75
+ perplexity: "sonar",
76
+ nvidia: "meta/llama-3.1-8b-instruct",
77
+ cerebras: "llama-3.3-70b",
78
+ openrouter: "meta-llama/llama-3.1-8b-instruct:free",
79
+ fireworks: "accounts/fireworks/models/gpt-oss-20b",
80
+ opencode: "gpt-5.1",
81
+ ollama: "qwen3-coder:480b-cloud",
82
+ "openai-local": "gpt-5.1",
83
+ };
84
+ return hardcoded[providerId] || "(unknown)";
85
+ }
86
+
87
+ function normalizeModel(providerId, modelId, providerCfg) {
88
+ const raw = String(modelId || "").trim();
89
+ if (!raw) return raw;
90
+
91
+ const prefixStrips = {
92
+ google: [/^google\/models\//i, /^google\//i],
93
+ anthropic: [/^anthropic\//i],
94
+ openai: [/^openai\//i],
95
+ xai: [/^xai\//i],
96
+ deepseek: [/^deepseek\//i],
97
+ perplexity: [/^perplexity\//i],
98
+ openrouter: [/^openrouter\//i],
99
+ fireworks: [/^fireworks\//i],
100
+ };
101
+
102
+ let normalized = raw;
103
+ for (const pattern of prefixStrips[providerId] || []) {
104
+ normalized = normalized.replace(pattern, "");
105
+ }
106
+
107
+ if (providerId === "google" && normalized.startsWith("models/")) {
108
+ normalized = normalized.replace(/^models\//i, "");
109
+ }
110
+
111
+ const listed = Array.isArray(providerCfg?.models)
112
+ ? providerCfg.models.map((entry) => String(entry?.id || "").trim()).filter(Boolean)
113
+ : [];
114
+ if (listed.includes(normalized)) return normalized;
115
+ if (listed.includes(raw)) return raw;
116
+
117
+ if (
118
+ providerId === "nvidia" &&
119
+ listed.length > 0 &&
120
+ (normalized.includes("gemini") || normalized.includes("grok") || normalized.includes("claude"))
121
+ ) {
122
+ return listed[0];
123
+ }
124
+
125
+ return normalized;
126
+ }
127
+
128
+ function mapProviderKey(providerId) {
129
+ if (providerId === "google") return "google";
130
+ if (providerId === "xai") return "xai";
131
+ return providerId;
132
+ }
133
+
134
+ async function smokeProvider(providerId, providerCfg, modelId) {
135
+ const messages = [{ role: "user", content: SMOKE_PROMPT }];
136
+ const started = Date.now();
137
+ try {
138
+ const timeoutMs =
139
+ providerId === "ollama"
140
+ ? Number(process.env.CREWSWARM_LIVE_OLLAMA_TIMEOUT_MS || 90000)
141
+ : providerId === "openai-local"
142
+ ? Number(process.env.CREWSWARM_LIVE_OPENAI_LOCAL_TIMEOUT_MS || 45000)
143
+ : Number(process.env.CREWSWARM_LIVE_PROVIDER_TIMEOUT_MS || 20000);
144
+ const reply = await _callLLMOnce(
145
+ providerCfg.baseUrl,
146
+ providerCfg.apiKey,
147
+ modelId,
148
+ mapProviderKey(providerId),
149
+ messages,
150
+ { stream: false, timeoutMs },
151
+ );
152
+ const text = String(reply || "").trim();
153
+ return {
154
+ ok: text.includes("PROVIDER_MATRIX_OK"),
155
+ reply: text.slice(0, 120),
156
+ durationMs: Date.now() - started,
157
+ };
158
+ } catch (error) {
159
+ return {
160
+ ok: false,
161
+ error: String(error?.message || error),
162
+ durationMs: Date.now() - started,
163
+ };
164
+ }
165
+ }
166
+
167
+ const cfg = readConfig();
168
+ const providers = cfg.providers || {};
169
+ const agents = Array.isArray(cfg.agents) ? cfg.agents : cfg.agents?.list || [];
170
+
171
+ const configuredProviders = Object.entries(providers)
172
+ .filter(([, value]) => value?.apiKey && value?.baseUrl)
173
+ .map(([id, value]) => ({
174
+ id,
175
+ baseUrl: value.baseUrl,
176
+ model: normalizeModel(id, modelFromConfig(id, value, agents), value),
177
+ listedModels: Array.isArray(value.models) ? value.models.length : 0,
178
+ }));
179
+
180
+ const results = [];
181
+ if (smokeMode) {
182
+ for (const provider of configuredProviders) {
183
+ const providerCfg = providers[provider.id];
184
+ results.push({
185
+ provider: provider.id,
186
+ model: provider.model,
187
+ ...(await smokeProvider(provider.id, providerCfg, provider.model)),
188
+ });
189
+ }
190
+ }
191
+
192
+ const payload = {
193
+ configPath,
194
+ smokeMode,
195
+ providers: configuredProviders,
196
+ results,
197
+ checklist: [
198
+ "Use `node scripts/live-provider-matrix.mjs --smoke` to run one tiny real call per configured provider.",
199
+ "Use `node scripts/live-provider-failover-matrix.mjs` to inspect route/fallback expectations.",
200
+ "Treat failures as wiring, auth, quota, or model-selection issues to investigate before release.",
201
+ ],
202
+ };
203
+
204
+ if (jsonMode) {
205
+ console.log(JSON.stringify(payload, null, 2));
206
+ process.exit(0);
207
+ }
208
+
209
+ console.log("CrewSwarm live provider matrix");
210
+ console.log("");
211
+ for (const provider of configuredProviders) {
212
+ console.log(
213
+ `${provider.id.padEnd(14)} model=${provider.model}${provider.listedModels ? ` listedModels=${provider.listedModels}` : ""}`,
214
+ );
215
+ }
216
+
217
+ if (smokeMode) {
218
+ console.log("");
219
+ console.log("Smoke results:");
220
+ for (const result of results) {
221
+ const status = result.ok ? "PASS" : "FAIL";
222
+ const detail = result.ok ? result.reply : result.error;
223
+ console.log(`${status.padEnd(5)} ${result.provider.padEnd(14)} ${result.model} ${detail}`);
224
+ }
225
+ } else {
226
+ console.log("");
227
+ console.log("Run with --smoke to send one tiny real request through each configured provider.");
228
+ }
@@ -241,13 +241,13 @@ else
241
241
  SVC_STATUS["mcp-server"]="up"
242
242
  fi
243
243
 
244
- # ── 8. Vibe Studio + file watcher (ports 3333, 3334) ────────────────────────
244
+ # ── 8. Vibe + file watcher (ports 3333, 3334) ───────────────────────────────
245
245
  if [[ "$START_STUDIO" -eq 1 ]]; then
246
246
  echo ""
247
- echo "Starting Vibe (Studio) + file watcher (ports 3333, 3334)..."
247
+ echo "Starting Vibe + file watcher (ports 3333, 3334)..."
248
248
  if [[ ! -d "$REPO_DIR/apps/vibe/dist" ]]; then
249
- echo " Building Studio (first run)..."
250
- (cd "$REPO_DIR" && npm run studio:build) >/dev/null 2>&1 || true
249
+ echo " Building Vibe (first run)..."
250
+ (cd "$REPO_DIR" && npm run vibe:build) >/dev/null 2>&1 || true
251
251
  fi
252
252
  sleep 1
253
253
  nohup "$NODE" "$REPO_DIR/apps/vibe/server.mjs" >> /tmp/studio.log 2>&1 &