crewswarm 0.9.1 → 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 (210) 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 +48 -5
  12. package/lib/bridges/gateway-ws.mjs +4 -0
  13. package/lib/bridges/tmux-bridge.mjs +200 -0
  14. package/lib/cli-process-tracker.mjs +2 -1
  15. package/lib/crew-lead/chat-handler.mjs +34 -0
  16. package/lib/crew-lead/http-server.mjs +340 -14
  17. package/lib/crew-lead/llm-caller.mjs +24 -8
  18. package/lib/crew-lead/prompts.mjs +7 -0
  19. package/lib/crew-lead/wave-dispatcher.mjs +53 -3
  20. package/lib/crew-lead/ws-router.mjs +219 -27
  21. package/lib/engines/engine-registry.mjs +9 -0
  22. package/lib/engines/rt-envelope.mjs +1 -0
  23. package/lib/engines/runners.mjs +26 -2
  24. package/lib/runtime/config.mjs +7 -0
  25. package/lib/runtime/paths.mjs +12 -8
  26. package/lib/sessions/session-manager.mjs +287 -0
  27. package/package.json +35 -15
  28. package/scripts/capture-build-flow.mjs +118 -0
  29. package/scripts/coverage-report.mjs +209 -0
  30. package/scripts/coverage-summary.mjs +47 -0
  31. package/scripts/dashboard-validation.mjs +74 -0
  32. package/scripts/dashboard.mjs +560 -70
  33. package/scripts/live-bridge-matrix.mjs +79 -0
  34. package/scripts/live-cli-matrix.mjs +166 -0
  35. package/scripts/live-crewchat-check.mjs +42 -0
  36. package/scripts/live-engine-matrix.mjs +50 -0
  37. package/scripts/live-provider-failover-matrix.mjs +107 -0
  38. package/scripts/live-provider-matrix.mjs +228 -0
  39. package/scripts/restart-all-from-repo.sh +4 -4
  40. package/scripts/smoke-dispatch.mjs +4 -1
  41. package/scripts/test-blast-radius.mjs +204 -0
  42. package/scripts/test-report-summary.mjs +88 -0
  43. package/scripts/test-reporter.mjs +651 -0
  44. package/scripts/test-rerun.mjs +136 -0
  45. package/scripts/tmux-bridge +130 -0
  46. package/apps/dashboard/dist/assets/chat-core-Cx4sTxDd.js.br +0 -0
  47. package/apps/dashboard/dist/assets/cli-process-COMRNPqr.js.br +0 -0
  48. package/apps/dashboard/dist/assets/components-BS9fQjE_.js.br +0 -0
  49. package/apps/dashboard/dist/assets/core-utils-CmOkXgzi.js.br +0 -0
  50. package/apps/dashboard/dist/assets/index-CF0aJRtC.css.br +0 -0
  51. package/apps/dashboard/dist/assets/index-DnClJ1ee.js +0 -2
  52. package/apps/dashboard/dist/assets/index-DnClJ1ee.js.br +0 -0
  53. package/apps/dashboard/dist/assets/orchestration-Ca2DLWN-.js.br +0 -0
  54. package/apps/dashboard/dist/assets/setup-wizard-CA0Or47w.js.br +0 -0
  55. package/apps/dashboard/dist/assets/tab-agents-tab-BgpIsjkw.js.br +0 -0
  56. package/apps/dashboard/dist/assets/tab-comms-tab-kguqTIzD.js.br +0 -0
  57. package/apps/dashboard/dist/assets/tab-contacts-tab-DiOyMYth.js.br +0 -0
  58. package/apps/dashboard/dist/assets/tab-engines-tab-BsdZVvU0.js.br +0 -0
  59. package/apps/dashboard/dist/assets/tab-memory-tab-Cu6u13EQ.js.br +0 -0
  60. package/apps/dashboard/dist/assets/tab-models-tab-BLEjmd19.js.br +0 -0
  61. package/apps/dashboard/dist/assets/tab-pm-loop-tab-Bfd449B4.js.br +0 -0
  62. package/apps/dashboard/dist/assets/tab-projects-tab-DhNWnlzt.js.br +0 -0
  63. package/apps/dashboard/dist/assets/tab-prompts-tab-DVkUNaJd.js.br +0 -0
  64. package/apps/dashboard/dist/assets/tab-services-tab-DU_LH3uG.js.br +0 -0
  65. package/apps/dashboard/dist/assets/tab-settings-tab-Bn4nXtDe.js +0 -1
  66. package/apps/dashboard/dist/assets/tab-settings-tab-Bn4nXtDe.js.br +0 -0
  67. package/apps/dashboard/dist/assets/tab-skills-tab-BpY0uZHW.js.br +0 -0
  68. package/apps/dashboard/dist/assets/tab-spending-tab-DEccQHnt.js.br +0 -0
  69. package/apps/dashboard/dist/assets/tab-swarm-chat-tab-BNrd88-r.js.br +0 -0
  70. package/apps/dashboard/dist/assets/tab-swarm-tab-B1AcjL1W.js.br +0 -0
  71. package/apps/dashboard/dist/assets/tab-usage-tab-BIOOnB-Y.js.br +0 -0
  72. package/apps/dashboard/dist/assets/tab-waves-tab-SaJDkb4x.js.br +0 -0
  73. package/apps/dashboard/dist/assets/tab-workflows-tab-B-soSy1k.js.br +0 -0
  74. package/apps/dashboard/dist/index.html.br +0 -0
  75. package/apps/dashboard/index.html +0 -6459
  76. package/apps/dashboard/package.json +0 -15
  77. package/apps/dashboard/src/app.js +0 -2823
  78. package/apps/dashboard/src/app.js.br +0 -0
  79. package/apps/dashboard/src/app.js.gz +0 -0
  80. package/apps/dashboard/src/chat/chat-actions.js +0 -1847
  81. package/apps/dashboard/src/chat/chat-actions.js.br +0 -0
  82. package/apps/dashboard/src/chat/unified-messages.js +0 -327
  83. package/apps/dashboard/src/chat/unified-messages.js.br +0 -0
  84. package/apps/dashboard/src/cli-process.js +0 -208
  85. package/apps/dashboard/src/cli-process.js.br +0 -0
  86. package/apps/dashboard/src/cli-process.js.gz +0 -0
  87. package/apps/dashboard/src/components/active-tasks-panel.js +0 -175
  88. package/apps/dashboard/src/components/active-tasks-panel.js.br +0 -0
  89. package/apps/dashboard/src/core/api.js +0 -18
  90. package/apps/dashboard/src/core/api.js.br +0 -0
  91. package/apps/dashboard/src/core/dom.js +0 -228
  92. package/apps/dashboard/src/core/dom.js.br +0 -0
  93. package/apps/dashboard/src/core/state.js +0 -91
  94. package/apps/dashboard/src/core/state.js.br +0 -0
  95. package/apps/dashboard/src/core/task-manager.js +0 -134
  96. package/apps/dashboard/src/core/task-manager.js.br +0 -0
  97. package/apps/dashboard/src/orchestration-status.js +0 -127
  98. package/apps/dashboard/src/orchestration-status.js.br +0 -0
  99. package/apps/dashboard/src/setup-wizard.js +0 -562
  100. package/apps/dashboard/src/setup-wizard.js.br +0 -0
  101. package/apps/dashboard/src/styles.css +0 -2085
  102. package/apps/dashboard/src/styles.css.br +0 -0
  103. package/apps/dashboard/src/styles.css.gz +0 -0
  104. package/apps/dashboard/src/tabs/agents-tab.js +0 -2237
  105. package/apps/dashboard/src/tabs/agents-tab.js.br +0 -0
  106. package/apps/dashboard/src/tabs/benchmarks-tab.js +0 -229
  107. package/apps/dashboard/src/tabs/benchmarks-tab.js.br +0 -0
  108. package/apps/dashboard/src/tabs/comms-tab.js +0 -955
  109. package/apps/dashboard/src/tabs/comms-tab.js.br +0 -0
  110. package/apps/dashboard/src/tabs/contacts-tab.js +0 -654
  111. package/apps/dashboard/src/tabs/contacts-tab.js.br +0 -0
  112. package/apps/dashboard/src/tabs/engines-tab.js +0 -175
  113. package/apps/dashboard/src/tabs/engines-tab.js.br +0 -0
  114. package/apps/dashboard/src/tabs/memory-tab.js +0 -182
  115. package/apps/dashboard/src/tabs/memory-tab.js.br +0 -0
  116. package/apps/dashboard/src/tabs/models-tab.js +0 -450
  117. package/apps/dashboard/src/tabs/models-tab.js.br +0 -0
  118. package/apps/dashboard/src/tabs/pm-loop-tab.js +0 -185
  119. package/apps/dashboard/src/tabs/pm-loop-tab.js.br +0 -0
  120. package/apps/dashboard/src/tabs/projects-tab.js +0 -663
  121. package/apps/dashboard/src/tabs/projects-tab.js.br +0 -0
  122. package/apps/dashboard/src/tabs/projects-tab.js.gz +0 -0
  123. package/apps/dashboard/src/tabs/prompts-tab.js +0 -160
  124. package/apps/dashboard/src/tabs/prompts-tab.js.br +0 -0
  125. package/apps/dashboard/src/tabs/services-tab.js +0 -202
  126. package/apps/dashboard/src/tabs/services-tab.js.br +0 -0
  127. package/apps/dashboard/src/tabs/settings-tab.js +0 -803
  128. package/apps/dashboard/src/tabs/settings-tab.js.br +0 -0
  129. package/apps/dashboard/src/tabs/skills-tab.js +0 -284
  130. package/apps/dashboard/src/tabs/skills-tab.js.br +0 -0
  131. package/apps/dashboard/src/tabs/spending-tab.js +0 -173
  132. package/apps/dashboard/src/tabs/spending-tab.js.br +0 -0
  133. package/apps/dashboard/src/tabs/swarm-chat-tab.js +0 -660
  134. package/apps/dashboard/src/tabs/swarm-chat-tab.js.br +0 -0
  135. package/apps/dashboard/src/tabs/swarm-tab.js +0 -538
  136. package/apps/dashboard/src/tabs/swarm-tab.js.br +0 -0
  137. package/apps/dashboard/src/tabs/usage-tab.js +0 -390
  138. package/apps/dashboard/src/tabs/usage-tab.js.br +0 -0
  139. package/apps/dashboard/src/tabs/waves-tab.js +0 -238
  140. package/apps/dashboard/src/tabs/waves-tab.js.br +0 -0
  141. package/apps/dashboard/src/tabs/workflows-tab.js +0 -747
  142. package/apps/dashboard/src/tabs/workflows-tab.js.br +0 -0
  143. package/apps/vibe/.crew/agent-memory/pipeline.json +0 -304
  144. package/apps/vibe/.crew/cost.json +0 -17
  145. package/apps/vibe/.crew/json-parse-metrics.jsonl +0 -27
  146. package/apps/vibe/.crew/pipeline-metrics.jsonl +0 -27
  147. package/apps/vibe/.crew/pipeline-runs/pipeline-0f90c392-2425-4ae5-850c-bd9d17b1d690.jsonl +0 -5
  148. package/apps/vibe/.crew/pipeline-runs/pipeline-1c269dd9-a63f-4fba-af81-5cf08048ef06.jsonl +0 -5
  149. package/apps/vibe/.crew/pipeline-runs/pipeline-288a7765-da24-4a22-89bc-1f3cc9b0562c.jsonl +0 -5
  150. package/apps/vibe/.crew/pipeline-runs/pipeline-2c78fd22-a657-4bd1-bc49-0679fb384409.jsonl +0 -5
  151. package/apps/vibe/.crew/pipeline-runs/pipeline-3da23550-22ed-4904-9a0a-8e79c1f3024c.jsonl +0 -5
  152. package/apps/vibe/.crew/pipeline-runs/pipeline-3e6fe08d-3264-404a-8df3-aab7efef10e7.jsonl +0 -5
  153. package/apps/vibe/.crew/pipeline-runs/pipeline-42eec610-57fe-4e09-9e7e-b315038495c2.jsonl +0 -5
  154. package/apps/vibe/.crew/pipeline-runs/pipeline-4438eb4c-ae13-42b1-90e2-b043d8983be8.jsonl +0 -5
  155. package/apps/vibe/.crew/pipeline-runs/pipeline-4740a9f5-86e7-44b6-a394-de433e291727.jsonl +0 -5
  156. package/apps/vibe/.crew/pipeline-runs/pipeline-49e1da6a-957e-48fd-9220-415019e4f8e2.jsonl +0 -5
  157. package/apps/vibe/.crew/pipeline-runs/pipeline-4c9251db-be68-427b-a3fc-a264f2b5778d.jsonl +0 -5
  158. package/apps/vibe/.crew/pipeline-runs/pipeline-6413fa33-a802-4b57-a8c0-a9056ad67842.jsonl +0 -5
  159. package/apps/vibe/.crew/pipeline-runs/pipeline-65e29a57-664d-4196-8109-017e364f182e.jsonl +0 -5
  160. package/apps/vibe/.crew/pipeline-runs/pipeline-6aa04bc5-9593-4b1f-b58d-3bf2978cb602.jsonl +0 -5
  161. package/apps/vibe/.crew/pipeline-runs/pipeline-6e1cba53-9b70-457e-99e0-59199149dd21.jsonl +0 -5
  162. package/apps/vibe/.crew/pipeline-runs/pipeline-749f41cc-4dac-4204-be64-873a6080a0d2.jsonl +0 -5
  163. package/apps/vibe/.crew/pipeline-runs/pipeline-74d68121-e181-4864-bd9a-c3211341dfaf.jsonl +0 -5
  164. package/apps/vibe/.crew/pipeline-runs/pipeline-8509bc24-142d-4e07-b44a-a50bf99d1103.jsonl +0 -5
  165. package/apps/vibe/.crew/pipeline-runs/pipeline-960339c6-07ca-43ce-9900-f6e1702b39b9.jsonl +0 -5
  166. package/apps/vibe/.crew/pipeline-runs/pipeline-9bef2dd2-6122-42e5-b3d9-19f4d80f9e40.jsonl +0 -5
  167. package/apps/vibe/.crew/pipeline-runs/pipeline-9c6480a9-7031-4146-b241-825b9a2d1de1.jsonl +0 -5
  168. package/apps/vibe/.crew/pipeline-runs/pipeline-9fd42426-8492-4157-9d5f-e1537c060489.jsonl +0 -2
  169. package/apps/vibe/.crew/pipeline-runs/pipeline-ad6d40a3-2f5e-46a9-a345-47caaccc51aa.jsonl +0 -5
  170. package/apps/vibe/.crew/pipeline-runs/pipeline-bc606133-8d5b-4535-8d85-f1a29cdaa981.jsonl +0 -5
  171. package/apps/vibe/.crew/pipeline-runs/pipeline-c1418f4e-b773-4ca1-84a3-216acf36e2f2.jsonl +0 -5
  172. package/apps/vibe/.crew/pipeline-runs/pipeline-c1a13ccd-634a-4d01-a4a7-1177b8a752ff.jsonl +0 -5
  173. package/apps/vibe/.crew/pipeline-runs/pipeline-c7d27b42-249e-4bd4-8f26-6aa998110b8a.jsonl +0 -5
  174. package/apps/vibe/.crew/pipeline-runs/pipeline-cca2e9b9-4a34-4d25-a311-5c793fa7e91e.jsonl +0 -5
  175. package/apps/vibe/.crew/sandbox.json +0 -7
  176. package/apps/vibe/.crew/session.json +0 -330
  177. package/apps/vibe/.crew/training-data.jsonl +0 -0
  178. package/apps/vibe/.github/workflows/studio-quality.yml +0 -37
  179. package/apps/vibe/.studio-data/project-messages/chuck-norris.jsonl +0 -18
  180. package/apps/vibe/.studio-data/project-messages/general.jsonl +0 -81
  181. package/apps/vibe/.studio-data/project-messages/studio-local.jsonl +0 -18
  182. package/apps/vibe/ARCHITECTURE.md +0 -3393
  183. package/apps/vibe/QUICK-REFERENCE.md +0 -211
  184. package/apps/vibe/ROADMAP.md +0 -41
  185. package/apps/vibe/STUDIO-SETUP-COMPLETE.md +0 -35
  186. package/apps/vibe/VISUAL-GUIDE.md +0 -378
  187. package/apps/vibe/capture-demo.mjs +0 -160
  188. package/apps/vibe/capture-full-demo.mjs +0 -255
  189. package/apps/vibe/capture-quickstart.mjs +0 -256
  190. package/apps/vibe/capture-vibe-assets.mjs +0 -71
  191. package/apps/vibe/capture-vibe-video.mjs +0 -260
  192. package/apps/vibe/check-buttons.js +0 -41
  193. package/apps/vibe/diagnose.html +0 -106
  194. package/apps/vibe/fix-buttons.js +0 -103
  195. package/apps/vibe/index.html +0 -3404
  196. package/apps/vibe/package-lock.json +0 -920
  197. package/apps/vibe/scripts/studio-pty-host.py +0 -117
  198. package/apps/vibe/src/main.js +0 -2940
  199. package/apps/vibe/src/register-all-languages.js +0 -98
  200. package/apps/vibe/start-studio.sh +0 -11
  201. package/apps/vibe/test/accessibility-tests.js +0 -77
  202. package/apps/vibe/test/browser-performance-audit.mjs +0 -205
  203. package/apps/vibe/test/performance-tests.js +0 -120
  204. package/apps/vibe/test/security-tests.js +0 -213
  205. package/apps/vibe/tests/e2e.local.mjs +0 -54
  206. package/apps/vibe/tests/server.smoke.mjs +0 -106
  207. package/apps/vibe/update_website.mjs +0 -74
  208. package/apps/vibe/vite.config.js +0 -19
  209. package/lib/crew-lead/chat-handler.mjs.bak +0 -1274
  210. 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 &